= ジョブ制御
:encoding: UTF-8
:lang: ja
//:title: Yash マニュアル - ジョブ制御
:description: Yash のジョブ制御の動作について

dfn:[ジョブ制御]とは、複数のコマンドを同時に実行し、必要に応じてそれらを中断・再開させる機能です。シェルは、オペレーティングシステムが提供する端末の機能やプロセスグループ管理機構などを用いて、ジョブ制御を実現します。

ジョブ制御が有効な時……

- シェルが起動する各プロセスは、{zwsp}link:syntax.html#pipelines[パイプライン]ごとに共通の一意なプロセスグループに属します。すなわち、シェルが起動するコマンドはそれぞれパイプラインごとにdfn:[ジョブ]として扱われます。
- シェルがジョブを起動しそのジョブのプロセスが終了するのを待っている間にそのプロセスが停止した場合、シェルは (プロセスが実際に終了したときと同様に) 次のコマンドの処理に移ります。このときシェルはジョブが停止したことを覚えているので、後でジョブを再開させることができます。
- ジョブが{zwsp}link:syntax.html#async[同期的]に実行される場合、そのジョブの実行中はそのジョブのプロセスグループが端末のフォアグラウンドプロセスグループになります。ジョブの実行が終了 (または停止) すると、再びシェルがフォアグラウンドになります。
- シェルが{zwsp}link:interact.html[対話モード]の場合、プロンプトを出す前に毎回コマンド +link:_jobs.html[jobs] -n+ を実行するのと同様にしてジョブの状態変化を報告します。
- link:syntax.html#async[非同期コマンド]の標準入力が自動的に /dev/null にリダイレクトされません。
- SIGTTIN, SIGTTOU, SIGTSTP シグナルを受けても、シェルは停止しません。
- link:params.html#sp-hyphen[特殊パラメータ +-+] の値に +m+ が含まれます。
- link:_wait.html[Wait 組込みコマンド]で待っているジョブが終了したとき、そのことを示すメッセージを出力します。(link:interact.html[対話モード]の時のみ。{zwsp}link:posix.html[POSIX 準拠モード]を除く)

ジョブ制御が無効な時、シェルが起動する各プロセスはシェルと同じプロセスグループに属しますが、実行した{zwsp}link:syntax.html#async[非同期コマンド]はそれぞれジョブ制御の対象となっていないジョブとして扱います。

ここでジョブ制御に関連する組込みコマンドを簡単に紹介します。

link:_jobs.html[jobs]::
現在シェルが管理しているジョブを表示します。
link:_fg.html[fg] および link:_bg.html[bg]::
ジョブをフォアグラウンドまたはバックグラウンドで実行します。主に停止したジョブを再開させるのに使います。
link:_wait.html[wait]::
ジョブが終了 (または停止) するまで待ちます。
link:_disown.html[disown]::
ジョブの存在を忘れます。
link:_kill.html[kill]::
プロセスにシグナルを送ります。

対話モードでジョブ制御が有効な時、シェルはプロンプトを出す直前にジョブの状態変化を報告します。これ以外のタイミングで状態変化を報告してほしい場合は、以下の{zwsp}link:_set.html#options[オプション]を指定することができます。

link:_set.html#so-notify[notify]::
タイミングにかかわらず、ジョブの状態が変化したら直ちにそれを報告します。
link:_set.html#so-notifyle[notify-le]::
link:lineedit.html[行編集]を行っている最中にジョブの状態が変化したら直ちにそれを報告します。

シェルが管理しているジョブは以下のタイミングで削除されます。

- ジョブの実行が終了した後、そのことを link:_jobs.html[jobs 組込みコマンド]で表示したとき
- link:_wait.html[Wait 組込みコマンド]でジョブの終了を待ったとき
- link:_disown.html[Disown 組込みコマンド]でジョブを削除したとき

対話シェルが自動的にジョブの状態変化を報告するときにはジョブは削除されません。

[[jobid]]
== ジョブ ID

いくつかの{zwsp}link:builtin.html[組込みコマンド]では、操作対象のジョブを指定するためにdfn:[ジョブ ID] という以下のような記法を用います。

+%+::
+%%+::
+%&#43;+::
現在のジョブ
+%-+::
前のジョブ
+%{{n}}+::
ジョブ番号が {{n}} のジョブ ({{n}} は自然数)
+%{{文字列}}+::
ジョブ名が{{文字列}}で始まるジョブ
+%?{{文字列}}+::
ジョブ名が{{文字列}}を含むジョブ

dfn:[現在のジョブ]及びdfn:[前のジョブ]とは、シェルが特定の方法で選んだジョブのことで、{zwsp}link:_fg.html[fg 組込みコマンド]などでジョブを選択しやすくするために用意されています。現在のジョブと前のジョブは以下の規則を満たすように選ばれます。

- 停止中のジョブがある場合は、現在のジョブはその中から選ばれます。
- 現在のジョブ以外に停止中のジョブがある場合は、前のジョブはその中から選ばれます。
- 現在のジョブと前のジョブは異なるジョブになるように選ばれます。ジョブが一つしかないときはそれが現在のジョブになり、前のジョブはなくなります。
- 現在のジョブが終了したときは、前のジョブが現在のジョブになります。これ以外に現在のジョブが変更される場合は、元の現在のジョブは前のジョブになります。
- フォアグラウンドで実行していたジョブが停止したときは、そのジョブは現在のジョブになります。

Yash には、現在のジョブを選択する方針を指示するためにいくつかの{zwsp}link:_set.html#options[オプション]が用意されています。ただしこれらのオプションよりも上記の規則のほうが優先します。

link:_set.html#so-curasync[cur-async]::
新しく{zwsp}link:syntax.html#async[非同期コマンド]を起動したとき、それは現在のジョブになります。
link:_set.html#so-curbg[cur-bg]::
link:_bg.html[Bg 組込みコマンド]でジョブを再開したとき、そのジョブは現在のジョブになります。
link:_set.html#so-curstop[cur-stop]::
実行中のジョブが停止したとき、そのジョブは現在のジョブになります。

これらの規則・オプションに反しない限り、一度選ばれた現在のジョブ・前のジョブはずっと現在のジョブ・前のジョブのままです。

POSIX は現在のジョブ・前のジョブの選択方法を細かく定めていないため、他のシェルでは選び方が異なることがあります。

// vim: set filetype=asciidoc expandtab:
