Skip to content

Instantly share code, notes, and snippets.

@showa-yojyo
Created July 27, 2026 13:57
Show Gist options
  • Select an option

  • Save showa-yojyo/621408d2d3ee3b702ce4b0cb79c23740 to your computer and use it in GitHub Desktop.

Select an option

Save showa-yojyo/621408d2d3ee3b702ce4b0cb79c23740 to your computer and use it in GitHub Desktop.
WIP
author プレハブ小屋 <2386769+showa-yojyo@users.noreply.github.com>
created 2026-07-27
draft true
tags
bash
coproc
title Bash coprocesses ノート

Bash coprocesses ノート

本稿で用いる術語:

  • 単純命令:命令であって、空白で区切られた一連の語で単に構成され、シェルの制御演算子のいずれかで終了するもの
  • 複合命令:ループ、条件分岐、ブロックなどで構成される命令

本題である coprocess の意味:

  • coproc から始まるシェル命令は coprocess というものだ。
  • coprocess はサブシェルで非同期実行される。まるでバックグラウンドジョブのように。
  • 実行側シェルと coprocess の間に双方向パイプが竣工する

Coprocess の構文はこういうものだ:

coproc NAME command redirections

名前が NAME である coprocess を定義する?

  • command は単純命令でも複合コマンドでもかまわない
  • NAME はシェル変数の名前だ
    • NAME を指示しない場合の coprocess の名前は COPROC となる

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 よりも前に設ける。

  • これらのファイル記述子をシェルコマンドやリダイレクトの引数として利用することが可能。
  • これらのファイル記述子はサブシェルから利用することは不可。

サブシェルのプロセス ID を値にとる変数

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 が停止する。その結果なのか、パイプが壊れる。


以上

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment