web-dev-qa-db-ja.com

バックグラウンドプロセスのPIDを取得する方法

シェルスクリプトからバックグラウンドプロセスを開始し、スクリプトが終了したらこのプロセスを強制終了します。

シェルスクリプトからこのプロセスのPIDを取得する方法私の知る限りでは、変数$!はバックグラウンドプロセスではなく現在のスクリプトのPIDを含んでいます。

327

起動時にバックグラウンドプロセスのPIDを保存する必要があります。

foo &
FOO_PID=$!
# do other stuff
kill $FOO_PID

ジョブ制御は対話式機能であり、制御端末に結び付けられているため、使用することはできません。スクリプトには必ずしも端末がまったく接続されていないため、ジョブ制御が必ずしも使用可能になるとは限りません。

496
camh

jobs -lコマンドを使用して特定のjobLにアクセスできます。

^Z
[1]+  Stopped                 guard

my_mac:workspace r$ jobs -l
[1]+ 46841 Suspended: 18           guard

この場合、46841がPIDです。

help jobsから:

-lジョブのプロセスグループIDと作業ディレクトリを報告します。

jobs -pは、PIDだけを表示するもう1つのオプションです。

125
jldupont
  • $$は現在のスクリプトのpidです
  • $!は最後のバックグラウンドプロセスのpidです

これはbashセッションからのサンプルトランスクリプトです(%1jobsから見られるようにバックグラウンドプロセスの序数を示します):

$ echo $$
3748

$ sleep 100 &
[1] 192

$ echo $!
192

$ kill %1

[1]+  Terminated              sleep 100
40
catwalk

Bashスクリプトのすべての子プロセスを強制終了するさらに簡単な方法:

pkill -P $$

-Pフラグはpkillおよびpgrepと同じように機能します - pkillを指定すると子プロセスは強制終了され、pgrepを指定すると子PIDは標準出力に出力されます。

25
Alexey Polonsky

これが私がしたことです。それをチェックアウトし、それが役立つことを願っています。

#!/bin/bash
#
# So something to show.
echo "UNO" >  UNO.txt
echo "DOS" >  DOS.txt
#
# Initialize Pid List
dPidLst=""
#
# Generate background processes
tail -f UNO.txt&
dPidLst="$dPidLst $!"
tail -f DOS.txt&
dPidLst="$dPidLst $!"
#
# Report process IDs
echo PID=$$
echo dPidLst=$dPidLst
#
# Show process on current Shell
ps -f
#
# Start killing background processes from list
for dPid in $dPidLst
do
        echo killing $dPid. Process is still there.
        ps | grep $dPid
        kill $dPid
        ps | grep $dPid
        echo Just ran "'"ps"'" command, $dPid must not show again.
done

それからちょうどそれをそれとして実行してください:もちろん適切なパーミッションで./bgkill.sh

root@umsstd22 [P]:~# ./bgkill.sh
PID=23757
dPidLst= 23758 23759
UNO
DOS
UID        PID  PPID  C STIME TTY          TIME CMD
root      3937  3935  0 11:07 pts/5    00:00:00 -bash
root     23757  3937  0 11:55 pts/5    00:00:00 /bin/bash ./bgkill.sh
root     23758 23757  0 11:55 pts/5    00:00:00 tail -f UNO.txt
root     23759 23757  0 11:55 pts/5    00:00:00 tail -f DOS.txt
root     23760 23757  0 11:55 pts/5    00:00:00 ps -f
killing 23758. Process is still there.
23758 pts/5    00:00:00 tail
./bgkill.sh: line 24: 23758 Terminated              tail -f UNO.txt
Just ran 'ps' command, 23758 must not show again.
killing 23759. Process is still there.
23759 pts/5    00:00:00 tail
./bgkill.sh: line 24: 23759 Terminated              tail -f DOS.txt
Just ran 'ps' command, 23759 must not show again.
root@umsstd22 [P]:~# ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
root      3937  3935  0 11:07 pts/5    00:00:00 -bash
root     24200  3937  0 11:56 pts/5    00:00:00 ps -f
3
Luis Ramirez

Pstreeを使うこともできます。

pstree -p user

これは通常 "user"の全プロセスのテキスト表現を与え、-pオプションはprocess-idを与えます。私の知る限りでは、プロセスを現在のシェルが所有しているかどうかには依存しません。フォークも表示されます。

2
villaa

pgrepは、親プロセスのすべての子PIDを取得できます。前述のように$$は現在のスクリプトのPIDです。それで、あなたがそれ自身の後で片付けるスクリプトが欲しいならば、これはトリックをするべきです:

trap 'kill $( pgrep -P $$ | tr "\n" " " )' SIGINT SIGTERM EXIT
1
errant.info