在已经运行的现有命令完成后如何运行命令?


32

如果我启动一个需要很长时间的脚本,那么在启动脚本后我将不可避免地意识到它,并希望一旦脚本完成就可以采取某种警报的方式。

因此,例如,如果我运行:

really_long_script.sh

然后按Enter ...完成后如何运行另一个命令?

Answers:


45

您可以使用来分隔多个命令;,因此它们会按顺序执行,例如:

really_long_script.sh ; echo Finished

如果仅在脚本以返回码0结尾(通常表示脚本已正确执行)时才希望执行下一个程序,则:

really_long_script.sh && echo OK

如果您想要相反的操作(即仅在当前命令失败时才继续操作),则:

really_long_script.sh || echo FAILED

您可以在后台运行脚本(但是请注意,除非将脚本输出(stdoutstderr)重定向到某处,否则脚本输出(和)将继续进入终端),然后wait为此:

really_long_script.sh &
dosomethingelse
wait; echo Finished

如果您已经运行了脚本,则可以使用将其挂起Ctrl-Z,然后执行以下操作:

fg ; echo Finished

fg带来了暂停过程中的前景(bg将使其在后台运行,很像开始&


@mlissner扩展了我的回答以涵盖此案
2011年

8
由于fg返回它继续执行的作业的值,因此fg && echo Finished如果要确保在执行另一个命令之前命令成功,则可以使用。
palswim

13

您还可以使用bash的作业控制。如果你开始

$ really_long_script.sh

然后按ctrl + z将其挂起:

^Z
[1]+  Stopped                 really_long_script.sh
$ bg

在后台重新启动作业(就像使用来启动作业一样really_long_script.sh &)。然后,您可以等待此后台作业

$ wait N && echo "Successfully completed"

其中N是作业ID(如果您没有运行任何其他后台作业,则可能为1),该ID也[1]如上所述显示。


11

如果该进程未在当前tty上运行,请尝试以下操作:

watch -g ps -opid -p <pid>; mycommand

2
我喜欢的创造性使用watch。超级简短的答案,一个人学习使用手表的一种新的有用方法
Piotr Czapla

2

事实证明,这并不难:您可以在现有命令运行时,在窗口中键入下一个命令,然后按Enter键,当第一个命令完成时,第二个命令将自动运行。

我猜有更优雅的方法,但这似乎可行。

编辑以添加为如果您想在命令完成后运行警报,则可以在.bashrc中创建这些别名,然后在运行alert时运行:

 alias alert_helper='history|tail -n1|sed -e "s/^\s*[0-9]\+\s*//" -e "s/;\s*alert$//"'
 alias alert='notify-send -i gnome-terminal "Finished Terminal Job" "[$?] $(alert_helper)"'

7
除非正在运行的脚本期望输入一点。
丹尼尔·贝克

@Daniel-是的...这是个问题。射击。
mlissner's

1

前一阵子我写了一个脚本来等待另一个过程的结束。NOISE_CMD如果设置正确notify-send ...DISPLAY则可能类似于。

#!/bin/bash

NOISE_CMD="/usr/bin/mplayer -really-quiet $HOME/sfx/alarm-clock.mp3"

function usage() {
    echo "Usage: $(basename "$0") [ PROCESS_NAME [ PGREP_ARGS... ] ]"
    echo "Helpful arguments to pgrep are: -f -n -o -x"
}

if [ "$#" -gt 0 ] ; then
    PATTERN="$1"
    shift
    PIDS="$(pgrep "$PATTERN" "$@")"

    if [ -z "$PIDS" ] ; then
        echo "No process matching pattern \"$PATTERN\" found."
        exit
    fi

    echo "Waiting for:"
    pgrep -l "$PATTERN" "$@"

    for PID in $PIDS ; do
        while [ -d "/proc/$PID" ] ; do
            sleep 1
        done
    done
fi

exec $NOISE_CMD

没有任何装饰,请立即发出一些声音。为了方便起见,此行为允许这样的操作(例如,您在下面调用脚本alarm.sh):

apt-get upgrade ; ~/bin/alarm.sh

当然,您可以使用这样的脚本做很多有趣的事情,例如让一个实例alarm.sh等待的alarm.sh,即等待其他命令。或者在其他登录用户的某些任务完成后立即执行命令...>:D

如果您想避免自己依赖pgrep并接受查找进程ID ,则上面脚本的旧版本可能会很有趣:

#!/bin/bash

if [ "$#" -lt 2 -o ! -d "/proc/$1" ] ; then
  echo "Usage: $(basename "$0") PID COMMAND [ ARGUMENTS... ]"
  exit
fi

while [ -d "/proc/$1" ] ; do
  sleep 1
done

shift
exec "$@"

稍微偏离主题,但在类似情况下很有用:一个可能感兴趣reptyr的工具,它可以从某些(父)shell“窃取”一个进程并从当前shell运行该进程。我已经尝试过类似的实现,reptyr并且对于我来说是最漂亮,最可靠的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.