@qidiandasheng
2019-11-29T16:55:02.000000Z
字数 2437
阅读 2925
终端
有时候我们在终端启动一个Web服务。但是,一旦我退出命令行窗口,这个应用就一起退出了,无法访问了。
我在关于终端里的进程里面讲到过关于后台任务和前台任务的概念。
那是不是把任务放到后台就可以了呢?答案是否的。所以只有当你退出命令行窗口,后台任务还在执行那这个进程叫做守护进程。
变为"后台任务"后,一个进程是否就成为了守护进程呢?或者说,用户退出 session(命令行窗口) 以后,"后台任务"是否还会继续执行?
Linux系统是这样设计的:
1. 用户准备退出 session
2. 系统向该 session 发出SIGHUP信号
3. session 将SIGHUP信号发给所有子进程
4. 子进程收到SIGHUP信号后,自动退出
上面的流程解释了,为什么"前台任务"会随着 session 的退出而退出:因为它收到了SIGHUP信号。
那么,"后台任务"是否也会收到SIGHUP信号?
这由 Shell 的huponexit
参数决定的。
$ shopt | grep huponexit
执行上面的命令,就会看到huponexit参数的值。注:如果是zsh的话是没有shopt
命令的,不知道去哪找。
大多数Linux系统,这个参数默认关闭(off)。因此,session 退出的时候,不会把SIGHUP信号发给"后台任务"。所以,一般来说,"后台任务"不会随着 session 一起退出。
Mac上也是默认关闭的。
Mac上默认关闭,但是"后台任务"的标准 I/O 也是继承自当前 session。所以一旦"后台任务"读写标准 I/O,就会发现当前session已经不存在了,所以就报错终止执行。
但是简单的没有I/O操作的后台任务,关闭当前session的时候,任务还是会继续执行的。比如说wget
下载资源。
$ nohup command &
nohup命令对进程做了三件事。
1. 阻止SIGHUP信号发到这个进程。
2. 关闭标准输入。该进程不再能够接收任何输入,即使运行在前台。
3. 重定向标准输出和标准错误到文件nohup.out。
也就是说,nohup命令实际上将子进程与它所在的 session 分离了。
注意,nohup命令不会自动把进程变为"后台任务",所以必须加上&符号。
另一种思路是使用 terminal multiplexer (终端复用器:在同一个终端里面,管理多个session)。
它们可以在当前 session 里面,新建另一个 session。这样的话,当前 session 一旦结束,不影响其他 session。而且,以后重新登录,还可以再连上早先新建的 session。
$ screen
执行以上命令之后,然后按下space或enter,就进入了一个新的session。
先按下ctrl + A
然后按ctrl + D
$ screen -r
screen -r
-> ctrl + C
-> ctrl + D
先进入那个新建的session,然后按ctrl + C
再按ctrl + D
。
$ screen -S name
# 切回指定 session
$ screen -r name
$ screen -r pid_number
# 列出所有 session
$ screen -ls
PM2 是一个带有负载均衡功能的 Node 应用的进程管理器。
apt install npm
npm install -g pm2
$ npm install pm2 -g # 命令行安装 pm2
$ pm2 start app.js -i 4 # 后台运行pm2,启动4个app.js
# 也可以把'max' 参数传递给 start
# 正确的进程数目依赖于Cpu的核心数目
$ pm2 start app.js --name my-api # 命名进程
$ pm2 list # 显示所有进程状态
$ pm2 monit # 监视所有进程
$ pm2 logs # 显示所有进程日志
$ pm2 stop all # 停止所有进程
$ pm2 restart all # 重启所有进程
$ pm2 reload all # 0 秒停机重载进程 (用于 NETWORKED 进程)
$ pm2 stop 0 # 停止指定的进程
$ pm2 restart 0 # 重启指定的进程
$ pm2 startup # 产生 init 脚本 保持进程活着
$ pm2 web # 运行健壮的 computer API endpoint (http://localhost:9615)
$ pm2 delete 0 # 杀死指定的进程
$ pm2 delete all # 杀死全部进程
$ pm2 start app.js -i max # 根据有效CPU数目启动最大进程数目
$ pm2 start app.js -i 3 # 启动3个进程
$ pm2 start app.js -x #用fork模式启动 app.js 而不是使用 cluster
$ pm2 start app.js -x -- -a 23 # 用fork模式启动 app.js 并且传递参数 (-a 23)
$ pm2 start app.js --name serverone # 启动一个进程并把它命名为 serverone
$ pm2 stop serverone # 停止 serverone 进程
$ pm2 start app.json # 启动进程, 在 app.json里设置选项
$ pm2 start app.js -i max -- -a 23 #在--之后给 app.js 传递参数
$ pm2 start app.js -i max -e err.log -o out.log # 启动 并 生成一个配置文件
你也可以执行用其他语言编写的app ( fork 模式):
#比如:pm2 --name "webgui.yml" -f start ssmgr -x -- -c /root/.ssmgr/webgui.yml
$ pm2 start my-bash-script.sh -x --interpreter bash
$ pm2 start my-python-script.py -x --interpreter python