Phi*_*ide 4 kill subshell output
我想实现类似这个Q/A 的东西,但是对于一个子外壳。这是我正在尝试的最小示例:
(subshell=$BASHPID
(kill $subshell & wait $subshell 2>/dev/null) &
sleep 600)
echo subshell done
Run Code Online (Sandbox Code Playgroud)
我怎样才能让它只subshell done
返回而不是:
./test.sh: line 4: 5439 Terminated ( subshell=$BASHPID; ( kill $subshell && wait $subshell 2> /dev/null ) & sleep 600 )
subshell done
Run Code Online (Sandbox Code Playgroud)
编辑:我在这里的术语可能是错误的,通过子外壳我的意思是第一组括号内的过程。
更新:
我想发布来自实际程序的片段以供上下文,上面是一个简化:
# 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
Run Code Online (Sandbox Code Playgroud)
笔记:
wait $subshell
不会工作,因为$subshell
它不是您正在运行的进程的子进程wait
。无论如何,您不会等待进程执行该操作,wait
因此这无关紧要。kill $subshell
将杀死子外壳,但sleep
如果子外壳在运行时设法启动它,则不会kill
。但是sleep
,您可以在同一进程中运行exec
bash
.说了这么多,你可以这样做:
(
subshell=$BASHPID
kill -s PIPE "$subshell" &
sleep 600
)
echo subshell done
Run Code Online (Sandbox Code Playgroud)
(如果您想要杀死而不仅仅是子shell,则替换sleep 60
为,在这种情况下,在您杀死它时甚至可能没有时间运行)。exec sleep 60
kill
sleep
sleep
无论如何,我不确定你想用它实现什么。
sleep 600 &
Run Code Online (Sandbox Code Playgroud)
sleep
如果这是您想要做的(或者(sleep 600 &)
如果您想sleep
从主 shell隐藏该进程),这将是一种更可靠的在后台启动的方式
现在用你的实际
sudo stdbuf -o0 wpa_supplicant -Dwext -i"$wifi" -c/etc/wpa_supplicant/wpa_supplicant.conf
Run Code Online (Sandbox Code Playgroud)
命令,请注意它sudo
会产生一个子进程来运行命令(如果只是因为它可能需要记录其状态或之后执行一些 PAM 会话任务)。stdbuf
然而wpa_supplicant
,将在同一个进程中执行,因此最终您将在wpa_supplicant
的祖先中拥有三个进程(除了脚本的其余部分):
如果您杀死 1,则不会自动杀死 2。但是,如果您杀死 2,除非它带有无法拦截的 SIGKILL 信号,否则会杀死 3,因为sudo
它将接收到的信号转发给它运行的命令.
无论如何,这不是您想在这里杀死的子shell,它是 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"
}'
Run Code Online (Sandbox Code Playgroud)
这样,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"
Run Code Online (Sandbox Code Playgroud)
下次它在管道消失后向该管道写入内容时,会wpa_supplicant
使用 SIGPIPE 自动终止(由系统,因此没有权限问题)。grep
一些 shell 实现不会等待sudo
aftergrep
返回(让它在后台运行,直到它获得 SIGPIPEd),并且使用bash
,您也可以使用grep ... <(sudo ...)
语法来做到这一点, wherebash
不等待sudo
任何一个 aftergrep
返回。