データをsftp接続にパイプする方法?


9

ftpは、put "|..." "remote-file.name"データをFTP接続にパイプするコマンドをサポートしています。sftpで利用できる同様のものはありますか?

sftpで次のエラーが発生します。

sftp 'jmw@backupsrv:/uploads'
sftp> put "| tar -cx /storage" "backup-2012-06-19--17-51.tgz"
stat | tar -cv /storage: No such file or directory

上記のように、sftpクライアントは明らかにコマンドを実行しません。

pipeコマンドを使用して、ファイルストリームをsftpに直接リダイレクトしたいと思います。(sftpサーバーにアップロードする前に、同じディスク上にバックアップファイルを作成するための十分なスペースがないためです。)


1
これにFIFOを使用することを考えましたが、SFTPもSCPもFIFOから読み取れません。
トムアンダーソン

1
また、これは私のアイデアです。qxs.ch
JMW

回答:


4

この問題の解決策を考え出すのはとても楽しかったです。両方のマシンにnc(netcat)ツールとSSH(SFTPは必要ありません)が必要です。

この例では、linux-aをバックアップする必要のあるデータがあるマシンと、バックアップlinux-bを受信する必要のあるマシンを呼び出します。

linux-aで、netcatにポート(2000を使用)で待機させ、それをファイルにリダイレクトします。これはただそこに座って、そのポートで何かが来るまで待機します。

[kenny@linux-b /var/backups]$ nc -l 2000 > backup.tgz

linux-bでは、linux-aへのsshトンネルを開いて、ポート2000を再び使用しました。これにより、localhostのTCPポート2000でスローしたものはすべて、netcatが待機しているlinux-aのTCPポート2000にリダイレクトされます。

[kenny@linux-a /var/data]$ ssh -L 2000:localhost:2000 -CfN linux-b

ここでtarアーカイブを作成しますが、出力をstdout(-を使用)に送信し、圧縮のためにgzipにパイプします。これを、ポート2000のTCPのlocalhostに送信する別のnetcatにパイプします。

[kenny@linux-a /var/data]$ tar cf - important-data | gzip -fc | nc localhost 2000

終わったね!linux-bでは、netcatはリッスンしなくなり、新しいファイルが作成されます。最良の部分は、tarアーカイブがlinux-aのハードディスクに配置されたことがないことです。

[kenny@linux-b /var/backups]$ file backup.tgz 
backup.tgz: gzip compressed data, from Unix, last modified: Thu Jul  5 13:48:03 2012

それがあなたが質問で正確に求めたものではないことは知っていますが、netcatが利用可能であれば、それはあなたのタイプの問題に対する実行可能な解決策です。

編集:私は1つのことを忘れていました。これらの手順に従えば、linux-aにSSHトンネルが浮かんでいることになります。プロセスIDが何であるかを調べて、強制終了します。

[kenny@linux-a /var/data]$ ps -ef | grep "ssh -L"
kenny     5741     1  0 13:40 ?        00:00:00 ssh -L 2000:localhost:2000 -CfN linux-b
kenny     5940  3360  0 14:13 pts/1    00:00:00 grep --color=auto ssh -L
[kenny@linux-a /var/data]$ kill 5741

3
私はそれが好きですが、2つの問題があります。sftponlyユーザーは通常、ポート転送を使用できず、sftponlyユーザーはsftpサーバーのncにアクセスできません(sshアクセスがないことに注意してください)
JMW

1
それは完全に正当な批判です。
ケニー・ラッシャート

トピック外ですが、なぜこの投稿に「The Prestige」のスクリーンショットが埋め込まれているのですか?
Rilindo 2012

4

これは、この質問をグーグルで見つけた最初の結果であり、まだ言及されていないため、ここでも見つけた解決策を追加します。

これにはcurls sftp実装を使用できます。curlはおそらく多くのシステムにすでにインストールされているため、カスタムクライアントを使用するソリューションよりもこの方法が適している場合があります。

使用例:

pg_dump -d database | pigz -1 | curl -u username -T - sftp://sftpserver/folder/dbbackup.sql.gz

curl.ssh/known_hosts鍵の検証にファイルを使用します。sshクライアントがcurlで使用されるライブラリでサポートされていない新しい暗号化標準を使用している場合、これは失敗する可能性があります

これを修正するには、次のコマンドを使用して、既知のホストファイルに他のキータイプを追加できます。

ssh-keyscan sftpserver >> ~/.ssh/known_hosts

または、-kフラグを使用してキーの検証を無効にできます(ただし、お勧めしません)


2

output-stream-generating-command | ssh user@remotehost 'input-stream-accepting-command' リモートユーザーが有効なシェルを持っている場合、オプションです。


5
これはsftpではありません
ジリブ

3
@JiriXichtknihaいいえ、そうではありませんが、SFTPはほとんどの場合SSHサーバーのサブシステムとして実装されており、これは質問から要求されている機能に最も近いものです(SFTPを介したパイプデータはプログラムで処理されます)反対側)。時々答えは「あなたは間違ったツールを使っています- this代わりにしてください」です。-これはその時の1つとして私を襲います。
voretaq7 2012年

2
sftpはプロトコルであり、sshを介したパイプとは異なります。リモート部分がSFTPのみの場合、提案は機能しません。
ジリブ

1
sshユーザーとしてログインすることはできません
JMW

1
@JMWその場合、私が知っている限り、ここでかなりうまくねじ込まれています-リモートシステムのコマンドへのパイプをサポートするsftpのバージョンを見たことがありません(おそらくS、誰かをシェルを持っていないあなたの状況はとにかくプログラムを実行します)。私は間違っているかもしれません-私はOpenSSHのSFTP機能とSunが出荷するために使用した独自のSSHサーバーにほとんど精通しています...
voretaq7

1

voretaq7は、sftpクライアントはサーバーへの接続にのみsftpの使用を許可されているユーザーのパイプによるデータ転送をサポートしないことを指摘しました。

幸い、sftpをサポートするlibssh2があります。そのため、libssh2を使用する他の2つのクライアントが必要です。

  • sftp_stdin_upload(sftpサーバーにアップロードするため)
  • sftp_stdout_download(sftpサーバーからダウンロードする場合)

ソースコードは次のURLにあります。http//www.qxs.ch/2012/07/05/sftp-upload-tool/


私はlibssh2プログラミングの経験があまりないので、ソースコードへのフィードバックに満足しています。


私にとっては機能しません:-( / usr / bin / ld:libssh2-1.4.2 / src / .libs / libssh2.a(knownhost.o):シンボル 'EVP_sha1' / usr / lib / libcryptoへの未定義の参照。 so.1.0.0:シンボルの追加エラー:コマンドラインにDSOがありませんcollect2:エラー:ldが1の終了ステータスを返しました
tobixen

このコードにはPOCステータスのみがあります。自由に修正してください。:-)
JMW 2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.