跳过正文

如何创建Linux服务

·1792 字·
目录

create service in linux
#

source: https://segmentfault.com/a/1190000014740871

  1. 什么是Systemd Service

    • systemd 服务是一种以 .service 结尾的单元(unit)配置文件,用于控制由Systemd 控制或监视的进程。简单说,用于后台以守护精灵(daemon)的形式运行程序。
    • Systemd 广泛应用于新版本的RHEL、SUSE Linux Enterprise、CentOS、Fedora和openSUSE中,用于替代旧有的服务管理器service。
    • 基本命令:
    systemctl command xxx.service
    # 其中command可以是start、stop、restart、enable等,比如:
    systemctl start httpd.service #启动Apache服务
    systemctl stop httpd.service #停止Apache服务
    systemctl restart httpd.service #停止Apache服务
    systemctl enable mariadb.service #将MariaDB服务设为开机启动
    
  2. Systemed Service 存放位置

    • Systemd Service 位于 /etc/systemd/system(供系统管理员和用户使用),/usr/lib/systemd/system(供发行版打包者使用),我们一般使用前者即可。
  3. 编写Systemd Service

    • Systemd 服务的内容主要分为三个部分,控制单元(unit)的定义、服务(service)的定义、以及安装部分。
    1. 控制单元 [Unit]
      • 在 Systemd 中,所有引导过程中 Systemd 要控制的东西都是一个单元。基本的用法如下:
      • Description:代表整个单元的描述,可根据需要任意填写。
      • Wants:本单元启动了,它“想要”的单元也会被启动。但是这个单元若启动不成功,对本单元没有影响。
      • Requires: 这个单元启动了,那么它“需要”的单元也会被启动; 它“需要”的单元被停止了,它自己也活不了。但是请注意,这个设定并不能控制启动顺序,因为它“需要”的单元启动也需要时间,若它“需要”的单元启动还未完成,就开始启动本单元,则本单元也无法启动,所以不建议使用这个字段。
      • OnFailure:若本单元启动失败了,那么启动这个单元作为折衷。
      • Before/After:指定启动顺序。
      • 看一个实际的例子:
      [Unit]
      Description=Protect ARP list
      Wants=network-online.target
      After=network.target
      
    2. 服务本体 [service]
      • 在定义完了 Systemd 用来识别服务的单元后,我们来定义服务本体。基本的用法如下:

      • Type:服务的类型,各种类型的区别如下所示

        • simple:默认,这是最简单的服务类型。意思就是说启动的程序就是主体程序,这个程序要是退出那么一切皆休。
        • forking:标准 Unix Daemon 使用的启动方式。启动程序后会调用 fork() 函数,把必要的通信频道都设置好之后父进程退出,留下守护精灵的子进程。
        • oneshot:适用于那些被一次性执行的任务或者命令,它运行完成后便了无痕迹。因为这类服务运行完就没有任何痕迹,我们经常会需要使用 RemainAfterExit=yes。意思是说,即使没有进程存在,Systemd 也认为该服务启动成功了。同时只有这种类型支持多条命令,命令之间用;分割,如需换行可以用\。
        • dbus:这个程序启动时需要获取一块 DBus 空间,所以需要和 BusName= 一起用。只有它成功获得了 DBus 空间,依赖它的程序才会被启动。
        • ExecStart:在输入的命令是start时候执行的命令,这里的命令启动的程序必须使用绝对路径,比如你必须用/sbin/arp而不能简单的以环境变量直接使用arp。
        • ExecStop:这是一个可选的指令, 用于设置当该服务被要求停止时所执行的命令行。 语法规则与 ExecStart= 完全相同。 执行完此处设置的所有命令行之后,该服务将被视为已经停止, 此时,该服务所有剩余的进程将会根据 KillMode= 的设置被杀死(参见 systemd.kill(5))。 如果未设置此选项,那么当此服务被停止时, 该服务的所有进程都将会根据 KillSignal= 的设置被立即全部杀死。 与 ExecReload= 一样, 也有一个特殊的环境变量 $MAINPID 可用于表示主进程的PID 。
        • ExecReload:这个不是必需,如果不写则你的service就不支持restart命令。
        • 具体可参考这里

        • 看一个实际的例子:
        [Service]
        Type=oneshot
        RemainAfterExit=yes
        ExecStart=/sbin/arp -f /etc/ip-mac
        ExecReload=/sbin/arp -f /etc/ip-mac
        ExecStop=/sbin/arp -d -a
        
    3. 安装服务 [install]
      • 服务编写完之后还需要被systemd装载,定义安装单元各个字段如下:
      • WantedBy:设置服务被谁装载,一般设置为multi-user.target
      • Alias:为service设置一个别名,可以使用多个名字来操作服务。
      • Also:在安装这个服务时候还需要的其他服务
    4. 完整的 Systemd Service 配置实例
    [Unit]
    Description=Clash service
    Wants=network-online.target
    After=network.target
    User=hiroi
    [Service]
    Type=simple
    ExecStart=/home/huonwe/repos/clash/clash
    [Install]
    WantedBy=multi-user.target
    
    • 之后重新加载systemctl
    systemctl daemon-reload
    
  4. 总结

    • Systemd Service 是一种替代/etc/init.d/下脚本的更好方式,它可以灵活的控制你什么时候要启动服务,一般情况下也不会造成系统无法启动进入紧急模式。所以如果想设置一些开机启动的东西,可以试着写 Systemd Service。当然了,前提是你使用的Linux发行版是支持它的才行。