マルチスレッドの Bash コードを開発したり、サーバー プロセスを管理したり、プロセス ウォッチドッグを作成したりする場合、主な課題の 1 つは通常、既存の Bash プロセスを正しく、効率的かつ正確に終了することです。この記事ではその方法を説明します。
Bash プロセス とは何ですか?
Bash プロセスは、単に実行中の実行可能ファイルです。たとえば、デスクトップ環境で電卓を起動すると、Bash プロセスが作成されます。このような bash には、2 つの主要なプロセス識別子、つまり PID と PPID 、 プロセス識別子 、および 親プロセス識別子が あります。
要約すると、 PID は 特定の実行中のアプリケーション (つまり、プロセス) の数値ベースの一意の ID を保持しますが、特定の実行中のアプリケーション (つまり、プロセス) の PPID には、この新しいアプリケーションを開始したプロセスの 親 PID が 格納されるため、「」という用語が使用されます。親’。
また、これによりツリー状の構造が形成され、 PPID が 0 のルート/最初のプロセスまでのすべてのプロセスが相互リンクされる様子がすぐにわかります。
PID と PPID の追加の洞察と実践的な例を提供する関連記事については 、「Bash での変数のエクスポート: その理由と方法」 の記事を参照してください。
Bash のプロセス管理は、一見すると簡単そうに見えます (ターミナルのコマンド ラインで
ps -ef
実行するだけで、システム上で実行中のすべてのプロセスが
PID
および
PPID
識別子の接頭辞とともに表示されます)。
プロセスを終了することさえ簡単そうに見えますが、より複雑なプロセス管理システムを扱う場合には、すぐに注意点や落とし穴が発生し始めます。
Bash プロセスの終了
コマンドラインで
gnome-calculator
起動し、その後プロセスを終了することから簡単に始めましょう。
ノーム電卓と
ps -ef | grep gnome-calculator
キル -9 $RELEVANT_PID
gnome-calculator
バックグラウンド モードで (コマンドの最後に
&
使用して) 起動したので、別の端末セッションを開始しなくても、端末のプロンプトがすぐに表示されるようになります。
次に、
ps -ef
パイプ (
|
) および
grep
コマンドと組み合わせて使用し、計算機のプロセス ID (
PID
) を特定しました。次に、signal 9
kill
コマンドで終了させました。このコードを試す場合は、コード内の
$RELEVANT_PID
を
ps
によって報告された PID に置き換えます。
バックグラウンドプロセスは、
kill -9
命令によって即座に終了されることに注意してください。ただし、Bash コマンド プロンプトはすぐに戻るため、プロセス スケジューラがバックグラウンド プロセスの終了を報告する前に戻ってきます。
そして、その通知が既存の作業とインラインである場合、つまり、プッシュ ベースよりもプル ベースである場合にのみ、通知が行われます。 Enter キーを押すと、システムは最初のバックグラウンド プロセスが終了したかどうかを確認し、終了または強制終了されたことを通知します。
[1]+ Killed gnome-calculator
。
kill command
に戻ると、シグナル 9
kill
、最も破壊的なキルの 1 つです。基本的には好意を示さずにその場でプログラムを終了します。ターミナル コマンド プロンプトで実行される
man signal.7
コマンドからアクセスできる「標準信号の信号番号付け」セクションを参照して、利用可能なすべての信号とそれらに一致する番号のリストを確認できます。
この記事では、プロセスを常に即時かつ効果的に終了するために シグナル 9 を使用します。ただし、 シグナル 9 キル/プロセス終了を使用している場合でも、プロセスが 無効な 状態で残ることがあります。
一般的な DevOps 作業ではこのような問題が頻繁に発生することはありません。発生した場合は、通常、最初のプログラムのコード (実行されているプロセス)、またはシステム ハードウェアまたはオペレーティング システムのいずれかに重大な問題があったことを意味します。
エラーの回避と所有プロセスのみの選択
上記のプロセスをもう一度やり直しますが、手動で入力する必要がなく、スクリプト内から PID を使用できるように、 PID の選択を自動化する方法はありますか?確かにあります。
ノーム電卓と
ps -ef | grep ‘gnome-calculator’ | grep -v ‘grep’ | awk ‘{print $2}’
ps -ef | grep ‘gnome-calculator’ | grep -v ‘grep’ | awk ‘{print $2}’ | xargs キル -9
ここでは、
gnome-calculator
バックグラウンド モードで再度起動し、再び
ps
と
grep
を使用してプロセスを見つけました。類似性はそこで終わります。 Bash のパイプ セット内の次の命令 (パイプ記号
|
を使用して、前のコマンドから次のコマンドに情報を渡します) では、
grep
プロセス自体を除外します (実行中に実行される
ps
出力の一部としてもリストされます)。コマンド シーケンスは、
grep
に
-v
オプションを使用し、単語
'grep'
を除外することで、
grep
によって自動的に取得されます。
最後に、
awk
を使用して、出力の 2 番目 (
$2
) 列のみを出力することにより、検出されたプロセスの
PID
(プロセス ID) を出力します。単一の
PID
のみが返されることがわかります。これは、開始した
gnome-calculator
1 つだけであるという事実と一致します。
最後のコマンドは、プロセスを終了する
kill -9
命令を含む
xargs
コマンドを追加します。 xargs 自体はパイプと同様に機能しますが、さまざまな入力情報を処理して正しく渡すことができるため、
kill
などの特定のプログラム (プレーンな
PID
がいつ送信されるかをネイティブに理解できない) が直接入力を受け入れることができるようになります。 、またはむしろオプション – ここで送信されるプロセス ID など。 xargs にはパイプ自体が接頭辞として付いていることに注意してください。
grep -v 'grep'
を含めることで、元の
grep
コマンドに関連付けられた
PID
を見つけることができないという最終的な
kill
コマンドのエラーを回避できるだけでなく (
'gnome-calculator'
の grep’ の義務を果たし、その後終了しているため)
'gnome-calculator'
テキスト)、第 2 に、元の
grep
が終了した後に開始された、同じプロセス ID を持つ別の新しいコマンド/プロセスが終了するリスクも防ぎます。このようなことが起こる可能性は低いですが、可能性はあります。
これらをコマンドに組み込むと見た目は良くなりますが、まだ完璧ではありません。これは 10 人のユーザーがいるサーバーで、10 人全員が電卓を起動しているとは何ですか? sudo のような権限があると仮定して、他のユーザーの電卓プロセスを本当に終了したいでしょうか?おそらくそうではありません。したがって、さらに一歩進んでコマンドを次のように定義できます。
ノーム電卓と
ps -ef | grep ‘gnome-calculator’ | grep -v ‘grep’ | grep “$(whoami)” | awk ‘{print $2}’
ps -ef | grep ‘gnome-calculator’ | grep -v ‘grep’ | grep “$(whoami)” | awk ‘{print $2}’ | xargs キル -9
この例では、小さな追加コマンド、つまり
grep "$(whoami)"
を挿入しました。これはサブシェル (
$(...)
) を実行し、そのサブシェル内で
whoami
を実行します。
whoami
コマンドは、現在ログインしているユーザーをターミナルに返します。ビンゴ!現在は、自分自身が所有するプロセスのみを終了します。
完璧?いいえ、残念ながら、このように詳細に調整されたコマンド ラインであっても、依然としてエラーが発生する可能性があります。たとえば、プロセス リストにロケールまたは奇妙な文字が含まれている場合、
grep
は依然として失敗する可能性があります。おそらく最も安全なバージョンは次のようなものでしょう。
ノーム電卓と
ps -ef | grep -Ei –binary-files=text “^$(whoami) [0-9 ]+:.*gnome-calculator$” | grep –binary-files=text -v ‘grep’ | awk ‘{print $2}’ | grep –binary-files=text -o ‘[0-9]+’ | xargs -I{} kill -9 “{}”
この例では、正規表現を使用して
grep
コマンドをさらに制限的に定義しました。ユーザー名 (サブシェルで
whoami
を使用) で始まり (
^
で示されます)、その後に必須のスペースが続き、その後に
0-9
と 0 ~ 9 の文字のみが続きます。スペース、少なくとも 1 つ以上 (
+
で示される)、その後に必須のコロン (一部)、その後にプログラム名までの任意の文字が続き、行末まで埋める必要があります (
$
)。
grep
拡張正規表現 (
-E
) を使用し、大文字と小文字は区別されません (
-i
オプション、または既存の
-E
オプションに追加される場合は単に
i
)
また、
--binary-files=text
を使用して、ロケールや奇数文字の奇妙な可能性から grep を保護し、置換文字列を示し、置換文字列を引用符で囲むことによって、より安全な方法で xargs を作成しました。
最後に、数字
0-9
のみを検索する正規表現を含む追加の
grep -o
を挿入しました。したがって、たとえ何らかのプログラムがこのプロセスをだましてコマンドラインを強制終了させようとしたとしても、それを実行するのはより困難です。
解析コマンド ラインを定義するための興味深い代替手段として、
killall
コマンドも検討してみるとよいでしょう。
ノーム電卓と
killall ‘gnome-calculator’
このコマンドの詳細については、
man killall
を使用してマニュアルにアクセスできます。
killall
コマンドを使用すると、指定したユーザーが所有するプロセスのみを強制終了する
--user
などのオプションを設定することもできます。
まとめ
さまざまな方法でプロセスを処理することで、プロセス ウォッチドッグ スクリプトの作成、プロセス処理の自動化、マルチスレッド bash コードの開発、プロセスの管理などをより適切に行うことができます。 新しく見つけた Bash スキルを楽しんでください!





