Linux防火墙

作者:

在

iptables

-t 指定表

-A 指定链

-j 指定规则

-s(–source)指定源ip

-d(–destination)目标ip

–dport 目标端口

-p 指定协议

-R INPUT 1 可替换INPUT表中第一条规则为新规则

iptables -F 全部删除

iptables -vnL –line-number 展示规则

iptables -vnL INPUT –line-number 具体的链条,-t可以指定表

删除规则

iptables -D INPUT 1   # 建议使用对应链上的序号删除

==注意==:规则就删除和增加,更改:就先删除原规则,再增加

自定义链

dnf -y install iptables-services # 使用iptables-services自动管理
systemctl start iptables.service
systemctl enable iptables.service

iptables -F  #清楚所有规则
service iptables save # 保存一下


iptables -t filter -N WEB_CHAIN  # 创建自定义链
iptables -t filter -A INPUT  -s 192.168.18.1 -j WEB_CHAIN   # 自定义链规则,绑定至filter表中的INPUT链
iptables -t filter -A WEB_CHAIN -p tcp -m multiport --dports 80,443 -j ACCEPT  # 自定义链规则为允许80,443端口  
iptables -t filter -A INPUT -p tcp  -m multiport --dports 80,443 -j DROP  # 拒绝所有80,443端口
iptables -L
curl 127.0.0.1  # 无法访问
# 浏览器访问192.168.18.129,可以访问
# 链的规则从1开始逐个匹配

[root@192 ~]# iptables -vnL --line-numbers
Chain INPUT (policy ACCEPT 2608 packets, 130K bytes)
num   pkts bytes target     prot opt in     out     source               destination
1     2372  118K WEB_CHAIN  all  --  *      *       192.168.18.1         0.0.0.0/0
2        3   180 DROP       tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            multiport dports 80,443

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 10120 packets, 1015K bytes)
num   pkts bytes target     prot opt in     out     source               destination

Chain WEB_CHAIN (1 references)
num   pkts bytes target     prot opt in     out     source               destination
1       18  2455 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            multiport dports 80,443

image-20260729201350618

iptables模块实验

​ 1. string模块

# 注意是output和sport
iptables -A OUTPUT -p tcp --sport 80 -m string --algo bm --string "world" -j REJECT

​ 2. ssh实验尽量使用xshell,mobaxterm中的文件管理也会占用ssh通道

​ 3. limit-burst和limit,这里背景是一个令牌桶算法深入理解令牌桶算法:实现分布式系统高效限流的秘籍 在高并发系统中,“限流” 是保障服务稳定的核心手段 —— 当请求量超 – 掘金

​ 4. tcp flag了解即可,一般是方式tcp异常包的

iptables -A INPUT -p tcp --tcp-flags SYN,FIN,ACK SYN
掩码:SYN, FIN, ACK(只检查这 3 个位,其他位无视)
目标:SYN(要求 SYN=1,FIN=0,ACK=0)
匹配结果:匹配 TCP 握手的第一步(纯 SYN 包),这是建立新连接的标准包。

iptables -A FORWARD -p tcp --tcp-flags ALL SYN,ACK
掩码:ALL(这是 SYN,ACK,FIN,RST,URG,PSH 的简写,检查所有标志位)
目标:SYN,ACK(要求 SYN=1,ACK=1,其他所有位必须为 0)
匹配结果:匹配 TCP 握手的第二步(SYN-ACK 包),即服务器响应客户端的包。

==高并发请求场景(令牌桶+iptables)==

令牌桶的“保护机制”拆解

1. 核心逻辑:控制“进入内核协议栈”的包速率

text

外部请求 ──→ 网卡 ──→ iptables (limit匹配) ──→ 允许进入协议栈 ──→ 应用服务
                         │
                         ▼ (无令牌)
                      直接 DROP(拒绝)
  • 关键点:拒绝发生在内核层,不经过用户态应用(如 Nginx/Java 进程)。
  • 好处:即使拒绝,也几乎不消耗 CPU/内存,避免了应用层处理带来的资源开销。

2. 令牌桶参数如何应对突发流量

参数含义高并发下的作用
--limit-burst初始令牌数(桶容量)允许短时突发流量通过,避免正常业务波动被误杀
--limit令牌补充速率长期平均速率的上限,保证整体负载可控

举例:

bash

iptables -A INPUT -p tcp --dport 80 -m limit --limit 100/minute --limit-burst 200 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j DROP
  • 瞬间来了 500 个并发请求:
    • 前 200 个有令牌 → 通过
    • 剩下 300 个 → 直接 DROP(不经过 Nginx)
  • 之后按 100 个/分钟(约 1.67 个/秒)补充令牌
  • 如果持续高压,长期速率被锁死在 ~1.67 req/s,服务器负载稳定

==总结==:

令牌桶 + iptables 是在网络层给服务器戴上一个“泄压阀”——超过阈值直接在内核丢弃,不让压力传导到应用层,从而保证服务在过载时仍能部分可用,而不是完全僵死。


iptables日常管理从rocky9.0开始推荐使用firewalld

启用 iptables 防火墙 – 文档 – Rocky Linux 文档

iptables snat实验

机器初始状态(如果你的机器ip和我的有区别,按照nat网卡和桥接网卡查询结果一起更改即可)

# server1
nat: 192.168.18.129/24 #使用dhcp分配的或者自行配置的ip地址都可以,确保可以上网
host-only: 192.168.199.128/24 

# server2
host-only: 192.168.199.129/24 # 默认无法上网,但是与server仅主机网卡处于一个子网

需要配置项目

# server1
1.开启 Linux 内核路由转发
默认情况下,Linux 收到不是发给自己的数据包会直接丢弃。我们需要允许它转发数据
sysctl -w net.ipv4.ip_forward=1   # 开启转发,立即且临时生效
echo "net.ipv4.ip_forward = 1" > /etc/sysctl.d/99-ipforward.conf  # 写入配置文件永久生效,此/etc/sysctl.conf文件是根配置,依然使用子配置文件的方式
sysctl -p # 立即加载配置文件中参数

iptables -F -t nat 
iptables -t nat -A POSTROUTING -s 192.168.199.0/24 -o ens160 -j MASQUERADE  # 网卡是可上网的网卡
# iptables -t nat -A POSTROUTING -s 192.168.199.0/24 -o ens160 -j SNAT --to-source 192.168.18.129
# server2
vi /etc/NetworkManager/system-connections/ens160.nmconnection
[ipv4]
method=manual
address1=192.168.199.129/24,192.168.199.128   # ip地址不变,网关更改为server1的ip地址
dns=114.114.114.114  # dns正常添加,否则无人能提供域名解析

配置完成后,按以下顺序在 Server2 上进行检查,很容易排查出卡在哪一步:

​ 1. 测试内网连通性: ping 192.168.199.128 (确保能连上 Server1)

​ 2. 测试跨网段连通性: ping 192.168.18.129 (确保能连上 Server1 的外网网卡,如果这一步通了,说明 Server1 的 ip_forward 转发成功了)

​ 3. 测试外网 IP 连通性: ping 114.114.114.114 (如果这一步通了,说明 iptables NAT 规则成功生效)

​ 4. 测试域名解析: ping www.baidu.com (如果这一步通了,说明 DNS 配置正确,实验完全成功)

两条核心命令解析

iptables -t nat -A POSTROUTING -s 192.168.199.0/24 -o ens160 -j MASQUERADE
  1. -t nat (去哪张表?)

指定我们要操作的是 nat 表,即修改数据包的源 IP 或目的 IP。

  1. -A POSTROUTING

A 代表 Append,POSTROUTING是nat表里的一个链,字面意思是“路由之后”

告诉内核,当数据包已经决定了要从哪块网卡送出去、即将离开Server1这一瞬间,把它拦下来执行后面的操作

  1. -s 192.168.199.0/24

只有来自192.168.199.0/24这个仅主机局域网段的数据包,才会触发这条规则

  1. -o ens33

限定只有当数据包打算从 ens33 发送出去时,规则才生效。

  1. -j MASQUERADE

j 代表 Jump(跳转动作)。MASQUERADE 的字面意思是“伪装”,它会对符合上述所有条件的数据包做动态源地址转换(Dynamic SNAT)

iptables -t nat -A POSTROUTING -s 192.168.199.0/24 -o ens160 -j SNAT --to-source 192.168.18.129

当检查到从 ens160 网卡出去、且源自内网 192.168.199.0/24 的数据包时,强行将其源 IP 地址(Source IP)重写为固定的 192.168.18.129

抓包分析观察nat过程

server1上开启tcpdump抓包

# 没有tcpdump,就dnf install tcpdump
# -nn 第一个n:不解析ip地址为域名,第二个n:不解析端口号为协议
[root@server1 ~]#  tcpdump -i any -nn host www.baidu.com
tcpdump: data link type LINUX_SLL2
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
23:53:46.110400 ens224 In  IP 192.168.199.129 > 180.101.49.44: ICMP echo request, id 12, seq 1, length 64
23:53:46.110423 ens160 Out IP 192.168.18.129 > 180.101.49.44: ICMP echo request, id 12, seq 1, length 64
23:53:46.121616 ens160 In  IP 180.101.49.44 > 192.168.18.129: ICMP echo reply, id 12, seq 1, length 64
23:53:46.121634 ens224 Out IP 180.101.49.44 > 192.168.199.129: ICMP echo reply, id 12, seq 1, length 64

server2上ping 百度一下,你就知道

iptables dnat实验

web server转发(端口转发)

在server2上启动一个http server,期望通过server1的nat网卡访问到

dnf install -y httpd
systemctl start httpd
# 宿主机浏览器访问192.168.199.129:80,可以看到网站
# 我们期望通过访问server1 192.168.18.129:8080 可以访问的的上述网站
iptables -t nat -A PREROUTING -d 192.168.18.129 -p tcp --dport 8080 -j DNAT --to-destination 192.168.199.129:80

-t nat:依然是在 nat 表中做配置

-A PREROUTING:在数据包刚进入 Server1、还没决定去哪里之前,把它拦下。因为如果等路由决定做完了,Server1 就会觉得“这是发给我 8080 的包,我自己又没开这个端口”,从而直接拒绝连接。

-d 192.168.18.129 -p tcp –dport 8080:只有当访问的“目的地 IP”是 Server1 外网卡,且协议是 TCP,且“目标端口”是 8080 时,才触发规则。

-j DNAT –to-destination 192.168.199.129:80:强行把这个数据包的“目的地”改成内网机 Server2 的 IP 和 80 端口。

ssh本地端口

可以使用192.168.18.129:3322 通过ssh连接至server2

# server1
iptables -t nat -A PREROUTING -d 192.168.18.129 -p tcp --dport 3322 -j DNAT --to-destination 192.168.199.129:22

ssh本地转发

将本机目的6666端口流量在路由前直接转发至22端口

# server1
iptables -t nat -A PREROUTING -p tcp --dport 6666 -j REDIRECT --to-port 22

可以使用192.168.18.129:6666连接至server1自己

firewalld核心命令

firewall-cmd --list-all --zone=public --permanent # 查看永久生效的
firewall-cmd --list-all --zone=public             # 查看所有public规则

firewall-cmd --zone=public --add-service=http  # 临时放行
firewall-cmd --zone=public --add-port=80/tcp   # 用端口放行
# 注意:永久生效仅重启后才能生效,如果想要永久配置立即生效需要reload
firewall-cmd --zone=public --add-port=80/tcp  --permanent # 永久生效
# firewall-cmd --reload

firewall-cmd --zone=public --remove-service=http
firewall-cmd --zone=public --remove-service=http --permanent # 永久删除

# 富规则,此处注意ip地址换成你自己的
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.18.1" port port="80" protocol="tcp" drop'

image-20260728192651597

image-20260728193150862

image-20260728193213105

==firewalld==

1. Firewalld 放行策略的两种思路

  • 方法一(服务名):基于预定义的服务协议(如 http)放行。它实际是端口和协议的“别名映射”,适合通用场景,但存在命名歧义风险(例如 http 默认对应 80/tcp,若不熟悉映射关系容易混淆)。
  • 方法二(端口+协议):直接指定具体端口和传输层协议(如 80/tcp)。这种方式的优势是精确、无歧义,无需依赖服务名数据库,排障时一目了然,符合精细控制的需求。

2. 区域(Zone)的默认逻辑

  • public 是 Firewalld 的默认区域。若不特意切换,所有网卡接口默认归属该区域,策略只管这一处即可,无需被其他区域概念干扰。
  • 临时规则(无 --permanent)立即生效但重启丢失;永久规则(加 --permanent)需重载配置,注意两者的生效时机差异。

3. 验证与排查的工具链逻辑

  • ss:查看服务端口的监听状态(LISTEN)及进程关联,确认 Python/HTTP 服务已正确绑定 0.0.0.0:端口。
  • curl:充当测试客户端,发起 HTTP 请求报文。通过 curl -I 仅查看响应头即可快速验证放行是否生效,无需依赖浏览器。
  • 抓包工具(tcpdump / Wireshark):分别工作在 Linux 命令行和 Windows 图形界面,本质相同——提供数据包层面的证据链,可确认请求是否真正到达网卡、防火墙是否丢弃、代理是否转发。

4. “不用名字”的设计原则

  • 防火墙策略精确到传输层(端口+TCP/UDP),而不依赖应用层别名(如 http),可以避免因服务名定义变化或误读带来的配置偏差。
  • 这与网络排查的思路一致:分层解耦——防火墙只负责网络层的门禁开关,不关心门内跑的具体是什么应用;应用层问题(如 403、500)交给 curl 返回内容和应用日志去判断。

==总结==:防火墙firewalld

1. Firewalld 永久生效与立即生效的逻辑

  • 运行时(Runtime):修改立即生效,但重启丢失。
  • 永久(Permanent):修改写入配置文件,但不会自动作用于当前运行状态。
  • 完整操作:必须执行 “永久修改 + 重载(Reload)” 组合。重载的作用是用永久配置覆盖当前运行时配置,使两者同步,从而达到既永久又立即生效。注意:--reload 会中断长连接,而 --complete-reload 更彻底。

2. 浏览器缓存 vs. curl 的测试差异

  • 浏览器(强缓存):默认遵循 HTTP 缓存协议(如 Cache-Control),命中强缓存时直接读取磁盘/内存文件,不向服务器发起网络请求。此时若用浏览器测试防火墙放行是否生效,会被缓存干扰,误以为服务异常或正常。
  • curl:每次都完整发起 TCP 连接和 HTTP 请求,默认不缓存任何资源,完全走网络链路。因此,验证防火墙策略、端口连通性、服务可用性时,curl 是更纯粹、更可信的测试工具,能绕过客户端缓存层的干扰。

3. 端口转发(Port Forwarding)的本质

  • 这是 DNAT(目标地址转换) 或 重定向(Redirection) 行为。操作对象是进入网卡的数据包。
  • 关键点:转发规则工作在防火墙的 nat 表(或 filter 表的 FORWARD 链配合),不依赖目标端口是否有程序在监听。它是在数据包到达本地协议栈之前,将目标端口(如 8080)修改为另一个端口(如 80),修改后再交由协议栈处理。因此,只要最终转到的那个端口上有程序监听,流量就能被正常接收。

4. 防火墙 IP 限制的局域网与外网差异

  • 局域网(同网段):设备基于 ARP 广播直接二层通信,防火墙可以依据源 IP 轻松实施访问控制(如禁止 192.168.1.x 访问)。
  • 外网(跨网段/公网):外网请求经过 NAT(网络地址转换)进入内网时,防火墙看到的是转换后的公网源 IP,或仅能看到网关接口。若想限制外网特定 IP,需在网关的外网接口入向做策略;若限制内网特定主机对外访问,需在 FORWARD 链或 OUTPUT 链做策略。本质上防火墙依然基于五元组过滤,只是外网流量通常绕过了直接的内网 IP 寻址,需配合路由和 NAT 一起分析。

5. Netfilter 五链四表

  • 内核数据包经历的核心钩子点为 五链:PREROUTING → INPUT → FORWARD → OUTPUT → POSTROUTING。
  • 数据流向:
    • 发往本机:PREROUTING(处理目标地址转换)→ INPUT(过滤进站)→ 本地进程。
    • 经本机转发(作为路由器):PREROUTING → FORWARD(过滤转发)→ POSTROUTING(处理源地址转换)。
    • 本机发出:OUTPUT(过滤出站)→ POSTROUTING。
  • 你说的“基本都在 filter”:是对的。filter 表挂载在 INPUT、FORWARD、OUTPUT 链上,用于允许/拒绝数据包(准入控制)。而 nat 表挂在 PREROUTING、POSTROUTING、OUTPUT 上,用于修改地址/端口。常规的”端口放行”操作在 filter 表的 INPUT 链;”端口转发”操作在 nat 表的 PREROUTING 链。

6. Firewalld 与 iptables 的冲突本质

  • 两者操作的是同一个内核 Netfilter 框架,但管理方式冲突:
    • Firewalld 是动态守护进程,维护自己的规则集快照,重启或 --reload 时会完全覆盖内核中的规则。
    • Iptables 命令直接读写内核当前规则集,是底层瞬时操作。
  • 冲突后果:手动用 iptables 添加的规则,不会被 firewalld 记录。一旦执行 firewall-cmd --reload,firewalld 会根据其配置文件重新生成规则,直接冲掉之前手动用 iptables 添加的所有规则。
  • 原则:生产环境只选其一。若用 firewalld,所有策略必须通过 firewall-cmd 管理;若必须引入 iptables 脚本,需通过 firewalld 的 --direct 或 --passthrough 接口注入,避免配置被冲刷。

image-20260728202717222

Firewalld实践

image-20260729205433466

image-20260729205444912

==注意==:启用一个服务器,下面添加防火墙

image-20260729211045891

image-20260729211241079


==解禁==

image-20260729211601745

image-20260729211611460


云平台的防火墙

阿里云安全组,腾讯云安全组等


实践

  从这段终端日志来看,你(或某个操作者)在一台 Rocky Linux 服务器上完成了一次典型的 Web 环境部署与安全测试,具体步骤如下:
  1. 安装 Nginx Web 服务器
    通过包管理器安装了nginx 及其依赖(nginx-core、nginx-filesystem)。

同时还安装了 rocky-logs-httpd(可能是日志相关包)和 cmatrix(一个终端字符动画小游戏,与业务无关,可能顺手装的)。

  1. 启动并验证 Nginx 启动Nginx服务,并查看状态,确认 运行正常(Active: active (running)),配置文件语法检查也通过了。

  2. 添加防火墙规则(阻断 Web 访问) 执行了一条 iptables 命令: iptables -A INPUT -p TCP --dport 80 -j DROP 意思是 在 INPUT 链添加规则,丢弃所有目标端口为 80 的 TCP 请求。

  3. 查看当前防火墙规则 用 iptables -vnl --line-numbers列出所有规则,确认刚才添加的 DROP规则已生效(显示在 Chain INPUT 的第一条)。

image-20260728133815591

image-20260728135020019

这条命令在INPUT 链 上添加了一条规则:丢弃所有目标端口为 80 的 TCP 数据包。

==注意==:默认添加的规则都在filter表里面

image-20260728135509259


定时任务

系统定时任务相关配置说明

配置文件/目录路径适合场景核心格式与要求触发机制与 Rocky 9 特有行为
/etc/cron.d/高频、精准定时的任务。(如:每 5 分钟同步一次数据,或每天凌晨 2:00 精准备份)任意命名的文件。格式必须包含“运行用户”:/5 * root /usr/bin/script独立 Crontab 格式,由 crond 守护进程直接管理,时间高度精准。
/etc/crontab系统自带的全局配置。不建议日常运维直接修改它。格式与 /etc/cron.d/ 完全一致,同样必须指定用户独立 Crontab 格式,属于历史保留的全局总入口,建议保持原样。
/etc/cron.hourly/需要每小时执行一次的普通脚本。纯可执行脚本按时执行,每小时的第 1 分钟左右,由 crond 强制触发执行。
/etc/cron.daily/每天跑一次,但对具体几点几分没有严格要求的任务(如清理临时文件)。纯可执行脚本Anacron 异步触发,默认在凌晨 03:00 – 22:00 之间随机时间执行。如果服务器半夜关机,开机后会自动补跑。
/etc/cron.weekly/每周跑一次的任务(如每周一次的大型日志轮转)。纯可执行脚本Anacron 异步触发,由 Anacron 自动控制在每周的某一天随机延迟执行。
/etc/cron.monthly/每月跑一次的任务(如每月度的数据对账、审计统计)。纯可执行脚本Anacron 异步触发,由 Anacron 自动控制在每月的某一天的随机延迟执行。

系统定时任务调用过程

[系统运行] 
   ↓
1. crond 守护进程每分钟扫描一次配置
   ↓
2. 每小时的第 1 分钟,crond 触发执行 `/etc/cron.d/0hourly`
   ↓
3. 0hourly 调用 `run-parts /etc/cron.hourly` 目录
   ↓
4. 该目录下有一个核心脚本叫 `0anacron`,它被执行了
   ↓
5. `0anacron` 唤醒了 `anacron` 进程
   ↓
6. anacron 检查上次执行时间,开始异步调度 `/etc/cron.daily/weekly/monthly` 目录中的脚本

为什么 Rocky Linux 9 要这么设计?

因为传统的 cron 很死板,如果任务定在凌晨 3 点,而当时服务器断电关机了,cron 开机后绝对不会补跑。 所以,RHEL 9 / Rocky 9 的策略是:用 cron 来保证每小时雷打不动地唤醒 anacron;再让 anacron 去负责天/周/月级别的任务。anacron 会记录上一次成功的执行时间,发现错过了就会在开机后自动补跑。

配置详解

[root@localhost cron.hourly]# cat /etc/cron.d/0hourly
# Run the hourly jobs
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
01 * * * * root run-parts /etc/cron.hourly  #每小时的第 1 分钟,以 root 身份去把 /etc/cron.hourly/ 目录里的脚本全跑一遍。
[root@localhost cron.hourly]# cat /etc/cron.hourly/0anacron
#!/usr/bin/sh
# Check whether 0anacron was run today already
if test -r /var/spool/anacron/cron.daily; then
    day=`cat /var/spool/anacron/cron.daily`
fi
if [ `date +%Y%m%d` = "$day" ]; then
    exit 0
fi

# Do not run jobs when on battery power
online=1
for psupply in /sys/class/power_supply/* ; do
    if [ `cat "$psupply/type" 2>/dev/null`x = Mainsx ] && [ -f "$psupply/online" ]; then
        if [ `cat "$psupply/online" 2>/dev/null`x = 1x ]; then
            online=1
            break
        else
            online=0
        fi
    fi
done
if [ $online = 0 ]; then
    exit 0
fi
/usr/sbin/anacron -s  #这里的 -s 它代表串行化执行)告诉 anacron 严格按照 /etc/anacrontab 里规定的延迟时间,排好队一个接一个地去跑 daily、weekly、monthly 里的任务,不要同时爆发,防止瞬间消耗尽服务器的 CPU 和 IO 资源

anacron的配置文件

[root@localhost cron.hourly]# cat /etc/anacrontab
# /etc/anacrontab: configuration file for anacron

# See anacron(8) and anacrontab(5) for details.

SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# the maximal random delay added to the base delay of the jobs
RANDOM_DELAY=45# 为了防止多台服务器或者多个大型任务在同一秒钟同时爆发,把 CPU 和磁盘 I/O 瞬间吃满,anacron 在启动任务前会随机生成一个 0 到 45 之间的分钟数,作为额外的等待时间

# the jobs will be started during the following hours only
START_HOURS_RANGE=3-22  # 允许任务启动的时间窗口(凌晨3点-晚上22点)

#周期(天数)        基础延迟(分钟)       任务标识符         具体执行的命令
#period in days   delay in minutes   job-identifier   command

# 每天当 anacron 被唤醒时,先等待 5 分钟加上一段随机时间,然后以较低的 CPU 优先级自动执行 /etc/cron.daily 目录下的所有无后缀脚本
1       5       cron.daily              nice run-parts /etc/cron.daily 
# 每隔 7 天当 anacron 被唤醒时,先等待 25 分钟加上一段随机时间,然后以较低的 CPU 优先级自动执行 /etc/cron.weekly 目录下的所有无后缀脚本
7       25      cron.weekly             nice run-parts /etc/cron.weekly
# 每月当 anacron 被唤醒时,先等待 45 分钟加上一段随机时间,然后以较低的 CPU 优先级自动执行 /etc/cron.monthly 目录下的所有无后缀脚本
@monthly 45     cron.monthly            nice run-parts /etc/cron.monthly

现在全局看下cron任务调度的特点

1. 针对“脚本目录”,它确实只是个“传话筒”

对于 /etc/cron.daily/、weekly/、monthly/,crond 唯一的贡献就是在每小时的第 1 分钟通过 0hourly 去唤醒 0anacron 脚本。一旦把 anacron 唤醒了,crond 就收工了。接下来的时间计算、漏跑补回、降低优先级(nice)执行,全由 anacron 独立完成。

2. 但对于“精准定时”,**亲自每分钟刷新**

虽然它把天/周/月的脚本目录外包给了 anacron,但crond自己依然在以 “每分钟扫描一次” 的频率盯着以下几个地方:

/etc/crontab(系统全局总入口文件)

/etc/cron.d/ 目录(你存放自定义精准任务的地方,比如你自己建的 my-sync 文件)

/var/spool/cron/ 目录(所有普通用户通过 crontab -e 提交的任务)

平时想使用系统定时任务的特性可写入的文件

​ 1. /etc/cron.d/ 由crond调用

​ 2. /etc/cron.daily/ 由crond调用

​ 3. /etc/cron.weekly/ 由于anacron调用,有补跑能力

​ 4. /etc/cron.hourly/ 由于anacron调用,有补跑能力

​ 5. /etc/cron.monthly/ 由于anacron调用,有补跑能力

​ 6. /etc/anacrontab 直接由anacron调用(本质上依然是依靠crond刷新/etc/cron.hourly/)

任务是否会补跑

anacron补跑的原理

[root@localhost cron.hourly]# cd /var/spool/anacron/
[root@localhost anacron]# ls
cron.daily  cron.monthly  cron.weekly  # anacron是如何知道有没有补跑?在相应周期anacron跑完之后,会更新对应文件,如果文件小于对应周期,则不补跑,否则,补跑并且结束后更新此文件

哪些任务会被补跑

仅被anacron管理的任务才会自己补跑,即/etc/cron.daily/,/etc/cron.monthly/,/etc/cron.weekly/下放入的脚本会补跑,其余均不会补跑。

另一个可以定时操作的服务

Systemd 中的Timer Unit不仅可以做到微秒级的定时,还原生支持失败重试

[root@localhost cron.daily]# systemctl list-timers
NEXT                        LEFT          LAST                        PASSED    UNIT                         ACTIVATES
Sun 2026-07-26 21:08:23 CST 1h 0min left  Sun 2026-07-26 19:48:01 CST 19min ago dnf-makecache.timer          dnf-makecache.service
Mon 2026-07-27 00:00:00 CST 3h 52min left -                           -         logrotate.timer              logrotate.service
Mon 2026-07-27 19:30:25 CST 23h left      Sun 2026-07-26 19:30:25 CST 37min ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service

dnf-makecache.timer(元数据缓存更新)

logrotate.timer(日志切割)

systemd-tmpfiles-clean.timer(临时文件清理)