我如何等待在另一个Shell中启动的程序


20

我有一个程序,它需要做大量的工作(大约需要4-5个小时),当它可以使用的所有数据都可用时,它就会由cron启动。有时,当我等待它完成时,我希望能够在完成时启动另一个(交互式)程序。等待电话看起来很有希望,但只会等待孩子。


我可以想到的唯一其他方法是从cronjob创建一个文件,然后在该进程上使用inotifywait,当文件删除后,您的第二个进程(运行inotifywait)可以启动。
slm

我认为您还可以使用ipc进程间通信来沿着这些思路做一些事情。man ipc
slm

虽然你不是在看一个服务重新启动它,神,monit的,或者在这个Q&A中提及会做的工作太多其他PKGS之一:unix.stackexchange.com/questions/75785/...
SLM

@slm可以在任何文件系统上使用inotify,例如在/ proc / _pid_ / fd / 1上等待close_write吗?
hildred

不确定,但这可能是另一种方法8-)。我记得有一个问题,那里有一些与进程监视相关的新内核功能,类似于inotifywait(用于文件)。我认为此新功能适用于正在进行中的事件,但我想很多问与答同时开始(8-)。我认为A是由我或Gilles提供的。
slm

Answers:


13

我绝对喜欢EDIT#3解决方案(请参见下面的内容)。

如果它不在同一个shell中,请使用while循环,条件是ps -p返回true。把睡眠中循环,以减少处理器的使用。

while ps -p <pid> >/dev/null 2>&1
do
   sleep 10
done 

或者您的UNIX支持/ proc(例如,HP-UX仍然不支持)。

while [[ -d /proc/<pid> ]]
do 
    sleep 10
done

如果要超时

timeout=6  # timeout after 1mn  
while ((timeout > 0)) && ps -p <pid> >/dev/null 2>&1
do
   sleep 10
   ((timeout -= 1))
done 

编辑#1

还有另一种方法:不要使用cron。使用批处理命令来堆叠您的作业。

例如,您可以每天堆放所有工作。可以对批处理进行调整,以允许某些并行性,因此阻止的作业不会停止所有堆栈(取决于操作系统)。

编辑#2

在您的主目录中创建一个fifo:

$ mkfifo ~/tata

在工作结束时:

echo "it's done" > ~/tata

在另一项工作(正在等待的工作)开始时:

cat ~/tata 

这不是在轮询它是旧的好阻塞IO。

编辑#3

使用信号:

在等待脚本的开头:

echo $$ >>~/WeAreStopped
kill -STOP $$

在您的长期工作结束时:

if [[ -f ~/WeAreStopped ]] ; then
    xargs kill -CONT < ~/WeAreStopped
    rm ~/WeAreStopped
fi

投票,!可爱的决定:浪费处理器时间或我的时间来调整睡眠。必须有一个更好的答案。
hildred

:)轮询对您有好处,轮询是无状态的,轮询是可靠的。
伊曼纽尔

轮询速度很慢,轮询会浪费处理器时间。
hildred

如果执行时间为0.01 s,则在4个小时内执行1440 ps会消耗14.4 s。远少于管理作业依赖项的调度程序:D
Emmanuel

我认为这可能是最好的选择:stackoverflow.com/questions/1058047/…,即使它很hacky。
slm

5

您可以修改cron作业以使用某些标志。

代替

2  2 * * *           /path/my_binary

您可以使用

2  2 * * *           touch /tmp/i_m_running; /path/my_binary; rm /tmp/i_m_running

只需用脚本甚至手动监视此文件。如果存在,则您的程序正在运行;否则,您可以随意做任何您想做的事情。

脚本样本:

while [[ -f /tmp/i_m_running ]] ; do
   sleep 10 ;
done
launch_whatever_you_want

如果您不喜欢使用sleep,则可以每X分钟修改一次脚本并通过cron运行它。

在这种情况下,脚本示例将为:

[[ -f /tmp/i_m_running ]] && { echo "Too early" ; exit ; }
launch_whatever_you_want

这种方式稍微容易一些,因为您不必查找cron进程的PID。


4

除了父进程等待其子进程之一完成之外,没有其他进程可以等待进程完成。如果可以,请通过脚本启动程序:

do_large_amount_of_work
start_interactive_program

如果您无法执行此操作,例如,在要从cron作业开始大量工作,但要从会话上下文开始交互式程序之前,那么请执行此操作

do_large_amount_of_work
notify_completion

有几种实现方法notify_completion。某些桌面环境提供了一种通知机制(在远程X显示器上打开一个窗口(为什么“无法打开显示器”?可能有用)?您也可以使用文件更改通知来创建一个。在Linux上,文件更改通知工具是inotify

do_large_amount_of_work
echo $? >/path/to/finished.stamp

对创建的反应/path/to/finished.stamp

inotifywait -e close_write -q /path/to/finished.stamp
start_interactive_program

如果您无法更改do_large_amount_of_work调用方式,但是您知道它最后修改的文件,则可以使用相同的机制在关闭该文件时做出反应。您还可以对其他事件做出反应,例如重命名文件(inotifywait有关可能的列表,请参见手册)。


0

让cronjob触发的脚本调用一个空的shell脚本,如果需要,可以在其中插入后续任务。

这与Gilles的方法非常相似。

cronjob-task.sh 包含:

# do_large_amount_of_work

./post-execute.sh

where post-execute.sh通常为空,除非您看到需要触发后续任务。

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.