如果我启动一个需要花费很长时间的脚本,我不可避免地会在启动脚本后意识到这一点,并希望在脚本完成后有办法发出某种警报。
例如,如果我运行:
really_long_script.sh
然后按回车键...完成后我如何运行另一个命令?
答案1
您可以使用 分隔多个命令;
,以便按顺序执行,例如:
really_long_script.sh ; echo Finished
如果您希望只有当脚本以返回代码 0 完成(通常意味着它已正确执行)时才执行下一个程序,那么:
really_long_script.sh && echo OK
如果您想要相反的操作(即,仅当当前命令失败时才继续),那么:
really_long_script.sh || echo FAILED
您可以在后台运行脚本(但请注意,除非您将其重定向到某处,否则脚本输出(stdout
和stderr
)将继续进入您的终端),然后wait
对它进行以下操作:
really_long_script.sh &
dosomethingelse
wait; echo Finished
如果您已经运行脚本,您可以使用暂停它Ctrl-Z
,然后执行如下操作:
fg ; echo Finished
将fg
暂停的进程带到前台(bg
会使其在后台运行,就像开始时一样&
)
答案2
如果该进程没有在当前 tty 上运行,请尝试以下操作:
watch -g ps -opid -p <pid>; mycommand
答案3
你也可以使用 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),它也如上显示[1]
。
答案4
不久前,我编写了一个脚本来等待另一个进程的结束。如果设置正确,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
对我来说,它是最漂亮、最可靠的。