systemd systemctl ExecStart超时处理

1
Job for xxx.service failed because a timeout was exceeded. See "systemctl status leanote.service" and "journalctl -xe" for details.

在CentOS上编写自定义启停服务脚本时,有时脚本文件中特意设置很长的等待时间或要完成任务的时间本身就很长,例如下面的脚本:

1
2
3
4
5
6
while true
do
  echo 'trying netcat'
  # do something
  sleep 300s
done

如果在后台服务脚本中直接执行该脚本,就会收到超时信息,服务自动终止,这是我所不希望看到的:

1
2
3
4
5
6
7
8
9
10
11
12
[Unit]
Description=leanote.service
After=network.target mongod.service

[Service]
Type=forking
ExecStart=/data/leanote/bin/run.sh
ExecStop=/bin/kill -SIGINT $MAINPID
ExecReload=/bin/kill -USR2 $MAINPID

[Install]
WantedBy=multi-user.target

执行“systemctl status 服务名”查看服务状态,可以看到由于systemd一直在等待run.sh脚本执行完成,但超时时间到了,自动结束了服务:leanote.service start operation timed out. Terminating.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# systemctl status leanote.service
● leanote.service
   Loaded: loaded (/usr/lib/systemd/system/leanote.service; enabled; vendor preset: disabled)
   Active: failed (Result: timeout) since 五 2020-12-04 21:32:28 CST; 2min 24s ago
  Process: 4279 ExecStart=/data/leanote/bin/run.sh & (code=killed, signal=TERM)

12月 04 21:30:58 db-srv run.sh[4279]: DEBUG 21:30:58  revel controller_type.go:64: Registered controller: App\memberindex    section=controller
12月 04 21:30:58 db-srv run.sh[4279]: DEBUG 21:30:58  revel controller.go:523: RegisterController:Registered controller  section=controller controller=App\\memberindex
12月 04 21:30:58 db-srv run.sh[4279]: DEBUG 21:30:58  revel controller_type.go:64: Registered controller: App\memberuser     section=controller
12月 04 21:30:58 db-srv run.sh[4279]: DEBUG 21:30:58  revel controller.go:523: RegisterController:Registered controller  section=controller controller=App\\memberuser
12月 04 21:30:58 db-srv run.sh[4279]: DEBUG 21:30:58  revel server.go:106: InitServerEngine: Found server engine and invoking  section=server name=go
12月 04 21:30:58 db-srv run.sh[4279]: Listening on.. 0.0.0.0:9000
12月 04 21:32:28 db-srv systemd[1]: leanote.service start operation timed out. Terminating.
12月 04 21:32:28 db-srv systemd[1]: Failed to start leanote.service.
12月 04 21:32:28 db-srv systemd[1]: Unit leanote.service entered failed state.
12月 04 21:32:28 db-srv systemd[1]: leanote.service failed.

解决这个问题也很简单,借助“bash -c”,bash -c的作用是将一个长字符串当做一条完整的命令来执行,如果在脚本路径后面加上后台运行符号(&),run.sh脚本就会在后台运行,不会一直处于挂起状态,systemd也就不会一直等待run.sh执行完成了。经过测试,完全符合预期,因此,最终的解决方案是:

1
ExecStart=/bin/bash -c "/data/leanote/bin/run.sh &"