ジョブ制御入門 - jobs/fg/bg/Ctrl+Z
この記事でできるようになること
- `Ctrl+Z` で実行中のコマンドを止めて、端末を取り戻せる
- `fg` と `bg` でフォアグラウンドとバックグラウンドを行き来できる
- `jobs` と `%番号` で複数のジョブを見分けて操作できる
前提知識(先に読むと理解しやすい記事)
この記事でできるようになること
Ctrl+Zで実行中のコマンドを 一時停止 して、端末を取り戻せるbg/fgで バックグラウンドとフォアグラウンド を自由に行き来できるjobsで ジョブの一覧 を確認し、%番号で 1 つずつ指定できる&を末尾に付けて 最初からバックグラウンドで実行 できる- 「端末が固まった」「終了したのにジョブが消えない」といった 詰まりどころ を抜けられる
対象読者: vim や長いコマンドの実行中に「ちょっとだけ別のコマンドを打ちたい」と思って詰まった方。Ctrl+C で全部止めてしまって悔しい思いをした方。
導入:リナが Ctrl+C で泣いた日
vim で長い設定ファイルを編集していました。途中で ls も打ちたくなったんです。でも新しいターミナル入力したコマンドを解釈してコンピュータに実行させる対話プログラム。の開き方が分からなくて、つい Ctrl+C を押しました。Ctrl+Z(コントロール ゼット)だ。Ctrl+C は「実行中のコマンドを 止めて終わらせる」。Ctrl+Z は「実行中のコマンドを 一時停止して脇に置く」だけなんだ。fg で元の作業に戻れるよ。Ctrl+Z(一時停止)/ bg(裏で再開)/ fg(前に戻す)/ jobs(一覧) だね。結論(実務の型)
- 端末を取り戻したいだけ →
Ctrl+Z→bg(裏で動かしたまま端末を解放) - 一時停止してそのまま放置 →
Ctrl+Zだけ(停止状態) - 元の作業に戻る →
fg - 何が動いているか分からなくなったら →
jobs
先に覚える「固まったように見えるとき」の抜け方
ジョブ制御では、画面が止まったように見える場面がある。次の表の順で試せば必ず抜けられる。
| 見えている状態 | 抜け方 |
|---|---|
| コマンドが動いたままプロンプトコマンドの入力を待っている状態を示す記号(例 $ や #)。が出ない | Ctrl+Z で一時停止する(プロンプトが戻る) |
Ctrl+Z の直後で何をすべきか不明 |
fg で元に戻すか、bg で裏に回す。どちらも取り消せる |
| 何が止まっているか分からない | jobs で一覧を見る。fg %1 のように番号で選ぶ |
| どうしても終わらせたい | jobs で番号を確認してから kill %1(% を必ず付ける) |
Ctrl+Z は終了ではない。押しても作業内容は消えないので、安心して試してほしい。
端末(ターミナル)とは
端末は「文字を打ち込んで、結果を文字で受け取る窓口」のこと。「ターミナル」「コンソール」も、ほぼ同じものを指す別の呼び方だよ。
この記事でいう「端末が戻る」は「$ の入力待ちに戻り、次のコマンドを打てる状態になる」という意味。その $ の記号をプロンプトと呼ぶ。
前提(対象環境)
- bash / zsh(ジョブ制御は POSIX シェルの標準機能。
dashにもjobs/fg/bgはある) - 非対話シェル(
sh -c '...'やシェルスクリプトの中)ではデフォルトで無効 - 本記事のキー操作は端末上の 対話的セッション が前提
1. 「ジョブ」と「プロセス」は何が違う?
結論: プロセスは OS 目線で動くプログラム単位。ジョブはシェル目線で打ったコマンド 1 単位。指定は
%番号。
ls | grep .txt | sort を打つとする。プロセスは 3 つ作られる。でもシェルから見れば ジョブは 1 つ なんだ。Ctrl+Z を押すと、シェルはジョブ単位でまとめて一時停止してくれるよ。フォアグラウンドとバックグラウンド
- フォアグラウンド(前面、foreground): あなたのキー入力を受け取る側。実行中は端末が返ってこない
- バックグラウンド(裏、background): 画面の裏で動く側。端末はあなたが自由に使える
レジに並ぶ列に例えると分かりやすい。フォアグラウンドは「今レジの前にいる人」。バックグラウンドは「番号札を持って別の場所で待っている人」だよ。
ジョブ番号と PID の違い
| 種類 | 例 | 付与する人 | 用途 |
|---|---|---|---|
| ジョブ番号 | %1 |
シェル | fg %1 / kill %1 等で指定 |
| PID | 12345 |
カーネルOS の中核となるプログラム。ハードウェアとソフトウェアの橋渡しをする。 | kill 12345 / ps の出力 |
覚え方: ジョブ番号には先頭に % を付ける。fg 1 ではなく fg %1。kill 1 ではなく kill %1。
kill 1 は「ジョブ 1 番」ではなく「PID 1 番のプロセス」への命令になる。PID 1 は systemd(システム全体の親玉)。一般ユーザーなら「Operation not permitted」で弾かれる。いずれにせよ、あなたが止めたかったジョブは止まらない。
2. Ctrl+Z:今すぐ一時停止する
結論:
Ctrl+Zは実行中のジョブを終わらせず、一時停止する。端末がすぐ手元に戻り、別のコマンドを打てる。
vim でも tail -f でも何でもいい。1 つコマンドを起動して、動いている状態で Ctrl+Z を押してみよう。fg で解凍すれば、何事もなく動き出すよ。試してみる
$ sleep 100
sleep 100 は 100 秒間なにもせずに待つコマンド。この 100 秒間、端末はふさがったままになる。
ここで Ctrl+Z を押す。
^Z [1]+ Stopped sleep 100 $
[1]+ Stopped が出れば成功。$ プロンプトが戻っていることに注目しよう。端末が手元に戻った。
[1]+ の意味
[1]= ジョブ番号 1 番+= 直近に操作したジョブ(fg/bgを番号なしで打つと、これが対象になる)Stopped= 停止中(CPU を使っていない)
この状態で別コマンドを打てる
$ ls $ pwd $ echo "別のことができる"
sleep は冷凍庫の中で止まったまま。その間に自由に他のコマンドを実行できる。これが Ctrl+Z の威力。
3. fg:呼び戻す / bg:裏で再開する
結論: 停止したジョブは
fgで前面に呼び戻す。bgなら停止したまま裏で再開する。vim はfgの往復が基本。
fg(foreground の略)は「前面に呼び戻して再開」。bg(background の略)は「裏で再開」だよ。fg。あなたが別の作業を続けるなら bg だね。fg:フォアグラウンドへ戻す
さっきの sleep 100 を戻してみる。
$ fg
sleep 100
sleep の続きが始まる。端末は再びふさがる。残り時間を待ってもいい。もう一度 Ctrl+Z で止めてもいい。
bg:バックグラウンドで再開
「裏で動かしながら端末は使い続けたい」なら bg を使う。
$ sleep 100 ^Z [1]+ Stopped sleep 100 $ bg [1]+ sleep 100 & $
表示が Stopped から &(バックグラウンドで実行中)に変わった。sleep は裏で時計を進める。あなたは他の作業ができる。
bg できないコマンドもある: vim のような画面全体を使う対話アプリは、裏でキー入力を待てない。そのため bg すると停止状態に戻ってしまう(Stopped (tty input))。vim は Ctrl+Z で停止 → 用が済んだら fg の往復で使うこと。
4. & を末尾に付ける:最初からバックグラウンド
結論: コマンドの末尾に
&を付ければ最初から裏で実行できる。出力は> file 2>&1で逃がすのが定石。
& を付けて起動 すると早いよ。Ctrl+Z → bg の 2 ステップを、1 ステップで済ませるってことですか?Ctrl+Z → bg は「実行してから気が変わって裏に回す」。& は「最初から裏で動かす」という違いだけだね。& の使い方
$ sleep 100 & [1] 12345 $
[1] がジョブ番号。12345 が PID。すぐにプロンプトが戻る。
$ jobs [1]+ Running sleep 100 &
Running 状態。止まらずに動いている。
よく使う実例:ログ収集を裏で
$ tail -f /var/log/syslog > mylog.txt & [1] 23456 $ # この間に別の作業 $ vim config.txt
tail -f を裏で動かしながら、vim で設定を編集できる。こうした並行作業がやりやすくなる。
& だけだと出力が混ざる: 標準出力(コマンドが出す普通の結果)は、リダイレクトしなければ そのまま端末に流れる。標準エラー出力(コマンドが出すエラーの文言)も同じ。あなたが別のコマンドを打っている最中に、突然その出力が割り込んでくる。長時間動かすなら > file 2>&1 でファイルへ逃がすこと。
5. jobs:今動いてるものを全部見る
結論:
jobsで現在のシェルが管理する全ジョブを一覧表示できる。個別指定は%番号で、%を必ず付ける。
jobs 一発。今のシェルが管理しているジョブを、全部一覧で出してくれるよ。基本:jobs
$ sleep 100 & [1] 12345 $ sleep 200 & [2] 12346 $ vim notes.txt # Ctrl+Z で停止 $ jobs [1] Running sleep 100 & [2]- Running sleep 200 & [3]+ Stopped vim notes.txt
3 つのジョブが見える。
+= 直近に操作したジョブ(番号なしのfg/bgの対象 =vim)-= その 1 つ前のジョブ(=sleep 200)
ジョブを個別に指定:%番号
$ fg %1 # sleep 100 を前面に $ bg %3 # vim を裏に(停止状態のまま) $ kill %2 # sleep 200 を終了
kill の前に確かめること
kill は GUI の「ウィンドウを閉じる」と違い、保存するか聞いてくれない。編集中のファイルがあると、保存していない内容はそのまま消える。
- 先に
jobsで「本当にそのジョブでよいか」を確かめる - エディタなど作業中のジョブは、
killではなくfgで戻して自分で保存してから終わらせる - 練習は
sleepを相手にする。sleepには消えて困る中身が無いので、安心して試せる
% プレフィックスを忘れない
kill 1 は PID 1(systemd)へのコマンド になる。一般ユーザーなら権限不足で弾かれる。rootすべての操作が許可された特別な管理者ユーザー。 で実行しても systemd が設定を読み直す動きに入るだけで、狙ったジョブは止まらない。「ジョブを指定するときは必ず %」を体に覚えさせよう。
jobs の便利オプション
| オプション | 効果 |
|---|---|
jobs -l |
PID も併せて表示 |
jobs -p |
PID だけを表示(スクリプト用) |
jobs -r |
実行中ジョブだけ |
jobs -s |
停止中ジョブだけ |
6. ターミナルを閉じたらジョブはどうなる?
結論: 既定では SIGHUP でジョブは終了する。生き残らせるには
nohup/disown。より確実なのはtmux。
nohup や disown だよ。もっと根本的に解決したいなら tmux だね。nohup:起動時に SIGHUP を無視させる
$ nohup ./long_script.sh > output.log 2>&1 & [1] 34567
nohup を付けて起動すると、シェル終了時の SIGHUP を無視する。ログアウトしてもジョブは生き残る。
disown:起動後に「シェルの管理下から外す」
$ ./long_script.sh & [1] 45678 $ disown %1 $ exit # ターミナルの窓を閉じても %1 は生き続ける
「& で動かし始めたあとに、長時間処理へ切り替えたくなった」場合は disown で対応できる。
より確実なのは tmux
nohup / disown は「ターミナル切断時にジョブが終了しないようにする」だけ。一方 tmux は「画面ごとサーバ側に保存しておく」。だから後から tmux attach でその画面に戻り、続きを見られる。長い処理を流して後でログを見たいなら tmux が向いている。→ tmux 入門
7. つまずきポイント集
結論: Ctrl+C と Ctrl+Z の混同、
kill 1事故、出力の乱入、vim の bg 失敗が代表的な落とし穴。
ピンチ 1: Ctrl+C と Ctrl+Z を取り違える
症状: 一時停止のつもりだったのに、ジョブが消えた。
原因: Ctrl+C(SIGINT で終了)と Ctrl+Z(SIGTSTP で一時停止)を混同した。
対処: 「C = Cancel(中止)、Z = Z 字に寝かせる(停止)」と覚える。Ctrl+Z は終了ではない。vim やエディタで押しても作業内容は保たれる。
ピンチ 2: kill %1 を kill 1 と打って怖い思いをする
症状: kill 1 を実行して「Operation not permitted」と言われた。止めたかったジョブは動いたままだった。
原因: ジョブ番号と PID を取り違えて、% を忘れた。kill 1 は PID 1(systemd)へシグナルを送る命令になる。
対処: ジョブ指定には必ず % を付ける。不安なら先に jobs -l で PID を確認する。kill %%(最後にアクセスしたジョブ)を使う手もある。
ピンチ 3: バックグラウンドジョブの出力が画面に乱入
症状: & で動かしたコマンドの出力が、他のコマンドを入力している最中に割り込んでくる。
原因: バックグラウンドでも、標準出力と標準エラー出力は既定で端末に流れる。
対処: > file 2>&1 & でファイルへ逃がす。捨ててよいなら > /dev/null 2>&1 & にする。
ピンチ 4: vim を bg したら止まったまま動かない
症状: vim を Ctrl+Z → bg した。しかし jobs で見ると Stopped (tty input) のまま動かない。
原因: vim は端末の入力を待つアプリ。バックグラウンドは端末から切り離された状態なので、キー入力を受け取れない。そのためシェルが自動的に停止状態へ戻す。
対処: vim や top のような対話的アプリは Ctrl+Z で停止 → 用が済んだら fg の往復だけで使う。bg には回さない。
8. 実用テンプレ:ジョブ制御の事故らない型
結論: vim の往復は
Ctrl+Z → 別作業 → fg。長い処理は& + > file 2>&1。ログアウトを跨ぐなら nohup / disown / tmux。
コピペ用:vim 編集中に別コマンドを打つ型
# 1. vim で編集中 $ vim config.txt # Ctrl+Z で一時停止 # 2. 端末が戻ってきたので別作業 $ ls /etc/ $ grep "error" /var/log/syslog # 3. vim に戻る $ fg
vim を閉じずに往復するのが要点。「Ctrl+Z → 別作業 → fg」のリズムを覚えよう。
コピペ用:長い処理を裏で動かす型
# 出力をファイルへ逃がしながら裏で実行 $ ./long_script.sh > output.log 2>&1 & [1] 12345 # 経過を確認 $ jobs $ tail -f output.log # 終了させたい場合 $ kill %1
> output.log 2>&1 を忘れると画面が荒れる。この 2 つはセットで覚える。
コピペ用:ログアウト後も継続させる型
# 起動時から nohup で $ nohup ./long_script.sh > output.log 2>&1 & [1] 12345 # あるいは起動後に disown $ ./long_script.sh > output.log 2>&1 & [1] 12345 $ disown %1 # tmux で画面ごと持ち越すのがより確実(推奨) $ tmux $ ./long_script.sh # Ctrl+b → d でデタッチ、後で tmux attach で復帰
ミニ課題で手を動かそう
結論: Ctrl+Z と fg の往復、3 ジョブの並行制御、出力をファイルへ逃がす実行の 3 課題で操作を定着させる。
この課題を試す場所: ジョブ制御はシェルの機能なので、本サイトの仮想ターミナルでは動かない。手元の Linux、WSL、macOS のターミナルで実行しよう。題材は sleep なので、失敗してもファイルは壊れない。
課題 1: Ctrl+Z → fg の往復
やること: sleep 30 を実行しよう。途中で一時停止して別のコマンドを打ち、そのあと元に戻そう。
ヒント1(方向づけ)を見る
「終了」ではなく「一時停止」のキーを使う。止めたあとは、一覧で状態を確かめてから元に戻そう。
ヒント2(コマンド名)を見る
一時停止は Ctrl+Z。状態の確認は jobs。元に戻すのは fg。
答えを見る
$ sleep 30 # 5 秒経ったところで Ctrl+Z で一時停止 $ jobs # → [1]+ Stopped sleep 30 を確認 $ ls # 別コマンドを打ってみる $ fg # sleep に戻って残り時間を待つ
課題 2: 3 つのジョブを並行で動かす
やること: 3 つのコマンドを最初から裏で動かそう。そのうち真ん中の 1 つだけを終了させよう。
ヒント1(方向づけ)を見る
最初から裏で動かす書き方がある。終了させるときは、ジョブの一覧で番号を確かめてから指定しよう。
ヒント2(コマンド名)を見る
裏で動かすのは末尾の &。一覧は jobs。終了は kill %2 のように % を付けて指定する。
答えを見る
$ sleep 100 & $ sleep 200 & $ sleep 300 & $ jobs # → [1] [2] [3] の 3 つが見えるはず $ kill %2 # 真ん中だけ終了 $ jobs # → [2] が消えていることを確認
課題 3: 出力をファイルへ逃がしながら裏で実行
やること: 出力のあるコマンドを裏で動かそう。他のコマンドの出力と混ざらないよう、結果をファイルへためよう。
ヒント1(方向づけ)を見る
裏で動かすだけでは、出力が画面に割り込んでくる。出力の行き先をファイルへ変える書き方を思い出そう。
ヒント2(コマンド名)を見る
行き先の変更は > ファイル名 2>&1。裏で動かすのは末尾の &。ためた内容は cat で見られる。
答えを見る
$ ls -R / > result.log 2>&1 & [1] 12345 $ jobs # Running を確認 $ tail result.log # ファイルへ出力が溜まっていく # ジョブが終わったら自動的に # [1]+ Done ls -R / > result.log 2>&1 # と通知される
2>&1 を付けているので、権限が無くて読めないディレクトリファイルをまとめて整理する入れ物。Windows や macOS の「フォルダ」と同じもの。のエラーもファイル側へ流れる。画面には出てこない。
Ctrl+Z の安心感、半端ないですね…これさえ知っていれば、vim を Ctrl+C で殺す事故は二度と起きません。今日の 3 行まとめ
Ctrl+Zで一時停止して端末を解放、戻るときはfg、裏で動かすならbg。これだけで vim をCtrl+Cで殺す事故が消える- ジョブ指定には必ず
%(kill %1とkill 1は別物)。PID と取り違えると init を終了させかねない - 長い処理を裏で動かすなら
& + > file 2>&1を癖にする。ログアウトを跨ぐならnohup/disown/tmuxを選ぶ