咱们运行 linux 服务器的主要目的是经过运行程序提供服务,好比 mysql、web server等。所以管理 linux 服务器主要工做就是配置并管理上面运行的各类服务程序。在 linux 系统中服务程序的管理主要由 init 系统负责。如同笔者在《初识 systemd》一文中的介绍,linux 的 init 系统已经从最初的 sysvinit 进化到了现在的 systemd。本文主要介绍在 systemd 环境中如何编写运行服务的配置文件。html
Unit 是 systemd 进行任务管理的基本单位,咱们在前文中已经介绍过,service 类型的 unit 表明一个后台服务进程。接下来咱们就详细的介绍如何配置 service 类型的 unit。下面咱们先来看一个简单的服务配置:mysql
[Unit] Description=Prometheus Server Documentation=https://prometheus.io/docs/introduction/overview/ After=network.target [Service] User=prometheus Restart=on-failure WorkingDirectory=/usr/local/share/prometheus/ ExecStart=/usr/local/share/prometheus/prometheus \ -config.file=/usr/local/share/prometheus/prometheus.yml [Install] WantedBy=multi-user.target
这是笔者主机上 prometheus 服务的配置文件。把上面的内容保存到文件 /lib/systemd/system/prometheus.service 中,而后就可使用 systemctl 命令管理 prometheus 服务了。注意,服务类型的配置文件名称必须以 .service 结尾。
查看上面配置信息的详细内容,咱们会发现整个配置的内容分为三个部分:
[Unit] unit 自己的说明,以及与其它有依赖关系的服务的设置,包括在什么服务以后才启动此 unit 之类的设置。
[Service] 不一样的 unit 类型就得要使用相对应的设置项目,好比 timer 类型的 unit 应该是 [Timer],socket 类型的 unit 应该是 [Socket]。服务类型的 unit 就是 [Service],这个项目内主要在规范服务启动的脚本、环境配置文件文件名、从新启动的方式等等。
[Install] 这个部分主要设置把该 unit 安装到哪一个 target 。linux
配置文件分为三个部分,每一个部分中均可以提供详细的配置信息。为了精确的控制服务的运行方式,咱们须要了解这些详细的配置选项,并最终让服务以咱们指望的方式运行。web
[Unit] 部分
Description 关于该 unit 的简易说明。
Documentation 文档相关的内容,如 Documentation=https://prometheus.io/docs/introduction/overview/
Documentation=man:sshd(8)
Documentation=file:/etc/ssh/sshd_config
After 说明本 unit 是在哪一个服务启动以后才启动的意思。仅是说明服务启动的顺序而已,并无强制要求 。
Before 与 After 的意义相反,在指定的服务启动前最好启动本个服务的意思。仅是说明服务启动的顺序而已,并没有强制要求 。
Requires 本 unit 须要在哪一个服务启动后才可以启动!就是设置服务间的依赖性。若是在此项设置的前导服务没有启动成功,那么本 unit 就不会被启动!
Wants 与 Requires 恰好相反,规范的是这个 unit 以后还要启动什么服务,若是这 Wants 后面接的服务若是没有启动成功,其实不会影响到这个 unit 自己!
Conflicts 这个项目后面接的服务若是有启动,那么本 unit 就不能启动!若是本 unit 启动了,则指定的服务就不能启动。redis
[Service] 部分
Type
说明这个服务的启动方式,会影响到 ExecStart,主要有下面几种类型:
simple:默认值,这个服务主要由 ExecStart 设置的程序来启动,启动后常驻于内存中。
forking:由 ExecStart 指定的启动的程序经过 spawns 产生子进程提供服务,而后父进程退出。
oneshot:与 simple 相似,不过这个程序在工做完毕后就结束了,不会常驻在内存中。
dbus:与 simple 相似,但这个服务必需要在取得一个 D-Bus 的名称后,才会继续运行!所以设置这个项目时,一般也要设置 BusName= 才行。
idle:与 simple 相似,意思是,要执行这个服务必需要全部的工做都顺利执行完毕后才会执行。这类的服务一般是开机到最后才执行便可的服务。
notify:与 simple 相似,但这个服务必需要收到一个 sd_notify() 函数发送的消息后,才会继续运行。sql
ExecStart
就是实际执行此服务的程序。接受 "命令 参数 参数..." 的格式,不能接受 <, >, >>, |, & 等特殊字符,不少的 bash 语法也不支持。因此,要使用这些特殊的字符时,最好直接写入到脚本里面去!ubuntu
ExecStartPre 和 ExecStartPost 分别在服务启动先后,执行额外的命令。vim
ExecStop 用来实现 systemctl stop 命令,关闭服务。
ExecReload 用来实现 systemctl reload 命令,从新加载服务的配置信息。bash
Restart 当设置为 Restart=1 时,若是服务终止,就会自动重启此服务。
RestartSec 与 Restart 配合使用,在服务终止多长时间以后才从新启动它。默认是 100ms。服务器
KillMode
能够是 process, control-group, none 中的一种,若是是 process 则服务终止时,只会终止主要的程序(ExecStart接的后面那串指令),若是是 control-group 时,则由此 daemon 所产生的其余 control-group 的程序,也都会被关闭。若是是 none 的话,则没有程序会被关闭。
TimeoutSec
若这个服务在启动或者是关闭时,由于某些缘故致使没法顺利 "正常启动或正常结束" 的状况下,则咱们要等多久才进入 "强制结束" 的状态!
RemainAfterExit
当设置为 RemainAfterExit=1 时,则当这个服务所属的全部程序都终止以后,此服务会再尝试启动。这对于 Type=oneshot 的服务颇有帮助!
环境变量的设置对不少程序来讲都是十分重要的,下面的配置则能够以不一样的方式为服务程序设置环境变量:
Environment 用来设置环境变量,可使用屡次:
[Service] # Client Env Vars Environment=ETCD_CA_FILE=/path/to/CA.pem Environment=ETCD_CERT_FILE=/path/to/server.crt
EnvironmentFile 经过文件的方式设置环境变量,能够把下面的内容保存到文件 testenv 中:
AAA_IPV4_ANCHOR_0=X.X.X.X BBB_IPV4_PRIVATE_0=X.X.X.X CCC_HOSTNAME=test.example.com
而后这样设置:
[Service]
EnvironmentFile=/testenv
接下来就能够在 ExecStart 配置中使用在文件中设置的环境变量,如:
ExecStart=/xxx --abc=xx${AAA_IPV4_ANCHOR_0}yy
[Install] 部分
WantedBy 这个设置后面接的大部分是 *.target unit。意思是,这个 unit 自己是附挂在哪一个 target unit 下面。
Also 当目前这个 unit 被 enable 时,Also 后面接的 unit 也要 enable 的意思。
Alias 当 systemctl enable 相关的服务时,则此服务会进行连接文件的建立!
Timer 类型的 unit 主要用来执行定时任务,并有可能取代 cron 服务。因为 timer 类型的 unit 常常与服务类型的 unit 一块儿使用,因此本文也附带介绍一下 timer unit 的配置。与服务类型的 unit 不一样,timer unit 配置文件中的主要部分是 [Timer],下面是其主要的配置项:
OnActiveSec 当 timers.target 启动后多久才执行这个 unit。
OnBootSec 当开机后多久才执行这个 unit。
OnStartupSec 当 systemd 第一次启动后多久才执行这个 unit。
OnUnitActiveSec 这个 timer 配置文件所管理的那个 unit 服务在最后一次启动后,隔多久后再执行一次。
OnUnitInactiveSec 这个 timer 配置文件所管理的那个 unit 服务在最后一次中止后,隔多久后再执行一次。
Unit 通常不须要设置,基本上咱们设置都是 服务名称.server + 服务名称.timer。若是你的服务名称和 timer 名称不相同,就须要在 .timer 文件中经过 Unit 项指定服务的名称。
OnCalendar 使用实际时间(非循环时间)的方式来启动服务。
Persistent 当使用 OnCalendar 的设置时,指定该功能要不要持续执行。
经过上面的介绍,相信你们对 systemd 服务类型和 timer 类型的 unit 配置已经有了基本的理解,下面让就让咱们配置两个实际的例子。
在 ubuntu 上咱们通常会手动编译并安装 redis。在安装完成后须要把 redis 配置为 systemd 管理的服务,下面介绍具体的配置过程。
添加 redis 配置文件
首先手动建立 /etc/redis 目录并添加配置文件:
$ sudo mkdir /etc/redis
并把代码目录中的配置文件 redis.conf 拷贝到 /etc/redis 目录中:
$ sudo cp /tmp/redis-4.0.0/redis.conf /etc/redis/
而后修改配置文件 /etc/redis/redis.conf 中的 supervised 为 systemd:
supervised systemd
接着继续在配置文件 /etc/redis/redis.conf 中配置工做目录,把 dir ./ 修改成:
dir /var/lib/redis
配置由 systemd 管理 redis 服务
建立 /etc/systemd/system/redis.service 文件
$ sudo vim /etc/systemd/system/redis.service
编辑其内容以下:
[Unit] Description=Redis In-Memory Data Store After=network.target [Service] User=redis Group=redis ExecStart=/usr/local/bin/redis-server /etc/redis/redis.conf ExecStop=/usr/local/bin/redis-cli shutdown Restart=always [Install] WantedBy=multi-user.target
启动服务并配置为开机启动:
$ sudo systemctl start redis $ sudo systemctl enable redis $ sudo systemctl status redis
备份文件的 bash 脚本:
#!/bin/bash mydate() { date "+%Y%m%d%H%M%S" } backupdate=$(mydate) tar -zcf /tmp/backup.${backupdate}.tar.gz /home/nick/learn
把上面的代码保存到文件 /usr/local/bin/backupdir.sh,并添加可执行权限:
$ sudo chmod +x /usr/local/bin/backupdir.sh
而后建立 service unit 配置文件:
[Unit] Description=nick backup learn dir service [Service] User=nick Group=nick Type=simple ExecStart=/usr/local/bin/backupdir.sh [Install] WantedBy=multi-user.target
把上面的 unit 配置保存到文件 /etc/systemd/system/nickbak.service。
而后执行下面的命令测试服务的执行状况:
$ sudo systemctl daemon-reload $ sudo systemctl start nickbak.service
这样的备份任务只会在执行 sudo systemctl start nickbak.service 时执行一次。下面咱们经过 timer unit 把它配置为定时执行。
建立 timer unit 配置文件:
[Unit] Description=nick backup learn dir timer [Timer] OnCalendar=*:0/15 Persistent=true Unit=nickbak.service [Install] WantedBy=multi-user.target
把上面的 unit 配置保存到文件 /etc/systemd/system/nickbak.timer。配置中 OnCalendar=*:0/15 表示每 15 分钟执行一次 nickbak.service 服务。
执行下面的命令把 nickbak.timer 设置为开机启动,并启动 nickbak.timer:
$ sudo systemctl daemon-reload $ sudo systemctl enable nickbak.timer $ sudo systemctl start nickbak.timer
如今来看看 nickbak.timer 的状态:
$ sudo systemctl status nickbak.timer
从如今开始 nickbak.timer 会每隔 15 分钟执行一次 nickbak.service 服务。
systemd 提供了服务管理(实际上是 unit 管理)的方方面面,咱们须要作的就是写好服务 unit 的配置文件,而后利用 systemd 来管理咱们的服务。这是一个看似简单实则繁琐的任务(不少的配置项其实须要咱们在实践中不断的调整并优化)。但愿本文对你们来讲是个简单的入门。
参考:
鸟哥的私房菜