[toc]php
systemd 是一个属于用户空间的系统服务管理程序,在红帽 RHEL7 上采用,替代了原来 RHEL6 上的 systemVinit。 其做用是,在内核启动完成后,初始化用户空间的进程,进程号为 1 、管理操做系统的运行级别,系统的服务启动和关闭,系统的挂载点。html
systemctl get-default
systemctl isolate multi-user.target 或 systemctl isolate runlevel3.target
systemctl set-default multi-user.target
systemd target | 解释 |
---|---|
runlevel0.target, poweroff.target | 关闭系统 —> 0 |
runlevel1.target, rescue.target | 单用户模式 —> 1 |
runlevel2.target, runlevel4.target, multi-user.target | 用户定义/域特定运行级别。默认等同于 3 —> 2,4 |
runlevel3.target, multi-user.target | 最经常使用模式,非图形化多用户 —> 3 |
runlevel5.target, graphical.target | 多用户图形化 —> 5 |
runlevel6.target, reboot.target | 重启 —> 6 |
/etc/systemd/system/
在 Systemd 下 unit 文件用于配置对资源的控制,每种资源对应不一样的 unit 文件类型,好比后台服务(service)、套接字(socket)、设备(device)、挂载点(mount) 等。 全部 unit 文件都包含两个通用段 [Unit] 、[Install] 和一个资源类型段,如 [Service] 就表示后台服务。java
service :守护进程的启动、中止、重启和重载是此类 unit 中最为明显的几个类型。nginx
socket :此类 unit 封装系统和互联网中的一个socket。当下,systemd支持流式, 数据报和连续包的AF_INET,AF_INET6,AF_UNIXsocket 。也支持传统的 FIFOs 传输模式。每个 socket unit 都有一个相应的服务 unit 。相应的服务在第一个“链接”进入 socket 或 FIFO 时就会启动(例如:nscd.socket 在有新链接后便启动 nscd.service)。shell
device :此类 unit 封装一个存在于 Linux设备树中的设备。每个使用 udev 规则标记的设备都将会在 systemd 中做为一个设备 unit 出现。udev 的属性设置能够做为配置设备 unit 依赖关系的配置源。centos
mount:此类 unit 封装系统结构层次中的一个挂载点。api
automount :此类 unit 封装系统结构层次中的一个自挂载点。每个自挂载 unit 对应一个已挂载的挂载 unit (须要在自挂载目录能够存取的状况下尽早挂载)。安全
target :此类 unit 为其余 unit 进行逻辑分组。它们自己实际上并不作什么,只是引用其余 unit 而已。这样即可以对 unit 作一个统一的控制。(例如:multi-user.target 至关于在传统使用 SysV 的系统中运行级别5);bluetooth.target 只有在蓝牙适配器可用的状况下才调用与蓝牙相关的服务,如:bluetooth 守护进程、obex 守护进程等)bash
对应到 centos6 其实就是 /etc/init.d/ 下面的服务脚本,只是到了 systemd 里面叫作 service unit 文件,命名必须以 .service 结尾。网络
service unit(服务脚本) 文件在系统中的存放路径
/usr/lib/systemd/system
[Unit] Description=nginx After=network.target [Service] Type=forking PIDFile=/alidata/server/nginx/logs/nginx.pid ExecStart=/alidata/server/nginx/sbin/nginx -c /alidata/server/nginx/conf/nginx.conf ExecReload=/alidata/server/nginx/sbin/nginx -s reload ExecStop=/alidata/server/nginx/sbin/nginx -s stop PrivateTmp=true [Install] WantedBy=multi-user.target
[Unit] :记录文件的通用信息,如描述,开机启动顺序
[Service] :记录 unit 文件类型,服务控制的相关指令
[Install] :安装信息
Description:对本service的描述。
Before, After:定义启动顺序,Before=xxx.service,表明本服务在xxx.service启动以前启动。After=xxx.service,表明本服务在xxx以后启动。
Requires: 这个单元启动了,那么它“须要”的单元也会被启动; 它“须要”的单元被中止了,它本身也活不了。可是请注意,这个设定并不能控制某单元与它“须要”的单元的启动顺序(启动顺序是另外控制的),即 Systemd 不是先启动 Requires 再启动本单元,而是在本单元被激活时,并行启动二者。因而会产生争分夺秒的问题,若是 Requires 先启动成功,那么皆大欢喜; 若是 Requires 启动得慢,那本单元就会失败(Systemd 没有自动重试)。因此为了系统的健壮性,不建议使用这个标记,而建议使用 Wants 标记。可使用多个 Requires。
Wants:推荐使用。本单元启动了,它“想要”的单元也会被启动。可是启动不成功,对本单元没有影响。
Type:service的种类,包含下列几种类型:
RemainAfterExit :当该服务的全部进程所有退出以后, 是否依然将此服务视为活动(active)状态。 默认值为 no
PIDFile :指定守护进程的 PID 文件,强烈建议在 Type=forking 的状况下明确设置此选项。由于有些服务启动以后会派生多个进程,systemd 将会不知道哪个才是该服务的主进程,指定 PID 文件有助于 Systemd 准确的找到服务的主进程。 systemd 不会写入此文件, 但会在此服务中止后删除它。 该指令要放在 ExecStart 上面。
ExecStart :启动服务时须要执行的命令,能够用 $变量名 引用 Environment 设置的进程环境变量 和 操做系统的环境变量 如 $USER
ExecStop :可选指令,用于设置服务被要求中止前所执行的指令,此处指令执行完后,该服务剩余的进程都会被 kill 掉。 若是该指令没填写,在中止服务时会直接 kill 该服务下的全部进程。
ExecStartPre :设置在 ExecStart 指令执行以前执行的命令
ExecStartPost :设置在 ExecStart 指令执行成功以后执行的命令
ExecStopPost :设置该服务中止以后执行的命令
Environment :设置进程的环境变量, 值是一个空格分隔的 VAR=VALUE 列表。 能够屡次使用此选项以增长新的变量或者修改已有的变量 (同一个变量以最后一次的设置为准)。 若设为空, 则表示清空先前全部已设置的变量。 注意: (1)不会在字符串内部进行变量展开(也就是"$"没有特殊含义); (2)若是值中包含空格或者等号, 那么必须在字符串两边使用双引号(")界定。 例如: Environment="VAR1=word1 word2" VAR2=word3 "VAR3=$word 5 6" 设置了 "VAR1", "VAR2", "VAR3" 三个变量,其值分别为 "word1 word2", "word3", "$word 5 6"
Alias : 启用时使用的别名,能够设为一个空格分隔的别名列表。 每一个别名的后缀(也就是单元类型)都必须与该单元自身的后缀相同。systemctl enable 命令将会为每一个别名建立一个指向该单元文件的软链接。 注意,由于 mount, slice, swap, automount 单元不支持别名,因此不要在这些类型的单元中使用此选项。
[Unit] Description=简单的Foo服务 [Service] ExecStart=/usr/sbin/foo-daemon [Install] WantedBy=multi-user.target
该单元文件建立了一个运行 /usr/sbin/foo-daemon 守护进程的服务,未设置 Type= 等价于 Type=simple 默认设置。 注意,本例中的 /usr/sbin/foo-daemon 必须在启动后持续运行到服务被中止。 若是该进程只是为了派生守护进程,那么应该使用 Type=forking
[Unit] Description=清理老旧的 Foo 数据 [Service] Type=oneshot ExecStart=/usr/sbin/foo-cleanup [Install] WantedBy=multi-user.target
Type=oneshot 用于只须要执行一次,不须要持久运行的单元,例如文件系统检查或者清理磁盘文件。此单元会启动后一直等待指定的动做完成, 而后再回到中止状态。 在 /usr/sbin/foo-cleanup 执行结束前, 该服务一直处于"启动中"(activating)状态,而一旦执行结束,该服务又当即变为"中止"(inactive)状态。 也就是说,对于 Type=oneshot 类型的服务,不存在"活动"(active)状态。 这意味着,若是再一次启动该服务,将会再一次执行该服务定义的动做。 注意,在前后顺序上晚于该服务的单元, 将会一直等到该服务变成"中止"(inactive)状态后, 才会开始启动。
Type=oneshot 是惟一能够设置多个 ExecStart= 指令的服务类型。 多个 ExecStart= 指令将按照它们出现的顺序依次执行, 一旦遇到错误,就会当即中止,再也不继续执行, 同时该服务也将进入"失败"(failed)状态。
[Unit] Description=简单的静态防火墙 [Service] Type=oneshot RemainAfterExit=yes ExecStart=/usr/local/sbin/simple-firewall-start ExecStop=/usr/local/sbin/simple-firewall-stop [Install] WantedBy=multi-user.target
有时候,单元须要执行一个程序以完成某个设置(启动), 而后又须要再执行另外一个程序以撤消先前的执行(中止)。 而第一次执行以后,该单元应该处于 活动(active) 状态,但实际上并没有任何进程在运行。网络配置服务就是一个典型的例子,只须要执行一次的服务。
能够经过设置 RemainAfterExit=yes 来知足这种需求。 在这种状况下,systemd 将会在启动成功后将该单元视为处于"活动"(active)状态(而不是"中止"(inactive)状态)。 RemainAfterExit=yes 虽然能够用于全部 Type= 类型, 可是在实践中主要用于 Type=oneshot 和 Type=simple 类型。 对于 Type=oneshot 类型, systemd 一直等到服务启动成功以后,才会将该服务置于"活动"(active)状态。 因此,依赖于该服务的其余单元必须等待该服务启动成功以后,才能启动。 可是对于 Type=simple 类型, 依赖于该服务的其余单元无需等待,将会和该服务同时并行启动。
[Unit] Description=nginx After=network.target [Service] Type=forking PIDFile=/alidata/server/nginx/logs/nginx.pid ExecStart=/alidata/server/nginx/sbin/nginx -c /alidata/server/nginx/conf/nginx.conf ExecReload=/alidata/server/nginx/sbin/nginx -s reload ExecStop=/alidata/server/nginx/sbin/nginx -s stop PrivateTmp=true [Install] WantedBy=multi-user.target
PrivateTmp 设为 yes 表示在进程的文件系统名字空间中挂载私有的 /tmp 与 /var/tmp 目录, 也就是不与名字空间外的其余进程共享临时目录。 这样作会增长进程的临时文件安全性,但同时也让进程之间没法经过 /tmp 或 /var/tmp 目录进行通讯。 同时,当服务中止以后,全部先前在临时目录中建立的文件都将被删除。
[Unit] Description=PHP7.0.8 start file [Service] Type=forking PIDFile=/alidata/server/php7.0.8/var/run/php-fpm.pid ExecStart=/alidata/server/php7.0.8/sbin/php-fpm --daemonize --fpm-config /alidata/server/php7.0.8/etc/php-fpm.conf --pid /alidata/server/php7.0.8/var/run/php-fpm.pid ExecStartPost=/usr/bin/chown www.www /alidata/server/php7.0.8/var/run/php7-fpm.sock StandardOutput=syslog StandardError=inherit [Install] WantedBy=multi-user.target
设置进程的标准输出(STDOUT)。 可设为 inherit, null, tty, journal, syslog, kmsg, journal+console, syslog+console, kmsg+console, socket, fd 之一。 syslog 表示 syslog 日志服务。 注意,此时全部日志都会隐含的复制一份到 journal 中。
设置进程的标准错误(STDERR)。 取值范围及含义与 StandardOutput= 相同。 但有以下例外:(1) inherit 表示使用 StandardOutput= 的值。 (2) fd 的文件描述符名称的默认值为 "stderr" 此值默认为 inherit
[Unit] Description=Filebeat sends log files to Logstash or directly to Elasticsearch. Documentation=https://www.elastic.co/products/beats/filebeat Wants=network-online.target After=network-online.target [Service] ExecStart=/usr/share/filebeat/bin/filebeat -c /etc/filebeat/filebeat.yml -path.home /usr/share/filebeat -path.config /etc/filebeat -path.data /var/lib/filebeat -path.logs /var/log/filebeat -E serverip=$serverip Restart=always [Install] WantedBy=multi-user.target
注意,在 Centos7 使用 Systemd 启动 filebeat 时是不会传递系统环境变量的。 filebeat 若是在配置文件中引用了系统的环境变量,那么会致使服务启动失败。 报错大概是找不到那个引用了系统变量自定义的那个字段。 有两个解决方法:
一、在 unit 文件中使用 Environment 相关参数,定义要使用的环境变量,在 ExecStart 启动命令时引用。 -E serverip=$serverip
二、在 /etc/profile.d/ 目录下建立定义系统环境变量的文件,里面的内容相似
export serverip=ifconfig eth0 | grep 'inet' | awk '{print $2}' | cut -d':' -f2
,而后在启动命令时直接用 $变量名 引用系统环境变量。
# /usr/lib/systemd/system/logstash.service # 自定义环境变量的写法 [Unit] Description=Logstash start program [Service] Type=simple Environment=LOGDIR=/alidata/log/logstash CONF=/alidata/logstash-6.5.2/ngx_app_api_log_analyze.conf DATA=/alidata/logstash-6.5.2/data ExecStartPre=/usr/bin/rm -rf $DATA ExecStartPre=/usr/bin/rm -rf $LOGDIR ExecStart=/alidata/logstash-6.5.2/bin/logstash -f $CONF -l $LOGDIR [Install] WantedBy=multi-user.target
# /etc/systemd/system/logstash.service [Unit] Description=logstash [Service] Type=simple User=logstash Group=logstash # Load env vars from /etc/default/ and /etc/sysconfig/ if they exist. # Prefixing the path with '-' makes it try to load, but if the file doesn't # exist, it continues onward. EnvironmentFile=-/etc/default/logstash EnvironmentFile=-/etc/sysconfig/logstash ExecStart=/usr/share/logstash/bin/logstash "--path.settings" "/etc/logstash" Restart=always WorkingDirectory=/ Nice=19 LimitNOFILE=16384 [Install] WantedBy=multi-user.target
# /etc/default/logstash LS_HOME="/usr/share/logstash" LS_SETTINGS_DIR="/etc/logstash" LS_PIDFILE="/var/run/logstash.pid" LS_USER="logstash" LS_GROUP="logstash" LS_GC_LOG_FILE="/var/log/logstash/gc.log" LS_OPEN_FILES="16384" LS_NICE="19" SERVICE_NAME="logstash" SERVICE_DESCRIPTION="logstash" JAVA_HOME="/usr/java/jdk1.8.0_162"
'''查看系统全部已安装的服务项''' systemctl list-unit-files --type=service '''查看系统全部运行的服务项''' systemctl list-units --type=service '''查看系统全部开机自启动的服务项''' systemctl list-unit-files --type=service | grep enabled '''查看出错的服务''' systemctl list-units --type=service --state=failed '''启动服务''' systemctl start nginx.service '''中止服务''' systemctl stop nginx.service '''重载服务的配置文件''' systemctl reload nginx.service '''查看服务的状态''' systemctl status nginx.service '''设置服务开机启动''' systemctl enable nginx.service '''禁用服务的开机启动''' systemctl disable nginx.service '''禁止服务的启动,用于防止服务被其余服务间接启动,也没法经过 start 或 restart 命令来启动''' systemctl mask nginx.service '''取消对服务的启动禁止''' systemctl unmask nginx.service '''从新读取全部服务项,修改或添加服务单元文件以后须要执行''' systemctl daemon-reload '''查看系统启动耗时''' systemd-analyze '''查看各项服务启动耗时''' systemd-analyze blame | grep .service