Systemd

Summary: Author: 张亚飞 | 阅读时间: 3 minute read | Published: 2016-04-22
Filed under Categories: LinuxTags: Note,

Systemd Linux 进程管理


开启服务资源消耗监测

# systemctl show docker | grep Accounting
CPUAccounting=no
BlockIOAccounting=no
MemoryAccounting=no
  • How to enable the accounting
# systemctl set-property zs_mall_service.service MemoryAccounting=yes
# systemctl set-property zs_mall_service.service CPUAccounting=yes
# systemctl set-property zs_mall_service.service TasksAccounting=yes
  • Checking…
# systemctl show docker | grep Accounting
CPUAccounting=yes
BlockIOAccounting=no
MemoryAccounting=yes

服务进程管理

本节将从service单元文件的编写(基础选项,起停及重载选项,依赖性处理选项,资源限制选项等),对服务进程基本操作,进程和进程组的查看和如何更好的杀死服务进程 四个方面介绍systemd下服务进程的管理.

service单元文件

systemd 的单元文件是受 XDG Desktop Entry .desktop 文件启发而产生,而最初起源是 Windows 下的 .ini 文件, .service 文件是 systemd 的本地配置文件,类似于 sysvinit 中的 /etc/init.d 里脚本的作用.

一个 .service 文件一定包含三个 Sections ,分别是[Unit],[Service],[Install].每个 Section 有不同的 Key,

例如

Unit 常见有 Description,Documentation,RequiresService 常见有 TypeInstall 常见有 Alias,WantedBy=,RequiredBy

具体查看 man systemd.unit,以及 man systemd.service systemd 单元文件的加载路径(优先级从上到下依次降低):

  • 系统模式
/etc/systemd/system/*
/run/systemd/system/*
/usr/lib/systemd/system/*
...

注: debian 下,关注:[/lib/systemd/system/*] 目录.一般来说,自己定义的 [.service] 放在 [/etc/systemd/system] 下.


systemd 下编写守护进程遵循的几点规则

开发人员需要了解 systemd 的更多细节.比如您打算开发一个新的系统服务,就必须了解如何让这个服务能够被 systemd 管理.这需要您注意以下这些要点: 后台服务进程代码不需要执行两次派生来实现后台精灵进程,只需要实现服务本身的主循环即可.(传统编写守护进程要至少调用一次fork,然后停止父进程) 不要调用 setsid(),交给 systemd 处理 不再需要维护 pid 文件.(传统编写守护进程,会自己在某个目录下,生成pid文件,一是记录本守护进程pid,另外一点是防止本守护进程被多次重启而导致出错或者导致多个实例在运行) Systemd 提供了日志功能,服务进程只需要输出到 stderr 即可,无需使用 syslog.(传统编写守护进程我们要将标准输出,出错,输入关闭或者重定向,日志信息都是发往 rsyslog) 处理信号 SIGTERM,这个信号的唯一正确作用就是停止当前服务,不要做其他的事情.(传统守护进程一般 SIGTERM 也是用来做这种事情的) SIGHUP 信号的作用是重启服务.(传统数据进程一般 SIGHUP 也是做这种事情的) 需要套接字的服务,不要自己创建套接字,让 systemd 传入套接字.(这个承接 systemd 快速启动优点而设立的,可以实现这个特点,也可以不实现) 使用 sd_notify() 函数通知 systemd 服务自己的状态改变.一般地,当服务初始化结束,进入服务就绪状态时,可以调用它.(没用过)

coam_service.service 服务配置运行文件示例

sudo vi /lib/systemd/system/coam_service.service

* [Unit]
Description=coam-cache-service
* [Service]
ExecStart=/data/home/coam/DevC/mysql2redis/build/coam_service
#ExecStop=/bin/kill -TERM $MAINPID
#ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
After=network.target
* [Install]
WantedBy=multi-user.target

其它配置

  • Ubuntu 管理一直停留在 A stop job is running for LSB: MYSQL init script (... / no limit),

查看 /lib/systemd/system/cs-mysqld.service 有以下配置:

# Disable service start and stop timeout logic of systemd for mysqld service.
TimeoutSec=0

TimeoutSec 表示重启服务的超时时间,默认以系统的设置:

  • /etc/systemd/system.conf
DefaultTimeoutStartSec=90s
DefaultTimeoutStopSec=90s

常用 Unit 管理命令

# 立即启动一个服务
$ sudo systemctl start apache.service

# 立即停止一个服务
$ sudo systemctl stop apache.service

# 重启一个服务
$ sudo systemctl restart apache.service

# 杀死一个服务的所有子进程
$ sudo systemctl kill apache.service

# 重新加载一个服务的配置文件
$ sudo systemctl reload apache.service

# 重载所有修改过的配置文件
$ sudo systemctl daemon-reload

# 显示某个 Unit 的所有底层参数
$ systemctl show httpd.service

其它说明

Systemd 默认从目录 /etc/systemd/system/ 读取配置文件.但是,里面存放的大部分文件都是符号链接,指向目录 /usr/lib/systemd/system/ ,真正的配置文件存放在那个目录. systemctl enable 命令用于在上面两个目录之间,建立符号链接关系.

# 设定为开机启动服务
$ sudo systemctl enable clamd@scan.service
# 关闭开机启动服务
$ sudo systemctl disable clamd@scan.service

等同于

$ sudo ln -s '/usr/lib/systemd/system/clamd@scan.service' '/etc/systemd/system/multi-user.target.wants/clamd@scan.service'

如果配置文件里面设置了开机启动,systemctl enable命令相当于激活开机启动. 与之对应的,systemctl disable命令用于在两个目录之间,撤销符号链接关系,相当于撤销开机启动.

$ sudo systemctl disable clamd@scan.service

配置文件的后缀名,就是该 Unit 的种类,比如sshd.socket.如果省略,Systemd 默认后缀名为.service,所以sshd会被理解成sshd.service.

$ pstree
systemd─┬─accounts-daemon─┬─{gdbus}
        │                 └─{gmain}
        ├─cgmanager
        ├─cron
        ├─dbus-daemon
        ├─grafana-server───10*[{grafana-server}]
        ├─influxd───8*[{influxd}]
        ├─irqbalance
        ├─mongod─┬─{Backgro.kSource}
        │        ├─{DeadlineMonitor}
        │        ├─{Network.cutor-0}
        │        ├─{Periodi.kRunner}
        │        ├─{WT Reco.plog.rs}
        │        ├─{WTCheck.tThread}
        │        ├─{WTJourn.Flusher}
        │        ├─{WTOplog.lThread}
        │        ├─{clientcursormon}
        │        ├─{listener}
        │        ├─11*[{mongod}]
        │        └─{signalP.gThread}
        ├─nginx───16*[nginx]
        ├─nscd───7*[{nscd}]
        ├─ntpd
        ├─php-fpm7.2───200*[php-fpm7.2]
        ├─rc.local───sudo───IntelliJIDEALic───4*[{IntelliJIDEALic}]
        ├─redis-server───3*[{redis-server}]
        ├─rsyslogd─┬─{in:imklog}
        │          ├─{in:imuxsock}
        │          └─{rs:main Q:Reg}
        ├─sshd─┬─sshd───sshd───sftp-server
        │      └─sshd───sshd───bash───pstree
        ├─starter───charon───16*[{charon}]
        ├─systemd───(sd-pam)
        ├─systemd-journal
        ├─systemd-logind
        └─systemd-udevd

Systemctl 定时器

每分钟运行一次 shell 脚本…

  • 创建运行脚本

/lib/systemd/system/com.sh

#!/bin/bash

cd $(dirname $0)
* [ ! -e "logs" ] && mkdir logs

time_str=$(date +%Y%m%d_%H%M%S)
echo "$time_str" > logs/"$time_str".log
  • 创建 Systemctl 服务…

/lib/systemd/system/com.service

* [Unit]
Description=Run script to log execution time
Requires=mysql.service
After=network.target mysql.service

* [Service]
Type=simple
ExecStart=/data/home/coam/Server/Run/Docs/Server/RunScripts/com.sh
  • 创建定时器…

/lib/systemd/system/com.timer

* [Unit]
Description=Run logtime every minutes
Requires=mysql.service
After=network.target mysql.service

* [Timer]
OnCalendar=*-*-* *:*:00
Unit=com.service

* [Install]
WantedBy=multi-user.target
  • 查看所有定时器…
sudo systemctl list-timers

journalctl 日志管理

  • 查看某个服务的动态日志,功能类似于(tail -f):
sudo journalctl -u zs_mc -f

Comments

Cor-Ethan, the beverage → www.iirii.com