この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
承認された回答:
注:
-
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
ただし、wpa_supplicant
を実行します 同じプロセスであるため、最終的にはwpa_supplicant
に(スクリプトの残りの部分に加えて)3つのプロセスがあります。 の祖先:
- サブシェル
- 1の子としてのsudo
- 2の子としてのwpa_supplicant(以前はstdbufを実行していた)
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
を実行します ルートとして。
もう少し待つ準備ができている場合は、
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"
wpa_supplicant
があります 次回SIGPIPEで自動的に強制終了されます(システムによって、許可の問題はありません)。 grep
の後にそのパイプに何かを書き込みます なくなった。
一部のシェル実装は、sudo
を待機しませんでした grep
の後 戻ってきました(SIGPIPEdを取得するまでバックグラウンドで実行したままにします)。bash
、grep ... <(sudo ...)
を使用してこれを行うこともできます 構文、ここでbash
sudo
を待ちません grep
の後 戻ってきました。
Grepの詳細は、一致を見つけた後、終了するのが遅いですか?