UnixスクリプトからのFTPリターンコードの確認
質問
現在、 ftp
を使用してファイルを作成および転送するUnixスクリプトを呼び出す夜間ジョブを作成しています。考えられるすべての戻りコードを確認したいと思います。 ftp
のmanページには戻りコードがリストされていません。リストの場所を知っている人はいますか?これを経験した人はいますか?ログ内の特定の戻り文字列をgrepする他のスクリプトがあり、エラーが発生すると電子メールを送信します。ただし、予期しないコードを見逃すことがよくあります。
次に、ログとメールに理由を入れています。
解決
ftp
コマンドは、私が遭遇したほとんどの実装でゼロ以外を何も返しません。
ログ内の3桁のコードを処理する方がはるかに優れています。バイナリファイルを送信している場合は、送信されたバイトが正しいことを確認できます。
3桁のコードは「シリーズコード」と呼ばれ、リストはここで見つけることができます
他のヒント
一度に1つのファイルのみを転送するスクリプトを作成し、そのスクリプトで grep
を使用して 226 Transfer complete
メッセージを確認しました。見つかった場合、 grep
は0を返します。
ftp -niv < "$2"_ftp.tmp | grep "^226 "
何か問題が発生した場合、ftpを実行し、ftpの終了コードを確認する方が簡単だと思います。
次の例のようにこれを行いました:
# ...
ftp -i -n $HOST 2>&1 1> $FTPLOG << EOF
quote USER $USER
quote PASS $PASSWD
cd $RFOLDER
binary
put $FOLDER/$FILE.sql.Z $FILE.sql.Z
bye
EOF
# Check the ftp util exit code (0 is ok, every else means an error occurred!)
EXITFTP=$?
if test $EXITFTP -ne 0; then echo "$D ERROR FTP" >> $LOG; exit 3; fi
if (grep "^Not connected." $FTPLOG); then echo "$D ERROR FTP CONNECT" >> $LOG; fi
if (grep "No such file" $FTPLOG); then echo "$D ERROR FTP NO SUCH FILE" >> $LOG; fi
if (grep "access denied" $FTPLOG ); then echo "$D ERROR FTP ACCESS DENIED" >> $LOG; fi
if (grep "^Please login" $FTPLOG ); then echo "$D ERROR FTP LOGIN" >> $LOG; fi
編集:エラーをキャッチするには、ftpコマンドの出力をgrepします。しかし、それは本当に最善の解決策ではありません。
Perl、Python、RubyなどのScriptlanguageを使用して、あなたがどれほどおなじみかを知りません。これらはすべて、使用可能なFTPモジュールを備えています。これにより、各コマンドの後にエラーをチェックできます。 Perlの例を次に示します。
#!/usr/bin/perl -w
use Net::FTP;
$ftp = Net::FTP->new("example.net") or die "Cannot connect to example.net: $@";
$ftp->login("username", "password") or die "Cannot login ", $ftp->message;
$ftp->cwd("/pub") or die "Cannot change working directory ", $ftp->message;
$ftp->binary;
$ftp->put("foo.bar") or die "Failed to upload ", $ftp->message;
$ftp->quit;
このロジックが機能するには、以下のようにftpコマンドからSTDERRもリダイレクトする必要があります
ftp -i -n $HOST >$FTPLOG 2>&1 << EOF
以下のコマンドでは、ftpコマンドが成功または失敗を返さないため、常に0(成功)が割り当てられます。したがって、ユーザーはそれに依存するべきではありません
EXITFTP=$?
lame answer私は知っていますが、ftpソースを取得して自分で確認する方法はどうですか
Anuragのソリューションが好きです。バイト転送の問題のために、grep -v&quot; bytes&quot;でコマンドを拡張しました
ie
grep&quot; ^ 530&quot; ftp_out2.txt | grep -v&quot; byte&quot;
-530の代わりに、Anuragと同じようにすべてのエラーコードを使用できます。
そこにファイルをFTPで送信したいと言いましたが、通常のBSD FTPクライアントがそこに到達したい唯一の方法であるかどうかは言いませんでした。 BSD FTPは、すべての解析を必要とするエラー状態のリターンコードを提供しませんが、管理者または管理者がファイルをインストールする場合、FTPでファイルを転送するために使用できる他のUnixプログラムがすべてあります。少しのコードですべてのエラー状態をキャッチしながら、FTPでファイルを転送する方法の例をいくつか示します。
FTPUSERはftpユーザーのログイン名です
FTPPASSはFTPパスワードです
FILEは、パス情報なしでアップロードするローカルファイルです(たとえば、/ whatever / file1.txtまたはwhatever / file1.txtではなく、file1.txt
FTPHOSTはFTPで送信するリモートマシンです
REMOTEDIRは、アップロード先のリモートマシン上の場所への絶対パスです
例を次に示します。
curl --user $ FTPUSER:$ FTPPASS -T $ FILE ftp:// $ FTPHOST /%2f $ REMOTEDIR
ftp-upload --host $ FTPHOST --user $ FTPUSER --password $ FTPPASS --as $ REMOTEDIR / $ FILE $ FILE
tnftp -u ftp:// $ FTPUSER:$ FTPPASS @ $ FTPHOST /%2f $ REMOTEDIR / $ FILE $ FILE
wput $ FILE ftp:// $ FTPUSER:$ FTPPASS @ $ FTPHOST /%2f $ REMOTEDIR / $ FILE
これらのプログラムはすべて、何か問題が発生した場合にゼロ以外の終了コードと、失敗した内容を示すテキストを返します。これをテストしてから、出力で必要な処理を実行したり、ログに記録したり、メールで送信したりできます。
ただし、次の点に注意してください:
-
&quot;%2f&quot; URLで使用され、次のパスがリモートマシン上の絶対パスであることを示します。ただし、FTPサーバーがchrootする場合、これをバイパスすることはできません。
-
ユーザーがいるサーバーへの実際のURL( ftp:// etc )を使用する上記のコマンドの場合パスワードが埋め込まれている場合、特殊文字が含まれている場合は、ユーザー名とパスワードをURLエンコードする必要があります。
-
場合によっては、各プログラムの構文に慣れれば、リモートディレクトリが絶対であり、ローカルファイルが単なるファイル名であるため、柔軟に対応できます。ローカルディレクトリの環境変数を追加するか、すべてをハードコーディングする必要がある場合があります。
-
本当に、絶対に通常のFTPクライアントを使用しなければならない場合、失敗をテストする1つの方法は、スクリプト内で、最初にファイルをPUTするコマンドを実行し、その後に同じGETを実行する別のコマンドを実行する別の名前でそれを返すファイル。 FTPが終了したら、ダウンロードしたファイルがシェルスクリプトに存在するかどうかをテストするか、元のファイルとチェックサムして、正しく転送されていることを確認します。ええ、それは悪臭を放ちますが、私の意見では、考えられるすべてのエラー状態に対して大量の解析を行うよりも、読みやすいコードを用意する方が良いと考えています。 BSD FTPはそれほど優れているわけではありません。
これが最終的に私が行ったものです。すべての助けてくれてありがとう。すべての答えは、正しい方向に私を導くのに役立ちます。 結果とログの両方をチェックするのは少しやり過ぎかもしれませんが、すべてのベースをカバーする必要があります。
echo "open ftp_ip
pwd
binary
lcd /out
cd /in
mput datafile.csv
quit"|ftp -iv > ftpreturn.log
ftpresult=$?
bytesindatafile=`wc -c datafile.csv | cut -d " " -f 1`
bytestransferred=`grep -e '^[0-9]* bytes sent' ftpreturn.log | cut -d " " -f 1`
ftptransfercomplete=`grep -e '226 ' ftpreturn.log | cut -d " " -f 1`
echo "-- FTP result code: $ftpresult" >> ftpreturn.log
echo "-- bytes in datafile: $bytesindatafile bytes" >> ftpreturn.log
echo "-- bytes transferred: $bytestransferred bytes sent" >> ftpreturn.log
if [ "$ftpresult" != "0" ] || [ "$bytestransferred" != "$bytesindatafile" ] || ["$ftptransfercomplete" != "226" ]
then
echo "-- *abend* FTP Error occurred" >> ftpreturn.log
mailx -s 'FTP error' `cat email.lst` < ftpreturn.log
else
echo "-- file sent via ftp successfully" >> ftpreturn.log
fi
コマンドからのすべての出力をログファイルに保存してから、コマンドからのリターンコードを確認し、0でない場合はログファイルを電子メールで送信するのはなぜですか?