ターミナルを閉じずにターミナルで実行中のスクリプトを強制終了するには(Ctrl + Cは機能しません)?


35

他のいくつかのプログラムを呼び出し、一連のコマンドを実行するbashスクリプトを作成しました。このスクリプトを端末から実行します。次に、スクリプトを強制終了します。

押してCtrl + Cもうまくいかないことがあります。スクリプトが別のプログラムを実行していることがあり、何らかの理由でkillシグナルが機能しないためです。

ただし、ターミナルウィンドウを閉じると、スクリプトが強制終了されます。

できることはありますか(キーボードの組み合わせ)、それは実際に端末ウィンドウを閉じずに端末ウィンドウを閉じることに似ています(コマンド履歴、現在のディレクトリ、出力履歴などを失いたくない)?


8
そのような場合、私は試してくださいCtrl + z
ケン14

そして、後にCtrl + z実行:kill -9 $(pgrep -f your_script.sh)
ノーム・マノス

回答:


38

選択肢はほとんどありません。1つは、スクリプトを停止し(CtrlZ)、スクリプトのPIDを取得SIGKILLしてプロセスグループに送信することです。

コマンドがシェルで実行されると、コマンドが開始するプロセスとそのすべての子は同じプロセスグループ(この場合はフォアグラウンドプロセスグループ)の一部になります。このグループのすべてのプロセスに信号を送信するには、プロセスリーダーに送信します。以下の場合はkill、コマンド、プロセス・リーダーは、このように表記されています。

kill -PID

PIDスクリプトのプロセスIDはどこにあります。

例:

test.shいくつかのプロセスを起動するスクリプトを考えてください。シェルで実行したとしましょう:

$ ./test.sh

別のターミナルで、

$ pgrep test.sh
17802
$ pstree -ps `!!`
pstree -ps `pgrep test.sh`
init(1)───sshd(1211)───sshd(17312)───sshd(17372)───zsh(17788)───test.sh(17802)─┬─dd(17804)
                                                                               ├─sleep(17805)
                                                                               └─yes(17803)

この場合、で作成されたプロセスグループにシグナルを送信するにはtest.sh、次のようにします。

kill -INT -17802

-INTは送信SIGINTに使用されるため、このコマンドはCtrlC端末を押すのと同じです。送信するにはSIGKILL

kill -KILL -17802

別の端末を開けない場合にのみ、スクリプトを停止する必要があります。可能であれば、を使用pgrepしてPIDを見つけます。

スクリプトが起動するコマンドの1つはtrapping SIGINTである可能性があり、これがおそらくCtrlC無効な理由です。ただし、SIGKILLわなにかけることはできず、通常は最後の手段です。殺す前にSIGTERM-TERM)を試してみてください。どちらSIGKILLSIGTERMのように設定することができ、キーボードショートカットの方法がSIGINTあります。

スクリプトにシェバン行が含まれていない場合、これはすべて意味がありません。このSOの答えから:

通常、親シェルは、スクリプトが同じシェル用に作成されていると推測します(最小限のBourneのようなシェルは/ bin / shでスクリプトを実行し、bashはbashサブプロセスとして実行します)...

このため、スクリプトの実行時に、スクリプトにちなんで名付けられたプロセス(またはコマンドラインにスクリプト名を持つプロセス)が見つからず、pgrep失敗します。

常にシバンラインを使用してください。


SIGKILLまたはのキーボードの組み合わせはありSIGTERMますか?
becko 14

ノー@becko、あなたは1を設定することはできません。superuser.com/a/417991/334516
muru

pgrep test.sh私のためにPIDを返しません。私は、単純なtest.shを試してみました: for i in {1..30}; do sleep 1 echo $i done 一方でtest.sh実行されて、私は実行しpgrep test.sh、別の端末では、何も返されません。どうしましたか?
ベッコ14

1
@beckoスクリプトをどのように実行しましたか?また試してみてくださいpgrep -f test.sh
ムル14

pgrep -f test.sh動作しません。私は、スクリプトを実行します./test.sh
becko

6

スクリプトに関連付けられているプロセスがわかっている場合は、次を使用してPIDを見つけることができます

 ps -A

次に、PID番号を使用して、対応するプロセスを強制終了します。

 kill -9 PID_Number

1
それは複雑すぎます。スクリプトは他のいくつかのプログラムを生成し、これらのプログラムは並列プロセスも生成します。これらすべてのプロセスを追跡することは非常に困難です。ターミナルウィンドウを閉じたときに起こることと類似した、より単純な解決策が必要です。
ベッコ14

pkill -P $$を試すことができます
ハリス14

1

ハリスが言ったように、実行することはできますKill -9 PID_Numberが、htop特定のプロセスを簡単に見つけることができるインタラクティブなプロセスブラウザーを備えたパッケージをインストールすることもできます。htopはプロセスの強制終了もサポートしています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.