了解 Linux 中的前台和后台进程
作为一名 Linux 系统管理员,你可能有时候想让某些进程在后台运行,这样你就可以继续在终端里干别的事,而不用等着后台进程跑完。Linux 系统支持同时运行多个进程,并且可以让程序在前台或后台执行。
在 Linux 系统上把命令或进程放到后台运行是个很常见的操作,尤其是当你想释放终端,或者从 SSH 会话断开连接时。特别是一些需要跑很久的命令,比如监听事件或完成复杂任务的命令,这种需求就更明显。
Linux 提供了几种方法来运行后台进程。这篇教程会介绍几种常用方法,通过示例教你怎么用,还会讲讲如何把进程从前台移到后台,或者反过来。
在这篇教程分为四个部分:
- 如何把正在运行的命令放到后台
- 如何直接在后台启动一个命令
- 如何关闭终端但让后台任务继续运行
- 如何使用
screen
命令
把正在运行的命令放到后台
当你运行一个需要长时间执行的命令时,问题在于你的终端会被这个命令“霸占”。你没法继续用这个终端干别的事,也不能关闭终端,因为一关命令就停了。
如果有个命令正在跑,你想把它丢到后台去释放终端,可以按键盘上的 Ctrl + Z
来暂停这个进程。来看个例子:
$ sleep 10000
^Z
[1]+ Stopped sleep 10000
想看看有哪些后台任务,可以用 jobs
命令:
$ jobs -l
[1]+ 1650 Stopped sleep 10000
要把一个暂停的任务拉回前台,可以用 fg
命令:
$ fg
如果有多个暂停的任务,你得用百分号加上任务 ID 来指定哪个任务要拉回前台:
$ fg %1
好了,现在我们知道怎么把进程丢到后台,也知道怎么把它拉回来。但如果我们想让这个命令在后台继续跑怎么办?可以用 bg
命令,后面加上百分号和任务 ID。下面的命令会让暂停的任务继续运行,同时保持在后台:
$ bg %1
[1]+ sleep 10000 &
再看看任务状态,可以看到进程还在后台,但状态从“暂停”变成了“运行”:
$ jobs -l
[1]+ 1650 Running sleep 10000 &
不过得注意一件事:你不能直接关闭当前终端,不然这些后台任务也会跟着停掉。如果真想关终端又不让任务停,可以用 disown
命令“脱离”这个任务。如果后台只有一个任务,下面这个命令就够了:
$ disown
如果有多个任务,就得指定任务 ID:
$ disown %1
这时候再用 jobs
命令,你会发现这个任务已经不在列表里了。现在可以放心关闭终端,命令还会继续跑:
$ jobs -l
你可以用 ps
命令继续监控这个运行中的命令:
$ ps aux | grep sleep
linuxco+ 1650 0.0 0.0 8084 524 pts/0 S 12:27 0:00 sleep 10000
如果想停掉这个命令,可以用 kill
命令加上进程 ID:
$ kill 1650
直接在后台启动命令
前面讲了怎么把正在跑的进程丢到后台,但其实你也可以一开始就让命令在后台运行。只需要在命令后面加个 &
符号就行:
$ sleep 10000 &
[1] 1900
跟之前一样,用 jobs
命令可以看到这个任务,而且它已经是在运行状态了,不需要我们手动丢到后台:
$ jobs -l
[1]+ 1900 Running sleep 10000 &
关闭终端但让后台任务继续运行
之前我们已经看到可以用 disown
命令让任务在终端关闭后继续跑。还有一个方法是用 nohup
命令。
nohup
能让进程忽略 SIGHUP
(挂起)信号。SIGHUP
信号会在终端关闭时发送给后台任务。所以用了 nohup
,你就可以把任务丢到后台,关掉终端,任务也不会停。来看个例子:
$ nohup sleep 10000 &
[1] 1908
nohup: ignoring input and appending output to 'nohup.out'
关掉终端再重新打开,然后运行下面这个命令,可以看到任务还在跑:
$ ps aux | grep sleep
linuxco+ 1908 0.0 0.0 8084 524 ? S 13:05 0:00 sleep 10000
使用 screen 命令
到目前为止,我们讲的都是 Linux 默认的后台运行方法。不过还有一些额外的工具可以用,最常用的可能是 screen
命令。
具体安装和详细用法可以参考相关链接,这里简单讲讲怎么用:
运行
screen
命令启动一个新的“屏幕”。可以加-S
选项给它取个名字:bash$ screen -S mycommand
在新的 screen 会话里,运行你想丢到后台的命令或脚本:
bash$ /path/to/myscript.sh
按键盘上的
Ctrl + A
,然后按D
,这样会“脱离”这个 screen。然后你可以关闭终端、退出 SSH 会话,screen 里的任务还会继续跑。想看看有哪些 screen,可以用这个命令:bash$ screen -ls There is a screen on: 2741.mycommand (04/08/2021 01:13:24 PM) (Detached) 1 Socket in /run/screen/S-linuxconfig.
要重新连接到一个 screen,用下面这个命令,把下面的数字换成你自己的进程 ID:
bash$ screen -r 2741