Bashのジョブ制御を使用してフォアグラウンドプロセスとバックグラウンドプロセスを管理する方法
序章
前のチュートリアルでは、 ps
, kill
、 と nice
コマンドを使用して、システム上のプロセスを制御できます。 このガイドでは、 bash
、Linuxシステム、および端末が連携して、プロセスとジョブの制御を提供します。
この記事では、フォアグラウンドプロセスとバックグラウンドプロセスの管理に焦点を当て、シェルのジョブ制御機能を活用してコマンドの実行方法をより柔軟にする方法を示します。
前提条件
このガイドに従うには、を実行しているコンピューターにアクセスする必要があります bash
シェルインターフェース。 bash
は多くのLinuxベースのオペレーティングシステムのデフォルトシェルであり、macOSを含む多くのUnixライクなオペレーティングシステムで利用できます。 このチュートリアルは、Ubuntu20.04を実行しているLinux仮想プライベートサーバーを使用して検証されていることに注意してください。
このガイドに従うためにリモートサーバーを使用する場合は、最初に初期サーバーセットアップガイドを完了することをお勧めします。 そうすることで、安全なサーバー環境がセットアップされます— root以外のユーザーを含む sudo
特権とUFWで構成されたファイアウォール—Linuxスキルを構築するために使用できます。
または、このページに埋め込まれているインタラクティブ端末を使用して、このチュートリアルのサンプルコマンドを試すこともできます。 次のインタラクティブターミナルの起動!ボタンをクリックしてターミナルウィンドウを開き、Linux(Ubuntu)環境での作業を開始します。
フォアグラウンドプロセスの管理
Linuxマシンで開始するほとんどのプロセスは、フォアグラウンドで実行されます。 コマンドは実行を開始し、プロセスの間、シェルの使用をブロックします。 このプロセスでは、ユーザーとの対話が可能になる場合もあれば、プロシージャを実行して終了する場合もあります。 デフォルトでは、すべての出力がターミナルウィンドウに表示されます。 次のサブセクションでは、フォアグラウンドプロセスを管理する基本的な方法について説明します。
プロセスの開始
デフォルトでは、プロセスはフォアグラウンドで開始されます。 これは、プログラムが終了するか状態が変わるまで、シェルと対話できないことを意味します。
一部のフォアグラウンドコマンドは非常にすばやく終了し、ほとんどすぐにシェルプロンプトに戻ります。 たとえば、次のコマンドは次のように出力します Hello World
ターミナルに移動してから、コマンドプロンプトに戻ります。
- echo "Hello World"
OutputHello World
他のフォアグラウンドコマンドは実行に時間がかかり、その間シェルアクセスをブロックします。 これは、コマンドがより広範な操作を実行しているため、またはコマンドが明示的に停止されるまで、または他のユーザー入力を受け取るまで実行されるように構成されているためである可能性があります。
無期限に実行されるコマンドは top
効用。 開始後、ユーザーがプロセスを終了するまで、実行を継続し、表示を更新します。
- top
あなたはやめることができます top
を押すことによって q
、ただし、他の一部のプロセスには専用の終了機能がありません。 それらを停止するには、別の方法を使用する必要があります。
プロセスの終了
単純なものを始めたとしましょう bash
コマンドラインでループします。 例として、次のコマンドは、出力するループを開始します Hello World
10秒ごと。 このループは、明示的に終了するまで永久に続きます。
- while true; do echo "Hello World"; sleep 10; done
ようではない top
、このようなループには「終了」キーがありません。 信号を送信してプロセスを停止する必要があります。 Linuxでは、カーネルは、実行中のプロセスにシグナルを送信して、プロセスが終了または状態を変更するように要求できます。 Linux端末は通常、ユーザーが CTRL + C
キーの組み合わせ。 SIGINTシグナルは、ユーザーがキーボードを使用して終了を要求したことをプログラムに通知します。
開始したループを停止するには、 CTRL
キーを押して、 C
鍵:
CTRL + C
ループが終了し、制御がシェルに戻ります。
によって送信されるSIGINTシグナル CTRL + C
組み合わせは、プログラムに送信できる多くの信号の1つです。 ほとんどの信号にはキーボードの組み合わせが関連付けられていないため、代わりに kill
コマンド。これについては、このガイドの後半で説明します。
プロセスの一時停止
前述のように、フォアグラウンドプロセスは、実行中はシェルへのアクセスをブロックします。 フォアグラウンドでプロセスを開始した後、ターミナルにアクセスする必要があることに気付いた場合はどうなりますか?
送信できるもう1つの信号は、「SIGTSTP」信号です。 SIGTSTPは「信号端子停止」の略で、通常は信号番号20で表されます。 を押すと CTRL + Z
、端末は「サスペンド」コマンドを登録します。このコマンドは、SIGTSTPシグナルをフォアグラウンドプロセスに送信します。 基本的に、これによりコマンドの実行が一時停止し、制御が端末に戻ります。
説明のために、 ping
接続するには google.com
5秒ごと。 次のコマンドは、 ping
でコマンド command
、これにより、コマンドに最大カウントを人為的に設定するシェルエイリアスをバイパスできます。
- command ping -i 5 google.com
コマンドを終了する代わりに CTRL + C
、 押す CTRL + Z
代わりは。 そうすることで、次のような出力が返されます。
Output[1]+ Stopped ping -i 5 google.com
The 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
:
バックグラウンドプロセスの管理
フォアグラウンドでプロセスを実行する代わりの主な方法は、プロセスをバックグラウンドで実行できるようにすることです。 バックグラウンドプロセスは、それを開始した特定の端末に関連付けられていますが、シェルへのアクセスをブロックしません。 代わりに、バックグラウンドで実行され、コマンドの実行中にユーザーがシステムと対話できるようにします。
フォアグラウンドプロセスがそのターミナルと相互作用する方法のため、ターミナルウィンドウごとに1つのフォアグラウンドプロセスしか存在できません。 バックグラウンドプロセスは、プロセスが完了するのを待たずにすぐに制御をシェルに戻すため、多くのバックグラウンドプロセスを同時に実行できます。
プロセスの開始
アンパサンド文字を追加することで、バックグラウンドプロセスを開始できます(&
)コマンドの最後まで。 これは、プロセスが完了するのを待たずに、実行を開始し、すぐにユーザーをプロンプトに戻すようにシェルに指示します。 コマンドの出力は(リダイレクトされたを除いて)引き続きターミナルに表示されますが、バックグラウンドプロセスが続行されるときに追加のコマンドを入力できます。
たとえば、同じことを開始できます ping
次のように入力して、バックグラウンドで前のセクションから処理します。
- command ping -i 5 google.com &
The 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
バックグラウンドで実行されているコマンド、 jobs
コマンドの出力は次のようになります。
Output[1]+ Running command ping -i 5 google.com &
これは、現在単一のバックグラウンドプロセスが実行されていることを示しています。 The [1]
コマンドのジョブ仕様またはジョブ番号を表します。 これは、次のような他のジョブおよびプロセス制御コマンドで参照できます。 kill
, fg
、 と bg
ジョブ番号の前にパーセント記号を付けます。 この場合、このジョブを次のように参照します。 %1
.
バックグラウンドプロセスの停止
現在のバックグラウンドプロセスをいくつかの方法で停止できます。 最も簡単な方法は、 kill
関連するジョブ番号を指定したコマンド。 たとえば、次のように入力して、実行中のバックグラウンドプロセスを強制終了できます。
- kill %1
端末がどのように構成されているかに応じて、すぐに、または次にヒットしたときに ENTER
、ジョブの終了ステータスが出力に表示されます。
Output[1]+ Terminated command ping -i 5 google.com
あなたがチェックした場合 jobs
もう一度コマンドを実行すると、現在のジョブはありません。
プロセス状態の変更
バックグラウンドでプロセスを開始および停止する方法がわかったので、プロセスの状態の変更について学習できます。
このガイドでは、プロセスの状態を変更する1つの方法、つまり、 CTRL + Z
. プロセスがこの停止状態にある場合、フォアグラウンドプロセスをバックグラウンドに移動したり、その逆を行ったりすることができます。
フォアグラウンドプロセスをバックグラウンドに移動する
コマンドをで終了するのを忘れた場合 &
開始しても、プロセスをバックグラウンドに移動できます。
最初のステップは、でプロセスを停止することです CTRL + Z
また。 プロセスが停止すると、 bg
バックグラウンドで再起動するコマンド:
- bg
今度はアンパサンドが追加されたジョブステータス行が再び表示されます。
Output[1]+ ping -i 5 google.com &
デフォルトでは、 bg
コマンドは、最後に停止したプロセスで動作します。 複数のプロセスを再開せずに連続して停止した場合は、ジョブ番号で特定のプロセスを参照して、正しいプロセスをバックグラウンドに移動できます。
すべてのコマンドをバックグラウンドで実行できるわけではないことに注意してください。 一部のプロセスは、アクティブな端末に直接接続された標準の入出力で開始されたことを検出すると、自動的に終了します。
バックグラウンドプロセスをフォアグラウンドに移動する
次のように入力して、バックグラウンドプロセスをフォアグラウンドに移動することもできます fg
:
- fg
これは、最近バックグラウンドで処理されたプロセスで動作します( +
の中に jobs
コマンドの出力)。 プロセスを即座に一時停止し、フォアグラウンドに配置します。 別のジョブを指定するには、そのジョブ番号を使用します。
- fg %2
仕事が最前線にあると、あなたはそれを殺すことができます CTRL + C
、完了させるか、一時停止して再びバックグラウンドに移動します。
SIGHUPの取り扱い
プロセスがバックグラウンドにあるかフォアグラウンドにあるかにかかわらず、プロセスはそれを開始したターミナルインスタンスとかなり緊密に結びついています。 端末が閉じると、通常、端末に関連付けられているすべてのプロセス(フォアグラウンド、バックグラウンド、または停止)にSIGHUP信号が送信されます。 これは、プロセスの制御端末がまもなく使用できなくなるため、プロセスが終了するように通知します。
ただし、端末を閉じてもバックグラウンドプロセスを実行したままにしたい場合があります。 これを達成する方法はいくつかあります。 より柔軟な方法の1つは、screenやtmuxなどのターミナルマルチプレクサを使用することです。 別の解決策は、のデタッチ機能を提供するユーティリティを使用することです。 screen
と tmux
、dtachのように。
ただし、これは常にオプションであるとは限りません。 これらのプログラムが利用できない場合や、実行を継続するために必要なプロセスをすでに開始している場合があります。 時には、これらはあなたが達成する必要があることに対してやり過ぎかもしれません。
使用する nohup
プロセスを開始するときに、プロセスが完了する前にターミナルを閉じたいことがわかっている場合は、を使用してターミナルを開始できます。 nohup
指図。 これにより、開始されたプロセスはSIGHUP信号の影響を受けなくなります。 ターミナルが閉じても実行を継続し、initシステムの子として再割り当てされます。
- nohup ping -i 5 google.com &
これにより、次のような行が返され、コマンドの出力が次のファイルに書き込まれることを示します。 nohup.out
:
Outputnohup: ignoring input and appending output to ‘nohup.out’
このファイルは、書き込み可能な場合は現在の作業ディレクトリに配置されますが、それ以外の場合はホームディレクトリに配置されます。 これは、ターミナルウィンドウを閉じても出力が失われないようにするためです。
ターミナルウィンドウを閉じて別のウィンドウを開くと、プロセスは引き続き実行されます。 あなたはそれをの出力に見つけることができません jobs
各ターミナルインスタンスは独自の独立したジョブキューを維持するため、コマンド。 ターミナルを閉じると、 ping
ジョブは、 ping
プロセスはまだ実行中です。
殺すには ping
プロセスでは、そのプロセスID(または「PID」)を見つける必要があります。 あなたはそれをすることができます pgrep
コマンド( pkill
コマンドですが、この2つの部分からなるメソッドにより、目的のプロセスのみを強制終了できます)。 使用する pgrep
そしてその -a
実行可能ファイルを検索するためのフラグ:
- pgrep -a ping
Output7360 ping -i 5 google.com
次に、返されたPIDを参照してプロセスを強制終了できます。これは、最初の列の番号です。
- kill 7360
あなたは削除したいかもしれません nohup.out
もう必要ない場合はファイルします。
使用する disown
The nohup
コマンドは便利ですが、プロセスの開始時に必要になることがわかっている場合に限ります。 The bash
ジョブ制御システムは、組み込みで同様の結果を達成する他の方法を提供します disown
指図。
The disown
コマンドは、デフォルト設定で、端末のジョブキューからジョブを削除します。 これは、このガイドで前述したジョブ制御メカニズムを使用して管理できなくなったことを意味します。 fg
, bg
, CTRL + Z
, CTRL + C
. 代わりに、ジョブはすぐにリストから削除されます jobs
出力され、端末に関連付けられなくなります。
このコマンドは、ジョブ番号を指定して呼び出されます。 たとえば、ジョブ2をすぐに否認するには、次のように入力します。
- disown %2
これにより、プロセスは nohup
制御端末が閉じられた後のプロセス。 例外は、ファイルにリダイレクトされていない場合、制御端末が閉じるときに出力が失われることです。
通常、ターミナルウィンドウをすぐに閉じない場合は、プロセスをジョブ制御から完全に削除する必要はありません。 あなたは合格することができます -h
にフラグを立てる disown
代わりに、SIGHUPシグナルを無視するようにプロセスをマークするためにプロセスを実行しますが、それ以外の場合は通常のジョブとして続行します。
- disown -h %1
この状態では、通常のジョブ制御メカニズムを使用して、ターミナルを閉じるまでプロセスを制御し続けることができます。 ターミナルを閉じると、起動時にファイルにリダイレクトしなかった場合、出力する場所がないプロセスで再びスタックします。
これを回避するには、プロセスがすでに実行された後で、プロセスの出力をリダイレクトしてみてください。 これはこのガイドの範囲外ですが、この投稿は、その方法について説明しています。
を使用して huponexit
シェルオプション
bash
子プロセスのSIGHUP問題を回避する別の方法があります。 The huponexit
シェルオプションは、 bash
子プロセスが終了すると、SIGHUPシグナルを送信します。
注: huponexit
このオプションは、シェル自体の内部からシェルセッションの終了が開始された場合のSIGHUPの動作にのみ影響します。 これが適用される場合のいくつかの例は、 exit
コマンドまたは CTRL + D
セッション内で押されます。
ターミナルプログラム自体を介して(ウィンドウを閉じるなどして)シェルセッションが終了すると、コマンド huponexit
影響なしになります。 それ以外の bash
SIGHUP信号を送信するかどうかを決定すると、端末自体がSIGHUP信号をに送信します。 bash
、これにより、シグナルが子プロセスに正しく伝播されます。
前述の警告にもかかわらず、 huponexit
オプションはおそらく管理が最も簡単なものの1つです。 次のように入力すると、この機能がオンかオフかを判断できます。
- shopt huponexit
オンにするには、次のように入力します。
- shopt -s huponexit
ここで、次のように入力してセッションを終了すると、 exit
、プロセスはすべて引き続き実行されます。
- exit
これには、最後のオプションと同じプログラム出力に関する注意事項があるため、これが重要な場合は、ターミナルを閉じる前にプロセスの出力をリダイレクトしたことを確認してください。
結論
ジョブ制御と、フォアグラウンドおよびバックグラウンドプロセスの管理方法を学習すると、コマンドラインでプログラムを実行する際の柔軟性が高まります。 多くのターミナルウィンドウやSSHセッションを開く代わりに、プロセスを早期に停止したり、必要に応じてバックグラウンドに移動したりすることで解決できることがよくあります。