子プロセスにいるときに一部の信号またはPIDによるシャットダウンを介して親プロセスを終了する正しいbashコマンド/ガイドラインは何ですか?
答え1
私が正しく理解したら、考えられる解決策の1つはtrap
シェルプロセスまたはコマンドを使用することです。
ソリューション1
メモ:それを使用するtrap
ことは、シェルを使用するときにのみ動作するようです。たとえば、端末でコマンドを実行したり、スクリプト(たとえばmyscript.sh
。trap
例を見てみましょう。
ps -fH
現在の親プロセス(シェル)に入ると、zsh
次のようになります。
%> ps -fH
#Output:
UID PID PPID C STIME TTY TIME CMD
edgar 17932 24608 0 23:37 pts/2 00:00:00 /bin/zsh
edgar 18001 17932 0 23:38 pts/2 00:00:00 ps -fH
それでは、子プロセスを実行しbash
てps -H
再入力します。
%> bash
(bash shell) %> ps -fH
#Output:
UID PID PPID C STIME TTY TIME CMD
edgar 17932 24608 0 23:37 pts/2 00:00:00 /bin/zsh
edgar 18012 17932 0 23:38 pts/2 00:00:00 bash
edgar 18030 18012 0 23:38 pts/2 00:00:00 ps -fH
ご覧のとおり、bashシェルの親プロセスにはzsh
PIDがあります17932
。
特定のプロセスのPPIDを取得するには、を使用する必要があります。たとえば、現在のプロセスの親プロセスIDをps -o ppid= $SOME_PID
取得するには、以下を使用する必要があります。bash
(bash shell) %> ps -o ppid= 18012
#Output:
17932
それとも、お勧めできる他のものがありますか?
(bash shell) %> ps -o ppid= $$
#Output
17932
$$
現在実行中のプロセスのプロセスIDを取得しています。この場合はbash
。
最後に、親プロセス(この場合)を終了するには、zsh
次のコマンドを実行する必要があります。
(bash shell) %> trap "echo Killing parent process $(ps -o ppid= $$); kill -9 $(ps -o ppid= $$)" 0
#Or
(bash shell) %> trap "kill -9 $(ps -o ppid= $$)" 0
入力exit
または押すと、Ctrl + D親プロセスzsh
も終了します。
(bash shell) %> exit
#zsh was killed too, so the terminal will show the following output:
Warning: Program '/bin/zsh' crashed
避けるためにzshがクラッシュしましたbash
シェルを2回実行できるというメッセージ
ソリューション2
このstrace
コマンドを使用すると、すべてのプロセスで機能します。
例を見てみましょう。
バックグラウンドでプロセスを実行し、strace
そのプロセスを終了できる親プロセスに接続します。
まず、シェルでbash
実行します。zsh
(zsh shell) %> bash
それでは、bash
シェルでバックグラウンドでプロセスを実行しましょう。この例では、このsleep
コマンドを使用して対応するPPID(親プロセスID)を取得します。
(bash shell) %> sleep 60& #sleep 1 minute (in background)
processID=$! #with $! we get the pid of the last executed process, in this case the sleep command
parentID=$(ps -o ppid= $processID)
ps -fH
出力を見ると、次のような結果が得られます。
UID PID PPID C STIME TTY TIME CMD
edgar 21593 21579 0 00:43 pts/1 00:00:00 /bin/zsh
edgar 22971 21593 0 01:03 pts/1 00:00:00 bash
edgar 23011 22971 0 01:07 pts/1 00:00:00 sleep 60
edgar 23012 22971 0 01:08 pts/1 00:00:00 ps -fH
bash
これで完了したら、親プロセスを終了しようとしますsleep 60
。これを行うには、次のコマンドを使用しますstrace -p
。
strace -p $processID ; kill -9 $parentID
strace -p は、PID を使用してプロセスをリンクするために使用されます。
プロセス$processID
(sleepコマンド)が完了すると、killコマンドが実行され、$ parentID(bashシェル)が終了します。
メモ:strace
シグナルを受け取ったときにコマンドを実行できるかどうかはわかりません。この方法は、プロセスが完了した後にのみ機能します。
上記のコマンドの説明
psの使用
によるとps --help
:
-f - フルリスト
--forest-H - プロセス階層を表示する
ps -f
出力には、単に使用するよりも多くの列が表示されますps
。私はすべてのプロセスをps -f
理解したPPID
。
ヘルプに示されているようにps -H
(を使用することもできます)を使用すると、プロセス階層が表示されます。つまり、特定のプロセスの各サブプロセスが特別な形式で表示されます。ps --forest
実行すると、ps -H
次のような結果が得られます。
PID TTY TIME CMD
2872 pts/1 00:00:00 zsh
3771 pts/1 00:00:00 bash
7259 pts/1 00:00:00 ps
ps
これがの子プロセスでありbash
、これがのプロセスであることがわかりますzsh
。
代わりに、以下を実行することもできますps f
(BSD構文)ps -H
。
%> ps f
#Output:
PID TTY STAT TIME COMMAND
2872 pts/1 Ss 0:00 /bin/zsh
3771 pts/1 S 0:00 \_ bash
7495 pts/1 R+ 0:00 \_ ps f
トラップの使用
の構文はtrap
次のとおりですtrap 'commands' SIGNAL
。これは、プロセスが特定のメッセージを受信するとSIGNAL
実行されることを意味します。より良い説明のために、次のようにcommands
入力できます。man trap
条件は、デフォルト定義ボリュームで定義されている<signal.h>ヘッダーのシグナル名テーブルにリストされているように、EXIT、0(EXITと同じ)、またはシンボル名(SIGプレフィックスなし)を使用して指定されたシグナルです。 POSIX.1-2017。
...
XSI互換システムでは、次の信号名に対応する条件でデジタル信号番号を使用することもできます。
1 SIGHUP
2 SIGINT
3 SIGQUIT
6 SIGABRT
9 SIGKILL
14 SIGALRM
15 SIGTERM
trap 'commands' 0
したがって、シェルを使用している場合、'commands'
シェルを終了するとトラップで指定された内容が実行されます。
たとえば、bash シェルは次のコードを受け取るecho
と実行されます。SIGINT
(bash_shell) %> echo Bash PID: $$
#Output:
Bash PID: 8529
(bash_shell) %> trap 'echo Bash got SIGINT signal' 2
(bash_shell) %> kill -SIGINT 8529
#Output:
^CBash got SIGINT signal
bashシェルでkill -SIGINT 8529
次を押すこともできます。Ctrl+C
メモ:一部の信号では機能しない可能性がありますtrap
(SIGKILLを使用してテストしましたが機能しません)。
殺して使う
man kill
またはを使用すると、man 1p kill
コマンドの詳細な説明を取得できます。
Kill -s シグナル名 pid
Kill -l [終了ステータス]
kill[-signal_name] pid
Kill [-signal_number] pid ...
-s signal_name
<signal.h>ヘッダーで定義されているシンボル名の1つを使用して送信する信号を指定します。 signal_name値は、SIGプレフィックスなしで大文字と小文字を区別せずに識別する必要があります。また、信号値がゼロであることを示すシンボル名0を認識する必要があります。 SIGTERMの代わりにその信号を送信する必要があります。
-signal_name
は -s signal_name と同じです。-signal_numberは、
kill()への有効な呼び出しでSIGTERMの代わりに使用される信号を表す負でない10進数signal_numberを指定します。使用した整数値とシグネチャ値との対応関係を下表に示します。次以外の signal_number を指定する効果は未定義です。
0 0
1 SIGHUP
2 SIGINT
3 SIGQUIT
6 SIGABRT
9 SIGKILL
14 SIGALRM
15 SIGTERM
したがって、コマンドはkill -9 8990
と同じですkill -SIGKILL 8990
。SIGKILL
プロセスに転送されると、プロセスは終了/終了します。