次のスクリプトがあります。
pid = $(ps -ef | grep my-service | awk '{print $2}')
これは私に実行中のプロセスのPIDを与えますmy-service
。実行中の複数のプロセスを処理し、my-service
最新のプロセスを除くすべての以前のプロセスを終了するようにスクリプトを更新したいと思います。ただし、実行中のプロセスが1つしかない場合は、そのプロセスを終了します。どうすればいいですか?
答え1
pgrep
(および)には、プロセス数を計算するための()、最新のPIDのみを取得するための()など、このタスクのいくつかのpkill
便利なパラメータがあります。 (詳細)-c
--count
-n
--newest
man pgrep
だから私たちはこのcase
声明を使うことができます。 pidが返されない場合は終了し、そうであればプロセスを終了します。複数のプロセスが見つかった場合は、grep -v
最新のPIDを除くすべてのPIDをターゲットにしてこれをkill
。
#!/bin/bash
die="my-service"
case $(pgrep -cf "$die") in
0) exit 0 ;;
1) pkill -f "$die" ;;
*) grep -v $(pgrep -nf "$die") <(pgrep -f "$die") | xargs kill ;;
esac
注:-f
上記で使用したパラメータは、コマンド全体と一致させるために使用されました。プロセス名のみを一致させるには、このパラメーターを使用しないでください。からman pgrep
:
-f、--完了
このパターンは通常、プロセス名とのみ一致します。 -fを設定すると、コマンドライン全体が使用されます。
答え2
procps-ngps
と unmodified を仮定すると、$IFS
次のことができます。
set -- $(ps -o pid= --sort=-start_time -C my-service)
case $# in
(0) ;;
(1) kill "$1";;
(*) shift; kill "$@"
esac
set
分配する位置パラメータ( $1
, $2
...) を名前付きプロセスの pid に追加し、逆順my-service
でソートします (最も最近開始されたものから)。start_time
その後、数字($#
)を基準にして0であれば何もせず、1であれば殺し、他の数字については最小を捨て、残りは殺しますshift
。
(ps -C name
一致するものを参照してください正確に報告された引数のリストではなく、完全なプロセス名にありますps -f
)