LoginSignup
0
0

More than 3 years have passed since last update.

tail -fをログ出力プロセスの終了と同時に終了

Posted at

やりたいこと

次のシェルスクリプトにおいて、 longjob の終了と同時に tail -f を終了させたい。

#!/bin/bash

longjob &>log & disown
tail -f log

条件:

  • 1つのシェルスクリプト内で行いたい。
  • 端末が終了しても longjob は継続させたい (つまり、& disown は譲れない)。
  • Ctrl-c の押下時に tail は終了させたいが longjob は終了させたくない。

解決策1

tail -f の開始前に、以下を行うバックグラウンドプロセスをあらかじめ起動しておく。

  1. longjob が終了するまで待機。
  2. tail のプロセスを kill。
#!/bin/bash

longjob &>log & disown

(
    # set PID_JOB
    PID_JOB=$!

    # set PID_TAIL
    while test -z $PID_TAIL; do PID_TAIL=$(ps --ppid=$$ | grep tail | awk '$0=$1'); done

    # wait PID_JOB
    while ps -p $PID_JOB >/dev/null; do sleep 0.5; done

    # kill PID_TAIL
    kill -INT $PID_TAIL
) &

tail -f log
  • tail の開始前に PID_TAIL=$(...) の部分が実行された場合、 $PID_TAIL は空文字になる。PID_TAIL を確実に設定するために、 # set PID_TAIL の部分は while で回している。
  • 問題点: longjob が終了すると kill -INT が発砲され、tail が異常終了する。

解決策2

tail をバックグラウンドで一旦起動しおいて fg で処理を戻す。

#!/bin/bash -i

longjob &>log & disown
PID_JOB=$!

tail -f log &
PID_TAIL=$!

(
    # wait PID_JOB
    while ps -p $PID_JOB >/dev/null; do sleep 0.5; done

    # kill PID_TAIL
    kill -INT $PID_TAIL 2>/dev/null
) &

fg 1 >/dev/null

  • 注意: シェバングが #!/bin/bash -i
    • fg はインタラクティブシェルにおいて利用可。
    • インタラクティブシェルとしてシェルスクリプトを起動するため。
  • longjob 終了前に Ctrl-c した場合に kill が失敗するため、エラーを捨てる。
  • fg したときに tail -f log と表示されるのを防ぐため、標準出力を捨てる。

うまく行かない方法

tee & trap

# Ctrl-c で longjob が終了してしまう
longjob 2>&1 | tee log
# Ctrl-c で終了できない
trap '' 1 2 15
nohup longjob 2>&1 </dev/null | tee log
# longjob は最後まで実行されるが、Ctrl-c で teeが終了し、それ以降のログが記録されない
# longjob に "trap '' 1 2 15" を記述した上で
nohup longjob 2>&1 </dev/null | tee log

longjob に trap '' 1 2 15tee log を記述した上で解決策2のようなコードを書けばできるが美しくはない。

wait

# wait PID_JOB の部分を wait $PID_JOB とするとこうなる。

wait: pid 5734 is not a child of this shell
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0