Kill

默默殺死subshel l?

  • December 21, 2019

我想實現類似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

編輯:我在這裡的術語可能是錯誤的,子shell是指第一組括號內的過程。

更新:

我想從實際程序中發布片段以獲取上下文,上面是一個簡化:

# 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將殺死子shell,但sleep如果子shell 在執行時已成功啟動它,則不會kill。但是,您可以sleep在同一程序中執行exec
  • 您可以使用 SIGPIPE 而不是 SIGTERM 來避免該消息
  • 在列表上下文中不加引號的變數在bash.

說了這麼多,你可以這樣做:

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

(如果您想殺死而不僅僅是子shell,請替換sleep 60為,在這種情況下,您殺死它時甚至可能沒有時間執行)。exec sleep 60``kill``sleep``sleep

無論如何,我不確定你想用它來實現什麼。

sleep 600 &

sleep如果這是您想要做的(或者(sleep 600 &)如果您想sleep從主 shell 隱藏該程序),這將是一種更可靠的在後台啟動的方式

現在用你的實際

sudo stdbuf -o0 wpa_supplicant -Dwext -i"$wifi" -c/etc/wpa_supplicant/wpa_supplicant.conf

命令,請注意,它sudo確實會產生一個子程序來執行該命令(如果只是因為它可能需要記錄其狀態或之後執行一些 PAM 會話任務)。stdbuf然而,將在同一個程序中執行,所以最後你將在的祖先wpa_supplicant中擁有三個程序(除了腳本的其餘部分) :wpa_supplicant

  1. 子殼
  2. sudo 作為 1 歲的孩子
  3. wpa_supplicant(之前執行 stdbuf)作為 2 的孩子

如果您殺死 1,則不會自動殺死 2。但是,如果您殺死 2,除非它帶有無法攔截的 SIGKILL 之類的信號,否則它將殺死 3,因為sudo它會將收到的信號轉發給它執行的命令.

無論如何,這不是您要在這裡殺死的子shell,它是 3 或至少 2。

現在,如果它正在執行root而腳本的其餘部分沒有執行,您將無法如此輕鬆地殺死它。

你需要kill做 as 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子shell 相同的程序中執行,就像我們使用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"

下次它在消失後向該管道寫入內容時會wpa_supplicant使用 SIGPIPE 自動終止(由系統執行,因此沒有權限問題) 。grep

一些 shell 實現不會等待sudoaftergrep返回(讓它在後台執行直到它獲得 SIGPIPEd),並且使用bash,您也可以使用grep ... <(sudo ...)語法來執行此操作,其中bash不等待sudo任何一個 aftergrep返回。

找到匹配項後,Grep 的更多資訊退出緩慢?

引用自:https://unix.stackexchange.com/questions/406689