前書き

このガイドでは、「+ bash 」、Linuxシステム、およびターミナルがどのように連携してプロセスとジョブの制御を提供するかについて説明します。 https://www.digitalocean.com/community/tutorials/how-to-use-ps-kill-and-nice-to-manage-processes-in-linux [前のガイド]で、「 ps + + kill + 、および + nice + `コマンドを使用して、システム上のプロセスを制御できます。

この記事では、フォアグラウンドプロセスとバックグラウンドプロセスの管理に焦点を当て、シェルのジョブ制御機能を活用してコマンドの実行方法の柔軟性を高める方法を示します。

前景プロセスの管理

Linuxマシンで開始するほとんどのプロセスはフォアグラウンドで実行されます。 このコマンドは実行を開始し、プロセスの間シェルの使用をブロックします。 プロセスは、ユーザーとの対話を許可する場合もあれば、単にプロシージャを実行して終了する場合もあります。 デフォルトでは、出力は端末ウィンドウに表示されます。 フォアグラウンドプロセスを管理する基本的な方法を以下で説明します。

プロセスを開始する

デフォルトでは、プロセスはフォアグラウンドで開始されます。 プログラムが終了するか状態を変更するまで、シェルと対話することはできません。

一部のフォアグラウンドコマンドは非常に迅速に終了し、すぐにシェルプロンプトに戻ります。 例えば、このコマンドは:

echo "Hello World"

これにより、「Hello World」が端末に出力され、コマンドプロンプトに戻ります。

他のフォアグラウンドコマンドは実行に時間がかかり、その間シェルアクセスをブロックします。 これは、コマンドがより広範な操作を実行しているため、または明示的に停止されるまで、または他のユーザー入力を受け取るまで実行するように構成されているためです。

無期限に実行されるコマンドは、 `+ top +`ユーティリティです。 開始後、ユーザーがプロセスを終了するまで実行を継続し、表示を更新します。

top

「q」と入力して終了できます。 一部のプロセスには専用の終了機能がありません。 それらを停止するには、別の方法を使用する必要があります。

プロセスの終了

コマンドラインで単純な `+ bash +`ループを開始するとします。 10秒ごとに「Hello World」を出力するループを開始できます。 このループは、明示的に終了するまで永遠に続きます。

while true; do echo "Hello World"; sleep 10; done

ループには「終了」キーはありません。 * signal *を送信してプロセスを停止する必要があります。 Linuxでは、カーネルはプロセスのシグナルを送信して、プロセスの終了または状態の変更を要求できます。 Linux端末は、通常、「+ CTRL-C +」キーの組み合わせが押されたときに「SIGINT」シグナル(通常、シグナル番号2)を現在のフォアグラウンドプロセスに送信するように構成されます。 SIGINTシグナルは、ユーザーがキーボードを使用して終了を要求したことをプログラムに伝えます。

開始したループを停止するには、コントロールキーを押しながら「c」キーを押します。

CTRL-C

ループが終了し、制御がシェルに戻ります。

`+ CTRL-C `の組み合わせによって送信されるSIGINTシグナルは、プログラムに送信できる多くのシグナルの1つです。 ほとんどのシグナルにはキーボードの組み合わせが関連付けられていないため、代わりに ` kill +`コマンドを使用して送信する必要があります(これについては後で説明します)。

プロセスの一時停止

前に述べたように、フォアグラウンドプロセスは実行中はシェルへのアクセスをブロックします。 フォアグラウンドでプロセスを開始した後、ターミナルにアクセスする必要があることに気付いた場合はどうなりますか?

送信できるもう1つの信号は、「SIGTSTP」信号(通常、信号番号20)です。 「+ CTRL-Z +」を押すと、ターミナルは「サスペンド」コマンドを登録し、SIGTSTPシグナルをフォアグラウンドプロセスに送信します。 これは基本的にコマンドの実行を一時停止し、制御を端末に返します。

デモのために、5秒ごとに「+ ping 」を使用してgoogle.comに接続します。 ` ping`コマンドの前に` + command`を追加します。これにより、コマンドで人為的に最大カウントを設定するシェルエイリアスをバイパスできます。

command ping -i 5 google.com

`+ CTRL-C `でコマンドを終了する代わりに、代わりに ` CTRL-Z +`と入力します:

CTRL-Z

次のような出力が表示されます。

Output[1]+  Stopped                 ping -i 5 google.com

`+ ping `コマンドは一時的に停止され、シェルプロンプトに再びアクセスできるようになりました。 これを表示するには、 ` ps +`プロセスツールを使用できます。

ps T
Output  PID TTY      STAT   TIME COMMAND
26904 pts/3    Ss     0:00 /bin/bash
29633 pts/3    T      0:00 ping -i 5 google.com
29643 pts/3    R+     0:00 ps t

`+ ping `プロセスはまだリストされていますが、「STAT」列には「T」が含まれていることがわかります。 ` ps +`のマニュアルページは、これが「(a)ジョブ制御信号によって停止された」ジョブを表していることを示しています。

プロセスの状態を変更する方法について詳しく説明しますが、今のところ、次のように入力して、フォアグラウンドでコマンドの実行を再開できます。

fg

プロセスが再開したら、 `+ CTRL-C +`で終了します:

CTRL-C

バックグラウンドプロセスの管理

フォアグラウンドでプロセスを実行する主な代替方法は、バックグラウンドで実行できるようにすることです。 バックグラウンドプロセスは、それを開始した特定の端末に関連付けられていますが、シェルへのアクセスをブロックしません。 代わりに、バックグラウンドで実行され、コマンドの実行中にユーザーがシステムと対話できるようにします。

フォアグラウンドプロセスがそのターミナルと対話する方法のために、すべてのターミナルウィンドウに対して1つのフォアグラウンドプロセスしか存在できません。 バックグラウンドプロセスは、プロセスの完了を待たずにすぐに制御をシェルに返すため、多くのバックグラウンドプロセスを同時に実行できます。

開始プロセス

コマンドの最後にアンパサンド文字(「&」)を追加することにより、バックグラウンドプロセスを開始できます。 これにより、プロセスが完了するのを待たずに、実行を開始してすぐにユーザーをプロンプトに戻すようシェルに指示します。 コマンドの出力は引き続き端末に表示されます(https://www.digitalocean.com/community/tutorials/an-introduction-to-linux-io-redirection[redirected]を除く)が、次のように追加のコマンドを入力できます。バックグラウンドプロセスが続行されます。

たとえば、次のように入力して、バックグラウンドの最後のセクションから同じpingプロセスを開始できます。

command ping -i 5 google.com &

次のような `+ bash +`ジョブ制御システムからの出力が表示されます。

Output[1] 4287

`+ ping +`コマンドからの通常の出力も表示されます:

OutputPING google.com (74.125.226.71) 56(84) bytes of data.
64 bytes from lga15s44-in-f7.1e100.net (74.125.226.71): icmp_seq=1 ttl=55 time=12.3 ms
64 bytes from lga15s44-in-f7.1e100.net (74.125.226.71): icmp_seq=2 ttl=55 time=11.1 ms
64 bytes from lga15s44-in-f7.1e100.net (74.125.226.71): icmp_seq=3 ttl=55 time=9.98 ms

ただし、コマンドを同時に入力することもできます。 バックグラウンドプロセスの出力は、フォアグラウンドプロセスの入力と出力に混在しますが、フォアグラウンドプロセスの実行を妨げることはありません。

バックグラウンドプロセスのリスト

停止またはバックグラウンド化されたプロセスをすべて表示するには、 `+ jobs +`コマンドを使用できます。

jobs

バックグラウンドで「+ ping +」コマンドを実行している場合、次のようなものが表示されます。

Output[1]+  Running                 command ping -i 5 google.com &

これは、現在1つのバックグラウンドプロセスが実行されていることを示しています。 `+ [1] `はコマンドの「ジョブ仕様」またはジョブ番号を表します。 これは、ジョブ番号の前にパーセント記号を付けることにより、「 kill 」、「 fg 」、「 bg 」などの他のジョブおよびプロセス制御コマンドで参照できます。 この場合、このジョブを「%1 +」と呼びます。

バックグラウンドプロセスの停止

いくつかの方法で現在のバックグラウンドプロセスを停止できます。 最も簡単な方法は、関連ジョブ番号で `+ kill +`コマンドを使用することです。 たとえば、次のように入力して、実行中のバックグラウンドプロセスを強制終了できます。

kill %1

端末の設定方法に応じて、すぐに、または次にEnterキーを押すと、ジョブの終了ステータスが表示されます。

Output[1]+  Terminated              command ping -i 5 google.com

`+ jobs`コマンドをもう一度チェックすると、現在のジョブは表示されません。

プロセス状態の変更

バックグラウンドでプロセスを開始および停止する方法がわかったので、プロセスの状態を変更する方法について説明できます。

以前に `+ CTRL-Z +`でプロセスを停止または一時停止する方法を説明したときに、1つの状態変化を示しました。 プロセスがこの停止状態にある場合、フォアグラウンドプロセスをバックグラウンドに移動したり、その逆を行うことができます。

前景プロセスを背景に移動する

コマンドを開始するときに `&`でコマンドを終了することを忘れても、プロセスをバックグラウンドに移動できます。

最初のステップは、 `+ CTRL-Z +`でプロセスを再び停止することです:

CTRL-Z

プロセスが停止したら、 `+ bg +`コマンドを使用してバックグラウンドでプロセスを再開できます。

bg

ジョブのステータス行が再び表示されますが、今回はアンパサンドが追加されています。

Output[1]+ ping -i 5 google.com &

デフォルトでは、 `+ bg +`コマンドは最後に停止したプロセスで動作します。 再起動せずに連続して複数のプロセスを停止した場合は、ジョブ番号でプロセスを参照して、正しいプロセスをバックグラウンドにできます。

すべてのコマンドをバックグラウンド化できるわけではないことに注意してください。 一部のプロセスは、アクティブな端末に直接接続された標準入出力で開始されたことを検出すると、自動的に終了します。

バックグラウンドプロセスをフォアグラウンドに移動する

`+ fg +`を入力して、バックグラウンドプロセスをフォアグラウンドに移動することもできます。

fg

これは、最後にバックグラウンド化されたプロセス( `+ jobs `出力の「」で示される)で動作します。 プロセスを直ちに中断し、フォアグラウンドに配置します。 別のジョブを指定するには、そのジョブ番号を使用します。

fg %2

ジョブがフォアグラウンドになったら、 `+ CTRL-C +`でジョブを強制終了するか、完了させるか、中断してバックグラウンドに戻すことができます。

SIGHUPの取り扱い

プロセスがバックグラウンドであるかフォアグラウンドであるかに関係なく、プロセスを開始したターミナルインスタンスとかなり密接に結びついています。 端末が閉じると、通常、端末に関連付けられているすべてのプロセス(フォアグラウンド、バックグラウンド、または停止)にSIGHUPシグナルを送信します。 これは、制御端末がまもなく利用できなくなるため、プロセスが終了することを通知します。 ターミナルを閉じてもバックグラウンドプロセスを実行したい場合はどうしますか?

これを実現する方法はいくつかあります。 最も柔軟な方法は、一般的にhttps://www.digitalocean.com/community/tutorials/how-to-install-and-use-screen-on-an-ubuntu-cloud-server[+ screen + `]またはhttps://www.digitalocean.com/community/tutorials/how-to-install-and-use-tmux-on-ubuntu-12-10—​2 [ + tmux + ]、またはhttps://www.digitalocean.com/community/tutorials/how-to-use-dvtm-and-dtach-as-a-terminal-window-manager-on-のような、少なくともこれらのデタッチ機能を提供するユーティリティan-ubuntu-vps [+ dtach +`]。

ただし、これは常にオプションとは限りません。 これらのプログラムが利用できない場合や、実行を継続するために必要なプロセスを既に開始している場合があります。 時々、これらはあなたが達成する必要があるものに対しては行き過ぎです。

nohupを使用する

プロセスの開始時に、プロセスが完了する前にターミナルを閉じたいことがわかっている場合は、 `+ nohup +`コマンドを使用してターミナルを開始できます。 これにより、開始されたプロセスはSIGHUPシグナルの影響を受けなくなります。 ターミナルが閉じても実行を継続します。 これは、initシステムの子として再割り当てされます。

nohup ping -i 5 google.com &

次のような行が表示され、コマンドの出力が `+ nohup.out +`という名前のファイル(書き込み可能な場合は現在のディレクトリ、そうでない場合はホームディレクトリ)に書き込まれることを示します。

Outputnohup: ignoring input and appending output to ‘nohup.out’

これは、ターミナルウィンドウが閉じられた場合に出力が失われないようにするためです。

ターミナルウィンドウを閉じて別のウィンドウを開いても、プロセスは実行されたままです。 各ターミナルインスタンスが独自の独立したジョブキューを維持するため、 + jobs +`コマンドの出力には表示されません。 ターミナルを閉じると、 `+ ping + _process_がまだ実行されていても、 + ping + _job_が破壊されました。

`+ ping `プロセスを強制終了するには、そのプロセスID(または「PID」)を検索する必要があります。 ` pgrep `コマンドでそれを行うことができます( ` pkill `コマンドもありますが、この2つの部分からなるメソッドは、目的のプロセスのみを強制終了することを保証します)。 ` pgrep `と ` -a +`フラグを使用して、実行可能ファイルを検索します。

pgrep -a ping
Output7360 ping -i 5 google.com

その後、返されたPID(最初の列の数値)を参照することにより、プロセスを強制終了できます。

kill 7360

不要になった場合は、 `+ nohup.out +`ファイルを削除できます。

disownを使用する

`+ nohup `コマンドは役立ちますが、プロセスを開始するときに必要になることがわかっている場合のみです。 ` bash `ジョブ制御システムは、組み込みコマンド ` disown +`で同様の結果を達成する他の方法を提供します。

`+ disown `コマンドは、デフォルト設定では、ターミナルのジョブキューからジョブを削除します。 つまり、このガイドで説明したジョブ制御メカニズム(「 fg 」、「 bg 」、「 CTRL-Z 」、「 CTRL-C 」など)を使用して管理することはできなくなります。 ` jobs +`出力のリストからすぐに削除され、端末に関連付けられなくなります。

コマンドは、ジョブ番号を指定して呼び出されます。 たとえば、ジョブ2をすぐに否認するには、次のように入力します。

disown %2

これにより、制御端末が閉じられた後、プロセスは「+ nohup +」プロセスの状態とは異なる状態になります。 例外は、制御端末がファイルにリダイレクトされていない場合、制御端末を閉じると出力が失われることです。

通常、端末ウィンドウをすぐに閉じない場合、ジョブ制御からプロセスを完全に削除することは望ましくありません。 プロセスにSIGHUPシグナルを無視するようマークするために、代わりに `+ -h `フラグを ` disown +`プロセスに渡すことができますが、そうでなければ通常のジョブとして続行します。

disown -h %1

この状態では、通常のジョブ制御メカニズムを使用して、ターミナルを閉じるまでプロセスの制御を続けることができます。 ターミナルを閉じると、起動時にファイルにリダイレクトしなかった場合、再び出力する場所がないプロセスでスタックします。

この問題を回避するには、プロセスが既に実行された後に、プロセスの出力をリダイレクトしてみてください。 これはこのガイドの範囲外ですが、http://etbe.coker.com.au/2008/02/27/redirecting-output-from-a-running-process/ [この投稿]をご覧ください。どうやってそれをするかを知るために。

huponexitシェルオプションの使用

Bashには、子プロセスのSIGHUP問題を回避する別の方法もあります。 `+ huponexit +`シェルオプションは、bashが終了時に子プロセスにSIGHUPシグナルを送信するかどうかを制御します。

Note

上記の警告にもかかわらず、 `+ huponexit +`オプションはおそらく最も簡単なオプションの1つです。 次のように入力して、この機能がオンかオフかを確認できます。

shopt huponexit

オンにするには、次を入力します。

shopt -s huponexit

これで、「+ exit +」と入力してセッションを終了すると、すべてのプロセスが引き続き実行されます。

exit

これには最後のオプションと同じプログラム出力に関する警告があるため、端末を閉じる前に重要な場合はプロセスの出力をリダイレクトしてください。

結論

ジョブ制御と、フォアグラウンドプロセスとバックグラウンドプロセスの管理方法を学習すると、コマンドラインでプログラムを実行する際の柔軟性が高まります。 多くのターミナルウィンドウまたはSSHセッションを開く必要はなく、多くの場合、いくつかの停止コマンドとバックグラウンドコマンドで対応できます。