web-dev-qa-db-ja.com

bashスクリプトで間違ったプロセスを強制終了しないようにする方法は?

いくつかの子プロセスを生成するbashスクリプトを作成しており、1時間ごとにcronジョブによって実行されます。実際には、リモートサーバーに対してrsyncコマンドと、関連するssh接続を実行しています。

Rsyncコマンドまたはスクリプトに時間がかかりすぎる場合、それとその子プロセスを強制終了しますが、最初に猶予期間を与えます。スクリプトは1時間ごとに実行されますが、次の2回の試行では、スクリプトの前のインスタンスが実行中であることがわかり、転送を開始する前に終了します。 3回目以降の試行は、新しい転送を開始する前に、まだ実行中の元のインスタンスを強制終了します。

PIDファイルに書き込むことでこれを制御することにしました。最初のインスタンスはそのPIDをファイルに書き込み、次の2回の試行は終了する前にPIDをファイルに書き込みます。 3回目の試行で最初の試行が強制終了され、PIDファイルが新しいPIDで上書きされます。正常に完了すると、PIDファイルが消去されます。すべての子供を殺すために、私は私が取得する元のスクリプトインスタンスのPGIDを使用することにしました:

previous_pid=$(head -n1 "$pid_file")
previous_groupid=$(ps -hp "$previous_pid" -o pgid:1)

それからそれを殺します:

kill -- -"$previous_pid"

私の懸念は、PIDファイルをクリーンアップせずに元のスクリプトが何らかの理由で停止し、PGIDを再利用するPIDが再利用されている状態になる可能性があるため、完全に無関係なプロセスを強制終了することです。 どうすればこれを回避できますか?

2
Arronical

スクリプトを取得して自分自身を殺します。たとえば、スクリプトの最初に次のようなものがあります。

kill_myself () {
    while sleep 1
    do
        if [[ -f /tmp/kill-myself ]]
        then
            rm /tmp/kill-myself
            kill -- -$1
        fi
    done
}

kill_myself $$ &

今、時が来たら:

touch /tmp/kill-myself

これをカスタマイズして、スクリプトの各インスタンスに独自のキルファイルを持たせ、どこかにログを記録することができます。次に、そのファイルを使用して、スクリプトの特定のインスタンスを強制終了します。


別の方法:pgrep/pkillを使用して、より詳細に一致させることができます。 pidファイルから読み取り、コマンド名や引数などと照合できます。

次のようなものは、スクリプトと同じ名前のプロセスのみを強制終了します(script-nameまたは/path/to/script-nameとして呼び出した場合)。

pkill -g "$previous_groupid" script-name

bash script-nameを実行すると、これは機能しません。または、単にrsyncコマンドを強制終了します。これにより、おそらくスクリプトはその後終了します。

pkill -g "$previous_groupid" rsync
3
muru