zoukankan      html  css  js  c++  java
  • Linux:使用systemd管理进程

    Blog:博客园 个人

    参考:Systemd服务管理教程 Systemd 入门教程:实战篇 Systemd 入门教程:命令篇

    概述

    systemd是目前Linux系统上主要的系统守护进程管理工具,由于init一方面对于进程的管理是串行化的,容易出现阻塞情况,另一方面init也仅仅是执行启动脚本,并不能对服务本身进行更多的管理。所以从CentOS 7 开始也由systemd取代了init作为默认的系统进程管理工具。

    systemd所管理的所有系统资源都称作Unit,通过systemd命令集可以方便的对这些Unit进行管理。比如systemctlhostnamectltimedatectllocalctl等命令,这些命令虽然改写了init时代用户的命令使用习惯(不再使用chkconfig、service等命令),但确实也提供了很大的便捷性。

    特点

    • 提供了服务按需启动 的能力,使得特定的服务只有在真定被请求时才启动,显著提高开机启动效率
    • 允许更多的进程并行启动: Systemd 通过 Socket 缓存、DBus 缓存和建立临时挂载点等方法进一步解决了启动进程之间的依赖,做到了所有系统服务并发启动。
    • 使用 CGroup 跟踪和管理进程的生命周期:通过 CGroup 不仅能够实现服务之间访问隔离,限制特定应用程序对系统资源的访问配额,还能更精确地管理服务的生命周期。
    • 专用的系统日志管理服务:Journald,这个服务的设计初衷是克服现有 Syslog 服务的日志内容易伪造和日志格式不统一等缺点,Journald 用 二进制格式 保存所有的日志信息,因而日志内容很难被手工伪造。Journald 还提供了一个 journalctl 命令来查看日志信息,这样就使得不同服务输出的日志具有相同的排版格式, 便于数据的二次处理。

    systemctl语法

    systemctl [OPTIONS...] {COMMAND} ...
    

    command:

    • start:启动指定的unit,例如systemctl start nginx
    • stop:关闭指定的unit,例如systemctl stop nginx
    • restart:重启指定unit,例如systemctl restart nginx
    • reload:重载指定unit,例如systemctl reload nginx
    • enable:系统开机时自动启动指定unit,前提是配置文件中有相关配置,例如systemctl enable nginx
    • disable:开机时不自动运行指定unit,例如systemctl disable nginx
    • status:查看指定unit当前运行状态,例如systemctl status nginx

    查看当前系统Unit

    # 列出正在运行的 Unit
    $ systemctl list-units
    
    # 列出所有Unit,包括没有找到配置文件的或者启动失败的
    $ systemctl list-units --all
    
    # 列出所有没有运行的 Unit
    $ systemctl list-units --all --state=inactive
    
    # 列出所有加载失败的 Unit
    $ systemctl list-units --failed
    
    # 列出所有正在运行的、类型为 service 的 Unit
    $ systemctl list-units --type=service
    
    # 查看 Unit 配置文件的内容
    $ systemctl cat docker.service
    

    查看Unit状态

    • enabled:已建立启动链接
    • disabled:没建立启动链接
    • static:该配置文件没有 [Install] 部分(无法执行),只能作为其他配置文件的依赖
    • masked:该配置文件被禁止建立启动链接
    # 显示系统状态
    $ systemctl status
    
    # 显示单个 Unit 的状态
    $ ystemctl status bluetooth.service
    
    # 显示远程主机的某个 Unit 的状态
    $ systemctl -H root@rhel7.example.com status httpd.service
    

    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
    
    # 显示某个 Unit 的指定属性的值
    $ systemctl show -p CPUShares httpd.service
    
    # 设置某个 Unit 的指定属性
    $ sudo systemctl set-property httpd.service CPUShares=500
    

    查看 Unit 的依赖关系

    # 列出一个 Unit 的所有依赖,默认不会列出 target 类型
    $ systemctl list-dependencies nginx.service
    
    # 列出一个 Unit 的所有依赖,包括 target 类型
    $ systemctl list-dependencies --all nginx.service
    

    Target 管理

    Target 就是一个 Unit 组,包含许多相关的 Unit 。启动某个 Target 的时候,Systemd 就会启动里面所有的 Unit。

    在传统的 SysV-init 启动模式里面,有 RunLevel 的概念,跟 Target 的作用很类似。不同的是,RunLevel 是互斥的,不可能多个 RunLevel 同时启动,但是多个 Target 可以同时启动。

    # 查看当前系统的所有 Target
    $ systemctl list-unit-files --type=target
    
    # 查看一个 Target 包含的所有 Unit
    $ systemctl list-dependencies multi-user.target
    
    # 查看启动时的默认 Target
    $ systemctl get-default
    
    # 设置启动时的默认 Target
    $ sudo systemctl set-default multi-user.target
    
    # 切换 Target 时,默认不关闭前一个 Target 启动的进程,systemctl isolate 命令改变这种行为,关闭前一个 Target 里面所有不属于后一个 Target 的进程
    $ sudo systemctl isolate multi-user.target
    

    journalctl语法

    Systemd 通过其标准日志服务 Journald 提供的配套程序 journalctl 将其管理的所有后台进程打印到 std:out(即控制台)的输出重定向到了日志文件。

    Systemd 的日志文件是二进制格式的,必须使用 Journald 提供的 journalctl 来查看,默认不带任何参数时会输出系统和所有后台进程的混合日志。

    默认日志最大限制为所在文件系统容量的 10%,可以修改 /etc/systemd/journald.conf 中的 SystemMaxUse 来指定该最大限制。

    语法:

    journalctl [OPTIONS...] [MATCHES...]
    

    示例

    # 查看所有日志(默认情况下 ,只保存本次启动的日志)
    $ sudo journalctl
    
    # 查看内核日志(不显示应用日志):--dmesg 或 -k
    $ sudo journalctl -k
    
    # 查看系统本次启动的日志(其中包括了内核日志和各类系统服务的控制台输出):--system 或 -b
    $ sudo journalctl -b
    $ sudo journalctl -b -0
    
    # 查看上一次启动的日志(需更改设置)
    $ sudo journalctl -b -1
    
    # 查看指定服务的日志:--unit 或 -u
    $ sudo journalctl -u docker.servcie
    
    # 查看指定服务的日志
    $ sudo journalctl /usr/lib/systemd/systemd
    
    # 实时滚动显示最新日志
    $ sudo journalctl -f
    
    # 查看指定时间的日志
    $ sudo journalctl --since="2012-10-30 18:17:16"
    $ sudo journalctl --since "20 min ago"
    $ sudo journalctl --since yesterday
    $ sudo journalctl --since "2015-01-10" --until "2015-01-11 03:00"
    $ sudo journalctl --since 09:00 --until "1 hour ago"
    
    # 显示尾部的最新 10 行日志:--lines 或 -n
    $ sudo journalctl -n
    
    # 显示尾部指定行数的日志
    $ sudo journalctl -n 20
    
    # 将最新的日志显示在前面
    $ sudo journalctl -r -u docker.service
    
    # 改变输出的格式:--output 或 -o
    $ sudo journalctl -r -u docker.service -o json-pretty
    
    # 查看指定进程的日志
    $ sudo journalctl _PID=1
    
    # 查看某个路径的脚本的日志
    $ sudo journalctl /usr/bin/bash
    
    # 查看指定用户的日志
    $ sudo journalctl _UID=33 --since today
    
    # 查看某个 Unit 的日志
    $ sudo journalctl -u nginx.service
    $ sudo journalctl -u nginx.service --since today
    
    # 实时滚动显示某个 Unit 的最新日志
    $ sudo journalctl -u nginx.service -f
    
    # 合并显示多个 Unit 的日志
    $ journalctl -u nginx.service -u php-fpm.service --since today
    
    # 查看指定优先级(及其以上级别)的日志,共有 8 级
    # 0: emerg
    # 1: alert
    # 2: crit
    # 3: err
    # 4: warning
    # 5: notice
    # 6: info
    # 7: debug
    $ sudo journalctl -p err -b
    
    # 日志默认分页输出,--no-pager 改为正常的标准输出
    $ sudo journalctl --no-pager
    
    # 以 JSON 格式(单行)输出
    $ sudo journalctl -b -u nginx.service -o json
    
    # 以 JSON 格式(多行)输出,可读性更好
    $ sudo journalctl -b -u nginx.serviceqq
     -o json-pretty
    
    # 显示日志占据的硬盘空间
    $ sudo journalctl --disk-usage
    
    # 指定日志文件占据的最大空间
    $ sudo journalctl --vacuum-size=1G
    
    # 指定日志文件保存多久
    $ sudo journalctl --vacuum-time=1years
    

    systemd工具集

    • systemctl:用于检查和控制各种系统服务和资源的状态
    • bootctl:用于查看和管理系统启动分区
    • hostnamectl:用于查看和修改系统的主机名和主机信息
    • journalctl:用于查看系统日志和各类应用服务日志
    • localectl:用于查看和管理系统的地区信息
    • loginctl:用于管理系统已登录用户和 Session 的信息
    • machinectl:用于操作 Systemd 容器
    • timedatectl:用于查看和管理系统的时间和时区信息
    • systemd-analyze 显示此次系统启动时运行每个服务所消耗的时间,可以用于分析系统启动过程中的性能瓶颈
    • systemd-ask-password:辅助性工具,用星号屏蔽用户的任意输入,然后返回实际输入的内容
    • systemd-cat:用于将其他命令的输出重定向到系统日志
    • systemd-cgls:递归地显示指定 CGroup 的继承链
    • systemd-cgtop:显示系统当前最耗资源的 CGroup 单元
    • systemd-escape:辅助性工具,用于去除指定字符串中不能作为 Unit 文件名的字符
    • systemd-hwdb:Systemd 的内部工具,用于更新硬件数据库
    • systemd-delta:对比当前系统配置与默认系统配置的差异
    • systemd-detect-virt:显示主机的虚拟化类型
    • systemd-inhibit:用于强制延迟或禁止系统的关闭、睡眠和待机事件
    • systemd-machine-id-setup:Systemd 的内部工具,用于给 Systemd 容器生成 ID
    • systemd-notify:Systemd 的内部工具,用于通知服务的状态变化
    • systemd-nspawn:用于创建 Systemd 容器
    • systemd-path:Systemd 的内部工具,用于显示系统上下文中的各种路径配置
    • systemd-run:用于将任意指定的命令包装成一个临时的后台服务运行
    • systemd-stdio- bridge:Systemd 的内部 工具,用于将程序的标准输入输出重定向到系统总线
    • systemd-tmpfiles:Systemd 的内部工具,用于创建和管理临时文件目录
    • systemd-tty-ask-password-agent:用于响应后台服务进程发出的输入密码请求

    systemd配置

    配置文件说明

    • 每一个Unit都需要有一个配置文件用于告知systemd对于服务的管理方式
    • 配置文件存放于/usr/lib/systemd/system/,设置开机启动后会在/etc/systemd/system目录建立软链接文件
    • 每个Unit的配置文件配置默认后缀名为.service
    • /usr/lib/systemd/system/目录中分为system和user两个目录,一般将开机不登陆就能运行的程序存在系统服务里,也就是/usr/lib/systemd/system
    • 配置文件使用方括号分成了多个部分,并且区分大小写

    相关文件说明:

    相关文件 CentOS6 CentOS7
    服务启动的脚本启动路径 /etc/init.d /usr/lib/systemd/system
    开机自启服务存放路径 /etc/rcN.d /etc/systemd/system/multi-user.target.wants/
    默认运行级别配置文件 /etc/inittab /etc/systemd/system/default.target

    配置说明

    Unit 段

    • Description:描述这个 Unit 文件的信息
    • Documentation:指定服务的文档,可以是一个或多个文档的 URL 路径
    • Requires:依赖的其它 Unit 列表,列在其中的 Unit 模板会在这个服务启动时的同时被启动。并且,如果其中任意一个服务启动失败,这个服务也会被终止
    • Wants:与 Requires 相似,但只是在被配置的这个 Unit 启动时,触发启动列出的每个 Unit 模块,而不去考虑这些模板启动是否成功
    • After:与 Requires 相似,但是在后面列出的所有模块全部启动完成以后,才会启动当前的服务
    • Before:与 After 相反,在启动指定的任务一个模块之间,都会首先确证当前服务已经运行
    • Binds To:与 Requires 相似,失败时失败,成功时成功,但是在这些模板中有任意一个出现意外结束或重启时,这个服务也会跟着终止或重启
    • Part Of:一个 Bind To 作用的子集,仅在列出的任务模块失败或重启时,终止或重启当前服务,而不会随列出模板的启动而启动
    • OnFailure:当这个模板启动失败时,就会自动启动列出的每个模块
    • Conflicts:与这个模块有冲突的模块,如果列出的模块中有已经在运行的,这个服务就不能启动,反之亦然

    Install 段

    这部分配置的目标模块通常是特定运行目标的 .target 文件,用来使得服务在系统启动时自动运行。这个区段可以包含三种启动约束:

    • WantedBy:和 Unit 段的 Wants 作用相似,只有后面列出的不是服务所依赖的模块,而是依赖当前服务的模块。它的值是一个或多个 Target,当前 Unit 激活时(enable)符号链接会放入 /etc/systemd/system 目录下面以 <Target 名> + .wants 后缀构成的子目录中,如 /etc/systemd/system/multi-user.target.wants/

    • RequiredBy:和 Unit 段的 Wants 作用相似,只有后面列出的不是服务所依赖的模块,而是依赖当前服务的模块。它的值是一个或多个 Target,当前 Unit 激活时,符号链接会放入 /etc/systemd/system 目录下面以 <Target 名> + .required 后缀构成的子目录中

    • Also:当前 Unit enable/disable 时,同时 enable/disable 的其他 Unit

    • Alias:当前 Unit 可用于启动的别名

    Service 段

    用来 Service 的配置,只有 Service 类型的 Unit 才有这个区块。它的主要字段分为服务生命周期和服务上下文配置两个方面。

    服务生命周期控制相关
    • Type:定义启动时的进程行为,它有以下几种值:
      • Type=simple:默认值,执行ExecStart指定的命令,启动主进程
      • Type=forking:以 fork 方式从父进程创建子进程,创建后父进程会立即退出
      • Type=oneshot:一次性进程,Systemd 会等当前服务退出,再继续往下执行
      • Type=dbus:当前服务通过D-Bus启动
      • Type=notify:当前服务启动完毕,会通知Systemd,再继续往下执行
      • Type=idle:若有其他任务执行完毕,当前服务才会运行
    • RemainAfterExit:值为 true 或 false(默认)。当配置为 true 时,Systemd 只会负责启动服务进程,之后即便服务进程退出了,Systemd 也仍然会认为这个服务还在运行中。这个配置主要是提供给一些并非常驻内存,而是启动注册后立即退出,然后等待消息按需启动的特殊类型服务使用的。
    • ExecStart:启动当前服务的命令
    • ExecStartPre:启动当前服务之前执行的命令
    • ExecStartPos:启动当前服务之后执行的命令
    • ExecReload:重启当前服务时执行的命令
    • ExecStop:停止当前服务时执行的命令
    • ExecStopPost:停止当其服务之后执行的命令
    • RestartSec:自动重启当前服务间隔的秒数
    • Restart:定义何种情况 Systemd 会自动重启当前服务,可能的值包括 always(总是重启)、on-success、on-failure、on-abnormal、on-abort、on-watchdog
    • TimeoutStartSec:启动服务时等待的秒数,这一配置对于使用 Docker 容器而言显得尤为重要,因其第一次运行时可能需要下载镜像,严重延时会容易被 Systemd 误判为启动失败杀死。通常,对于这种服务,将此值指定为 0,从而关闭超时检测
    • TimeoutStopSec:停止服务时的等待秒数,如果超过这个时间仍然没有停止,Systemd 会使用 SIGKILL 信号强行杀死服务的进程
    服务上下文配置相关
    • Environment:为服务指定环境变量
    • EnvironmentFile:指定加载一个包含服务所需的环境变量的列表的文件,文件中的每一行都是一个环境变量的定义
    • Nice:服务的进程优先级,值越小优先级越高,默认为 0。其中 -20 为最高优先级,19 为最低优先级
    • WorkingDirectory:指定服务的工作目录
    • RootDirectory:指定服务进程的根目录(/ 目录)。如果配置了这个参数,服务将无法访问指定目录以外的任何文件
    • User:指定运行服务的用户
    • Group:指定运行服务的用户组
    • MountFlags:服务的 Mount Namespace 配置,会影响进程上下文中挂载点的信息,即服务是否会继承主机上已有挂载点,以及如果服务运行执行了挂载或卸载设备的操作,是否会真实地在主机上产生效果。可选值为 shared、slaved 或 private
      • shared:服务与主机共用一个 Mount Namespace,继承主机挂载点,且服务挂载或卸载设备会真实地反映到主机上
      • slave:服务使用独立的 Mount Namespace,它会继承主机挂载点,但服务对挂载点的操作只有在自己的 Namespace 内生效,不会反映到主机上
      • private:服务使用独立的 Mount Namespace,它在启动时没有任何任何挂载点,服务对挂载点的操作也不会反映到主机上
    • LimitCPU / LimitSTACK / LimitNOFILE / LimitNPROC 等:限制特定服务的系统资源量,例如 CPU、程序堆栈、文件句柄数量、子进程数量等

    注意:如果在 ExecStart、ExecStop 等属性中使用了 Linux 命令,则必须要写出完整的绝对路径。对于 ExecStartPre 和 ExecStartPost 辅助命令,若前面有个 “-” 符号,表示忽略这些命令的出错。因为有些 “辅助” 命令本来就不一定成功,比如尝试清空一个文件,但文件可能不存在。

    Unit 文件占位符

    在 Unit 文件中,有时会需要使用到一些与运行环境有关的信息,例如节点 ID、运行服务的用户等。这些信息可以使用占位符来表示,然后在实际运行被动态地替换实际的值。

    • %n:完整的 Unit 文件名字,包括 .service 后缀名
    • %p:Unit 模板文件名中 @ 符号之前的部分,不包括 @ 符号
    • %i:Unit 模板文件名中 @ 符号之后的部分,不包括 @ 符号和 .service 后缀名
    • %t:存放系统运行文件的目录,通常是 “run”
    • %u:运行服务的用户,如果 Unit 文件中没有指定,则默认为 root
    • %U:运行服务的用户 ID
    • %h:运行服务的用户 Home 目录,即 %{HOME} 环境变量的值
    • %s:运行服务的用户默认 Shell 类型,即 %{SHELL} 环境变量的值
    • %m:实际运行节点的 Machine ID,对于运行位置每个的服务比较有用
    • %b:Boot ID,这是一个随机数,每个节点各不相同,并且每次节点重启时都会改变
    • %H:实际运行节点的主机名
    • %v:内核版本,即 “uname -r” 命令输出的内容
    • %%:在 Unit 模板文件中表示一个普通的百分号

    修改配置文件后重启

    修改配置文件以后,需要重新加载配置文件,然后重新启动相关服务。

    # 重新加载配置文件
    $ sudo systemctl daemon-reload
    
    # 重启相关服务
    $ sudo systemctl restart foobar
    

    常见中间件配置

    Nginx

    [Unit]
    Description=nginx
    After=network.target
      
    [Service]
    Type=forking
    ExecStart=/usr/local/nginx/sbin/nginx
    ExecReload=/usr/local/nginx/sbin/nginx -s reload
    ExecStop=/usr/local/nginx/sbin/nginx -s quit
    PrivateTmp=true
      
    [Install]
    WantedBy=multi-user.target
    

    MySQL

    [Unit]
    Description=MySQL Server
    Documentation=man:mysqld(8)
    Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
    After=network.target
    After=syslog.target
    
    [Install]
    WantedBy=multi-user.target
    
    [Service]
    User=mysql
    Group=mysql
    
    Type=forking
    
    PIDFile=/var/run/mysqld/mysqld.pid
    
    # Disable service start and stop timeout logic of systemd for mysqld service.
    TimeoutSec=0
    
    # Execute pre and post scripts as root
    PermissionsStartOnly=true
    
    # Needed to create system tables
    ExecStartPre=/usr/bin/mysqld_pre_systemd
    
    # Start main service
    ExecStart=/usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid $MYSQLD_OPTS
    
    # Use this to switch malloc implementation
    EnvironmentFile=-/etc/sysconfig/mysql
    
    # Sets open_files_limit
    LimitNOFILE = 5000
    
    Restart=on-failure
    
    RestartPreventExitStatus=1
    
    PrivateTmp=false
    
  • 相关阅读:
    POJ 2236 Wireless Network(并查集)
    POJ 2010 Moo University
    POJ 3614 Sunscreen(贪心,区间单点匹配)
    POJ 2184 Cow Exhibition(背包)
    POJ 1631 Bridging signals(LIS的等价表述)
    POJ 3181 Dollar Dayz(递推,两个long long)
    POJ 3046 Ant Counting(递推,和号优化)
    POJ 3280 Cheapest Palindrome(区间dp)
    POJ 3616 Milking Time(dp)
    POJ 2385 Apple Catching(01背包)
  • 原文地址:https://www.cnblogs.com/Rohn/p/14489587.html
Copyright © 2011-2022 走看看