使用systemctl托管linux后台程序

在 Linux 中如果想让一个程序保持在后台运行,一般会使用 nohub 命令,或者是使用 screen 之类的命令创建一个独立的会话来运行。但是如果还想实现一些额外的功能,比如:跟随系统自动启动、进程挂掉后自动重启等,就会比较麻烦了。

还有一种选择是将需要后台运行的程序作为一个 service(服务),交给系统中的 systemctl 组件托管。就像 Nginx、MySQL 等程序一样,不仅可以自动开机启动,而且启动、停止程序也方便了很多。

关于 SYSTEMCTL

systemctl 是 Linux 系统中使用最广泛的系统服务管理命令行工具之一,它是 Systemd init 系统的一部分,用于启动、停止和管理系统服务。

早期版本的 Linux 中并不包含 Systemd,而是使用 service 命令管理系统服务。新的 Linux 操作系统(比如 CentOS 7/Ubuntu 16.04)使用 Systemd 来管理系统服务,因此 systemctl 已经成为管理系统服务的标准方式。但为了向后兼容 Systemd 仍然包含对 service 命令的支持。

因此在现在的 Linux 系统中,servicesystemctl 命令都可以用来管理当系统服务。

创建服务

这里以一个开源的内网穿透工具 FRP 作为例子,为服务端程序配置一个服务,并保持在后台运行。

每一个服务都有一个对应的配置文件,在系统的 /usr/lib/systemd/system/ 目录下,后缀为 .service。文件名就是服务的名字,在控制服务的的时候会用到。比如 Nginx 的服务名就叫 nginx,重启服务对应的命令是: service nginx restart

理论上服务名可以随便取,不过建议选个简短有意义的名字。这里新建的服务叫 frps

创建文件 /usr/lib/systemd/system/frps.service ,文件的内容如下:

[Unit]
Description=frps service
After=network.target syslog.target
Wants=network.target
[Service]
Type=simple
ExecStart=/usr/local/frp/frps -c ./frps.toml
WorkingDirectory=/usr/local/frp
[Install]
WantedBy=multi-user.target

文件中常用可配置的各项解释如下:

Unit 区块

  • Description:描述了该服务的信息,一般是用于说明和显示(比如运行 service xxx status 会显示)。
  • After:指定这些服务启动后,再启动此服务。这里指定了 network.targetsyslog.target,表示需要在网络服务和系统日志服务启动之后再启动 FRP。
  • Before:先启动本服务,再启动指定的这些服务,与 After 相反。
  • Requires:依赖的其它服务,列在其中的项会在这个服务启动时同时被启动。并且,如果其中任意一个服务启动失败,这个服务也会被终止。
  • Wants:在启动当前服务时同时启动 Wants 中的其他项。与 Requires 相似,但 Wants 不会管其他的服务是否启动成功。这里指定了 network.target,表示 FRP 启动会同时启动 network.target 服务。
Requires / Wants 与 After/Before 不同,不保证顺序,所以一般需要搭配使用。

Service 区块

  • Type:指定了该服务的类型。一般是 simple,表示该服务是一个简单的可执行程序。
  • ExecStart:指定了启动该服务时要执行的程序路径和参数。按实际填写,程序路径要使用绝对路径。后面的是 -c ./frps.toml 都是传递给程序的启动参数。
  • ExecReload:重载当前服务时执行的命令。配置后 service xxx reload 才会有效,不需要可以不写。
  • ExecStop:停止当前服务时执行的命令。如果不写,执行 service xxx stop 时会直接停止掉程序。
  • WorkingDirectory:指定了该服务的工作目录。如果不需要也可以省略这项。这里是因为在传递给 FRP 的参数中使用了相对路径,所以才设成程序所在目录。
  • Environment:为服务指定环境变量
  • User:指定运行服务的用户
  • Group:指定运行服务的用户组

Install 区块

  • WantedBy:指定了该服务的安装位置。这里是 multi-user.target,表示该服务将被安装到 multi-user.target 目标中,即系统的多用户模式下运行,一般不用改。

创建好后,在终端里运行 service frps status 应该就能看到相应的输出了。不过此时服务还未生效,处于未激活(inactive)的状态。

systemctl状态

在终端内输入:

systemctl daemon-reload # 重载systemctl
systemctl enable frps   # 在 systemctl 中将 frps 服务状态设为启用
service frps start  # 启动 frps 服务(刚配置好服务需要手动启动一下,或者重启 Linux也行)

这样就成功在 systemctl 中管理刚才创建的服务了。

通过 service frps status 可以看到相关的运行信息,不出意外的话服务应该处于活动(active)状态。

启用systemctl服务

最下方显示的是标准IO流中的内容(也就是直接在终端中运行程序,程序显示出来的内容)。如果 service 不能正常启动程序,可以根据下面的信息进行排查。

有些系统中,使用 status 查看状态时会进入一个交互模式,此时按方向键是滚动屏幕内容,按 q 退出。

管理服务

配置好服务后,就可以直接通过 service 相关的命令启停程序了。常用的命令如下(其中 xxx 要换成相应服务名):

service xxx start   # 启动服务
service xxx stop    # 停止服务
service xxx restart # 重启服务(先停止再启动)
service xxx status  # 查看指定服务的状态

移除服务

如果需要移除这个服务,与创建服务反向操作即可。还是以 frps 服务为例,终端里运行:

service frps stop # 启动 frps 服务
systemctl disable frps  # 在 systemctl 中禁用 frps 服务
systemctl daemon-reload # 重载systemctl

禁用服务后,将对应的文件 /usr/lib/systemd/system/frps.service 删除即可。

配置服务自动重启

对于一些需要在退出后自动重启的服务(比如进程意外崩溃后自动恢复),也可以交给 systemctl 管理。

配置服务进程退出后自动重启,还需要在 Service 区块中额外添加几项:

  • Restart:是否自动重启,可选:always / noalways 表示总是自动重启(除非通过systemctl stop);no 表示不自动重启(默认值)
  • RestartSec:重启的间隔秒数(数字),当进程退出后,等待这个时间之后再启动进程。默认值0.1
  • StartLimitInterval: 最多重启次数。如果服务进程一直重启失败,超过这么多次后就不再继续重启了。0表示不限次数重启。

举个frp的客户端(frpc)的例子,有时候网络中断或者其他原因会导致frpc的进程自动退出。这时想等待10s之后再重启程序,最多重试5次,就可以在Service区块里加上

Restart=always
RestartSec=10
StartLimitInterval=5

修改完之后需要 systemctl daemon-reload 重新加载一下,才会生效。

配置好后可以简单验证一下。启动frpc服务后,直接 kill 进程,然后通过 systemctl status 查看服务状态。

如下图,可以看到刚kill完进程已退出,过了10s后进程又处于运行中了,自动重启生效了。

另外关于自动重启,这里也附上一篇写得比较详细的文章,有需要的话可以参考:

https://blog.csdn.net/ownfire/article/details/124120927

除特别注明外,本站内容皆为 咸鱼先锋 原创,可自由引用,但请注明来源和链接。
https://xyuxf.com/archives/2264
欢迎关注 咸鱼先锋 (微信号公众号:xyuxf),获取干货推送
THE END
分享
二维码
< <上一篇
下一篇>>
文章目录
关闭
目 录