终端关闭后继续执行命令的方法
在使用VSCode远程开发时,经常碰到有一些脚本要跑很长时间的情景,比如提交并跟踪MapReduce任务、训练模型、处理数据、网络IO等。这时候我们希望脚本自己在后台跑,但一个很头疼的问题是脚本跟终端挂在一起。一旦去吃饭电脑进入休眠模式,本地的VSCode很可能会断开和远程开发机的连接,进而导致终端自动退出。而之前说脚本是跑到终端上的,这就导致吃完饭回来发现脚本被终止的尴尬情况。
为了让脚本流畅的跑到后台,在这里盘点几种Linux系统下终端关闭后继续执行命令的方法。
1. 使用 nohup
nohup
(no hang up)
命令可以让你在关闭终端后继续执行命令,并将输出重定向到一个文件:
1 | nohup your_command & disown |
优点: - 简单易用,只需在命令前加上
nohup
并在后面加上 &
。 -
命令会继续运行,即使你退出终端。
缺点: - 输出会默认写入 nohup.out
文件,可能需要手动处理日志文件。如果你想输入到别的文件,使用">"指令重定向输出。
- 没有提供重新连接的功能,如果你想查看命令的执行情况,需要查看输出文件。
-
如果没有disown
命令,实测终端意外关闭是会影响后台命令的执行的。之前是nohup之后就把运行的那个终端手动exit
退出掉。但这两种办法都有个问题,不管disown
还是exit
了,新的shell都不能控制原来的脚本了。如果跑一半出问题了,只能ps -aux | grep xxx
去找之前的进程id,然后kill
掉。如果原来的shell里要配置环境变量,这里还得重新配置一波,很折磨。
2. 使用 screen
(推荐)
screen
是一个窗口管理器,可以让你在多个虚拟终端之间切换,并在断开连接后继续运行命令:
1 | screen -S session_name |
你可以使用 screen -r session_name
来重新连接到该会话。
优点: - 可以在会话之间切换,支持多窗口。 -
断开连接后命令继续运行,可以随时重新连接查看命令的执行情况,screen -r session_name
非常好用。
- 支持多用户会话共享。
缺点: - 配置和使用相对复杂,需要学习一些基本命令。 - 默认情况下,窗口管理和导航操作需要记住一些快捷键。比如要知道按下 Ctrl+A 然后按 D 来分离会话,不然会僵住。
更高级的还可以使用
tmux
,它与screen
类似,但功能更强大。由于我们这边只讨论终端关闭后执行命令,screen
完全够用,出于简单使用screen
就够了。
3. 使用 &
和
disown
你可以将命令放到后台执行,并使用 disown
命令将其从当前
shell 会话中分离:
1 | your_command & |
这个方法感觉和nohup一样,不过似乎没有默认把输出定向到nohup.out
,会丢日志。
4. 使用 at
命令
at
命令可以在指定的时间执行命令,即使你已经退出了终端:
1 | echo "your_command" | at now |
优点: - 可以定时执行命令,适用于需要延迟执行的任务。 - 即使终端关闭,命令也会按计划执行。
缺点: - 主要用于一次性任务,不适合长时间运行的后台进程。 - 没有提供重新连接的功能,无法查看命令的实时执行情况。
好处就是可以执行定时任务,at
能够支持多种时间,感觉还是比较灵活的,比如:
1 | # 指定具体时间 |
总结
- 简单的后台运行:如果你不需要重新连接查看输出,
nohup
和&
+disown
是不错的选择。 - 会话管理和多窗口:如果你需要在多个会话之间切换,并能随时查看和管理命令的执行情况,
screen
和tmux
更加适合。tmux
功能更强大,但screen
更简单易用。 - 定时任务:如果你需要定时执行任务,
at
是一个不错的选择。这里需要用一点管道知识,通过echo
命令将你要执行的命令传递给at
,使用方法是echo "your_command" | at now
,at
支持多种时间指定方式。
根据实际需求选择合适的方法,可以提高效率并更好地管理后台任务(可以安心干饭了)。