- 締切済み
shでftp⇒接続切らずに成否確認して削除可?
ftpで多数のファイルを転送(put)したいです。 転送した後に転送エラーがないか確認し、 転送エラーがなければローカルのファイルを削除する、 ということを1ファイルずつ行いたいです。 ftpコマンドをヒアドキュメントやコマンドファイルを使用して実行する場合、 転送エラーがあったかどうかは、ftpの出力結果を見ないと分からないので、 いったんftpコマンドを終了する必要があると思います。 そうすると、1ファイルずつftpのコネクションを張りなおさないとならないので、 WAN経由での接続を考慮すると相当効率が悪いと思うのですが、 接続を切らずに実現することは可能でしょうか。 理想案: 転送先にftp接続 すべての対象ファイルに対し、 ┣ファイルをput ┗putが成功したら ┗ファイルを削除 ftp接続を切断 現実案: すべての対照ファイルに対し、 ┣転送先にftp接続 ┣ファイルをput ┣ftp接続を切断 ┗putが成功したら ┗ファイルを削除 現実案の実装だと、こんな感じかと思います。 実際に動かしてないので、間違いあるかもですが。 for file in `ls` do ftp -n ${hostname} > ftp.log << _EOF user ${user} ${pass} put ${file} bye _EOF if [ `grep "err" ftp.log` ]; then exit 1; else rm -f ${file} fi done
- みんなの回答 (3)
- 専門家の回答
みんなの回答
- notnot
- ベストアンサー率47% (4900/10358)
>途中で失敗した場合や停止した場合の再実行の際、すべて再実行となるのを避けたいのです。 そんなものは、ログをちゃんと解析すればどうとでもなります。 失敗した時点から後を再送すれば良いだけ。 あと、 >標準出力には一切出力しないという制限があるので、 と >expectは使用できないかと思います。 に何の関係があるのかわかりません。何かの勘違いでは?
- notnot
- ベストアンサー率47% (4900/10358)
No1です。 >例えば、ftpコマンドを子プロセスとして標準入力待ちとなる状態で起動しておいて、その子プロセスにメッセージを送ることは可能でしょうか。 expectコマンドを使えば可能です。ただエラー判定まですると、かなり面倒だと思います。 使い方は検索してください。 私なら、そんなことはしないで、 転送先にftp接続 すべての対象ファイルに対し、 ┗ファイルをput ftp接続を切断 すべての対象ファイルに対し、 ┗putが成功していたら ┗ファイルを削除 と、最初にまとめてputしますね。
お礼
調べた限りでは、こちらのサイトによると <http://www.itmedia.co.jp/enterprise/articles/0805/13/news040_3.html> kshにはコプロセスというのがあり、 親プロセスから子プロセスに入力したり、 子プロセスの出力を親プロセスで受け取ったり、 というのが簡単にできるようです。 bashでこれと同等のことをやろうとすると、 どのような方法が考えられるのでしょうか。
補足
例では`ls`してるだけですが、 実際には多量のファイルを転送することになるので、 途中で失敗した場合や停止した場合の再実行の際、 すべて再実行となるのを避けたいのです。 また、後だし情報ですいませんが、 標準出力には一切出力しないという制限があるので、 expectは使用できないかと思います。
- notnot
- ベストアンサー率47% (4900/10358)
>接続を切らずに実現することは可能でしょうか。 shスクリプトからftpを起動するやり方では不可能です。 自分で、ftpに代わるプログラムを書けば可能です。 >if [ `grep "err" ftp.log` ]; then これはおかしい。 >if `grep "err" ftp.log` ; then
お礼
> 自分で、ftpに代わるプログラムを書けば可能です。 shスクリプトで実現可能かどうかを教えてください。
補足
例えば、ftpコマンドを子プロセスとして 標準入力待ちとなる状態で起動しておいて、 その子プロセスにメッセージを送ることは可能でしょうか。 イメージはこんな感じ? ftp -n ${hostname} > ftp.log & FTP_PID=$$ ${FTP_PID}プロセスに入力 "user ${user} ${pass}" (*1) for file in `ls` do ${FTP_PID}プロセスに入力 "put ${file}" (*1) putが完了するのを待機(*2) if `grep "err" ftp.log` then exit 1; else rm -f ${file} fi done ${FTP_PID}プロセスに入力 "bye" (*1) (*1)の子プロセスの標準入力に親プロセスから入力を渡すこと (*2)の子プロセスのput完了を確認すること ができれば実現できそうな気がしてます。 (*2)はftp.logをチェックしてればできそうですが、 (*1)はどうやったらできるのか全然わかりません。 (*1)の実現方法、もしくは、もっといい方法があれば (こういうときはこうやるんだぜ~とか) 教えてください。
補足
数千数万のファイルになるので、失敗した際に 「ログ見て、転送済みのファイルを手で削除して、再実行」 という手作業だと未転送のファイルを誤削除する可能性もあり、極力避けたいのです。 expectについては、ftpコマンドを実行して、ftpのプロンプトをexpectしながら実行する、ということであれば、標準出力が必要になりませんか? 下記のようなイメージだと思ったのですが、 私の勘違いであれば教えてください。 ftp ${hostname} !expect "User:" ${user} !expect "Password:" ${pass} !for file in `ls` !do !expect "ftp>" put ${file} !if (何らかのエラーハンドリング) then bye; !exit 1; !else !rm -f ${file} !fi !done !expect "ftp>" bye そもそもftpの中でforやifなんて使えない気がしますが、 こういうことをおっしゃってたわけではないのでしょうか。