[关闭]
@qidiandasheng 2019-11-29T08:55:02.000000Z 字数 2437 阅读 2351

启动守护进程

终端


介绍

有时候我们在终端启动一个Web服务。但是,一旦我退出命令行窗口,这个应用就一起退出了,无法访问了。

我在关于终端里的进程里面讲到过关于后台任务和前台任务的概念。

那是不是把任务放到后台就可以了呢?答案是否的。所以只有当你退出命令行窗口,后台任务还在执行那这个进程叫做守护进程

变为"后台任务"后,一个进程是否就成为了守护进程呢?或者说,用户退出 session(命令行窗口) 以后,"后台任务"是否还会继续执行?

Linux系统是这样设计的:

  1. 1. 用户准备退出 session
  2. 2. 系统向该 session 发出SIGHUP信号
  3. 3. session SIGHUP信号发给所有子进程
  4. 4. 子进程收到SIGHUP信号后,自动退出

上面的流程解释了,为什么"前台任务"会随着 session 的退出而退出:因为它收到了SIGHUP信号。

那么,"后台任务"是否也会收到SIGHUP信号?
这由 Shell 的huponexit参数决定的。

  1. $ shopt | grep huponexit

执行上面的命令,就会看到huponexit参数的值。注:如果是zsh的话是没有shopt命令的,不知道去哪找。

大多数Linux系统,这个参数默认关闭(off)。因此,session 退出的时候,不会把SIGHUP信号发给"后台任务"。所以,一般来说,"后台任务"不会随着 session 一起退出。

Mac上也是默认关闭的。


标准I/O

Mac上默认关闭,但是"后台任务"的标准 I/O 也是继承自当前 session。所以一旦"后台任务"读写标准 I/O,就会发现当前session已经不存在了,所以就报错终止执行。

但是简单的没有I/O操作的后台任务,关闭当前session的时候,任务还是会继续执行的。比如说wget下载资源。


nohup 命令

$ nohup command &

nohup命令对进程做了三件事。

  1. 1. 阻止SIGHUP信号发到这个进程。
  2. 2. 关闭标准输入。该进程不再能够接收任何输入,即使运行在前台。
  3. 3. 重定向标准输出和标准错误到文件nohup.out

也就是说,nohup命令实际上将子进程与它所在的 session 分离了。
注意,nohup命令不会自动把进程变为"后台任务",所以必须加上&符号。


Screen 命令

另一种思路是使用 terminal multiplexer (终端复用器:在同一个终端里面,管理多个session)。

它们可以在当前 session 里面,新建另一个 session。这样的话,当前 session 一旦结束,不影响其他 session。而且,以后重新登录,还可以再连上早先新建的 session。

新建一个session

  1. $ screen

执行以上命令之后,然后按下space或enter,就进入了一个新的session。

切回原来的session

先按下ctrl + A然后按ctrl + D

进入已经新建过的session

  1. $ screen -r

停止session

screen -r -> ctrl + C -> ctrl + D
先进入那个新建的session,然后按ctrl + C再按ctrl + D

为session指定名字

  1. $ screen -S name
  2. # 切回指定 session
  3. $ screen -r name
  4. $ screen -r pid_number
  5. # 列出所有 session
  6. $ screen -ls

PM2 命令

PM2 是一个带有负载均衡功能的 Node 应用的进程管理器。

安装

  1. apt install npm
  2. npm install -g pm2

用法

  1. $ npm install pm2 -g # 命令行安装 pm2
  2. $ pm2 start app.js -i 4 # 后台运行pm2,启动4个app.js
  3. # 也可以把'max' 参数传递给 start
  4. # 正确的进程数目依赖于Cpu的核心数目
  5. $ pm2 start app.js --name my-api # 命名进程
  6. $ pm2 list # 显示所有进程状态
  7. $ pm2 monit # 监视所有进程
  8. $ pm2 logs # 显示所有进程日志
  9. $ pm2 stop all # 停止所有进程
  10. $ pm2 restart all # 重启所有进程
  11. $ pm2 reload all # 0 秒停机重载进程 (用于 NETWORKED 进程)
  12. $ pm2 stop 0 # 停止指定的进程
  13. $ pm2 restart 0 # 重启指定的进程
  14. $ pm2 startup # 产生 init 脚本 保持进程活着
  15. $ pm2 web # 运行健壮的 computer API endpoint (http://localhost:9615)
  16. $ pm2 delete 0 # 杀死指定的进程
  17. $ pm2 delete all # 杀死全部进程

运行进程的不同方式

  1. $ pm2 start app.js -i max # 根据有效CPU数目启动最大进程数目
  2. $ pm2 start app.js -i 3 # 启动3个进程
  3. $ pm2 start app.js -x #用fork模式启动 app.js 而不是使用 cluster
  4. $ pm2 start app.js -x -- -a 23 # 用fork模式启动 app.js 并且传递参数 (-a 23)
  5. $ pm2 start app.js --name serverone # 启动一个进程并把它命名为 serverone
  6. $ pm2 stop serverone # 停止 serverone 进程
  7. $ pm2 start app.json # 启动进程, 在 app.json里设置选项
  8. $ pm2 start app.js -i max -- -a 23 #在--之后给 app.js 传递参数
  9. $ pm2 start app.js -i max -e err.log -o out.log # 启动 并 生成一个配置文件
  10. 你也可以执行用其他语言编写的app ( fork 模式):
  11. #比如:pm2 --name "webgui.yml" -f start ssmgr -x -- -c /root/.ssmgr/webgui.yml
  12. $ pm2 start my-bash-script.sh -x --interpreter bash
  13. $ pm2 start my-python-script.py -x --interpreter python

参考

Linux 守护进程的启动方法
Linux 技巧:让进程在后台可靠运行的几种方法
PM2 使用介绍

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注