シェルスクリプトの標準入力をバックグラウンドコマンドに渡す方法

シェルスクリプトの標準入力をバックグラウンドコマンドに渡す方法

シェルスクリプトでは、シェルスクリプトと同じ標準入力を使用してバックグラウンドコマンドを開始しようとします。

#!/bin/sh
# ...

the-program &

ただし、the-program上記の方法はシェルスクリプトと同じ標準入力にアクセスできません。私のシェルマニュアルによると(ダッシュ(1)):

シェルが対話型でない場合、非同期コマンドの標準入力はに設定されます/dev/null

試してみましthe-program & <&0たが、欲しい効果が得られなかったようです。標準入力はthe-programまだです/dev/null

私はシェルスクリプトの標準入力をコピーし、何らかの方法で新しいファイルディスクリプタをバックグラウンドプロセスに渡して新しいファイルディスクリプタを生成することを検討しました。ただし、バックグラウンドプロセスは何らかの方法でこの新しいファイル記述子を標準入力/dev/nullにリダイレクトする必要があります。このアイデアが可能かどうかわからず、POSIX shで実装する方法もわかりません。

答え1

うん、POSIXsh仕様要件非対話式シェルを介して非同期的に開始されたコマンドを呼び出すと(monitorIOWジョブ制御オプションが有効になっていない場合)、その標準入力は/ dev / nullにリダイレクトされます。

ジョブ制御が無効になっている場合(参照set-m、非同期リストの標準入力は、明示的なリダイレクトが実行される前に同じ属性を持つファイルに割り当てられているかのように処理する必要があります/dev/null。ジョブ制御が有効な場合、これは発生しません。すべての場合において、標準入力の明示的なリダイレクトはこのアクティビティを上書きする必要があります。

一般的な解決策は次のとおりです。

{ cmd <&3 3<&- & } 3<&0

これはあなたが考えているのと同じです。

例:

$ sh -c 'readlink /proc/self/fd/0 & wait' < /
/dev/null
$ sh -c '{ readlink /proc/self/fd/0 <&3 3<&- & } 3<&0; wait' < /
/

zsh別のオプションは、シミュレーションでもこの要件を無視する方法を使用することです。sh

$ zsh -c 'readlink /proc/self/fd/0 & wait' < /
/
$ zsh --emulate sh -c 'readlink /proc/self/fd/0 & wait' < /
/

関連情報