この質問は以前に提起され、回答されたと疑われますが、検索が正しいかどうかはわかりません。
起動時にURLとポートを含む行を出力する終了しないプロセス(サーバー)があります。その行を変数としてキャプチャして他のプログラムに渡すことができるようにしたいと思います。
だから私は次のようにします:
% export URL=`server start` &
URL
ただし、(私の考えでは:-))終了せserver
ずに実行され続けるため、設定されません。
server
他の場所で使用するために印刷されたURLを変数としてキャプチャするにはどうすればよいですか?
答え1
次のことを試すことができます。
server start &
cat /proc/${!}/fd/1
これでサーバーが起動し、$!対応するIDが返されます。 fd/1 は、/proc で使用できるプロセスの標準出力です。
注:異なるプロセスIDを返す可能性があるため、startと$!間に異なるコード行があってはいけません。
答え2
解決策
FIFO(名前付きパイプ)を生成します。他のユーザーから隠す必要がある場合は、事前に一時
mktemp -d
ディレクトリを作成し、その中にFIFOを作成します(この回答では簡潔にするためにこれを行いません)。mkfifo myfifo
サーバープロセスがFIFOに書き込まれ、FIFOからスクリプトを読み取るようにします。サーバーの起動後に読み取り用にFIFOを開いて閉じる(リーダーがないように)、SIGPIPEはサーバープロセスに送信されるため、先読み用にFIFOを開いて開いたままにすることをお勧めします。一方、FIFOを事前に開くことはホロブロックを読み込み、一部のプロセスが書き込みのために FIFO を開くまで待ちます。この問題を解決するには、読み取りと書き込みのために FIFO を開き、後で記述子を閉じます。
exec 3<>myfifo
バックグラウンドでサーバーを起動し、FIFOに書き込むようにします。
server start >&3 &
(
>&3
そして>myfifo
技術的に異なります。私たちにとって、両方のフォーマットはここで動作します)。FIFOから正確に1行を読み込みます。
<&3 IFS= read -r URL
(
<&3
そして<myfifo
技術的に異なります。私たちにとって、両方のフォーマットはここで動作します)。cat
バックグラウンドで起動し、プロセスがスクリプトの標準出力に印刷されるようにします(または出力を別のものにcat
リダイレクトするか、/dev/null
必要に応じて調整します)。server
この手順を省略すると、FIFO に印刷量が多すぎるとブロックが発生します。cat
これは、実行したジョブの後にプロセスが何も印刷しないという確信がある場合にのみ必要です。read
そのような場合でも、cat
何の害もありません。一般的に別の問題があります。
server
読み取り用に開いているすべての記述子を閉じた後、SIGPIPEを使用して終了できます。私たちはserver
書くための記述子を自分で持っています。そして読んでSIGPIPEは発生しません。これが発生した場合は、cat
FIFOから読み取りを開始すると問題が解決します。それから始めてください
cat
。<myfifo cat 3>&- &
myfifo
ここでは、読み取りのみを有効にしてcat
書き込みを許可する記述子を継承することはできません。重要なことは、cat
書き込みのためにFIFOを開いたままにしてはいけません。これは後で重要になります。ディスクリプタを閉じてFIFOのみを開いたままに
cat
します。server
FIFOの接続を解除することもできます(これにより、FIFOを使用するプロセスは中断されません)。exec 3>&- rm myfifo
これにより、スクリプトの将来の子孫はその記述子を継承しません。
仕事
$URL
。終了すると、他
server
のプロセスは書き込み用にFIFOを開かず、cat
EOF条件に遭遇して終了します。この時、私たちが始める方法がcat
重要です。継承されたファイル記述子が保持されると、正式にcat
FIFOの作成者になるため、自動的に終了することはできません。ログアウトcat
後は自動的にログアウトすることを保証しますserver
。スクリプトが終わったら、おそらく
wait
次のことが起こりたいと思います。wait
(これは他のバックグラウンドジョブがないと仮定します。)これがないと、スクリプトは以前に
wait
終了してserver
バックグラウンドにserver
残ることがあります。cat
スクリプトが必要かどうかを決定しますwait
。
概念の証拠
#!/bin/sh
# fake server
server() {
echo 'example.com'
for i in 1 2 3 4 5 6 7; do echo 'server running'; sleep 1; done
}
mkfifo myfifo
exec 3<>myfifo
server start >&3 &
<&3 IFS= read -r URL
<myfifo cat 3>&- &
exec 3>&-
rm myfifo
echo "The URL is $URL"
sleep 2
echo "Still working with $URL"
sleep 2
echo "Done. Waiting for the server to close."
wait