append
出力をファイルにリダイレクトする簡単なスクリプトがあります。
filename="/home/ronnie/tmp/hello"
date=$(date)
echo "$date" >> $filename
それでは、エラーを生成するdate=$(date)
ように変更したとしましょう。date= $(date)
私の修正されたスクリプト:
filename="/home/ronnie/tmp/hello"
date= $(date)
echo "$date" >> $filename 2>> $filename
#Also tried echo "$date" >> $filename 2>&1
上記のスクリプトはエラーをtest.sh: line 5: Fri: command not found
ファイルにリダイレクトすると思いましたが、hello
ファイルに新しい行を追加し、エラーが私のstdout
。
私のバッシュバージョン:
ronnier@ronnie:~/tmp$ bash --version
GNU bash, version 4.2.24(1)-release (i686-pc-linux-gnu)
だから私はどこに間違って行きましたか?
答え1
エラーを引き起こす行は、date =$(date)
エラーがstderrに送信されることです。このステップでは、stderrをどこにもリダイレクトしません。後続の行はstderrを$ filenameに送信しますが、これはエラーを引き起こす行ではありません。
目的の効果を得る1つの方法は、スクリプトを実行してstderrを別の場所に送信することです。
./myscript 2>> errors.txt
この時点で error.txt にはエラーが含まれます。
したがって、問題は、エラーを生成する行がスクリプト自体のエラーであり、出力がリダイレクトされるスクリプトから呼び出された外部コマンドによって発生したエラーではないことです。つまり、リダイレクトする必要があるトップレベルのスクリプト出力です。
答え2
シェルは行 5 に達するとエラーメッセージを発行します。現在、シェルのエラーストリームはリダイレクトされません。
を書き込むと、date= $(date) 2>/dev/null
「コマンドが見つかりません」というメッセージが、エラーストリームがリダイレクトされるコマンドではなく、シェルに表示されます。したがって、まだエラーメッセージが表示されます。
エラーメッセージが表示されないようにするには、コマンド全体をグループに入れ、グループ全体のエラーフローをリダイレクトします。
{ date= $(date); } 2>/dev/null
中かっこを使用している場合、コマンドはまだ親シェルで実行されるため、環境やその他の状態を変更できます(ここでは実行されません)。関数本体またはサブシェルにコマンドを配置することもできます(括弧で囲まれたコマンドは別のシェルプロセスで実行されます)。
exec
コマンド名なしで組み込みコマンドのリダイレクトを使用して、シェルのファイル記述子を永久に(または少なくとも次に変更するまで)リダイレクトできます。
exec 2>/dev/null
# From this point on, all error messages are lost
date= $(date)
…
exec 2>/some/log/file
# From this point on, all error messages go to the specified file