服务 (service) 管理

服务 (service) 管理

服务 (service) 本质就是进程(守护进程),但是是运行在后台的,通常都会监听某个端口,等待其它程序的请求,比如sshd,其实就是后台的一个进程,监听 22 端口,等待ssh连接,比如mysqld前面我们接触过的很多最后带了一个字母 d 的都是类似的进程)、防火墙等,因此我们又称为守护进程(daemon),是 Linux 中非常重要的知识点。

在 Linux 中,无论何时当你安装任何带有服务和守护进程的包,系统默认会把这些服务的初始化及 systemd 脚本添加进去,不过此时它们并没有被启用。我们需要手动的开启或者关闭那些服务。

systemd使用 .service 文件而不是 bash 脚本。systemd 将所有守护进程添加到 cgroups 中排序,你可以通过浏览/cgroup/systemd文件查看系统等级。

service 命令

1
service 服务名 [start|stop|restart|reload|status]

CentOS7.0后很多服务不再使用service,而是systemctl(后文的systemctl小节)

比如:

service network start

service network stop

防火墙的状态

service firewalld status

可以看到在当前版本中 Centos 7 中,service firewalld 调用的,实际上是重定向到 systemctl:Redirecting to /bin/systemctl ……….

关闭防火墙

service firewalld stop


service指令管理的服务在/etc/init.d查看,/etc/init.d下的服务仍然还是用service管理,不会显示Redirecting to /bin/systemctl

当然,systemctl本身也是兼容service的,可以管理/etc/init.d下的服务。

network是一个基础服务,所有依赖网络的服务都要求network服务正常运行,如果network服务关闭,有的服务比如ssh将直接瘫痪(不会自动关闭,但是会瘫痪)


service命令本身是一个 shell 脚本,它在/etc/init.d/目录查找指定的服务脚本,然后调用该服务脚本来完成任务。

自己写 service 脚本试试

/etc/init.d 下创建文件 lkser  

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/bin/bash
# source function library
. /etc/rc.d/init.d/functions
# chkconfig: 345 85 15
# description: This is a lk Test Service.
usage() {
  echo " usage:$0 {start|stop|restart} "
}

start() {
  echo "lk Service Started!"
}

stop() {
  echo "lk Service Stopped!"
}

restart() {
  stop
  start
}

#main function
case $1 in
  start)
     start
     ;;
  stop)
     stop
     ;;
  restart)
     restart
     ;;
  *)
     usage
     ;;
esac

. /etc/rc.d/init.d/functions :functions 这个脚本是给/etc/init.d里边的文件使用的(可理解为全局文件)。

然后赋权 chmod +x lkser 否则执行的时候会提示:

然后执行:

66666666 !!!

查看服务名

运行setup命令,然后选择 系统服务 就可以看到全部服务

<SysV initscripts>标签下的,就是/etc/init.d下的几个服务

前面有 * 号的,会随着 Linux 的启动自动启动,把光标放到 * 号上,按空格键取消 * 号,这样你就可以在这里设置服务自启动

按 enter 确定,按 tab 切换确定和取消

服务自启动就是后面要谈到的服务的运行级别的问题。

Centos7 以后,使用systemctl,可以更方便的查看所有服务:systemctl -t service

具体请查看后文的systemctl小节。

运行级别和 chkconfig 命令

运行级别相关知识,请回看《Linux 指令基础》的指定运行级别小节。

Linux 系统有0-6这 7 中运行级别,Linux 运行级别的重点是使管理员可以控制在特定条件下运行的服务。对系统进行这种细粒度控制可以增强安全性,因为您可以确保没有多余的服务在运行

从 centos7 开始,/etc/inittab 不在起作用,不再使用runlevel这个概念,转而开始使用targets这个概念

查看当前运行级别:runlevel

获取默认的运行级别:systemctl get-default

设置默认的运行级别:systemctl set-default TARGET.target

Linux 系统开机流程:

chkconfig

通过chkconfig命令可以给服务的各个运行级别设置自启动/关闭。(从查看服务名小节中可知,setup命令中也可以修改)。

chkconfig指令管理的服务在/etc/init.d查看 (只能管理这些服务),注意:Centos7.0后,可以systemctl简化操作,这两个命令的区别查看常用指令小节。


chkconfig基本用法

chkconfig --list:查看服务在各个运行级别下的开启关闭情况

开的意思就是如果系统以此运行级别开机,则开机运行,关的意思就是开机不运行

chkconfig --list 服务名:查看特定服务在各个运行级别下的开启关闭情况

chkconfig --level 5 服务名on/off:让特定服务在运行级别 5 开启或关闭,chkconfig重新设置服务后自启动或关闭,需要重启机器 reboot 生效

chkconfig --level 35 mysqld on:设定 mysqld 在等级 3 和 5 为开机运行服务,--level 35表示操作只在等级 3 和 5 执行,on 表示启动,off 表示关闭

chkconfig mysqld on:设定 mysqld 在各等级为 on,“各等级”包括 2、3、4、5 等级,1 和 6 一般不包含在内,因为一个是关机,一个是重启        

systemctl 命令

systemd是 Linux 系统最新的初始化系统 (init),作用是提高系统的启动速度,尽可能启动较少的进程,尽可能更多进程并发启动。

systemd对应的进程管理命令是systemctl,centos7 以后,推荐使用systemctl命令来管理服务,而不再使用servicechkconfigsystemctl命令的功能包含了servicechkconfig的功能,而且功能更多。当然servicechkconfig还是可以继续使用。

systemctl命令兼容了service,即systemctl也会去/etc/init.d目录下查看,执行相关程序。

systemctl主要的功能就是查看服务当前的运行状态和开机是否自启


systemd核心概念 unit(单元)类型:unit 表示不同类型的systemd对象,通过配置文件进行标识和配置;文件中主要包含了系统服务、监听 socket、保存的系统快照以及其它与 init 相关的信息

下面为 unit 类型(路径:/usr/lib/systemd/system/) :

  • service:文件扩展名为.service, 用于定义系统服务,最常见

  • target:文件扩展名为.target用于模拟实现运行级别

    最常见的就是这 7 个文件:ll *.target

  • device:用于定义内核识别的设备

  • mount:定义文件系统挂载点

  • socket:用于标识进程间通信用的 socket 文件,也可在系统启动时,延迟启动服务,实现按需启动

  • snapshot:管理系统快照

  • swap:用于标识 swap 设备

  • automount:文件系统的自动挂载点

  • path:用于定义文件系统中的一个文件或目录使用,常用于当文件系统变化时,延迟激活服务


那么如何查看这些类型呢?可以使用-t加上类型去查看,以service为例

systemctl -t service

……

  • LOAD: 是否载入内存

  • ACTIVE:父 unit 是否正在运行

  • SUB: 子 unit 是否正在运行

  • ACTIVE 和 SUB 都表示运行状态,运行状态即:当前程序是否在运行,可能的值:

    • active(running):正有一只或多只程序正在系统中执行的意思;

    • active(exited):仅执行一次就正常结束的服务,目前并没有任何程序在系统中执行;

    • active(waiting):正在执行当中,不过还需要等待其他的事件才能继续处理;

    • inactive:这个服务目前没有运行;

    • dead:程序已经清除;

加上all参数,查看已经载入但是没有运行的 units,基本上就是查看系统所有服务得意思

systemctl --all -t service

……

当然还可以是别的类型,比如 target 类型

systemctl --all -t target

常用指令

任务 旧指令 新指令
检查服务状态 service httpd status systemctl status httpd.service(服务详细信息)systemctl is-active httpd.service(仅显示是否 Active)
启动某服务 service httpd start systemctl start httpd.service
停止某服务 service httpd stop systemctl stop httpd.service
重启某服务 service httpd restart systemctl restart httpd.service

服务运行情况(对service命令的兼容)

1
systemctl status/is-active/show/start/stop/restart/ xxx.service(也可以简写成xxx)

运行状态:

  • active(running):正有一只或多只程序正在系统中执行的意思;

  • active(exited):仅执行一次就正常结束的服务,目前并没有任何程序在系统中执行;

  • active(waiting):正在执行当中,不过还需要等待其他的事件才能继续处理;

  • inactive:这个服务目前没有运行;

  • dead:程序已经清除;


系统的所有服务的运行状态(不包括/etc/init.d下的服务):systemctl --all -t service

查看服务的状态信息:systemctl status sshd

  • loaded 表示启动状态,sshd.service会开机自启

  • active 表示运行状态,active 表示正在运行

  • pid 不用说,表示进程 ID

  • 下面也列出了此服务的日志信息


服务是否正在运行:systemctl is-active sshd


查看服务所有配置详细信息:systemctl show sshd

……


systemctl start firewalld.service:开启防火墙

systemctl status firewalld.service:查看防护墙状态

systemctl stop  firewalld.service:关闭防护墙


服务开机自启情况

启动状态:程序是否开机自启

  • enabled:这个 daemon 将在(3 或者 5 这两个级别)开机时被执行;

  • disabled:这个 daemon 在(3 或者 5 这两个级别)开机时不会被执行;

  • static:这个 daemon 不可以自己启动(enable 不可),不过可能会被其他的 enabled 的服务来唤醒(关联属性的服务);

  • mask:这个 daemon 无论如何都无法被启动,因为已经被强制注销(非删除),可通过systemctl unmask方式改回原本状态

查看所有已安装(loaded)的 unit 文件的开机自启情况(当然,不包括/etc/init.d下的服务):systemctl list-unit-files

……

其中 STATE 为启动状态

带上 service 参数,则只会显示服务(.service)的开机自启情况

systemctl list-unit-files --type=service


查看所有已启动服务:systemctl list-units --type=service

结果列跟 systemctl list-unit-files --type=service 类似,只是范围有差别,这里只列出已启动的 unit,systemctl list-unit-files --type=service 会列出所有的 unit


设置服务在 3 和 5 这两个运行级别开机自启动或者禁止启动

centos7 简化运行级别为graphical.target.wantsmulti-user.target.wants两个 target,systemctl enable/disable 就是设置此服务在 3 和 5 的运行级别是否自启

systemctl enable/disable xxx.service(也可以简写成xxx)

操作/etc/init.d下的服务的时候本质上还是调用chkconfig,在 level 2、3、4、5 中开启自启。相当于chkconfig --level 2345 服务名 on/off或者chkconfig 服务名 on/off

操作/etc/init.d以外的服务的服务的时候就是到/usr/lib/systemd/system/下删除或者创建对应服务的链接文件,我现在的运行级别是 5,但是它是到 3 对应的运行级别下修改,因为运行级别为 5 的自启动服务包含了运行级别为 3 的自启动服务


查询某个服务是否是自启动的

systemctl is-enabled 服务名


chkconfig注释里说清楚了 chkconfigsystemctl(管理软件自启动相关指令)的区别:

chkconfig只能控制/etc/init.d下的服务(setup命令的结果中的<SysV>下的服务就是/etc/init.d下的服务),无法控制systemd中的服务,

但是systemctlsystemd的服务控制命令)可以操作/etc/init.d下的服务,并覆盖chkconfig对这些服务的自启动设置:

举个例例子

lkser 是我在/etc/init.d下新建的服务。

systemctl enable lkser

操作/etc/init.d下的服务的时候本质上还是调用chkconfig,在 level 2、3、4、5 中开启自启。相当于chkconfig --level 2345 服务名 on/off或者chkconfig 服务名 on/off


查看systemd的服务启动情况(systemd看不到/etc/init.d下的服务):systemctl list-unit-files --service,这个前面已经演示了

查看特定运行级别下的服务:systemctl list-dependencies [target]

比如:

systemctl list-dependencies graphical.target

可以注意到其包含了运行级别为 3 的服务

红灯表示没运行,绿灯表示正在运行


systemctl list-dependencies sshd:获取服务的依赖项列表

相关目录

  • /usr/lib/systemd/system/:每个服务最主要的启动脚本的配置放在这,有点类似以前的/etc/init.d

  • /run/systemd/system/:系统执行过程中所产生的服务脚本所在目录,这些脚本的优先级要比/usr/lib/systemd/system/高;

  • /etc/systemd/system/:管理员根据主机系统的需求所创建的执行脚本所在目录,执行优先级比/run/systemd/system/高;

    其中的 service 文件全都是链接文件,指向/usr/lib/systemd/system/下的 service 文件

从上面的功能及优先级次序,我们可以知道,/etc/systemd/system/目录下的相关配置,决定系统了会不会执行某些服务,所以该目录下面一般放着一大堆链接文件。而/usr/lib/systemd/system/下,则放着实际执行的systemd启动脚本配置文件。同时,每一个运行级别在这个目录下都有对应的目录,下面放着对应运行级别会启动的服务,比如最常见的两个运行级别对应的文件就是graphical.target.wantsmulti-user.target.wants

因此如果你想要修改某个服务启动的设置,应该去/usr/lib/systemd/system/下面修改,systemctl enable/disable 命令(操作/etc/init.d以外的服务时)实际上就是在/usr/lib/systemd/system/目录下创建连接或者删除连接。/etc/systemd/system/仅是链接到正确的执行脚本配置文件而已。所以想要看执行脚本设置,应该就得要到/usr/lib/systemd/system/去查阅。

详解 /usr/lib/systemd/system

systemctl命令管理systemd的资源 Unit。systemd的 Unit 放在目录/usr/lib/systemd/system(Centos) 或/etc/systemd/system(Ubuntu)

centos:

…….

这里还有我们熟悉的服务:

这个目录下主要有四种类型的文件.mount,.service,.target,.wants

  • .mount文件,比如tmp.mount

    .mount文件定义了一个挂载点,[Mount]节点里配置了 What,Where,Type 三个数据项,等同于以下命令:

    1
    
    mount -t [Type] [What] [Where]
  • .service文件,比如atd.service

    .service文件定义了一个服务,分为[Unit],[Service],[Install]三个小节,常用的配置项如下,如果需要查看完整的配置项,请看systemd.service 中文手册 [译者:金步国]

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    
    [Unit]
    Description  # 描述,
    After # 在 哪些服务启动之后再启动
    ConditionPathExists # 执行条件
    [Service]
    Type # 服务类型,可以简单设置为 simple
    EnvironmentFile # 环境变量所在文件,一般指定 PATH
    ExecStart # systemctl start 时执行的脚本
    ExecStop # systemctl stop 时执行的脚本
    Restart # 什么时候重启
    User # 以什么用户执行此服务
    Group # 以什么用户执行此服务
    [Install]
    Alias # 服务别名
    WangtedBy # 在什么模式下使用,一般在指定为多用户模式 multi-user.target   
  • .target文件,.target定义了一些基础的组件,供.service文件调用

  • .wants文件,.wants文件定义了要执行的文件集合,每次执行,.wants文件夹里面的文件都会执行

自定义 service 服务

我们可以自定义 service 服务,然后用 systemctl 来管理我们的服务,常见的做法时将一些脚本通过 service 服务包一层,然后通过 systemctl 来实现在任意目录下的一键执行,而且可以设置其开机自启,非常方便。

自定义 service 服务非常简单,在前面的详解 /usr/lib/systemd/system小节我们已经了解过service文件有哪些常见配置,现在我们就来写一个简单版本的 service 服务

首先我们在/opt目录下创建两个两个脚本

start.sh:

1
2
#!/usr/bin/env bash
echo service start >> /opt/log.txt

执行命令chmod a+rwx start.sh赋权。

stop.sh

1
2
#!/usr/bin/env bash
echo service stop >> /opt/log.txt

执行命令chmod a+rwx stop.sh赋权。

然后创建simpleserv.service文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
[Unit]
Description=Simple Service
After=network.target 

[Service]
Type=simple
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
ExecStart=/opt/start.sh
ExecStop=/opt/stop.sh
RemainAfterExit=yes
Restart=on-failure

[Install]
WantedBy=multi-user.target

并将其复制到/usr/lib/systemd/system/或者/etc/systemd/system/

关于这两个目录的作用,请看相关目录小节

然后执行systemctl daemon-reload刷新一下,然后即可通过systemctl start simpleserv启动服务,启动之后通过systemctl status simpleserv查看服务状态如下:

1
2
3
4
5
6
7
8
[root@iZbp1ag455gf8nrfdeqknwZ system]# systemctl status simpleserv 
● simpleserv.service - Simple Service
   Loaded: loaded (/usr/lib/systemd/system/simpleserv.service; disabled; vendor preset: disabled)
   Active: active (exited) since Sun 2024-02-18 23:28:36 CST; 1s ago
  Process: 23075 ExecStart=/opt/start.sh (code=exited, status=0/SUCCESS)
 Main PID: 23075 (code=exited, status=0/SUCCESS)

Feb 18 23:28:36 iZbp1ag455gf8nrfdeqknwZ systemd[1]: Started Simple Service.

通过systemctl stop simpleserv关闭服务,此时日志文件/opt/log.txt的日志如下

1
2
service start
service stop

甚至还可以通过systemctl enable simpleserv设置此服务开机自启。

注意,在simpleserv.service中有一个配置项RemainAfterExit=yes,其作用是确定当该服务的所有进程全部退出之后是否依然将此服务视为活动 (active) 状态。默认值为 no

因为我们的ExecStart配置的start.sh脚本就是一个简单的 echo 语句,执行完之后,进程就退出了,此时如果不配置RemainAfterExit=yes的话,执行完ExecStart的命令后,service 就视为 inactive 状态,就会自动调用ExecStop中的脚本。因此为了保证ExecStart的脚本执行完之后,服务保持启动,我们就需要设置RemainAfterExit=yes

.service文件的完整的配置项介绍,请看systemd.service 中文手册 [译者:金步国]

在实际的场景中,ExecStart一般不会为一个简单的 echo 命令,一般都会是一个长期执行的进程,比如 java 进程,此时也就不需要配置RemainAfterExit=yes了。

systemctl 常见错误

  • code=exited, status=203/EXEC,可能原因

    • ExecStart或者ExecStop的脚本路径不对,或者脚本权限不够,不可执行,或者脚本没有 shebang 行,或者 shebang 行路径错误

    • SELinux 可能阻止了脚本的执行,可以到/var/log/audit/audit.log中检查,消息格式为type=AVC msg=audit([...]): avc: denied { execute },或者直接执行 ausearch -ts recent -m avc -i.

日志管理

Systemd 进程管理工具 — Linux latest 文档

Systemd 统一管理所有 Unit 的启动日志。带来的好处就是,可以只用 journalctl 一个命令,查看所有日志(内核日志和应用日志)。日志的配置文件是 /etc/systemd/journald.conf

journalctl 功能强大,用法非常多。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# 查看所有日志(默认情况下 ,只保存本次启动的日志)
[Linux]# journalctl

# 查看内核日志(不显示应用日志)
[Linux]# journalctl -k

# 查看系统本次启动的日志
[Linux]# journalctl -b
[Linux]# journalctl -b -0

# 查看上一次启动的日志(需更改设置)
[Linux]# journalctl -b -1

# 查看指定时间的日志
[Linux]# journalctl --since="2012-10-30 18:17:16"
[Linux]# journalctl --since "20 min ago"
[Linux]# journalctl --since yesterday
[Linux]# journalctl --since "2015-01-10" --until "2015-01-11 03:00"
[Linux]# journalctl --since 09:00 --until "1 hour ago"

# 显示尾部的最新10行日志
[Linux]# journalctl -n

# 显示尾部指定行数的日志
[Linux]# journalctl -n 20

# 实时滚动显示最新日志
[Linux]# journalctl -f

# 查看指定服务的日志
[Linux]# journalctl /usr/lib/systemd/systemd

# 查看指定进程的日志
[Linux]# journalctl _PID=1

# 查看某个路径的脚本的日志
[Linux]# journalctl /usr/bin/bash

# 查看指定用户的日志
[Linux]# journalctl _UID=33 --since today

# 查看某个 Unit 的日志
[Linux]# journalctl -u nginx.service
[Linux]# journalctl -u nginx.service --since today

# 实时滚动显示某个 Unit 的最新日志
[Linux]# journalctl -u nginx.service -f

# 合并显示多个 Unit 的日志
[Linux]# 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
[Linux]# journalctl -p err -b

# 日志默认分页输出,--no-pager 改为正常的标准输出
[Linux]# journalctl --no-pager

# 以 JSON 格式(单行)输出
[Linux]# journalctl -b -u nginx.service -o json

# 以 JSON 格式(多行)输出,可读性更好
[Linux]# journalctl -b -u nginx.serviceqq
 -o json-pretty

# 显示日志占据的硬盘空间
[Linux]# journalctl --disk-usage

# 指定日志文件占据的最大空间
[Linux]# journalctl --vacuum-size=1G

# 指定日志文件保存多久
[Linux]# journalctl --vacuum-time=1years

防火墙相关

什么是防火墙?防火墙相当于一个拦截器,Linux 系统外的程序想要访问系统端口,必须先通过防火墙,如果没有配置防火墙,则请求会被拦截,配置了防火墙规则,这个请求就可以通过防火墙正常访问端口。

在生产环境,一定要打开防火墙

centos7 以后,防火墙(firewall)的服务不再是iptables,而是firewalld需要 root 权限才可以运行

firewall-cmd --state:查看 firewall 的状态

firewall-cmd --query-port=8089/tcp:查询端口状态

firewall-cmd --permanent --add-port=8089/tcp:开启端口,重新载入,才能生效,对于协议,可以通过netstat -anp查看对应端口的 IP

firewall-cmd --permanent --remove-port=8089/tcp:移除端口,重新载入,才能生效

firewall-cmd --reload:刷新(重载)防火墙配置

firewall-cmd --list-ports:查看已经开放的端口

其他操作

systemctl status firewalld.service:防火墙的状态

systemctl start firewalld.service:开启防火墙

systemctl stop firewalld.service:关闭防火墙

systemctl restart firewalld.service:重启防火墙

案例:

在防火墙中打开一个端口,然后用 Windows 中用telnet命令测试

首先本地启动 Tomcat,使用 8080 端口,这个时候 8080 端口没有开启,在 Windows 中用telnet 访问 Linux 虚拟机的 8080 是不通的,然后防火墙开启 8080 端口,然后 reload 防火墙,再在 Windows 中用telnet 访问 Linux 虚拟机的 8080 端口,就是通的了。

打开的端口和关闭的端口都各自有一个列表,添加端口就相当于在开启列表里加了一个端口。

0%