次のコマンドを使用してcrontabによって毎日呼び出される小さなスクリプトがあります。
/homedir/MyScript &> some_log.log
このメソッドの問題は、some_log.logがMyScriptの終了後にのみ作成されることです。プログラムの実行中にプログラムの出力をファイルにフラッシュしたいので、次のようなことができます
tail -f some_log.log
進捗状況などを追跡します。
次のコマンドを使用してcrontabによって毎日呼び出される小さなスクリプトがあります。
/homedir/MyScript &> some_log.log
このメソッドの問題は、some_log.logがMyScriptの終了後にのみ作成されることです。プログラムの実行中にプログラムの出力をファイルにフラッシュしたいので、次のようなことができます
tail -f some_log.log
進捗状況などを追跡します。
sys.stdout.flush()
。たとえば、Pythonで。
回答:
bash自体が実際にログファイルに出力を書き込むことはありません。代わりに、スクリプトの一部として呼び出すコマンドは、それぞれ個別に出力を書き込み、必要に応じてフラッシュします。したがって、あなたの質問は、bashスクリプト内のコマンドを強制的にフラッシュする方法であり、それはそれらが何であるかによって異なります。
私はここでこれに対する解決策を見つけました。OPの例を使用して、基本的に実行します
stdbuf -oL /homedir/MyScript &> some_log.log
その後、出力の各行の後にバッファがフラッシュされます。私はよくこれを組み合わせnohup
て、リモートマシンで長いジョブを実行します。
stdbuf -oL nohup /homedir/MyScript &> some_log.log
これにより、ログアウト時にプロセスがキャンセルされることはありません。
stdbuf
GNU coreutilsの一部であり、ドキュメントはgnu.org
script -c <PROGRAM> -f OUTPUT.txt
キーは-fです。男のスクリプトからの引用:
-f, --flush
Flush output after each write. This is nice for telecooperation: one person
does 'mkfifo foo; script -f foo', and another can supervise real-time what is
being done using 'cat foo'.
バックグラウンドで実行:
nohup script -c <PROGRAM> -f OUTPUT.txt
busybox
!(私のシェルはその後フリーズしますが、何でも)
を使用tee
して、フラッシュせずにファイルに書き込むことができます。
/homedir/MyScript 2>&1 | tee some_log.log > /dev/null
これは役に立ちますか?
tail -f access.log | stdbuf -oL cut -d ' ' -f1 | uniq
これにより、stdbufユーティリティを使用してaccess.logからの一意のエントリがすぐに表示されます。
stdbuf
現在Ubuntuで利用できますが、どこで入手したかわかりません。
stdbuf
はcoreutilus
(で見つかりましたapt-file search /usr/bin/stdbuf
)の一部です。
ここで問題を見つけたのは、スクリプトから実行するプログラムがジョブを終了するのを待たなければならないということです。
スクリプトでプログラムをバックグラウンドで実行する場合は、さらに何かを試すことができます。
一般に、sync
終了する前にを呼び出すと、ファイルシステムバッファをフラッシュでき、少し役立つ場合があります。
スクリプトでいくつかのプログラムをバックグラウンド(&
)で開始した場合、スクリプトを終了する前に、プログラムが終了するのを待つことができます。それがどのように機能するかについての考えを持っているためにあなたは以下を見ることができます
#!/bin/bash
#... some stuffs ...
program_1 & # here you start a program 1 in background
PID_PROGRAM_1=${!} # here you remember its PID
#... some other stuffs ...
program_2 & # here you start a program 2 in background
wait ${!} # You wait it finish not really useful here
#... some other stuffs ...
daemon_1 & # We will not wait it will finish
program_3 & # here you start a program 1 in background
PID_PROGRAM_3=${!} # here you remember its PID
#... last other stuffs ...
sync
wait $PID_PROGRAM_1
wait $PID_PROGRAM_3 # program 2 is just ended
# ...
数字wait
だけでなく仕事でも機能するのでPID
、スクリプトの最後に怠惰な解決策を置く必要があります
for job in `jobs -p`
do
wait $job
done
より難しいのは、バックグラウンドで他の何かを実行する何かを実行する場合、すべての子プロセスの終了を検索して待機する必要があるためです(その場合)。たとえば、デーモンを実行する場合は、おそらくそうではありません。それが終了するのを待つ:-)。
注意:
wait $ {!}は、「最後のバックグラウンドプロセスが完了するまで待つ」ことを意味し$!
ます。ここで、は最後のバックグラウンドプロセスのPIDです。したがって、wait ${!}
直後に配置することは、バックグラウンドで送信せずにprogram_2 &
直接実行するprogram_2
ことと同じです。&
の助けからwait
:
Syntax
wait [n ...]
Key
n A process ID or a job specification
おかげで@user3258569
、スクリプトはおそらくで動作する唯一のものbusybox
です!
しかし、その後、シェルは私にとって凍っていました。原因を探すと、スクリプトのマニュアルページに「非対話型シェルでは使用しないでください」という大きな赤い警告が見つかりました。
script
主にインタラクティブなターミナルセッション用に設計されています。stdinがターミナルではない場合(例:)echo foo | script
、スクリプトセッション内のインタラクティブシェルがEOFを見逃しscript
、セッションをいつ閉じるかわからないため、セッションがハングする可能性があります。詳細については、「注意」セクションを参照してください。
本当。script -c "make_hay" -f /dev/null | grep "needle"
私のために殻を凍らせていました。
警告に反して、echo "make_hay" | script
EOFを通過すると思ったので試してみました
echo "make_hay; exit" | script -f /dev/null | grep 'needle'
そしてそれはうまくいきました!
manページの警告に注意してください。これはうまくいかないかもしれません。
stdbufの代わりにawk '{print} END {fflush()}'
、これを行うためのbashが組み込まれていればいいのですが。通常は必要ありませんが、古いバージョンではファイル記述子にbash同期のバグがある可能性があります。
それがうまくいくかどうかはわかりませんが、電話するのはsync
どうですか?
sync
は低レベルのファイルシステム操作であり、アプリケーションレベルでのバッファリングされた出力とは関係ありません。
sync
必要に応じて、ダーティなファイルシステムバッファを物理ストレージに書き込みます。これはOSの内部です。OS上で実行されているアプリケーションは、ディスクブロックが物理ストレージに書き込まれているかどうかに関係なく、常にファイルシステムの一貫したビューを確認します。元の質問の場合、アプリケーション(スクリプト)はおそらくアプリケーション内部のバッファーに出力をバッファリングしており、OSは出力が実際にstdoutに書き込まれることを(まだ)認識していません。したがって、架空の「同期」タイプの操作では、スクリプトに「到達」してデータを引き出すことはできません。
を使用したMacOSXのバックグラウンドプロセスでこの問題が発生しましたStartupItems
。これが私がそれを解決する方法です:
私が作るsudo ps aux
と、それmytool
が起動していることがわかります。
Mac OS Xがシャットダウンしたときに(バッファリングのために)mytool
出力がsed
コマンドに転送されないことがわかりました。ただし、を実行するsudo killall mytool
とmytool
、出力がsed
コマンドに転送されます。したがって、Mac OSXがシャットダウンしたときに実行されるstop
ケースを追加しましたStartupItems
。
start)
if [ -x /sw/sbin/mytool ]; then
# run the daemon
ConsoleMessage "Starting mytool"
(mytool | sed .... >> myfile.txt) &
fi
;;
stop)
ConsoleMessage "Killing mytool"
killall mytool
;;
好むと好まざるとにかかわらず、これがリダイレクトの仕組みです。
あなたの場合、スクリプトの出力(スクリプトが終了したことを意味します)はそのファイルにリダイレクトされます。
あなたがしたいのは、スクリプトにそれらのリダイレクトを追加することです。