春江暮客

春江暮客的个人学习分享网站

在类Unix系统中管理长时间任务

2023-07-21 技术
在类Unix系统中管理长时间任务

在 Linux 或其他类 Unix 系统里,提前知道任务会跑很久时,我们通常会直接用 nohupscreentmux 启动。但更常见的情况是:命令已经在当前 shell 里跑起来了,过了一会才发现它会持续很久,这时候再重开一个会话就很麻烦。

这篇文章解决的就是这个场景:如何把一个已经在前台运行的长任务切到后台,并尽量在退出 shell 后继续保持运行。

在类Unix系统中,管理后台作业是提高工作效率的重要技能。本文将指导您如何使用Ctrl+Z、bg和disown命令将正在运行的作业移到后台,并确保在注销后它们能够继续运行。

主要步骤:

  • 使用Ctrl+Z暂停作业:
  • 使用bg将作业移到后台:
  • disown命令在注销后保持作业运行

开始前先注意两点

  1. 这种方法更适合普通命令行任务,不适合依赖交互输入的程序。
  2. 如果任务会持续输出大量日志,最好尽早把标准输出和错误输出重定向到文件。

使用Ctrl+Z暂停作业:

当作业在前台运行时,也就是一时不小心运行了一个长时间运行的命令后,首先使用Ctrl+Z键盘快捷键(同时按住)将其暂停。这将暂停作业并将控制权返回给Shell。

使用bg将作业移到后台:

一旦作业被暂停,您可以使用bg命令将其移到后台运行。bg命令会重新启动作业,并允许它在您处理其他任务时继续运行。 要将暂停的作业移到后台,请按照以下步骤操作:

获取job编号

使用jobs命令

jobs
# [1] + suspended python insert.py

可以看到暂停的任务为python insert.py,最前面的是命令编号,此处为1

命令迁移到后台

要将编号为1的作业移到后台,运行bg %1。

bg %1
# [1] + running python insert.py

命令从暂停状态恢复运行

使用disown命令在注销后保持作业运行:

默认情况下,在类Unix系统中注销时,与您的Shell会话关联的所有正在运行的作业都会被终止。但是,我们可以使 用disown命令将作业从Shell的作业控制中移除,使其父进程交给出事程序, 就能在注销后继续保持运行。

要将作业移出Shell并在注销后继续运行,只需要命令编号,前面可以知道是1,那么运行

disown %1

就可以了。该命令没有返回,但是重新运行jobs后可以看到已经不见了,说明成功。 一旦作业被移出Shell,即使您注销系统,它也将继续运行。 但请注意,您将无法使用Shell的作业控制功能来控制或监视作业。

一个更稳妥的实际流程

如果任务已经启动,而且你希望尽量稳妥地保住输出,推荐顺序是:

  1. Ctrl+Z 暂停任务
  2. bg %1 恢复到后台
  3. 确认任务是否持续运行
  4. 再执行 disown %1

如果任务非常重要,下一次更建议直接用 tmuxscreen 启动,而不是事后补救。

如何验证任务是否还在运行

可以用下面几种方式检查:

jobs
ps -ef | grep insert.py
tail -f your.log

如果 jobs 里已经看不到,但 ps 还能查到进程,通常说明 disown 已经成功把它从当前 shell 的作业控制里移除了。

常见问题

1. 退出 shell 后任务还是停止了

常见原因:

  1. 程序仍然依赖当前终端输入输出
  2. 没有正确从 shell 作业控制中分离
  3. 程序本身收到 HUP 后会主动退出

2. disown 之后找不到任务了

这是正常现象。

disown 的结果就是让任务不再出现在 jobs 里,后续要用 pspgrep 或日志文件来确认它是否还活着。

3. 后台任务一直刷屏,终端很乱

最直接的修复方法是下次启动时就重定向输出,例如:

python insert.py > insert.log 2>&1

延伸阅读

结论:

在类Unix系统中管理后台作业对于多任务处理和优化工作效率至关重要。首先通过使用Ctrl+Z暂停作业、然后使用bg将其移到后台以及disown命令将其与Shell分离,您可以确保作业在注销后继续运行。

请记住,如果需要,要重定向作业的输出,并考虑使用像screen或tmux这样的工具来进行更高级的作业管理。

友情链接

其它