【问题标题】:Wait for process to end OR user input to continue等待进程结束或用户输入继续
【发布时间】:2019-07-11 21:54:54
【问题描述】:

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

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


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

用户可以等待计时器到 0 并自动关闭,或者如果他们单击关闭按钮,它会立即关闭。

【问题讨论】:

    标签: bash macos kill


    【解决方案1】:

    如果你想在 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,kill -0 ${waitpid} 检查进程是否仍然存在(它没有杀死进程)。 ps -q ${waitpid} 也适用于 Linux,但不适用于 Mac - 感谢 @leetbacoon 提及这一点。 read -n 1 -t 1 表示“读取一个字符,但最多只能等待 1 秒”(您也可以在此处使用 0.5 之类的分数)。该命令的返回状态取决于它是否可以在指定的时间内读取一个字符。

    【讨论】:

    • 这对我有用,谢谢,但是我不得不使用 kill -0 "${waitpid}" 而不是 ps -q ${waitpid},因为 macOS 版本的 ps 没有那个标志。
    • 感谢您的反馈。 kill -0 甚至没有记录在 linux 手册页中。我猜这意味着信号 0,但如果我发出 kill -l,信号零不会列出,但它也可以在那里工作。很好,你找到了!我在答案中更新它,因为它看起来更便携。
    • 不记得我在哪里看到的,但kill -0 不会杀死任何东西,它只是检查该进程是否正在运行。如果是,退出代码是0。如果不是,退出代码≥1(afaik 它只有 1,但为了安全起见,我会说≥1)。
    【解决方案2】:

    这样的东西可能对你有用

    #!/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 'Press any key to continue',所以我可以假设您已经知道它的作用,&& kill $doStuffPid 将在read 退出时将kill 后台进程(如果您使用^C 终止脚本,这也有效)。

    【讨论】:

      【解决方案3】:

      如果你愿意使用嵌入式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 替换为您的流程。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-09-19
        • 1970-01-01
        • 1970-01-01
        • 2013-12-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多