web-dev-qa-db-ja.com

Linux上のプロセスのkill -9が効果を持たない可能性はありますか?

Webサイトにアクセスすると、テキスト文字列を自動的に強調表示するプラグインを作成しています。これは検索結果のハイライトに似ていますが、自動で多くの単語が含まれます。アレルギーのある人が、食べ物のサイトを閲覧するときなど、言葉を際立たせるために使用できます。

しかし、私には問題があります。空の新しいFFウィンドウを閉じようとすると、プロセス全体が何らかの形でブロックされます。プロセスを強制終了すると、すべてのウィンドウが消えますが、Firefoxプロセスは存続します(親PIDは1で、シグナルをリッスンせず、多くのリソースを開いており、CPUを消費しますが、動きません)。

2つの質問:

  1. プロセスがkill -9(ユーザーとしてもrootとしても)をリッスンしないようにすることもできますか?

  2. 再起動以外にできることはありますか?

[編集]これは問題のあるプロセスです:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
digulla  16688  4.3  4.2 784476 345464 pts/14  D    Mar28  75:02 /opt/firefox-3.0/firefox-bin

と同じ ps -ef | grep firefox

UID        PID  PPID  C STIME TTY          TIME CMD
digulla  16688     1  4 Mar28 pts/14   01:15:02 /opt/firefox-3.0/firefox-bin

残っている唯一のプロセスです。ご覧のとおり、ゾンビではなく、実行中です! PIDで殺しても、名前で殺しても、-9を殺すことを聞きません! straceで接続しようとすると、straceもハングし、強制終了できません。出力もありません。私の推測では、FFはいくつかのカーネルルーチンでハングしますが、どれですか?

[編集2] sigjuiceによるフィードバックに基づく:

ps axopid,comm,wchan

プロセスがハングするカーネルルーチンを表示できます。私の場合、問題のプラグインはBeagle Indexer(openSUSE 11.1)でした。プラグインを無効にした後、FFは再びすばやく幸せなキツネになりました。

64
Aaron Digulla

OPのコメントに記載されているように、プロセスステータス(STAT)のDは、プロセスが「割り込み不可能なスリープ」状態であることを示します。実際には、これは通常、I/Oを待機しており、そのI/O操作が完了するまで、死ぬことも含めて何もできない/できないことを意味します。

D状態のプロセスは通常、操作が完了する前にほんの一瞬だけ存在し、R/Sに戻ります。私の経験では、プロセスがDで動かなくなった場合、ほとんどの場合、到達不能なNFSまたは他のリモートファイルシステムと通信しようとしている、障害のあるハードドライブにアクセスしようとしている、または何らかの方法でハードウェアを使用している不安定なデバイスドライバーの。このような場合、回復してプロセスを停止させる唯一の方法は、fs/drive/hardwareをバックアップして実行し、I/Oが完了するか、システムを放棄して再起動することです。 NFSの特定の場合、マウントは最終的にタイムアウトし、I/O操作から(失敗コードで)戻ることもありますが、これはマウントオプションに依存し、NFSマウントが永久に待機するように設定されることは非常に一般的です。

これは、Zのステータスを持つゾンビプロセスとは異なります。

125
Dave Sherohman

Parent-idが本当に1であることを再確認してください。そうでない場合、これがfirefoxである場合、最初にSudo killall -9 firefox-binを試してください。その後、Sudo killall -9 [process-id]を使用して特定のプロセスIDを個別に強制終了します。

プロセスがkill -9(ユーザーまたはルートとして不要)をリッスンしないことはどうして可能ですか?

プロセスが<defunct>を行ってから、親が1で zombie になった場合、できません手動で強制終了します。 initのみが可能です。ゾンビプロセスはすでに死んでいてなくなっています-もはやプロセスではなく、プロセステーブルエントリとそれに関連する終了コードのみであるため、殺される能力を失い、収集を待っています。親を殺す必要があり、明らかな理由でinitを殺すことはできません。

しかし、より一般的な情報については here を参照してください。再起動すると、当然すべてが終了します。

8
John Feminella

私は最近 Double Fork の落とし穴に陥り、最終的に私の答えを見つける前にこのページに到達しました。問題が同じでなくても、症状は同じです。

  • WYKINWYT:あなたが殺したものはあなたが思ったものではない

SNMPデーモンの例に基づいて、最小限のテストコードを以下に示します

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

int main(int argc, char* argv[])
{
    //We omit the -f option (do not Fork) to reproduce the problem
    char * options[]={"/usr/local/sbin/snmpd",/*"-f","*/-d","--master=agentx", "-Dagentx","--agentXSocket=tcp:localhost:1706",  "udp:10161", (char*) NULL};

    pid_t pid = fork();
    if ( 0 > pid ) return -1;

    switch(pid)
    {
        case 0: 
        {   //Child launches SNMP daemon
            execv(options[0],options);
            exit(-2);
            break;
        }
        default: 
        {
            sleep(10); //Simulate "long" activity

            kill(pid,SIGTERM);//kill what should be child, 
                              //i.e the SNMP daemon I assume
            printf("Signal sent to %d\n",pid);

            sleep(10); //Simulate "long" operation before closing
            waitpid(pid);
            printf("SNMP should be now down\n");

            getchar();//Blocking (for observation only)
            break;
        }
    }
    printf("Bye!\n");
}

最初のフェーズでは、メインプロセス(7699)がSNMPデーモン(7700)を起動しますが、このデーモンは現在Defunct/Zombieであることがわかります。横に、指定したオプションを持つ別のプロセス(7702)が表示されます

[nils@localhost ~]$ ps -ef | tail
root       7439      2  0 23:00 ?        00:00:00 [kworker/1:0]
root       7494      2  0 23:03 ?        00:00:00 [kworker/0:1]
root       7544      2  0 23:08 ?        00:00:00 [kworker/0:2]
root       7605      2  0 23:10 ?        00:00:00 [kworker/1:2]
root       7698    729  0 23:11 ?        00:00:00 sleep 60
nils       7699   2832  0 23:11 pts/0    00:00:00 ./main
nils       7700   7699  0 23:11 pts/0    00:00:00 [snmpd] <defunct>
nils       7702      1  0 23:11 ?        00:00:00 /usr/local/sbin/snmpd -Lo -d --master=agentx -Dagentx --agentXSocket=tcp:localhost:1706 udp:10161
nils       7727   3706  0 23:11 pts/1    00:00:00 ps -ef
nils       7728   3706  0 23:11 pts/1    00:00:00 tail

10秒間シミュレートした後、わかっている唯一のプロセス(7700)を強制終了します。最後にwaitpid()で成功したもの。しかし、プロセス7702はまだここにあります

[nils@localhost ~]$ ps -ef | tail
root       7431      2  0 23:00 ?        00:00:00 [kworker/u256:1]
root       7439      2  0 23:00 ?        00:00:00 [kworker/1:0]
root       7494      2  0 23:03 ?        00:00:00 [kworker/0:1]
root       7544      2  0 23:08 ?        00:00:00 [kworker/0:2]
root       7605      2  0 23:10 ?        00:00:00 [kworker/1:2]
root       7698    729  0 23:11 ?        00:00:00 sleep 60
nils       7699   2832  0 23:11 pts/0    00:00:00 ./main
nils       7702      1  0 23:11 ?        00:00:00 /usr/local/sbin/snmpd -Lo -d --master=agentx -Dagentx --agentXSocket=tcp:localhost:1706 udp:10161
nils       7751   3706  0 23:12 pts/1    00:00:00 ps -ef
nils       7752   3706  0 23:12 pts/1    00:00:00 tail

Getchar()関数に文字を与えた後、メインプロセスは終了しますが、pid 7002のSNMPデーモンはまだここにあります

[nils@localhost ~]$ ps -ef | tail
postfix    7399   1511  0 22:58 ?        00:00:00 pickup -l -t unix -u
root       7431      2  0 23:00 ?        00:00:00 [kworker/u256:1]
root       7439      2  0 23:00 ?        00:00:00 [kworker/1:0]
root       7494      2  0 23:03 ?        00:00:00 [kworker/0:1]
root       7544      2  0 23:08 ?        00:00:00 [kworker/0:2]
root       7605      2  0 23:10 ?        00:00:00 [kworker/1:2]
root       7698    729  0 23:11 ?        00:00:00 sleep 60
nils       7702      1  0 23:11 ?        00:00:00 /usr/local/sbin/snmpd -Lo -d --master=agentx -Dagentx --agentXSocket=tcp:localhost:1706 udp:10161
nils       7765   3706  0 23:12 pts/1    00:00:00 ps -ef
nils       7766   3706  0 23:12 pts/1    00:00:00 tail

結論

double forkメカニズムを無視したという事実により、killアクションは成功しなかったと考えられました。しかし実際には、間違ったプロセスを単に殺しました!!

-fオプション(Do Not(Double)Fork)を追加することで、すべてが期待どおりになります

1
NGI

このプロセスは、強制終了したときに(たとえばinitによって)再起動される可能性がありますか?

これは簡単に確認できます。 kill -9 PIDの後にPIDが同じ場合、プロセスは強制終了されていませんが、変更されている場合、プロセスは再起動されています。

1
Georg Schölly
Sudo killall -9 firefox

動作するはずです

編集:[PID]をfirefoxに変更

0
karim79

ps -ef | grep firefox;そして、あなたは3つのプロセスを見ることができ、それらをすべて殺します。

0
ManofPhysics

また、pstreeを実行して親を殺すこともできます。これにより、リーフだけでなく、問題のあるプロセスツリー全体を確実に取得できます。

0
Eric Holmberg