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

Wait for process to end OR user input to continue

我有一个在后台运行命令的 bash 脚本。执行后,它会向用户显示:Press any key to continue(由 read -n1 -r -p 'Press any key to continue' value 提供支持)

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


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

用户可以等待计时器归零,它会自动关机,或者如果他们点击关机按钮,它会立即关机。

类似的内容可能适合您

#!/bin/bash

doStuff() {
    local pidOfParent=""

    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 'Press any key to continue' 所以我可以假设你已经知道那是做什么的,&& kill $doStuffPid 将在 read 退出时 kill 后台进程(这也适用于您使用 ^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 替换为您的命令即可。这里 $! return 是最后启动的子进程的 pid,kill -0 ${waitpid} 检查进程是否仍然存在(它不会终止进程)。 ps -q ${waitpid} 也适用于 Linux,但不适用于 Mac - 谢谢@leetbacoon 提到这一点。 read -n 1 -t 1 表示 "read one character, but only wait up to 1 second"(您也可以在此处使用分数,例如 0.5)。 return 此命令的状态取决于它是否可以在指定时间内读取一个字符。

如果愿意使用嵌入式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
)

用您的流程替换 sleep 10 的地方。