进程完成后运行 bash 命令

进程完成后运行 bash 命令

我有两个使用 GPU 和训练 ML 模型的脚本。我想在睡觉前启动它们,这样它们就会在晚上起作用,我希望在早上看到一些结果。

但由于 GPU 内存有限,我想串行运行它们而不是并行运行。

我可以用python train_v1.py && python train_v2.py;但假设我开始训练train_v1.同时,由于训练时间较长,我开始并完成了第二个脚本的实现,train_v2.py我想在python train_v1.py完成后自动运行它。

我怎样才能做到这一点?谢谢。

答案1

这是一种不涉及循环和检查其他进程是否仍然存在的方法,或者train_v1.py以与通常执行的方式不同的方式进行调用:

$ python train_v1.py
^Z
[1]+  Stopped                 python train_v1.py
$ % && python train_v2.py

^Z是我在进程运行时按Ctrl+通过向其发送信号进入睡眠状态。然后,我告诉 shell 用 唤醒它,将其用作命令,我可以在末尾添加 。这使得它的行为就像您从一开始就做的一样。Ztrain_v1.pySIGTSTP%&& python train_v2.pypython train_v1.py && python train_v2.py

相反%,您也可以使用fg.这是同一件事。如果您想了解有关 shell 的这些类型功能的更多信息,可以阅读bash 联机帮助页的“作业控制”部分

编辑:如何继续添加到队列中

正如 jamesdlin 在评论中指出的那样,如果您尝试train_v3.py在 v2 开始之前继续添加模式,您会发现不能:

$ % && python train_v2.py
^Z
[1]+  Stopped                 python train_v1.py

train_v1.py因尚未开始而停止train_v2.py,并且您无法停止/暂停/睡眠甚至尚未开始的东西。

$ % && python train_v3.py

会导致相同的结果

python train_v1.py && python train_v3.py

因为%对应于最后一个挂起的进程。v3人们不应该尝试这样添加,而应该使用历史记录:

$ !! && python train_v3.py
% && python train_v2.py && python train_v3.py

人们可以像上面那样进行历史扩展,或者使用键绑定(如 up)调用最后一个命令并将 v3 添加到末尾。

$ % && python train_v2.py && python train_v3.py

这是可以重复的事情,以向管道中添加更多内容。

$ !! && python train_v3.py
% && python train_v2.py && python train_v3.py
^Z
[1]+  Stopped                 python train_v1.py
$ !! && python train_v4.py
% && python train_v2.py && python train_v3.py && python train_v4.py

答案2

如果你已经启动了python train_v1.py,你可以使用pgrep轮询该进程直到它消失,然后运行你的第二个Python脚本:

while pgrep -u "$USER" -fx 'python train_v1.py' >/dev/null
do
    # sleep for a minute
    sleep 60
done
python train_v2.py

通过使用-f和 ,-x您可以匹配用于启动第一个 Python 脚本的确切命令行。在某些系统上,pgrep实现一个-q选项,使其安静(就像grep -q),这意味着/dev/null不需要重定向到。

-u选项将匹配限制为您正在运行的命令(而不是同一系统上的朋友或其他人)。

如果您还没有开始第一个脚本:

正如评论中提到的,您可以在第一个脚本之后立即启动第二个脚本。第二个脚本不存在或尚未准备好运行这一事实并不重要(只要它在第一个脚本完成时准备好运行即可):

python train_v1.py; python train_v2.py

这样做将启动第二个脚本,无论第一个脚本的退出状态如何。正如您在问题中所示,使用&&代替;也可以工作,但需要第一个脚本成功完成才能启动第二个脚本。

答案3

您可以使用以下命令启动第一个脚本

python train_v1.py; touch finished

然后简单地创建一个循环,定期检查是否finished存在:

while [ ! -f finished ] ; do     
    sleep 5
done
python train_v2.py
rm finished

答案4

如果您不需要知道第一个脚本的退出状态,那么我推荐类似的东西拘萨罗南达写了什么

如果您确实需要知道退出状态(在这种情况下您可能不需要,但其他人可能会寻找执行此操作的解决方案),那就更复杂了。我写了一个Linux 小型实用程序pwait它允许您等待进程完成并找出其退出状态。

相关内容