Bash 等待进程结束或用户输入继续

Bash 等待进程结束或用户输入继续,bash,macos,kill,Bash,Macos,Kill,我有一个在后台运行命令的bash脚本。执行后,它向用户显示:按任意键继续(由read-n1-r-p“按任意键继续”值供电) 我想让一些东西在后台监视命令,以查看它何时完成,如果是,我希望脚本继续。另一方面,这个过程可能仍在继续,我希望用户能够按下一个键来杀死这个过程,而不是等待它完成 我想最简单的可视化方法是: 用户可以等待计时器变为0,计时器将自动关闭,或者如果单击“关闭”按钮,计时器将立即关闭。类似的操作可能适合您 #!/bin/bash doStuff() { local p

我有一个在后台运行命令的bash脚本。执行后,它向用户显示:
按任意键继续
(由
read-n1-r-p“按任意键继续”值供电

我想让一些东西在后台监视命令,以查看它何时完成,如果是,我希望脚本继续。另一方面,这个过程可能仍在继续,我希望用户能够按下一个键来杀死这个过程,而不是等待它完成


我想最简单的可视化方法是:


用户可以等待计时器变为0,计时器将自动关闭,或者如果单击“关闭”按钮,计时器将立即关闭。

类似的操作可能适合您

#!/bin/bash

doStuff() {
    local pidOfParent="$1"

    for i in $(seq 10); do
        echo "stuff ${i}" > /dev/null
        sleep 1
    done

    kill $pidOfParent
}

doStuff $$ &

doStuffPid="$!"

read -n1 -rp 'Press any key to continue' && kill $doStuffPid
细分

doStuff
是我们的函数,包含您希望在后台运行的内容,即音乐

$
是正在运行的脚本的PID,我们将其传递到函数中,使其成为更具描述性的
pidOfParent
,在该函数中,我们在完成工作后
kill

调用函数后的
&
将其置于后台

$获取最后执行的命令的PID,因此我们现在有了刚刚启动的后台进程的PID


您提供了
read-n1-rp“按任意键继续”
,因此我可以假设您已经知道这是怎么回事,
&kill$dostufpid
在退出
read
时杀死后台进程(如果使用
^C
终止脚本,此操作也有效).

如果您想等待pid,直到用户点击一个键,您可以按如下操作:

./long_command.sh &
waitpid=$!
echo "Hit any key to continue or wait until the command finishes"
while kill -0 ${waitpid} > /dev/null ; do
    #if [[ ${#KEY} -gt 0 ]] ; then
    if read -n 1 -t 1 KEY ; then
        kill ${waitpid}
        break
    fi
done

只需用您的命令替换
long_command.sh
。这里是
$
返回上次启动的子进程的pid,并检查该进程是否仍然存在(它没有终止该进程)
ps-q${waitpid}
也适用于Linux,但不适用于Mac——感谢@leetbacon提到这一点
read-n1-t1
表示“读取一个字符,但最多只能等待1秒”(这里也可以使用0.5这样的分数)。此命令的返回状态取决于它是否能在指定时间内读取字符。

如果您愿意使用embedded expect,可以编写:

expect <(cat <<'EOD'
spawn sleep 10
send_user "Press any key to continue\n"
stty raw -echo
expect {
  -i $user_spawn_id -re ".+" {}
  -i $spawn_id eof {}
}
EOD
)

expect这对我有用,谢谢,但是我不得不使用
kill-0“${waitpid}”
而不是
ps-q${waitpid}
,因为macOS版本的
ps
没有这个标志。谢谢你的反馈
kill-0
甚至没有记录在linux手册页中,。我猜它的意思是信号0,但如果我发出
kill-l
,信号0不会被列出,但它在那里也起作用。很好,你找到了!我在答案中更新了它,因为它看起来更便携。我记不起在哪里看到过它,但是
kill-0
没有杀死任何东西,它只是检查进程是否正在运行。如果是,则退出代码为
0
。如果不是,则退出代码为≥ <代码>1
(好吧,只有1,但为了安全起见,我会说≥ 1).