この質問の完全なタイトルは次のとおりです。
Bash: bash スクリプトに別のプロセスを呼び出すループが含まれているため、control-c でプロセスを終了できない場合の対処方法: 電源のオン/オフ ボタンにもっと良い解決策はありますか?
この質問のタイトルはかなり自明ですが、より詳細な情報は次のとおりです。
別のプログラムを呼び出す bash スクリプトを実行しています。(別のプログラムを実行します。)
このプログラムはデータ/曲線フィッティングプログラムであり、中断することはできませんCTRL-C
。しかし、これを読むと、役職、私はそれを殺すことができることを発見しましたCTRL-\
仮説的な考え...
つまり、Ctrlキーを押しながら\
キーを連打するだけで、しかし昨日、とても高価なメカニカルキーボードを購入し、別の安いキーボードを購入するお金が足りず、(新しいメカニカルキーボードが磨り減る前に、10^6回のキー入力を使い切りたくないので)「マッシュ」しても構わないと思っている場合、または、家が以下の理由で古いキーボードを探す時間がない場合はどうなるでしょうか。非常に混乱したり、同時に火事などの緊急事態が発生したりするため...
また、ループがこのフィッティング プログラムを呼び出しており、おそらく 1000 個のデータ ファイルをフィッティングしている場合、\
キーを 1000 回押すと長い時間がかかる可能性があります。
ハイパースペースの思考...
あるいは、bash スクリプトで間違いを犯し、実際に無限ループを実行している場合はどうなるでしょうか?
このような状況で親スクリプトの実行を停止するにはどうすればよいでしょうか。コンピュータのプラグを抜き、電源ボタンを 10 秒間押し続けて電源をオフにするか、火の中に投げ込んで動作を停止することもできますが、これらの解決策は、データ損失が発生する可能性があるため、無意味に思えます。
理論上は、システム モニターを実行して bash プロセスを終了することもできますが、同じ名前のプロセスが多数ある場合は、見つけるのが難しい場合があります... さらに、シングル コア コンピューター、または N 個のコアなどを持つマルチコア コンピューターで、N 個のプロセスが実行されていて、すべてが 100 % CPU を使用しようとしている可能性があります。 または、1 つのプロセスが 4 GB を超える RAM を使用していて、そのためにコンピューターが非常に遅くなっている可能性があります... 少なくとも現時点では、システム モニターを実行するには遅すぎます。 この後の次善のオプションは、CTRL-ALT-F1 を押して root としてログインし、問題のある bash 親を見つけることですps -A
...kill PID
ただし、コンピューターの負荷が高く、スワップに継続的に書き込んでいる場合は、これに何分もかかることがあります。
SIG TERM exec cpu_broken.sh; reconvene; clear screen; clear thought_processes; continue...
もっと良い解決策はありますか?
答え1
つまり、基本的には、すべてにアクセスできないようにするスクリプトを実行し、それを停止するための迅速かつ簡単なソリューションが必要です。電源を入れ直す代わりに、SYSRQキー (多くの場合、キーと同じです) を押したまま、、、、、、をPRTSC1 つずつ押すこともできます。基本的に、これは実行中のすべてのプロセスを終了し、システムを再起動する安全な方法です。REISUB
代わりにsudo nano /proc/sysrq-trigger
、そのファイルにbと書いて保存します。システムはすぐに再起動します。
答え2
プロセス グループ全体を強制終了する必要があります。プロセス グループ ID (PGID) は、グループを開始したプロセスの PID です。プロセス グループを強制終了するには、プロセス グループを開始したプロセスの PID、つまり、すべてを開始したスクリプトまたはコマンドを見つける必要があります。構文は次のとおりです。
kill -- -PGID
例えば:
kill -- -1234
ここで 1234 は PGID (プロセス グループ ID) です。
これにより、プロセス グループ内のすべてのプロセスに SIGTERM が送信されます。別のシグナル (例: SIGKILL (9)) を送信するには、次のようにします。
kill -9 -1234
PGID を見つける方法:
できるよ:
ps -eo 'pid,ppid,pgid,cmd'
これにより、PID、PPID (親プロセス ID)、PGID、およびプロセス名が表示されます。
grep
これで、またはその他の適切な方法を使用して PGID を見つけ、上記の方法でそれを強制終了することができます。
PPID を表示するコマンドを作成した理由は、次のようにして PPID の一致に基づいてプロセスを強制終了することもできるためですpkill
。
pkill -P PPID
例えば:
pkill -P 6789
この方法を使用する場合、すべての親プロセス (および子プロセス) を見つけてそれらを強制終了する必要があります。そのため、すべてのプロセスを停止したい場合は、プロセス ツリー全体を強制終了する方がよいと思います。
答え3
通常、top
、htop
または同様のものを使用してプロセスを見つけて強制終了できます (または、プロセスの名前または PID がわかっている場合はkillall
、pkill
などを使用できます)。たとえば、 を使用するとtop
、ターミナルから実行中のスクリプトを選択し、k+を押して強制終了できますEnter。
それが機能しない場合は、k+ 9+ EnterSIGKILL シグナルを使用する必要があります。SIGKILL は、プロセスを直ちに終了するように要求し、SIGTERM のようにプロセスがリソースのクリーンアップなどを完了するまで待機しません。Ctrl+Cプロセスは、SIGTERM のように、プロセスを中断するために SIGINT のみを送信します。
htop のツリー ビュー ( を押すt) を使用すると、スクリプトの親プロセスを特定し、それらを強制終了してループが継続しないようにすることもできます。
参照:
- Unix シグナル: POSIX シグナル - Wikipedia
- UNIX マニュアルページ: シグナル (7)(インストールされたバージョンを取得するには、実行してください
man 7 signal
)