Skip to main content

22.命令脱离终端会话运行

#命令脱离终端会话运行 什么意思呢?打开一个终端,用户命令行启动一个程序在后台运行,而一旦终端会话断开的同时,后台运行的程序也就停止了。 比如运行个go程序:

package main

import (
"fmt"
"os"
"time"
)

func main() {
pid := os.Getpid()
fmt.Println(pid) // 打印进程id
time.Sleep(1000 * time.Second) // 休眠1000秒,保持程序一直运行
}
$ go run main.go &  // 以后台方式,运行起来
[1] 50768

然后打开一个新的终端,来观察这个程序的状态,如下:

新终端窗口

$ ps aux | grep 50768
dev 50768 0.0 0.0 4973164 5712 s010 SN 2:20AM 0:00.01 /var/folders/9q/xmn0xglx2vvbcvvd91_c6zgw0000gq/T/go-build657799047/b001/exe/main
提示

可以看到进程号是在的,很是说明程序还在内存当中运行着。

而当我们强制关闭原来运行的终端时,在新的终端中:

新的终端

$ ps aux | grep 50768

结果是在内存中没有一个进程号为50768,说明这个后台程序已经随着终端的断开而退出。这是因为会话一结束,linux会自动 向由这个终端会话运行的全部后台程序发送1 SIGHUP信号,来终止全部(守护进程的程序不算)的程序。那有没有一直保持程序的运行, 哪怕终端的连接会话关闭了,程序也能一直保持运行?可以的?

推荐做法1: nohup方式运行命令

字面上的意思,用这种方式运行后台程序,terminal会话终端后,linux不会给这个程序发送SIGHUB信号,自然就没有 退出的情况发生。如打开一个终端,使用nohup方式运行go`程序,然后退出这个终端,如下: 临时终端

$ nohup go run main.go &   
[1] 12633
appending output to nohup.out

而在新的终端,依然还是可以看见这个进程号

用于观察的终端

ps aux | grep 12633
wuchuheng 12720 0.0 0.0 408103296 1264 s009 S+ 3:32PM 0:00.00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn --exclude-dir=.idea --exclude-dir=.tox 12633
wuchuheng 12633 0.0 0.5 9129872 41664 s002 SN 3:28PM 0:00.30 go run main.go

说明用这程度方式,进程是真的脱离了终端会话独自在后台运行。

tip

如果不想要输出日志,那么可以 nohup go run main.go > /dev/null 2>&1

系统自启动方式

把启动命令写在/etc/rc.local, linux启动时会自动运行这个文件上的命令。 原因是这个是系统启动级别的运行,运行这个命令是系统而不是用户,如果用户不是超级管理员 那这个进程,用户是无法杀死的。

可行但不推荐的方法-定时任务

定时任务可以运行,但给人的感觉不是很好理解,我要启动一个常驻后台的程序,不能直接启动要加入定时才行,有点费解。