web-dev-qa-db-ja.com

キンダー/ジェントラー/サブトラーに相当するkillallの代替(例:「endall」)?

killallよりも穏やかな方法で、同じ名前のすべてのプロセスを終了するにはどうすればよいですか?プロセスを中断したくありませんが、適切に終了する時間を残してください。


こちらもご覧ください:

buntuでプロセスを強制終了するにはどうすればよいですか

システムモニターでは、Kill ProcessとEnd Processの違いは何ですか?

なぜkillall(時々?)を2回適用する必要があるのですか?

tl; dr

16

1. `killall`はすでにニース(SIGTERM)

killallはデフォルトでSIGTERMを送信します。これは、alreadyであり、アプリケーションが自分でクリーンアップする機会を残すニースのアプローチです。 「今すぐ死ぬ!」アプローチはSIGKILLシグナルを送信することで、killallのオプションとして指定する必要があります。から GNU Cライブラリ:終了シグナル

マクロ:intSIGTERM

[...]通常の方法で、pollylyプログラムに終了を要求します。


2.システムモニターの「プロセスの終了」も同様に素晴らしい(SIGTERMも)

GNOMEシステムモニターに関する質問にリンクします。それは、その「プロセスの終了」アクションにもSIGTERMを使用します(そして、私はその質問に対する答えに矛盾していることに気付きます)。あなた自身を確認するためにソースコードでそれを見つけることができます:

data/menus.ui

<item>
  <attribute name="label" translatable="yes">_End</attribute>
  <attribute name="action">win.send-signal-end</attribute>
  <attribute name="accel">&lt;Primary&gt;e</attribute>
  <attribute name="target" type="i">15</attribute>
</item>

ここの15はシグナル番号です。信号15はSIGTERMです。また、システムモニターは、他の質問が尋ねられて回答されるかなり前にSIGTERMを使用しています。


技術的補遺(コメントへの回答)

git blameのGithub表現を調べて、GNOMEシステムモニターのソースコードで信号がどのように記述されるかについて行われた変更を以下に示します。

83007f2 2013年7月24日GActionパラメータを使用して信号を送信するための重複コードを置換
e766b2d 2013年7月18日GActionへのポート処理ポップアップメニュー
97674c79 2012年10月3日ProcData構造体を取り除きます
8c5296c 2011年7月3日ソースファイル全体でインデントを統一します。

これらはいずれもSIGQUITからSIGTERMに変更されておらず、最後の質問はリンクされた質問が行われる前のものでした。

42
hvd

@hvdによる答えは基本的に正しいです。それをさらにバックアップするために、initプロセスは、コンピューターをシャットダウンするときに最初にSIGTERMをプロセスに送信し、その後、まだ終了していない場合は遅延後にSIGKILLを送信します。プロセスはSIGKILLを処理/無視できません。

しかし、もう少し詳しく説明すると、本当の答えは、プログラムがそれを処理していることを確実に知る方法がないということです。 SIGTERMは、プログラムの終了を丁寧に要求するために使用する最も一般的なシグナルですが、すべてのシグナル処理は、プログラムがシグナルで何かを行うことに依存します。

別の言い方をすれば、他の回答に基づいて、@ Josまたは@AlexGregで作成されたプログラムがある場合、おそらくSIGQUITを処理しますが、SIGTERMを処理しないため、SIGTERMを送信することはSIGQUITよりも「ソフト」ではありません。

あなたが自分でそれをいじることができるように、私はいくつかのコードを書きました。以下をsignal-test.cとして保存してから、

gcc -o signal-test signal-test.c

その後、./signal-testを実行して、killall -s <signal>で異なる信号を送信するとどうなるかを確認できます。

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

int flag = 0;

void handle_signal(int s)
{
    flag = s;
}

int main(int argc, char *argv[])
{
    signal(SIGTERM, handle_signal);
    signal(SIGQUIT, handle_signal);

    while(flag == 0){
        sleep(1);
    }
    printf("flag is %d\n", flag);
    return flag;
}

現状では、コードはSIGTERMとSIGQUITの両方を適切に処理します。行signal(SIG...をコメントアウトして(行の先頭で//を使用して)シグナルハンドラーを削除してから、実行して再度シグナルを送信できます。これらの異なる出力を見ることができるはずです:

$ ./signal-test
Terminated

$ ./signal-test
Quit (core dumped)

$ ./signal-test
flag is 15

$ ./signal-test
flag is 3

信号を処理するかどうかによって異なります。

シグナルを無視してみることもできます:

signal(SIGTERM, SIG_IGN);

それを行ってからSIGTERMを送信しても何も行われない場合は、SIGKILLを使用してプロセスを終了する必要があります。

詳細はman 7 signalにあります。この方法でsignal()を使用することは、移植性がないと見なされることに注意してください-代替手段よりもずっと簡単です!

もう1つの小さな脚注-Solarisではkillallはすべてのプロセスを強制終了しようとします。それらのすべて。 rootで実行すると驚くかもしれません:)

5
Roger Light

「すべて終了」はkillall -s SIGQUIT [process name]になります。おしゃれなソリューションが必要な場合は、alias endall='killall -s SIGQUIT'を定義してください。

2
Jos