在类Unix系统中管理长时间任务
在 Linux 或其他类 Unix 系统里,提前知道任务会跑很久时,我们通常会直接用 nohup、screen 或 tmux 启动。但更常见的情况是:命令已经在当前 shell 里跑起来了,过了一会才发现它会持续很久,这时候再重开一个会话就很麻烦。
这篇文章解决的就是这个场景:如何把一个已经在前台运行的长任务切到后台,并尽量在退出 shell 后继续保持运行。
在类Unix系统中,管理后台作业是提高工作效率的重要技能。本文将指导您如何使用Ctrl+Z、bg和disown命令将正在运行的作业移到后台,并确保在注销后它们能够继续运行。
主要步骤:
- 使用Ctrl+Z暂停作业:
- 使用bg将作业移到后台:
- disown命令在注销后保持作业运行
开始前先注意两点
- 这种方法更适合普通命令行任务,不适合依赖交互输入的程序。
- 如果任务会持续输出大量日志,最好尽早把标准输出和错误输出重定向到文件。
使用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的作业控制功能来控制或监视作业。
一个更稳妥的实际流程
如果任务已经启动,而且你希望尽量稳妥地保住输出,推荐顺序是:
Ctrl+Z暂停任务bg %1恢复到后台- 确认任务是否持续运行
- 再执行
disown %1
如果任务非常重要,下一次更建议直接用 tmux 或 screen 启动,而不是事后补救。
如何验证任务是否还在运行
可以用下面几种方式检查:
jobs
ps -ef | grep insert.py
tail -f your.log
如果 jobs 里已经看不到,但 ps 还能查到进程,通常说明 disown 已经成功把它从当前 shell 的作业控制里移除了。
常见问题
1. 退出 shell 后任务还是停止了
常见原因:
- 程序仍然依赖当前终端输入输出
- 没有正确从 shell 作业控制中分离
- 程序本身收到 HUP 后会主动退出
2. disown 之后找不到任务了
这是正常现象。
disown 的结果就是让任务不再出现在 jobs 里,后续要用 ps、pgrep 或日志文件来确认它是否还活着。
3. 后台任务一直刷屏,终端很乱
最直接的修复方法是下次启动时就重定向输出,例如:
python insert.py > insert.log 2>&1
延伸阅读
结论:
在类Unix系统中管理后台作业对于多任务处理和优化工作效率至关重要。首先通过使用Ctrl+Z暂停作业、然后使用bg将其移到后台以及disown命令将其与Shell分离,您可以确保作业在注销后继续运行。
请记住,如果需要,要重定向作业的输出,并考虑使用像screen或tmux这样的工具来进行更高级的作业管理。
- 原文作者:春江暮客
- 原文链接:https://www.bobobk.com/861.html
- 版权声明:本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。