サブシェルを自動的に終了しますか?

サブシェルを自動的に終了しますか?

私はこのようなことを達成したい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実行できますsleepexec
  • SIGTERM の代わりに SIGPIPE を使用すると、メッセージを回避できます。
  • リストコンテキストで引用されていない変数はにありますbash

すべてを言うと、次のことができます。

(
  subshell=$BASHPID
  kill -s PIPE "$subshell" &
  sleep 600
)
echo subshell done

(サブシェルだけでなくシャットダウンしたい場合sleep 60に置き換えてください。この場合、サブシェルをシャットダウンしたときにサブシェルが実行されるまでの時間さえない場合があります。)exec sleep 60killsleepsleep

とにかく、あなたがそれで何を達成したいのか分かりません。

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_supplicantwpa_supplicant

  1. サブシェル
  2. 1歳の時 sudo
  3. 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サブシェルと同じプロセスで実行されます。$BASHPIDexec

パイプを介してpidを取得し、killrootとして実行します。

もう少し待つ覚悟をしていたら、

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 ...)bashsudogrep

詳細については、次を参照してください。一致するものを見つけた後、Grepはゆっくり終了しますか?

おすすめ記事