はい

はい

与えられた壁時間だけ持続するパイプを作る簡単な方法はありますか?

時間が経つにつれて、STDOUTに記録されている内容(バイトや行ではない)の「スナップショット」を撮ることができるようにしたいです。それはまるで

tail -f /var/log/whatever.log | pipe_for_seconds 10 > ./10_second_sample_of_log

私はBASHを使用していますが、他のシェルでこれがより簡単な場合はこれについて聞きたいです。

答え1

ゲヌコアツールバージョン7.0以降、次のコマンドがありますtimeout

timeout 10 tail -f /var/log/whatever.log 

もしあなたなら本物わずかに異なるプロセスをタイムアウトしてからパイプを接続するには、パイプが必要ですtimeout

tail -f /var/log/whatever.log | timeout 10 cat > ./10_second_sample_of_log

しかし、参考にしてくださいパイプラインの一部を終了すると、バッファリングによって問題が発生する可能性があります。、信号、およびプログラムの動作によって異なります(この質問は関連する問題をカバーしています。パイプラインでバッファリングをオフにする)。通常変わります。終了コード過程も同じだ。

(最近)coreutilsがないと、この単純なタイムアウトプログラムもうまく機能します。 http://www.unixlabplus.com/unix-prog/timeout/timeout.html またはパール方法:

tail -f /var/log/whatever.log | perl -n -e 'BEGIN{alarm 10; $|=1}; print;'

(注:$|=1出力バッファリングはオフになります。これは上記のようにパイプ内の出力損失を防ぐためです。)

(少し年をとった)ネットワークパイプパッケージにはtimelimitコマンドもあります(一部のLinuxシステムではまだ見つかります)。

この同様の質問にはいくつかのオプションがあります。シェルスクリプトにタイムアウトを導入する方法は?

答え2

これは働きます:

tail -f /var/log/whatever.log > ten_second_sample & sleep 10 && kill $!

tailsleep10秒間バックグラウンドで並列に開始以来 kill $!最後に開始されたバックグラウンドプロセスのPID。

答え3

tail -fPID の終了に依存することは、PID が早すぎる(たとえば、ファイルが存在しない場合など)、信頼できない可能性があります。もう1つのより一般的な解決策は、タイムアウトの前に「キルタイマー」が完了すると、andの使用も中止waitされますkill %%%%bashで始まった最新の操作 - usingの使用を意味します&)。

設定は次のとおりです(sleep 2パラメータなどを含むカスタムコマンドがあり、タイムアウトが10秒に設定されています)。

# Your command that may take some (or not) time to execute:
sleep 2 &
# Set a timer that kills the last started job
sleep 10 & wait -n 1; kill %%; wait -n 1

この設定は、タイムアウトに達するか、カスタムコマンドが実行を完了するのを待ちます(この場合は常にsleep 2最初に停止します)。これにより、コマンドまたはタイムアウトがそれぞれ終了しますkill %%。最後のコマンドは、wait -n 1コマンドまたはタイムアウトが実際に終了するまで追加の実行をブロックします(オプションですが必須です)。

メモ。必要で予期したとおり、以前に並列に実行されたコマンドは影響を受けません。

はい

readタイムアウトのある名前付きパイプから行を読み取るがタイムアウトフラグを使用しないより実用的な例:

# Custom bash function to set timeout in seconds for the most recently started job (parallel execution).
timeout() { sleep $1 & wait -n 1; kill %%; wait -n 1 }

# Example 1:
mkfifo /tmp/test
read ln </tmp/test &
timeout 10

何も記録されないため、/tmp/test10秒後にタイムアウトします。コマンドがすぐに終了しても終了タイマーが停止することを示すために:

# Example 2:
mkfifo /tmp/test
echo "Hello" >/tmp/test &
ln="$(read ln </tmp/test && echo -e "$ln" & timeout 10)"
echo "Line was read: $ln"

名前付きパイプの実際の使用に注意してください。サブシェルで実行されるため、read ln(親)スクリプトからはアクセスできません。したがって、echo(他の)変数に保存するために行が印刷されますln

関連情報