Systemd服务笔记

前言

今天离线数仓调度 airflow 任务出现问题,经过查看服务状态,确定是 airflow worker 的存在问题,并行dag最大是数量16,但是发现不止16个, 而查看配置文件是对的,所以就怀疑是启动脚本存在问题。发现启动是以 systemd 服务化启动的,确定了是停止脚本的问题。所以回头来记录一下 systemd 的知识。

systemd 介绍

systemdLinux 的系统基础组件的几个,提供了一个系统和服务管理,运行以 PID 为 1 并负责启动其他程序

systemd 特性

  • 并行启动
  • 按需启动Daemon进程
  • 利用 cgroups 监视进程
  • 支持快照和系统恢复
  • 维护挂载点和自动挂载点
  • 各个服务间的依赖关系精密控制

systemd 基本使用

分析场景

  • 显示系统状态 systemctl status

tree 状显示

  • 激活的Unit systemctlsystemctl list-units

活动状态的服务

  • 失败的Unit systemctl --failed
  • 所有可用的Unit systemctl list-unit-files

/usr/lib/systemd/system//etc/systemd/system

  • 显示指的Unit状态 systemctl status <PID>

具体一饿指的的信息

Unit使用

一个配置文件可以描述内容 .service 系统服务、 .mount 挂载点、 .sockets Socket .device 系统设备、.swap 交换分区 、.path 文件路径、等等, 具体查看 https://man.archlinux.org/man/systemd.unit.5

  • 激活 systemctl start <名称>
  • 停止 systemctl stop <名称>
  • 重启 systemctl restart <名称>
  • 重新加载配置 systemctl reload <名称>
  • 状态 systemctl status <名称>
  • 是否自动启动 systemctl is-enabled <名称>
  • 开机自动启动 systemctl enable <名称>
  • 取消自动启动 systemctl disable <名称>
  • 禁用 systemctl mask <名称>
  • 取消禁用 systemctl unmask <名称>
  • 帮助 systemctl help <名称>
  • 重新载入 systemd 系统配置 systemctl daemon-reload

systemd 的文件

Unit 配置文件的位置

  • /usr/lib/systemd/system 第三方软件的系统Unit
  • /etc/systemd/system 系统管理员安装的Unit

Unit 文件的基本构成

  • 第一部分 unit, 记录unit文件的通用信息

    • 1)Description:名称和基本功能
    • 2)Documentation:帮助文档
    • 3)Require:当前服务是需要哪个特定的服务的,比如:Require=nginx.service,这就表示当前服务是需要nginx服务,那么在启动当前这个服务的时候,会自动将nginx也启动起来;而且一旦发现nginx服务停止了,那么当前这个服务也就会自动停止 (require无法指定启动次序,需要结合Before After来用,否则经常出现各种问题)
    • 4)Wants:建议同时启动某服务,比如:Wants=nginx.service 表示系统中最好启动nginx服务,但是即使不启动nginx,当前这个服务也没啥影响
    • 5)Before:定义启动顺序,例子:Before=nginx.service,表示该服务需要在nginx启动之前启动
    • 6)After:定义启动顺序,同上
    • 7)Condition…=:有许多指令Condition允许管理员在启动单元之前测试某些条件
    • 8)Assert…=: 与以 开头的指令类似Condition,这些指令检查运行环境的不同方面以决定单元是否应该激活。但是,与Condition指令不同,否定结果会导致该指令失败。
  • 7)Conflicis:当一个服务启动的时候,会立刻停止与之相冲突的服务

  • 第二部分 service, 记录service具体信息(启动、配置等)

    • 1)Type:指定service的类型
      • simple : 服务的主进程在 start 行中指定。
      • forking: 当服务 fork 子进程时使用此服务类型,几乎立即退出父进程。这systemd表明即使父进程退出,该进程仍在运行。需要一个后台守护进程一直在运行,比如运行nginxapachesshd
      • oneshot: 程序执行完成就自动结束了,没有后台进程,比如执行一个shell
      • dbus: 这表明该单元将在 D-Bus 总线上命名
      • notify: 这表示服务将在完成启动时发出通知
      • idle: 这表示在调度所有作业之前不会运行服务
    • 2)ExecStart:指定如何启动服务(指定启动服务要执行的命令)
      • 如果服务类型是oneshot类型,那么可以直接写上他要执行命令即可,通常不能添加参数和选项
      • 如果服务类型不是oneshot类型,那么在写要执行的命令的时候,可以添加一些参数,比如指定选项、配置文件、用户 (如果要执行多个命令,那么多个命令之间用;分割,如果需要换行可以用 来续行)
    • 3)ExecStartPre, ExecStartPost:指定在执行启动服务之前、之后要执行什么命令
    • 4)ExecStop:停止服务
    • 5)ExecStopPost:这可用于指定要在停止命令之后执行的命令。
    • 6)Restart:表示systemd将尝试自动重新启动服务的情况
    • 7)PIDFile:指定pid文件的路径
    • 8)TimeoutSec:这配置systemd在停止或停止服务之前将等待的时间量,然后将其标记为失败或强制终止它
    • 9)RestartSec:如果启用了自动重新启动服务,则指定在尝试重新启动服务之前等待的时间量。
    • 10)EnvironmentFile:环境文件配置,使用其中的环境变量
  • 第三部分 install, 记录安装信息(运行方式)

    • WantedBy:指定运行级别, WantedBy=multi-user.target
    • RequiredBy:该指令与指令非常相似WantedBy,但它指定了一个必需的依赖项,如果不满足该依赖项将导致激活失败。

编写一个简单的 Unit 文件

# /home/xxx/apps/xxx-app-env.conf
# XXX APP 环境变量文件
APP_HOME=/home/xxx/apps
# This file is the systemd service for XXXXX. Put this file in /usr/lib/systemd/system per default
[Unit]
Description=Service for XXX APP
After=mysqld.service
Wants=mysqld.service

[Service]
EnvironmentFile=/home/xxx/apps/xxx-app-env.conf
User=root
Group=root
Type=simple
ExecStart=/bin/sh -c "/usr/bin/su - xxx -c 'java -jar ${APP_HOME}/app.jar > /var/log/xxx/app.log'"
Restart=on-failure
RestartSec=10s

[Install]
WantedBy=multi-user.target

REF

comments powered by Disqus