kill -9 <pid>
で強制終了できないプロセスがあります。特に私がそのプロセスの所有者であるため、そのような場合の問題は何ですか。そのkill
オプションを回避できるものはないと思いました。
kill -9
( [〜#〜] sigkill [〜#〜] )は、プロセスを強制終了する権限がある場合は常に機能します。基本的に、プロセスはsetuidやsetgidではなく、ユーザーが開始するか、rootである必要があります。例外が1つあります。rootでもPID 1(init
プロセス)に致命的な信号を送信できません。
しかしながら kill -9
の動作は保証されていません即時。 SIGKILLを含むすべてのシグナルは非同期で配信されます。カーネルは、シグナルの配信に時間がかかる場合があります。通常、信号の配信には最大で数マイクロ秒かかり、ターゲットがタイムスライスを取得するのにかかる時間だけです。ただし、ターゲットに シグナルをブロック がある場合、シグナルはターゲットがブロックを解除するまでキューに入れられます。
通常、プロセスはSIGKILLをブロックできません。しかし、カーネルコードは可能であり、プロセスは システムコール を呼び出すときにカーネルコードを実行します。カーネルコードは、システムコールに割り込むと、カーネルのどこかに、またはより一般的には一部のカーネルの不変条件に違反する、不適切な形式のデータ構造が生じる場合に、すべての信号をブロックします。したがって、(バグや設計ミスにより)システムコールが無期限にブロックされた場合、事実上プロセスを強制終了する方法がない可能性があります。 (ただし、プロセスは、システムコールが完了すると強制終了されます。)
システムコールでブロックされたプロセスは 無停電スリープ です。 ps
またはtop
コマンドは、(ほとんどのユニスでは)状態D
で表示します(元は「disk」と思います)。
長い中断のないスリープの典型的なケースは、サーバーが応答していないときに [〜#〜] nfs [〜#〜] を介してファイルにアクセスするプロセスです。最新の実装では、中断のないスリープを強制する傾向はありません(たとえば、Linuxでは、intr
マウントオプションにより、NFSファイルアクセスを中断する信号を許可します)。
Z
またはH
出力にps
(またはLinuxではtop
とマークされたエントリ、区別がわからない)が表示される場合があります。これらは技術的にはプロセスではなく、ゾンビプロセスであり、プロセステーブルのエントリにすぎず、親プロセスに子の死を通知できるように保持されます。親プロセス 注意を払う (または死ぬ)になると、それらはなくなります。
いつかプロセスが存在し、次の理由で強制終了できません:
top
では、信号Ztop
では、Dによって通知されます。ゾンビプロセス があるようです。これは無害です。ゾンビプロセスが消費する唯一のリソースは、プロセステーブルのエントリです。親プロセスが死んだり、子供の死に反応したりすると、この問題は解消されます。
top
または次のコマンドを使用して、プロセスがゾンビであるかどうかを確認できます。
ps aux | awk '$8=="Z" {print $2}'
手がかりがないか、/var/log/kern.log
および/var/log/dmesg
(または同等のもの)を確認してください。私の経験では、NFSマウントのネットワーク接続が突然切断された場合、またはデバイスドライバーがクラッシュした場合にのみ、これが発生しました。ハードドライブもクラッシュした場合に発生する可能性があると私は信じています。
lsof
を使用すると、プロセスが開いているデバイスファイルを確認できます。
Killは実際にはシグナルを送信することを意味します。送信できる信号は複数あります。 kill -9は特別なシグナルです。
シグナルを送信するとき、アプリケーションはそれを扱います。そうでなければ、カーネルがそれを扱います。アプリケーションでシグナルをトラップできます。
しかし、私はキル-9は特別だと言った。アプリケーションがそれを取得しないという点で特別です。カーネルに直接移動し、可能な限り最初の機会にアプリケーションを本当に強制終了します。言い換えれば、それを殺します
kill -15は、SIGNAL TERMINATEを表すシグナルSIGTERMを送信します。つまり、アプリケーションに終了するように指示します。これは、シャットダウンするときがきたことをアプリケーションに知らせるためのわかりやすい方法です。ただし、アプリケーションが応答していない場合は、kill -9を実行すると、アプリケーションが強制終了されます。
kill -9が機能しない場合は、カーネルが正常に動作していない可能性があります。再起動が必要です。今までに起こったことを思い出すことはできません。
まず、そのゾンビプロセス(非常に可能性が高い)かどうかを確認します。
ps -Al
次のようなものが表示されます。
0 Z 1000 24589 1 0 80 0 - 0 exit ? 00:00:00 soffice.bin <defunct>
(左側の「Z」に注意してください)
5番目の列が1でない場合は、親プロセスがあることを意味します。 その親プロセスIDを強制終了してみてください。
そのPPID = 1、それを殺さないでください!!の場合、他のどのデバイスまたはプロセスがそれに関連している可能性があるかを考えてください。
たとえば、マウントされたデバイスまたはSambaを使用していた場合は、マウント解除してみてください。それはゾンビプロセスを解放するかもしれません。
[〜#〜]ノート[〜#〜]:ps -Al
(またはtop
)は、「Z」ではなく「D」を示します。これは、リモートマウント(NFSなど)に関連している可能性があります。私の経験では、再起動がそこに行く唯一の方法ですが、そのケースをより詳しくカバーする他の回答をチェックすることができます。
InitプロセスはSIGKILLの影響を受けません。
これは、カーネルスレッド、つまりPPIDが0の「プロセス」にも当てはまります。
他の人が述べたように、無停電睡眠中のプロセスはすぐに(または場合によってはまったく)殺すことはできません。特定のシナリオ、特にプロセスがNFSで待機している一般的なケースでこの問題を解決するために、別のプロセス状態TASK_KILLABLEが追加されたことは注目に値します。参照 http://lwn.net/Articles/288056/
残念ながら、これはカーネルのどこかで使用されているとは思いませんが、NFSです。
私がたくさん見るのに役立つ小さなスクリプトを作りました!
これを使用して、パスに指定された名前のプロセスを強制終了できます(これに注意してください!!)または、「-u username」パラメーターを使用して、特定のユーザーのプロセスを強制終了できます。
#!/bin/bash
if [ "$1" == "-u" ] ; then\n
PID=`grep "$2" /etc/passwd | cut -d ":" -f3`
processes=`ps aux | grep "$PID" | egrep -v "PID|ps \-au|killbyname|grep" | awk '{ print $2}'`
echo "############# Killing all processes of user: $2 ############################"
else
echo "############# Killing processes by name: $1 ############################"
processes=`ps aux | grep "$1" | egrep -v "killbyname|grep" | awk '{ print $2}' `
fi
for process in $processes ; do
# "command" stores the entire commandline of the process that will be killed
#it may be useful to show it but in some cases it is counter-productive
#command=`ps aux | grep $process | egrep -v "grep" | awk '{ print $2 }'`
echo "Killing process: $process"
echo ""
kill -9 $process
done
プロセスにkill -9を送信した場合でも、そのpidは停止しますが、プロセスは自動的に再起動します(たとえば、gnome-panel
、それは再起動します):ここではそうでしょうか?
から ここでは元々 :
straceが何かを表示するかどうかを確認します
strace -p <PID>
gdbでプロセスにアタッチしてみてください
gdb <path to binary> <PID>
プロセスが、アンマウント、カーネルモジュールの削除、または物理的な切断/取り外しが可能なデバイスと対話していた場合は、それを試してください。
このような問題がありました。これは私がstrace
で起動し、Ctrl
+ C
で中断したプログラムでした。最終的にT
(トレースまたは停止)状態になりました。どのようにして起こったのか正確にはわかりませんが、SIGKILL
で強制終了することはできませんでした。
要するに、私はgdb
でそれを殺すことに成功しました:
gdb -p <PID>
> kill
Kill the program being debugged? (y or n) y
> quit
ジルの答えからの手がかりに基づいて、システムリソースを使用している「Z」(psで「」)とマークされたプロセスがありました。それは、待機しているポートが開いていて、それに接続できました。これはkill -9
上に。その親は "1"(つまりinit
)だったので、理論的には消えるだけです。しかし、そうではありませんでした。実行されていませんでした。
だから私の場合、それはゾンビでしたが、それでもリソースを消費しています... FWIW。
そして、それはkill -9
。
そして、その親はinit
でしたが、刈り取られていませんでした(片付け)。つまりinit
にはゾンビの子供がいました。
また、問題を解決するために再起動する必要はありませんでした。問題を回避するには、再起動で「うまくいくはず」でしたが、シャットダウンが高速になりました。ただ優雅ではありませんが、それはまだ可能でした。
そして、それはゾンビプロセスが所有するLISTENポートでした(そして、ローカルホストにローカルホストに接続されたCLOSE_WAITステータスのような他のいくつかのポート)。そしてそれはまだ接続を受け入れました。ゾンビとしても。まだポートをクリーンアップするまでには至っていなかったので、受け入れられる可能性はありませんでしたが、着信接続はまだtcpリスニングポートのバックログに追加されていました。
内部に "システムコール"(この場合はioctl)を実行していて、戻るのに数時間かかっていた(これは予想された)内部スレッドがあったことがわかりました。どうやら、システムはそれから戻るまで「ずっと」それを殺すことができない。数時間後、それはクリアされ、ソケットはすべて自動的に閉じられました。悲惨な死の時間だ!
また、dmesgをチェックして、カーネルパニック(つまり、カーネルバグ)があったかどうかを確認します。