【Linux】ジョブ管理(バックグラウンドとフォアグラウンド)について

Linux では、ジョブ管理を使うと、複数のタスクを同時に扱えます。この記事では、プロセスをバックグラウンドにする操作と、フォアグラウンドに戻す操作、バックグラウンドのジョブを管理する方法を確認します。

この記事でわかること
  1. フォアグラウンドとバックグラウンドの違いと、Ctrl+Z・jobs・fg・bg の使い方
  2. コマンドの末尾に & を付けて、最初からバックグラウンドで起動する方法
  3. シェルを終了すると、停止中のジョブも終了してしまうことと、その対策
検証環境

ホスト名は ubuntu-1、ユーザー名は hirotano で、OS は Ubuntu Server です。テキストエディタは nano(画面の表示は GNU nano 6.2)を使います。

画面イメージについて

この記事の画面は、実際の画面ではなく、実行時の画面から見るポイントを抜き出して描いたイメージです。長い出力は途中を省略しています。

バックグラウンドとフォアグラウンド

フォアグラウンドとバックグラウンドは、複数のタスクを並行して扱うための考え方です。作業中のタスクをいったん脇に置いて、別の作業をすれば、あるタスクが終わるのを待たずに、次のタスクを始められます。デスクトップのウィンドウを最小化したり、元に戻したりする操作に近いイメージです。

シェルでコマンドを実行すると、そのコマンドはフォアグラウンドのプロセスとして動きます。フォアグラウンドのプロセスがある間は、シェルは次のコマンドを受け付けません。

実行中のプロセスで Ctrl+Z を押すと、プロセスが一時停止(Stopped)して、シェルに戻ります。停止したプロセスは、バックグラウンドのジョブとして、シェルの管理下に残ります。

停止中のジョブは、次のどちらかで再開できます。

コマンド動作
fg停止中のジョブを、フォアグラウンドで再開する。ユーザーのキー入力を受け付ける
bg停止中のジョブを、バックグラウンドで再開する。& を付けて起動したのと同じ状態になる
フォアグラウンド実行中停止中(Stopped)一時停止バックグラウンド実行中コマンドを実行コマンド &Ctrl+Zfgbgfg
図1 ジョブの状態と、状態を切り替える操作

設定ファイルを複数開いて、見比べながら編集するときなど、タスクを並行して進めるときに便利です。

動作確認(nano エディタを使用)

Ubuntu Server に標準で入っているテキストエディタ nano を使って、プロセスをバックグラウンドにする手順と、フォアグラウンドに戻す手順を確認します。

nano でファイルを開く

新しいターミナルを開きます。nano の後ろに、編集したいファイル名を指定します。ここでは myfile1.txt を開きます。

$ nano myfile1.txt
ターミナル画面イメージ
hirotano@ubuntu-1:~$ 1hirotano@ubuntu-1:~$ nano myfile1.txt
図2 nano を起動するコマンド(実際の画面ではなく、表示内容のポイントを示したイメージです)
No.表示意味
1nano myfile1.txtファイル名を指定して nano を起動するコマンド

テキストを入力して、Ctrl+T を押す

ファイルにテキスト(ここでは myfile1)を入力して、編集中のまま、バックグラウンドへ移したいとします。nano のキーボードショートカット Ctrl+T を押します。画面の下のメニューには、^T Execute と表示されています。^ は Ctrl キーを意味します。

nano の編集画面画面イメージ
  GNU nano 6.2                    myfile1.txt1myfile1    ^G Help      ^O Write Out ^W Where Is  ^K Cut       ^T Execute^X Exit      ^R Read File ^\ Replace   ^U Paste     ^J Justify
図3 テキストを入力した状態の nano(^T Execute の行を強調)(実際の画面ではなく、表示内容のポイントを示したイメージです)
No.表示意味
1myfile1入力したテキスト

Ctrl+Z で nano を一時停止する

Ctrl+T を押すと、画面の下に Command to execute: と表示されて、nano の中からコマンドを実行できる状態になります。メニューには ^Z Suspend(中断)が表示されます。この状態で Ctrl+Z を押すと、nano が一時停止します。

nano のコマンド実行画面画面イメージ
  GNU nano 6.2                    myfile1.txtmyfile1   Command to execute:^G Help       M-F New Buffer ^S Spell Check ^J Full Justify ^V Cut Till End^C Cancel     M-\ Pipe Text  ^Y Linter      ^O Formatter    ^Z Suspend
図4 Ctrl+T を押した後の nano。^Z Suspend が表示されている(実際の画面ではなく、表示内容のポイントを示したイメージです)
補足:Ctrl+T を押さなくても中断できる場合がある

nano のバージョンによっては、編集画面で、Ctrl+T を押さずに、直接 Ctrl+Z を押しても中断できます。nano 7.2 では、Ctrl+T なしで中断できることを確認しました。

シェルに戻ったことを確認する

nano が一時停止して、シェルに戻ります。Use "fg" to return to nano. と表示されて、nano をフォアグラウンドに戻す方法が示されます。

ターミナル画面イメージ
hirotano@ubuntu-1:~$ nano myfile1.txt Use "fg" to return to nano. 1[1]+  Stopped                 nano myfile1.txthirotano@ubuntu-1:~$ 
図5 nano を中断してシェルに戻った状態(実際の画面ではなく、表示内容のポイントを示したイメージです)
No.表示意味
1[1]+ Stopped nano myfile1.txtジョブ番号 1 の nano myfile1.txt が、停止中(Stopped)であることを示す

この [1]+ Stopped nano myfile1.txt は、次のような意味です。

表示意味
[1]ジョブ番号。fg や bg でジョブを指定するときに使う
+現在のジョブ(fg や bg を引数なしで実行したときの対象)。ひとつ前のジョブには - が付く
Stoppedジョブの状態。一時停止している
nano myfile1.txtジョブのコマンド

jobs で一覧を確認する

バックグラウンドに待機しているジョブは、jobs コマンドで確認できます。シェルが管理しているジョブの一覧が表示されます。

$ jobs
ターミナル画面イメージ
1hirotano@ubuntu-1:~$ jobs2[1]+  Stopped                 nano myfile1.txthirotano@ubuntu-1:~$ 
図6 jobs の実行結果(実際の画面ではなく、表示内容のポイントを示したイメージです)
No.表示意味
1jobsジョブの一覧を表示するコマンド
2[1]+ Stopped nano myfile1.txtジョブ番号 1 の nano が停止中

-l オプションを付けると、ジョブ番号に加えて、プロセス ID も表示されます。

$ jobs -l

fg でフォアグラウンドに戻す

フォアグラウンドに戻すには、fg の後ろに、jobs で確認したジョブ番号を指定します。ここではジョブ番号が 1 なので、fg 1 と入力します。

$ fg 1
ターミナル画面イメージ
hirotano@ubuntu-1:~$ jobs[1]+  Stopped                 nano myfile1.txt1hirotano@ubuntu-1:~$ fg 1
図7 fg 1 を実行する(実際の画面ではなく、表示内容のポイントを示したイメージです)
No.表示意味
1fg 1ジョブ番号 1 をフォアグラウンドに戻すコマンド

プロセスがフォアグラウンドに戻って、作業を続けられます。入力したテキストも、そのまま残っています。

nano の編集画面画面イメージ
  GNU nano 6.2                    myfile1.txtmyfile1    ^G Help      ^O Write Out ^W Where Is  ^K Cut       ^T Execute^X Exit      ^R Read File ^\ Replace   ^U Paste     ^J Justify
図8 フォアグラウンドに戻った nano(実際の画面ではなく、表示内容のポイントを示したイメージです)

バックグラウンドとフォアグラウンドをうまく使えば、タスクを終了せずに、複数のファイルを並行して編集できます。

バックグラウンドでプロセスを起動する

コマンドの末尾にアンパサンド(&)を付けて実行すると、プロセスを起動した直後に、バックグラウンドのジョブにできます。

いま、nano myfile1.txt が、バックグラウンドに待機しているとします。

ターミナル画面イメージ
1hirotano@ubuntu-1:~$ jobs2[1]+  Stopped                 nano myfile1.txthirotano@ubuntu-1:~$ 
図9 nano myfile1.txt が停止中の状態(実際の画面ではなく、表示内容のポイントを示したイメージです)
No.表示意味
1jobsジョブの一覧を表示するコマンド
2[1]+ Stopped nano myfile1.txtジョブ番号 1 の nano が停止中

この状態で、myfile2.txt を nano で編集するのに、最初からバックグラウンドで起動したいとします。この場合は、nano myfile2.txt & を実行します。ジョブ番号(ここでは 2)とプロセス ID(ここでは 1537)が表示されて、シェルに戻ります。

$ nano myfile2.txt &
ターミナル画面イメージ
1hirotano@ubuntu-1:~$ nano myfile2.txt &2[2] 1537hirotano@ubuntu-1:~$ 
図10 バックグラウンドで nano を起動する(実際の画面ではなく、表示内容のポイントを示したイメージです)
No.表示意味
1nano myfile2.txt &末尾の & で、バックグラウンドで起動するコマンド
2[2] 1537ジョブ番号が 2、プロセス ID が 1537

jobs で確認すると、nano myfile2.txt がジョブ番号 2 として、一覧に追加されています。

ターミナル画面イメージ
1hirotano@ubuntu-1:~$ jobs[1]-  Stopped                 nano myfile1.txt2[2]+  Stopped                 nano myfile2.txt
図11 jobs の実行結果(ジョブが2つ)(実際の画面ではなく、表示内容のポイントを示したイメージです)
No.表示意味
1[1]-ひとつ前のジョブ。nano myfile1.txt
2[2]+現在のジョブ。nano myfile2.txt
補足:& を付けても Stopped になるのはなぜか

nano のように、端末からのキー入力や、画面への出力が必要なプログラムは、バックグラウンドになると、端末の入出力を待つ状態で停止します。上の例でも、nano myfile2.txt & で起動した nano は、Stopped と表示されています。sleep のように、端末の入力を必要としないコマンドは、Running と表示されて、そのまま動き続けます。

myfile2.txt を編集したいときは、fg 2 で、ジョブ番号 2 をフォアグラウンドに戻します。

$ fg 2
ターミナル画面イメージ
hirotano@ubuntu-1:~$ hirotano@ubuntu-1:~$ jobs[1]-  Stopped                 nano myfile1.txt[2]+  Stopped                 nano myfile2.txt1hirotano@ubuntu-1:~$ fg 2
図12 fg 2 を実行する(実際の画面ではなく、表示内容のポイントを示したイメージです)
No.表示意味
1fg 2ジョブ番号 2 をフォアグラウンドに戻すコマンド

myfile2.txt の編集を続けられます。

nano の編集画面画面イメージ
  GNU nano 6.2                    myfile2.txt     ^G Help      ^O Write Out ^W Where Is  ^K Cut       ^T Execute^X Exit      ^R Read File ^\ Replace   ^U Paste     ^J Justify
図13 フォアグラウンドに戻った nano(myfile2.txt)(実際の画面ではなく、表示内容のポイントを示したイメージです)

注意点

シェルを終了すると、停止中のジョブも一緒に終了します。たとえば、テキストを編集して、保存していない状態で nano がバックグラウンドにあるときにシェルを終了すると、編集した内容は失われます。

nano myfile1.txt がバックグラウンドにある状態で、exit を実行して、シェルを抜けます。

ターミナル画面イメージ
hirotano@ubuntu-1:~$ jobs[1]+  Stopped                 nano myfile1.txt1hirotano@ubuntu-1:~$ exit
図14 バックグラウンドにジョブがある状態で exit を入力する(実際の画面ではなく、表示内容のポイントを示したイメージです)
No.表示意味
1exitシェルを終了するコマンド

もう一度ログインして jobs を実行すると、バックグラウンドのジョブは消えています。

ターミナル画面イメージ
1hirotano@ubuntu-1:~$ jobshirotano@ubuntu-1:~$ 
図15 再ログイン後の jobs(ジョブは表示されない)(実際の画面ではなく、表示内容のポイントを示したイメージです)
No.表示意味
1何も表示されないバックグラウンドのジョブがなくなっている

これを避けるために、ログアウトする前に jobs コマンドを実行して、待機中のジョブがないかを確認する習慣をつけるとよいです。待機中のジョブがあれば、fg で戻して、保存してから終了します。

補足:実行中のジョブはどうなるか

bash では、インタラクティブなシェルが SIGHUP を受け取って終了するときに、実行中のジョブにも、停止中のジョブにも SIGHUP を送ります(停止中のジョブには、SIGHUP を届けるために SIGCONT も送ります)。disown でジョブをジョブ一覧から外すか、disown -h で SIGHUP を送らない印を付けると、SIGHUP が送られなくなります。ログインシェルの終了時にも SIGHUP を送るかどうかは、shopt の huponexit で決まります。

まとめ

実行中のプロセスは Ctrl+Z で一時停止してバックグラウンドのジョブにでき、jobs で確認し、fg でフォアグラウンドに、bg でバックグラウンドの実行中に戻せます。コマンドの末尾に & を付けると、最初からバックグラウンドで起動できます。シェルを終了すると停止中のジョブも終了するので、ログアウトの前に jobs で確認します。

操作・コマンド動作
Ctrl+Zフォアグラウンドのプロセスを一時停止して、シェルに戻る
jobsジョブの一覧を表示する(-l でプロセス ID も表示)
fg 番号ジョブをフォアグラウンドで再開する
bg 番号停止中のジョブをバックグラウンドで再開する
コマンド &コマンドをバックグラウンドで起動する
disownジョブをジョブ一覧から外す(-h は SIGHUP を送らない印を付ける)

コメント