実行中のジョブの一覧を確認するにはjobsコマンドを利用する。
user01@ubuntu1:~$ sleep 10 & ……sleepをバックグラウンドで実行させる
[1] 6807
user01@ubuntu1:~$ jobs ……ジョブの一覧を確認する
[1]+ 実行中 sleep 10 &
user01@ubuntu1:~$ jobs -l ……プロセスIDも表示させる
[1]+ 6807 実行中 sleep 10 &
user01@ubuntu1:~$
[1]+ 終了 sleep 10
user01@ubuntu1:~$ jobs ……ジョブを再確認する
user01@ubuntu1:~$ ……何もない
実行中のフォアグラウンドプロセスを一時中断する(サスペンドする)には、[Ctrl]+[Z]キーを押す。
user01@ubuntu1:~$ vi hello.c ……エディタを起動する
[1]+ 停止 vi hello.c ……編集中に[Ctrl]+[Z]で一時停止してみたところ。エディタを終了してしまうと、また開き直すのが面倒なので、一時停止を利用する
user01@ubuntu1:~$ man stdio ……マニュアルを参照する
[2]+ 停止 man stdio ……これも[Ctrl]+[Z]で一時停止させてみたことろ
user01@ubuntu1:~$ jobs ……ジョブの確認
[1]- 停止 vi hello.c ……ジョブが2つ停止状態になっている
[2]+ 停止 man stdio
user01@ubuntu1:~$
停止中、もしくはバックグラウンドで実行中のジョブをフォアグラウンドで実行させるには、「fg <ジョブ指定子>」コマンドを実行する(単に「<ジョブ指定子>」だけ入力して[Enter]キーを押してもよい)。
<ジョブ指定子>とは、対象となるジョブを指定するための表記のことであり、次のような書式で指定する。
書式 | 意味 |
---|---|
(なし) | 省略するとカレントジョブ「%%」を指定したことになる |
%数字 | 指定した番号のジョブ |
%% | カレントジョブ。ジョブ番号に「+」記号付きで表示されているジョブ |
%+ | カレントジョブ(同上) |
% | カレントジョブ(同上) |
%- | 直前のジョブ(カレントジョブの1つ前にアクティブだったジョブ)。ジョブ番号に「-」記号付きで表示されているジョブ |
%文字列 | ジョブ名の先頭が「文字列」で始まるジョブ。複数マッチする場合はエラー |
%?文字列 | ジョブ名の途中に「文字列」を含むジョブ。複数マッチする場合はエラー |
ジョブ指定子(job_spec)の書式 |
引数なしで単に「fg」とだけ入力すると、カレントジョブがフォアグラウンドで実行される。
停止中のジョブをバックグラウンドで実行再開させるには、「<ジョブ指定子> &」とするか、「bg <ジョブ指定子>」コマンドを実行する。単に「bg」だけ入力すると、カレントジョブがバックグラウンドで実行される。
最後にフォアグラウンドで動作していたジョブ(もしくは & 付きでバックグラウンド実行させたジョブ)を「カレントジョブ」と言う。fgやbgコマンドで<ジョブ指定子>を省略した場合、もしくは「%%」を指定した場合は、このカレントジョブが対象となる。
「%-」を指定すると、カレントジョブの1つ前のジョブ(以前のカレントジョブ)が対象となる。
どれがカレントジョブで、どれがその1つ前のジョブかは、jobsコマンドのジョブ番号欄を見ると分かる。[+]が付いているのがカレントジョブ、[-]が付いているのがその1つ前のジョブである。
user01@ubuntu1:~$ sleep 100 ……新しいジョブ
^Z ……一時停止させる
[5]+ 停止 sleep 100
user01@ubuntu1:~$ jobs ……ジョブ一覧の確認
[1] 停止 vi hello.c
[3] 停止 man gcc
[4]- 停止 less /etc/hosts ……1つ前のカレントジョブ
[5]+ 停止 sleep 100 ……カレントジョブ。「%%」や「%+」で参照できる
user01@ubuntu1:~$ %- ……最後に停止したジョブの、さらに1つ前のジョブを起動するにはこれを使う
less /etc/hosts
[4]+ 停止 less /etc/hosts ……一時停止させてみる
user01@ubuntu1:~$ jobs ……ジョブ一覧の確認
[1] 停止 vi hello.c
[3] 停止 man gcc
[4]+ 停止 less /etc/hosts ……今度はこれがカレントジョブになっている
[5]- 停止 sleep 100 ……カレントジョブのさらに1つ前のジョブ
user01@ubuntu1:~$ %vi ……「vi」で始まるジョブを実行する
vi hello.c
[1]+ 停止 vi hello.c
user01@ubuntu1:~$ %5 ……番号指定で起動してみる
sleep 100
user01@ubuntu1:~$
例えば2つのコマンドを交互に切り替えて実行したい場合は(例:エディタとmanコマンドなど)、[Ctrl]+[Z]で停止、「%-」で直前のコマンドを起動、というサイクルを繰り返せば簡単である。
デフォルトでは、bashはバックグラウンドジョブが入力待ちなどで停止したり、終了したりしても、ユーザーにすぐに通知することはない。ユーザーが[Enter]キーを押したときに、ジョブの変化があれば停止や終了の通知をするようになっている。
これを変更して、状態に変化があればすぐに通知(表示)させることもできる。このためには、bashで「set -o notify」か「set -b 」を実行する。
user01@ubuntu1:~$ set -o notify ……即時通知を有効にする
user01@ubuntu1:~$ sleep 10 & ……バックグラウンドで10秒スリープさせる
[3] 7070
user01@ubuntu1:~$ [3] 終了 sleep 10 ……終了すると、すぐに表示された([Enter]キーなどを押す必要はない)
元に戻すのは「set +o notify」か「set +b」である。
以上の他にもいくつかジョブコントロール関連のコマンドがあるので、簡単に補足しておく。
プロセスを強制終了させたり、シグナル(通知)を送信したりする場合、UNIX/Linuxではkillコマンドを利用する。このときにプロセスIDだけでなく、ジョブ指定子を指定してもよい(これを実現するために、killはbashの内部組み込みコマンドとして実装されている。外部コマンドの/bin/killでは、%%が何を指すのか判断できない)。例えば「kill %%」とすればカレントジョブがkillの対象となる。
suspendはbashシェル自体をサスペンド(一時停止)するためのコマンドである。他のシェルから(もしくはbashから)ネストして起動されたbashの場合、suspendを実行すると、いったん実行を中断して、元のシェルへ戻ることができる。ただしログインシェルの場合はサスペンドできない(戻るべき親シェルがないため)。
waitにジョブ指定子を付けて実行すると、指定されたジョブが終了するのを待つ。
引数なしでwaitを実行すると、現在実行中のジョブがすべて完了するのを待つ。「wait -n」とすると、どれか1つのジョブが終了するのを待つ。
disownにジョブ指定子を付けて実行すると、指定されたジョブがbashのジョブ(jobs)の一覧から外され、ジョブコントロールの対象外となる。プロセスとしてはそのまま存在しているので、psコマンドなどでは確認できるが、bashの管理対象外となる。
ユーザーはシステムからログアウトするけれども、いったん起動したプログラムをそのままずっと継続して実行させておきたい、というような場合に利用できる。disownを使わないと、自分が起動したジョブはログアウト時にすべて終了させられてしまう。
なお、これに似たコマンドとしてnohupというコマンドもある。disownは、既に起動したジョブ(プロセス)をログアウトしても終了しないようにするコマンドだ。一方、nohupはこれから起動するプログラムに対して、ログオフしても終了しないようにするためのものである。nohupには起動するコマンド名や引数などを与えて実行する(詳細は「man nohup」コマンド参照)。
今回はbashの持つジョブコントロール機能についてまとめてみた。Windows OSの場合は(そしてGUIでLinuxなどを使っている場合は)、ジョブコントロール機能など使わなくても、必要なら複数のコマンドウィンドウを開いて、同時に複数のウィンドウ上で作業すれば済むことかもしれない。だが管理用コンソール画面が1つしか使えないようなケースでは(ssh接続してシステムを管理している場合など)、たった1つの端末画面でも簡単にジョブを切り替える方法を知っていれば便利に使えるだろう。ぜひ覚えておいていただきたい。
Copyright© Digital Advantage Corp. All Rights Reserved.