こんにちは、かつコーチです。
ターミナルで長時間かかる処理を実行しているとき、「別の作業もしたいのにターミナルが占有されて困る」という経験はありませんか。
この記事では、Ubuntu 26.04 LTSでの実例を交えながら、ジョブ管理(fg・bg)と、プロセスを終了させるシグナル・killコマンドの基本を解説します。
ジョブ管理・シグナルとは?
ジョブの定義:シェルが管理する処理の単位
ジョブとは、シェル(ターミナルの操作を受け付けるプログラム)が管理する、実行中または一時停止中の処理の単位です。
1つのターミナルの中で複数のコマンドを実行し、それぞれをフォアグラウンド(操作中の状態)・バックグラウンド(裏で動かす状態)に切り替えながら管理できます。
シグナルの定義:プロセスに送る制御用の合図
シグナルとは、OSからプロセスに対して送られる、動作を制御するための合図です。
「終了してほしい」「一時停止してほしい」といった指示を、シグナルという形でプロセスに伝えます。
なぜジョブ管理・シグナルの知識が必要なのか
サーバー運用やスクリプト実行の場面では、以下のような理由でこれらの知識が役立ちます。
- 時間のかかるバッチ処理をバックグラウンドに回し、同じターミナルで別の作業を並行して行う
- 応答しなくなったプロセスを、適切な方法で安全に終了させる
- Ctrl+Cで処理を止めるときに、実際は何が起きているのかを理解する
killという名前から「強制的に殺すコマンド」というイメージを持たれがちですが、実際にはさまざまな種類のシグナルを送るための汎用コマンドです。
基本の書き方:fg・bg・killの使い方
手順1:Ctrl+Zでジョブを一時停止し、bgでバックグラウンドに回す
実行中のコマンドを一時停止するにはCtrl+Zを押します。
$ tar czf backup.tar.gz /var/www
^Z
[1]+ Stopped tar czf backup.tar.gz /var/www
一時停止した状態のジョブを、そのままバックグラウンドで再開させるにはbgコマンドを使います。
$ bg
[1]+ tar czf backup.tar.gz /var/www &
これでtarコマンドはバックグラウンドで動き続け、同じターミナルで別のコマンドを入力できるようになります。
手順2:jobsで実行中のジョブ一覧を確認する
複数のジョブを扱っているときは、jobsコマンドで一覧を確認できます。
$ jobs
[1]+ Running tar czf backup.tar.gz /var/www &
[2]- Stopped vim memo.txt
[1]のような番号がジョブ番号で、後述するfg・bgで操作するときに使います。
手順3:fgでバックグラウンドのジョブをフォアグラウンドに戻す
バックグラウンドのジョブを再びフォアグラウンド(操作対象)に戻すにはfgコマンドを使います。
$ fg %1
tar czf backup.tar.gz /var/www
%1はジョブ番号1を指定する書き方です。
ジョブ番号を省略すると、直近のジョブが対象になります。
手順4:killでシグナルを送る
プロセスにシグナルを送るにはkillコマンドを使います。
$ kill 3301
これは、PID3301のプロセスに対してSIGTERM(デフォルトのシグナル、正常終了の依頼)を送っています。
より強制的に終了させたい場合は-9(SIGKILL)を指定します。
$ kill -9 3301
代表的なシグナルは以下の通りです。
| シグナル名 | 番号 | 意味 |
|---|---|---|
| SIGHUP | 1 | 設定の再読み込みなど(プロセスによって解釈が異なる) |
| SIGINT | 2 | 割り込み(Ctrl+Cと同じ) |
| SIGTERM | 15 | 正常終了の依頼(デフォルト) |
| SIGKILL | 9 | 強制終了(プロセス側で無視できない) |
つまずきやすい設定・注意点
ジョブ番号(%1など)とPID(3301など)は別物です。fg・bgはジョブ番号、killはPIDを使うのが基本ですが、kill %1のようにジョブ番号を指定することもできます。
どちらを指定しているか混同しないよう注意しましょう。
よくあるつまずきポイント・エラー対処
kill -9を最初から使ってしまう
私が駆け出しの頃、応答しないプロセスに遭遇するたびに、いきなりkill -9を使う癖がついていました。
❌Before:応答しないプロセスに対して、最初からkill -9で強制終了する
$ kill -9 4102
SIGKILLはOSレベルで強制的にプロセスを止めるシグナルで、プロセス側は後処理(一時ファイルの削除、データベース接続のクローズなど)を一切行えません。
あるとき、書き込み中のログファイルを扱っていたプロセスをSIGKILLで止めてしまい、ログファイルが中途半端な状態で壊れてしまったことがありました。
✅After:まずSIGTERM(デフォルトのkill)で正常終了を依頼し、それでも終了しない場合だけSIGKILLを使う
$ kill 4102
$ ps -p 4102
$ kill -9 4102
kill(オプションなし)でSIGTERMを送り、数秒待ってpsでまだ存在するか確認します。
それでも終了しない場合に初めてSIGKILLを使う、という段階を踏むことで、後処理を行う機会をプロセスに与えられます。
バックグラウンドに回したはずのジョブがターミナルを閉じたら消えた
もう1つの実体験として、bgでバックグラウンドに回した処理が、SSH接続を切った瞬間に止まってしまったことがあります。
❌Before:bgにすれば安全だと思い込み、そのままSSHセッションを切断する
✅After:ログアウトしても実行を継続させたい場合は、SIGHUPを無視させるnohupや、screen・tmuxのような専用ツールを使う
$ nohup tar czf backup.tar.gz /var/www > backup.log 2>&1 &
SSH接続が切れると、シェルは実行中のジョブにSIGHUP(ハングアップシグナル)を送ることがあり、これによってbgにしただけのジョブも終了してしまう場合があります。nohupはこのSIGHUPを無視するようプロセスに指示するコマンドで、ログアウト後も処理を継続させたいバッチ処理では定番の組み合わせです。
より対話的に作業を続けたい場合は、screenやtmuxのような、セッションそのものを維持できるツールを使う選択肢もあります。
応用・一歩先の使い方
disownでジョブをシェルの管理下から切り離す
すでにバックグラウンドで動いているジョブを、あとからnohup相当の状態にしたい場合はdisownコマンドが使えます。
$ tar czf backup.tar.gz /var/www &
$ disown %1
disownは該当ジョブをシェルの管理対象から外し、シェル終了時にSIGHUPが送られないようにします。
killallとpkillで名前を指定して終了させる
PIDを毎回調べるのが面倒な場合、プロセス名で指定できるkillall・pkillも便利です。
$ killall nginx
$ pkill -f "php artisan queue:work"
ただし名前で一致する複数のプロセスをまとめて終了させてしまうため、意図しないプロセスまで巻き込まないよう、対象範囲を事前にps aux | grepなどで確認してから実行することをおすすめします。
まとめ
この記事のポイント
- ジョブはシェルが管理する処理の単位で、
Ctrl+Zで一時停止、bgでバックグラウンド化、fgでフォアグラウンドに戻せる - シグナルはプロセスへの制御用の合図で、
killコマンドで送信する - SIGTERM(デフォルト)は正常終了の依頼、SIGKILL(
-9)は強制終了で後処理ができない - 終了処理はまずSIGTERM、応答がなければSIGKILLという順番で行うのが安全
- ログアウト後も処理を継続させたい場合は
nohupやdisown、screen・tmuxを活用する
次に読むべき記事
プロセスを手動で管理する方法を学んだら、次はOS起動時からサービスを自動管理する仕組みである「systemdの基本:サービスを管理する仕組み」に進んでみてください。killで行っていた操作を、systemdがどう体系化しているかが見えてきます。
タグ: Linux, 中級者向け, プロセス管理