| author | プレハブ小屋 <2386769+showa-yojyo@users.noreply.github.com> | ||
|---|---|---|---|
| created | 2026-07-27 | ||
| draft | true | ||
| tags |
|
||
| title | Bash coprocesses ノート |
本稿で用いる術語:
- 単純命令:命令であって、空白で区切られた一連の語で単に構成され、シェルの制御演算子のいずれかで終了するもの
- 複合命令:ループ、条件分岐、ブロックなどで構成される命令
本題である coprocess の意味:
- 語
coprocから始まるシェル命令は coprocess というものだ。 - coprocess はサブシェルで非同期実行される。まるでバックグラウンドジョブのように。
- 実行側シェルと coprocess の間に双方向パイプが竣工する
Coprocess の構文はこういうものだ:
coprocNAME command redirections
名前が NAME である coprocess を定義する?
- command は単純命令でも複合コマンドでもかまわない
- NAME はシェル変数の名前だ
- NAME を指示しない場合の coprocess の名前は
COPROCとなる
- NAME を指示しない場合の coprocess の名前は
Bash Reference Manual が推奨する coprocess の定義形式の特徴:
- 名前を明示的に与える
- 中括弧で一体化した命令列を与える
coproc some-name { some-command; }command が複合命令ならば NAME は optional となる件で、Bash はこう判断する:coproc の直後にある語によって、その語を変数名と解釈するかどうかを決める。複合コマンドを開始する予約語でない場合、その語は coprocess の名前だと解釈する。
command が単純命令である場合、NAME は使用不可だ。Bash が NAME と命令の最初 の語とを区別することができないからだ。
Coprocess を定義すると、名前が NAME or COPROC である配列が定義側の環境に作られる。
| 配列 | 中身 |
|---|---|
${COPROC[0]} |
命令 command の標準出力のファイル記述子 |
${COPROC[1]} |
命令 command の標準入力のファイル記述子 |
Bash はこれらのファイル記述子に関与するパイプを、command が指定する redirection よりも前に設ける。
- これらのファイル記述子をシェルコマンドやリダイレクトの引数として利用することが可能。
- これらのファイル記述子はサブシェルから利用することは不可。
coprocess に付随するサブシェルのプロセス ID は変数 NAME_PID から値として得られる。
- 組み込みコマンド
waitを使って coprocess の終了を待つことが可能。
- 非同期命令として作成されるという性質から、命令
coprocはいつでも成功する。 - coprocess の返り値は command の終了状態と等しい。
bash - How to use 'coproc' to interact with another command driven program - Stack Overflow : この例はスクリプトでない形で再現可能。二つ目を再現しよう:
$ coproc myproc { bash; }
[1] 1006159
$ echo 'echo "$RANDOM"; echo "$RANDOM"; echo "$RANDOM"; echo "$RANDOM"' >&"${myproc[1]}"
$ while read -t 1 -u "${myproc[0]}" line; do
echo "$line"
done
11112
819
21141
25519
$ ps
PID TTY TIME CMD
1399 pts/2 00:00:14 bash
1006159 pts/2 00:00:00 bash
1006160 pts/2 00:00:00 bash
1006602 pts/2 00:00:00 ps
$ kill %+
[1]+ Terminated coproc myproc { bash; }Note
&>ではなく>&を使ったのは、${myproc[@]}がファイル記述子であることによる?- ファイル記述子から入力を読むのに
read -uを用いることが可能だ。もちろんread <&"${myproc[0]}"もアリだ。
Coprocesses - bash Pocket Reference : この例をコンソールで再現すると Send coprocess some input のコマンドで coprocess が停止する。その結果なのか、パイプが壊れる。
以上