私はこのようなことを達成したいQ&Aしかし、サブシェルの場合。私が試している最小限の例は次のとおりです。
(subshell=$BASHPID
(kill $subshell & wait $subshell 2>/dev/null) &
sleep 600)
echo subshell done
subshell done
次の代わりにリターンのみを作成するにはどうすればよいですか?
./test.sh: line 4: 5439 Terminated ( subshell=$BASHPID; ( kill $subshell && wait $subshell 2> /dev/null ) & sleep 600 )
subshell done
編集:ここで私の用語が間違っている可能性があります。サブシェルとは、最初の角かっこセット内のプロセスを意味します。
修正する:
文脈を把握するために、実際のプログラムの一部を公開したかった。上記の内容を単純化すると、次のようになります。
# If subshell below if killed or returns error connected variable won't be set
(if [ -n "$2" ];then
# code to setup wpa configurations here
# If wifi key is wrong kill subshell
subshell=$BASHPID
(sudo stdbuf -o0 wpa_supplicant -Dwext -i$wifi -c/etc/wpa_supplicant/wpa_supplicant.conf 2>&1 \
| grep -m 1 "pre-shared key may be incorrect" \
&& kill -s PIPE "$subshell") &
# More code which does the setup necessary for wifi
) && connected=true
# later json will be returned based on if connected is set
答え1
メモ:
wait $subshell
$subshell
実行中のプロセスの子ではないため、機能しませんwait
。とにかくこれを行うプロセスを待たないので、wait
実際には重要ではありません。kill $subshell
サブシェルは終了しますが、sleep
サブシェルの実行中に正常に起動した場合は終了しません。ただし、同じプロセスでkill
実行できますsleep
exec
- SIGTERM の代わりに SIGPIPE を使用すると、メッセージを回避できます。
- リストコンテキストで引用されていない変数はにあります
bash
。
すべてを言うと、次のことができます。
(
subshell=$BASHPID
kill -s PIPE "$subshell" &
sleep 600
)
echo subshell done
(サブシェルだけでなくシャットダウンしたい場合sleep 60
に置き換えてください。この場合、サブシェルをシャットダウンしたときにサブシェルが実行されるまでの時間さえない場合があります。)exec sleep 60
kill
sleep
sleep
とにかく、あなたがそれで何を達成したいのか分かりません。
sleep 600 &
sleep
それが必要な場合(またはメインシェルでプロセスを非表示にし(sleep 600 &)
たい場合sleep
)、バックグラウンドで実行する方がより安定したアプローチになります。
今実際の状況で
sudo stdbuf -o0 wpa_supplicant -Dwext -i"$wifi" -c/etc/wpa_supplicant/wpa_supplicant.conf
コマンドを実行する場合は、子プロセスをsudo
作成してコマンドを実行します(状態を記録するか、後でいくつかのPAMセッション操作を実行する必要がある場合にのみ)。stdbuf
ただし、同じプロセスで実行されるため(残りのスクリプトに加えて)祖先には3つのプロセスがありますwpa_supplicant
。wpa_supplicant
- サブシェル
- 1歳の時 sudo
- wpa_supplicant(stdbufを実行する前)を2の子として使用する
1人を殺すと自動的に2人が死ぬことはありません。しかし、2つを殺すと、傍受できないSIGKILLのような信号が来ない限り、受信した信号を実行するコマンドに渡すsudo
ため、3つが死にます。
とにかくここで殺したいのはサブシェルではなく、3つまたは少なくとも2つです。
スクリプトが実行中で、root
残りのスクリプトはそうでない場合は簡単に終了できません。
kill
完了する必要があるため、root
以下が必要です。
sudo WIFI="$wifi" bash -c '
(echo "$BASHPID" &&
exec stdbuf -o0 wpa_supplicant -Dwext -i"$WIFI" -c/etc/wpa_supplicant/wpa_supplicant.conf 2>&1
) | {
read pid &&
grep -m1 "pre-shared key may be incorrect" &&
kill -s PIPE "$pid"
}'
これは、私たちが使用したようにwpa_supplicant
サブシェルと同じプロセスで実行されます。$BASHPID
exec
パイプを介してpidを取得し、kill
rootとして実行します。
もう少し待つ覚悟をしていたら、
sudo stdbuf -o0 wpa_supplicant -Dwext -i"$wifi" -c/etc/wpa_supplicant/wpa_supplicant.conf 2>&1 |
grep -m1 "pre-shared key may be incorrect"
SIGPIPE を使用して自動的に終了しますwpa_supplicant
(システムによって、権限の問題はありません)。次回grep
消えたら、そのパイプに何かを書き込みます。
sudo
一部のシェル実装では、1つが返されるのを待たずgrep
(SIGPIPEDが受信されるまでバックグラウンドで実行されるようにします)、1つが返されるのを待たない構文を使用してこれを実行することもbash
できます。grep ... <(sudo ...)
bash
sudo
grep
詳細については、次を参照してください。一致するものを見つけた後、Grepはゆっくり終了しますか?
答え2
bash -i
サブシェルは、プロンプトを表示する対話型ログインシェルなどのシェルのサブシェルコマンドです$
。あなたはしません持つサブシェルでコマンドを実行 - スタンドアロンプロセスとして実行することを選択できます。 stdout / stderrが進行状況バーの外観をめちゃくちゃにしたくないので、親シェルが子シェルの死を報告したり通知したくないので、これは適切であると思われます。
これを達成するためのいくつかの標準ツールがあります。悪魔そしていいえ。 (あなたも見ることができます男性 ページ.) あなたができる最善は北面。以下は、これを使用して単純なプログラムを実行する例です。いいえnohup.outを生成します。
$ nohup true 2>&1 > /dev/null &
プログラムまたはプログラムのラッパースクリプトが適切なPIDを/tmp/my.pidに書き込むようにしてください。 bashでは、これを変数として使用できます$$
。次に、進行状況バーを使用してプロセスを監視します。
$ kill `cat /tmp/my.pid`
もはやプログラムで処理が必要ない場合。またはプログラム名をkillall
。
答え3
あなたはこれを探しているかもしれません
#!/bin/bash
(subshell=$BASHPID
(kill $subshell & wait $subshell 2>/dev/null) &
sleep 600) &
wait $! 2>/dev/null
echo subshell done
ここで、子シェルはバックグラウンドに配置され、親シェルは待ちますが、出力が/ dev / nullに送信されるのを待ちます。Terminated
メッセージがキャプチャされます。
たとえば、スタンバイキャプチャ出力をファイルに変更すると、次の内容が表示されwait $! 2>wait_output
ます。
./foo.sh: line 5: 1939 Terminated ( subshell=$BASHPID; ( kill $subshell & wait $subshell 2> /dev/null ) & sleep 600 )
Terminated
親シェルに表示されます。
終了する前に、どのような活動があったかを確認するために小さな検査を行います。
#!/bin/bash
(subshell=$BASHPID
(sleep 1; kill $subshell & wait $subshell 2>/dev/null) &
sleep 600) & wait 2>wait_output
echo subshell done
この例は、印刷する前に1秒間一時停止されますsubshell done
。この例はまた、バックグラウンドプロセスを実行し、同じ行で待機する方法を示しています(例:& wait 2>wait_output
これが関連しているかどうかわかりません)wait $!
。
ここで注目すべき重要な点は、メッセージがTerminated
最上位の親シェル操作制御から来ることです。これがサブシェルが終了してメッセージを生成する理由です。これが出力をキャプチャしたい場所です。wait
コマンド出力をリダイレクトすると、これは完了です。