服务 (service) 管理

服务 (service) 管理

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

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

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

service 命令

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

#!/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/) :


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

systemctl -t service

……

加上 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 命令的兼容)

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

运行状态:


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

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


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


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

……


systemctl start firewalld.service:开启防火墙

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

systemctl stop  firewalld.service:关闭防护墙


服务开机自启情况

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

查看所有已安装(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:获取服务的依赖项列表

相关目录

从上面的功能及优先级次序,我们可以知道,/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

自定义 service 服务

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

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

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

start.sh:

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

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

stop.sh

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

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

然后创建 simpleserv.service 文件:

[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 查看服务状态如下:

[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 的日志如下

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 常见错误

日志管理

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

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

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

# 查看所有日志(默认情况下 ,只保存本次启动的日志)
[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 端口,就是通的了。

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

iptables

参考文档:iptables 文档

删除已添加的规则

# 添加一条规则
iptables -A INPUT -s 192.168.1.5 -j DROP

将所有 iptables 以序号标记显示,执行:

iptables -L -n --line-numbers

比如要删除 INPUT 里序号为 8 的规则,执行:

iptables -D INPUT 8

开放指定的端口

iptables -A INPUT -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT               #允许本地回环接口(即运行本机访问本机)
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT    #允许已建立的或相关连的通行
iptables -A OUTPUT -j ACCEPT         #允许所有本机向外的访问
iptables -A INPUT -p tcp --dport 22 -j ACCEPT    #允许访问22端口
iptables -A INPUT -p tcp --dport 80 -j ACCEPT    #允许访问80端口
iptables -A INPUT -p tcp --dport 21 -j ACCEPT    #允许ftp服务的21端口
iptables -A INPUT -p tcp --dport 20 -j ACCEPT    #允许FTP服务的20端口
iptables -A INPUT -j reject       #禁止其他未允许的规则访问
iptables -A FORWARD -j REJECT     #禁止其他未允许的规则访问

屏蔽 IP

iptables -A INPUT -p tcp -m tcp -s 192.168.0.8 -j DROP  # 屏蔽恶意主机(比如,192.168.0.8
iptables -I INPUT -s 123.45.6.7 -j DROP       #屏蔽单个IP的命令
iptables -I INPUT -s 123.0.0.0/8 -j DROP      #封整个段即从123.0.0.1到123.255.255.254的命令
iptables -I INPUT -s 124.45.0.0/16 -j DROP    #封IP段即从123.45.0.1到123.45.255.254的命令
iptables -I INPUT -s 123.45.6.0/24 -j DROP    #封IP段即从123.45.6.1到123.45.6.254的命令是

指定数据包出去的网络接口

只对 OUTPUT,FORWARD,POSTROUTING 三个链起作用。

iptables -A FORWARD -o eth0