GNU/Linux >> Linux の 問題 >  >> Linux

サブシェルを黙って殺しますか?

この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. サブシェル
  2. 1の子としてのsudo
  3. 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を取得するまでバックグラウンドで実行したままにします)。bashgrep ... <(sudo ...)を使用してこれを行うこともできます 構文、ここでbash sudoを待ちません grepの後 戻ってきました。

Grepの詳細は、一致を見つけた後、終了するのが遅いですか?


Linux
  1. サブシェルの出力をプロセスにリダイレクトしますか?

  2. プロセスの子孫?

  3. Linuxで実行中のプロセスを強制終了する方法

  1. Linux での kill コマンドの例

  2. wget を強制的にタイムアウトにする

  3. kill -- -0 は何をしますか?

  1. kill:コマンドが見つかりません

  2. 切り離された画面セッションを強制終了します

  3. linux:バックグラウンド タスクを強制終了するようにしました