关于systemctl服务中TYPE参数的那些事
前言最近发现mongodb总是莫名其妙的挂掉,一边查找原因,一边想着如果能自动重启就好了,于是mongodb的自动重启这件事就提上日程了。本来以为最多半小时的事,没想到还是遇到了一些奇妙的问题,为了找原因花费了不少时间。在这里记录一下,以便其他同学避免踩坑。踩坑历程再现操作系统:Ubuntu 18.04建立了一个/lib/systemd/system/mongo.service文件,在文件上写上对
前言
最近发现mongodb总是莫名其妙的挂掉,一边查找原因,一边想着如果能自动重启就好了,于是mongodb的自动重启这件事就提上日程了。本来以为最多半小时的事,没想到还是遇到了一些奇妙的问题,为了找原因花费了不少时间。在这里记录一下,以便其他同学避免踩坑。
踩坑历程再现
操作系统:Ubuntu 18.04
建立了一个/lib/systemd/system/mongo.service文件,在文件上写上对应内容
[Unit]
Description=mongodb
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
ExecStart=/dev/usr/mongodb/bin/mongod --dbpath /dev/usr/mongodb/data
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/dev/usr/mongodb/bin/mongod --shutdown --dbpath /dev/usr/mongodb/data
PrivateTmp=true
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
关键就是
Restart=always
RestartSec=5
这两句话,能够在mongodb挂掉之后自动重启。
然后使用
systemctl daemon-reload
systemctl start mongo.service
启动mongodb服务,发现半天没有反应,只能ctrl-c结束掉,感觉不太对劲。
查了一下有数据,本来以为万事大吉,但使用journalctl -xe没有看到错误,但systemctl status mongo.sercice查了一下看输出却显示没有进入running一直是start的状态
● mongo-server.service - mongodb
Loaded: loaded (/lib/systemd/system/mongo-server.service; enabled; vendor preset: enabled)
Active: activating (start) since Fri 2021-02-19 14:37:13 CST; 1min 21s ago
Process: 20076 ExecStop=/dev/usr/mongodb/bin/mongod --shutdown --dbpath /dev/usr/mongodb/data
Main PID: 18870 (code=exited, status=0/SUCCESS); Control PID: 22030 (mongod)
Tasks: 24 (limit: 4915)
CGroup: /system.slice/mongo-server.service
└─22030 /dev/usr/mongodb/bin/mongod --dbpath /dev/usr/mongodb/data
Feb 19 14:37:14 ecs-ae0d-0006 mongod[22030]: 2021-02-19T14:37:14.220+0800 I CONTROL [initandlisten] ** Remote systems will be unab
Feb 19 14:37:14 ecs-ae0d-0006 mongod[22030]: 2021-02-19T14:37:14.220+0800 I CONTROL [initandlisten] ** Start the server with --bin
Feb 19 14:37:14 ecs-ae0d-0006 mongod[22030]: 2021-02-19T14:37:14.220+0800 I CONTROL [initandlisten] ** addresses it should serve r
Feb 19 14:37:14 ecs-ae0d-0006 mongod[22030]: 2021-02-19T14:37:14.220+0800 I CONTROL [initandlisten] ** bind to all interfaces. If
Feb 19 14:37:14 ecs-ae0d-0006 mongod[22030]: 2021-02-19T14:37:14.220+0800 I CONTROL [initandlisten] ** server with --bind_ip 127.0
Feb 19 14:37:14 ecs-ae0d-0006 mongod[22030]: 2021-02-19T14:37:14.220+0800 I CONTROL [initandlisten]
Feb 19 14:37:14 ecs-ae0d-0006 mongod[22030]: 2021-02-19T14:37:14.222+0800 I FTDC [initandlisten] Initializing full-time diagnostic data
Feb 19 14:37:14 ecs-ae0d-0006 mongod[22030]: 2021-02-19T14:37:14.223+0800 I NETWORK [initandlisten] listening via socket bound to 127.0.0.1
Feb 19 14:37:14 ecs-ae0d-0006 mongod[22030]: 2021-02-19T14:37:14.223+0800 I NETWORK [initandlisten] listening via socket bound to /tmp/mong
Feb 19 14:37:14 ecs-ae0d-0006 mongod[22030]: 2021-02-19T14:37:14.223+0800 I NETWORK [initandlisten] waiting for connections on port 27017
~
于是开始各种尝试和查询资料,直到将type这个参数删除,终于一切正常了。
再次使用systemctl status mongo.sercice
● mongo-server.service - mongodb
Loaded: loaded (/lib/systemd/system/mongo-server.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2021-02-19 14:41:32 CST; 4s ago
Process: 22548 ExecStart=/dev/usr/mongodb/bin/mongod --dbpath /dev/usr/mongodb/data --fork --logpath /var/log/mongodb/mongod.log (code=exi
Main PID: 22557 (mongod)
Tasks: 24 (limit: 4915)
CGroup: /system.slice/mongo-server.service
└─22557 /dev/usr/mongodb/bin/mongod --dbpath /dev/usr/mongodb/data --fork --logpath /var/log/mongodb/mongod.log
Feb 19 14:41:31 ecs-ae0d-0006 systemd[1]: Starting mongodb...
Feb 19 14:41:31 ecs-ae0d-0006 mongod[22548]: about to fork child process, waiting until server is ready for connections.
Feb 19 14:41:31 ecs-ae0d-0006 mongod[22548]: forked process: 22557
Feb 19 14:41:32 ecs-ae0d-0006 mongod[22548]: child process started successfully, parent exiting
Feb 19 14:41:32 ecs-ae0d-0006 systemd[1]: Started mongodb.
找到了type这突破口就简单多了,顺藤摸瓜查了一下type参数的作用和用法,一切真相大白。
正确的配置方式
forking
[Unit]
Description=mongodb
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
ExecStart=/dev/usr/mongodb/bin/mongod --dbpath /dev/usr/mongodb/data --fork --logpath /var/log/mongodb/mongod.log
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/dev/usr/mongodb/bin/mongod --shutdown --dbpath /dev/usr/mongodb/data
PrivateTmp=true
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
simple或不填
[Unit]
Description=mongodb
After=network.target remote-fs.target nss-lookup.target
[Service]
#Type=forking
ExecStart=/dev/usr/mongodb/bin/mongod --dbpath /dev/usr/mongodb/data
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/dev/usr/mongodb/bin/mongod --shutdown --dbpath /dev/usr/mongodb/data
PrivateTmp=true
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
原因分析
这个Type参数的问题看似诡异,甚至好像是bug,其实隐藏着对于systemctl理解不清的问题。
这个Type参数作用是用来标志systemctl是否要跟踪处理服务进程是否启动成功,如果是forking则是需要跟踪对应的MAINPID是否存在,只有检测到MAINPID存在才能确定这个服务启动成功。这就需要保证被启动的那个服务能够按照标准协议来把pid写入对应文件或是进行对应处理。如果是simple或是不填,则systemctl认为这是一般的应用程序,只要启动就能保证成功,而不会去检查对应的服务是否真的执行成功。
这也就解释了两个现象:
- 要想把type设置成forking,需要在mongodb的启动选项上使用–fork,又由于有fork则必须带上–logpath
- 为什么设置成forking之后要等一会才能运行完sytemctl start指令,因为它要检查是否成功,而simple则一闪而过。
另附type的取值
-
Type
:定义启动时的进程行为。它有以下几种值。 -
Type=simple
:默认值,执行ExecStart
指定的命令,启动主进程 -
Type=forking
:以 fork 方式从父进程创建子进程,创建后父进程会立即退出 -
Type=oneshot
:一次性进程,Systemd 会等当前服务退出,再继续往下执行 -
Type=dbus
:当前服务通过D-Bus启动 -
Type=notify
:当前服务启动完毕,会通知Systemd
,再继续往下执行 -
Type=idle
:若有其他任务执行完毕,当前服务才会运行
参考链接
- http://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-commands.html
- https://bbs.archlinux.org/viewtopic.php?id=191669
更多推荐
所有评论(0)