Linux下注册系统服务

前言

init

历史上,Linux 的启动一直采用 init 进程。在类 Unix 的计算机操作系统中,init(初始化的简称)是在启动计算机系统期间启动的第一个进程。init 是一个守护进程,它将持续运行,直到系统关闭。它是所有其他进程的直接或间接的父进程。因为 init 的参数全在/etc/init.d目录下,所以使用 init 启动一个服务,应该这样做:

sudo /etc/init.d/nginx start

service

service 是一个运行System V init的脚本命令。那么什么是 System V init 呢?也就是 /etc/init.d 目录下的参数。所以分析可知 service 是去/etc/init.d目录下执行相关程序,服务配置文件的存放目录就是/etc/init.d。

使用 service 启动一个服务

service nginx start

可以理解成 service 就是 init.d 的一种实现方式。
所以这两者启动方式(或者是停止、重启)并没有什么区别。

sudo /etc/init.d/nginx start
// 等价于
service nginx start

但是这两种方式均有如下缺点:

  1. 启动时间长。init 进程是串行启动,只有前一个进程启动完,才会启动下一个进程。
  2. 启动脚本复杂。init 进程只是执行启动脚本,不管其他事情。脚本需要自己处理各种情况,这往往使得脚本变得很长。

systemd

systemd 就是为了解决这些问题而诞生的。它的设计目标是,为系统的启动和管理提供一套完整的解决方案。
根据 Linux 惯例,字母d是守护进程(daemon)的缩写。 systemd 这个名字的含义,就是它要守护整个系统。

使用了 systemd,就不需要再用 init 了。systemd 取代了initd,成为系统的第一个进程(pid 等于 1),其他进程都是它的子进程。

systemd 的优点是功能强大,使用方便,缺点是体系庞大,非常复杂。systemd 并不是一个命令,而是一组命令,涉及到系统管理的方方面面。systemctl 是 systemd 的主命令,用于管理系统。

总结

  • init 是最初的进程管理方式
  • service 是 init 的另一种实现
  • systemd 则是一种取代 initd 的解决方案

使用

将程序注册为系统服务,需要编辑 xxx.service 配置文件,并将文件存储到 /usr/lib/systemd/system/ 目录下

配置文件介绍

[Unit] 区块:启动顺序与依赖关系。
  • Description:简短描述
  • Documentation:文档地址
  • Requires:当前 Unit 依赖的其他 Unit,如果它们没有运行,当前 Unit 会启动失败
  • Wants:与当前 Unit 配合的其他 Unit,如果它们没有运行,当前 Unit 不会启动失败
  • BindsTo:与Requires类似,它指定的 Unit 如果退出,会导致当前 Unit 停止运行
  • Before:如果该字段指定的 Unit 也要启动,那么必须在当前 Unit 之后启动
  • After:如果该字段指定的 Unit 也要启动,那么必须在当前 Unit 之前启动
[Service] 区块:启动行为
  • Type:定义启动时的进程行为。它有以下几种值。
    • Type=simple:默认值,执行ExecStart指定的命令,启动主进程
    • Type=forking:以 fork 方式从父进程创建子进程,创建后父进程会立即退出
    • Type=oneshot:一次性进程,Systemd 会等当前服务退出,再继续往下执行
    • Type=dbus:当前服务通过D-Bus启动
    • Type=notify:当前服务启动完毕,会通知Systemd,再继续往下执行
    • Type=idle:若有其他任务执行完毕,当前服务才会运行
  • ExecStart:启动当前服务的命令
  • ExecStartPre:启动当前服务之前执行的命令
  • ExecStartPost:启动当前服务之后执行的命令
  • ExecReload:重启当前服务时执行的命令
  • ExecStop:停止当前服务时执行的命令
  • ExecStopPost:停止当其服务之后执行的命令
  • RestartSec:自动重启当前服务间隔的秒数
  • Restart:定义何种情况 Systemd 会自动重启当前服务,可能的值包括always(总是重启)、on-success、on-failure、on-abnormal、on-abort、on-watchdog
  • TimeoutSec:定义 Systemd 停止当前服务之前等待的秒数
  • Environment:指定环境变量

注意:Type=simple 时,如果启动脚本中 以 nohup & 形式启动进程时,此时启动脚本后会自动 kill 当前服务。

[Install] 区块

定义如何安装这个配置文件,即怎样做到开机启动。

  • WantedBy字段:表示该服务所在的 Target。

Target的含义是服务组,表示一组服务。默认的启动 Target 就是 multi-user.target(多用户命令行))。在这个组里的所有服务,都将开机启动。这就是为什么 systemctl enable 命令能设置开机启动的原因。

程序准备

这里我们注册的服务名为 test_systemd.service

[Unit]
Description=test program
After=network.target
Wants=network.target

[Service]
Type=simple
ExecStart=/root/test_systemd/test_systemd_start.sh
ExecStop=/bin/kill -9 $MAINPID
ExecReload=/bin/kill -s HUP $MAINPID

[Install]
WantedBy=multi-user.target

服务启动要执行的程序为 test_systemd_start.sh

#!/bin/bash
/root/test_systemd/test_while.sh >> /dev/null

test_while.sh 程序内容为

#!/bin/bash
i=1
while [ $i -le 10000  ];do
    let i=$i+1
    sleep 10
    echo `date` >> /root/test_systemd/while_sh.log
done

总结如下

  1. 我们要注册的服务,启动要做的操作为:开启一个进程,每隔10秒,向 while_sh.log 日志文件追加一条日志记录
  2. 停止要做的操作为:将上面的进程给 kill 掉

验证

chmod a+x test_systemd_start.sh # 添加执行权限
chmod a+x test_while.sh
cp test_systemd.service /usr/lib/systemd/system/ # 将配置文件拷贝到指定目录
systemctl daemon-reload # 重新加载配置文件
systemctl start test_systemd # 等价于 systemctl start test_systemd.service
tail -f /root/test_systemd/while_sh.log

常用命令为

systemctl  status  xxx      # 查看服务状态
systemctl  start  xxx       # 启动服务
systemctl  stop  xxx        # 停止服务
systemctl  restart  xxx     # 重启服务
systemctl  enable  xxx      # 启用服务开机自启动
systemctl  disable  xxx     # 禁止服务开机自启动

如果启动失败,可以通过以下命令排查

systemctl  status  xxx
journalctl -xe

参考

Systemd 入门教程:命令篇
Systemd 入门教程:实战篇
Linux init、service、systemctl 三者区别
Linux:注册系统服务

posted @ 2024-04-20 18:59  strongmore  阅读(235)  评论(0编辑  收藏  举报