systemd&&定时任务
2348 字
12 分钟
systemd&&定时任务
systemd&&定时任务
[TOC]
systemctl
在Linux系统(特别是Centos7)中对服务进行启动、关闭、重启的操作使用sytemctl
-
systemctl start xx
-
systemctl stop xx
-
systemctl restart xx
-
systemctl status xx
-
systemctl reload xx
状态查询命令:[root@Rocky10 ~]# systemctl status sshd● sshd.service - OpenSSH server daemon Loaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; preset: enabled) Active: active (running) since Fri 2026-03-06 09:12:51 CST; 7h ago Invocation: 982b5a7bcc964c5f99bc720ec3a786d4 Docs: man:sshd(8) man:sshd_config(5)======================================='更方便的判断!'root@rocky10:~# systemctl is-(tab补齐)is-active is-enabled....(1)验证服务是否处于活动状态[root@Rocky10 ~]# systemctl is-active sshdactive(2)验证单元是否处于开机自启状态![root@Rocky10 ~]# systemctl is-enabled sshdenabled======================================='列出当前系统所有正在活跃的服务'[root@Rocky10 ~]# systemctl list-units --type=service --state=active UNIT LOAD ACTIVE SUB DESCRIPTION accounts-daemon.service loaded active running Accounts Service alsa-state.service loaded active running Manage atd.service loaded active running Deferred auditd.service loaded active running Security ..............======================================='列出当前系统所有设置为开机自启的服务'[root@Rocky10 ~]# systemctl list-unit-files --type=service --state=enabledUNIT FILE STATE PRESETaccounts-daemon.service enabled enabledatd.service enabled enabledaudit-rules.service enabled enabledauditd.service enabled enabled..............======================================='屏蔽与取消屏蔽:'systemctl mask name.service# 屏蔽服务(创建指向/dev/null的链接,阻止启动)systemctl unmask name.service# 取消屏蔽服务⚠️注意:disable的服务可手动启动,mask的服务则完全无法启动
[root@Rocky10 ~]# ps -ef | grep crondroot 1417 1 0 09:12 ? 00:00:00 /usr/sbin/crond -n# 定时任务服务![root@Rocky10 ~]# systemctl mask crondCreated symlink '/etc/systemd/system/crond.service' → '/dev/null'.# 定向到空![root@Rocky10 ~]# systemctl start crondFailed to start crond.service: Unit crond.service is masked.# 屏蔽后,无法手动启动![root@Rocky10 ~]# systemctl unmask crondRemoved '/etc/systemd/system/crond.service'.[root@Rocky10 ~]# systemctl is-active crondactive服务单元结构
systemd 使用 unit 文件 来管理系统资源
常见的 unit 类型包括:
.service:定义一个服务(进程).timer:定义定时器(类似 cron,但更强大).socket:用于 socket 激活(按需启动服务).target:类似于运行级别(如 multi-user.target)- …
所有 unit 文件通常放在 以下目录(按优先级从高到低):
/etc/systemd/system/- 管理员自定义配置(最高优先级)/run/systemd/system/- 运行时生成的配置/usr/lib/systemd/system/- 系统默认配置
'如何启停服务'假设你有一个名为 myapp.service 的服务:systemctl restart myapp.service....# 参考上面的笔记!⚠️注意:.service 后缀可省略================================================systemctl start myapp 等价于 start myapp.service================================================如果你是通过,编译安装Nginx,而且没有通过yum安装那么你不能够通过systemctl进行管理,比如服务的启动,暂停...必须手动书写服务的配置、格式如下!!!'单元文件结构'[Unit]# 主要用于定义服务的依赖关系和描述信息!Description=服务描述After=network.target remote-fs.target# 定义启动顺序(此服务在指定目标之后启动)Before=xxx# 在某个 unit 启动之前启动本unitRequires=依赖服务.service# 强依赖(依赖服务必须成功启动)# 若依赖项失败,本 unit 也失败Wants=依赖服务.service# 弱依赖,即使依赖项失败,本 unit 仍尝试启动
[Service]Type=forking|simple|oneshot|notify# 服务类型ExecStart=/usr/sbin/服务名# 启动命令ExecReload=/bin/kill -s HUP $MAINPID# 重载配置命令ExecStop=/bin/kill -SIGTERM $MAINPID# $MAINPID 是一个 systemd 变量,它代表服务的主进程ID# 这条命令的作用是向主进程发送一个标准的终止信号# 这是停止服务的正确方式PIDFile=/run/服务名.pid# 可以用一个文件来记录服务的pidRestart=on-failure# 什么时候重启?# 仅非正常退出时重启(退出码非 0、被信号终止、超时等)# 手动 systemctl stop,它不会重启!TimeoutStopSec=5# 停止服务的超时时间# 最多等待 5 秒,如果 5 秒后进程仍未退出,systemd 将强制杀死它
[Install]WantedBy=multi-user.target# 控制服务在什么系统运行级别(target)下自动启动# 当系统进入这个运行级别时,会自动启动本服务'大多数运行级别为3即可'Restart=always vs Restart=on-failure
| 策略 | 行为 | 适用场景 |
|---|---|---|
always | 任何退出都重启(包括正常退出 exit 0、手动 stop、崩溃等) | 守护进程型服务(如数据库、Web 服务),希望始终运行 |
on-failure | 仅非正常退出时重启(退出码非 0、被信号终止、超时等) | 脚本/批处理任务,希望失败时重试,正常完成则不重启 |
👑实验案例
编写一个简单的 service 单元(执行脚本)
- 场景:每天都输出
当前时间到 /home/test.txt
步骤 1:创建脚本[root@R11 sh]# pwd/server/sh[root@R11 sh]# vim log-time.sh#!/bin/bashecho "$(date): Hello from systemd timer!" >> /home/test.txt[root@R11 sh]# chmod +x log-time.sh[root@R11 sh]# ll log-time.sh-rwxr-xr-x 1 root root 72 Mar 14 16:28 log-time.sh
步骤 2:创建 service 文件/etc/systemd/system/log-time.service================!注意是service并不是server================[root@R11 sh]# vim /etc/systemd/system/log-time.service[Unit]# 服务描述Description=time to /home/test.txt
[Service]# oneshot:跑一次就退出,正好匹配"跑完就退"的脚本Type=oneshot# 执行脚本(绝对路径)ExecStart=/server/sh/log-time.sh# User=www# Group=www# !前提是这个用户得有权限!# 可选:指定运行用户(避免 root 写文件)# ⚠️ 不加 [Install] 段:开机自启的是 timer,不是 service# service 是被动激活的(由 timer 触发),不用 enable
[root@R11 sh]# ll /etc/systemd/system/log-time.service-rw-r--r-- 1 root root 178 Mar 14 16:34 /etc/systemd/system/log-time.service
步骤 3:创建对应的 timer 文件/etc/systemd/system/log-time.timer✅ 关键规则:.timer 文件名必须与 .service 文件名前缀一致# (即 log-time.timer 对应 log-time.service)[root@R11 sh]# vim /etc/systemd/system/log-time.timer[Unit]# timer 强依赖同名 serviceDescription=Run log-time.service every dayRequires=log-time.service
[Timer]# 每天运行一次(默认通常是午夜 00:00)# 或更精确:OnCalendar=*-*-* 02:00:00OnCalendar=daily# 错过触发时间(如关机/休眠),系统启动后立即补执行一次Persistent=true# 触发目标(默认就是同名 service,显式写出更清晰;文件名不一致时可用 Unit= 指定)Unit=log-time.service
[Install]# 开机自启的是 timer(触发器),不是 serviceWantedBy=timers.target
步骤 4:启用并启动 timer[root@R11 sh]# systemctl daemon-reload# 重载 systemd 配置[root@R11 sh]# systemctl enable --now log-time.timer# 启用并启动 timer⚠️ 不要手动 start log-time.service,它应由 timer 触发# 这里启动的是.timer[root@R11 sh]# systemctl status log-time.timer● log-time.timer - Run log-time.service every day Loaded: loaded (/etc/systemd/system/log-time.timer; enabled; preset: disabled) Active: active (waiting) since Sat 2026-03-14 16:58:43 CST; 15s ago Invocation: 6f95ba8ec5044123abb448cdd024a5e3 Trigger: Sun 2026-03-15 00:00:00 CST; 7h left Triggers: ● log-time.service
Mar 14 16:58:43 R11 systemd[1]: Started log-time.timer - Run log-time.service every day[root@R11 sh]# ll /home/total 0[root@R11 sh]# systemctl restart log-time.timer[root@R11 sh]# journalctl -u log-time.service | tail -3# 查看指定服务的日志Mar 14 18:03:47 R11 systemd[1]: Starting log-time.service - time to /home/test.txt...# 启动服务..Mar 14 18:03:47 R11 systemd[1]: log-time.service: Deactivated successfully.Mar 14 18:03:47 R11 systemd[1]: Finished log-time.service - time to /home/test.txt.# 成功写入!![root@R11 sh]# ll /home/total 4-rw-r--r-- 1 root root 177 Mar 14 18:03 test.txt# 重启完timer服务就会手动执行一次定时任务[root@R11 sh]# cat /home/test.txtSat Mar 14 06:03:47 PM CST 2026: Hello from systemd timer!OnCalendar
OnCalendar 支持类似 cron 的语法,但更灵活:
| 示例 | 含义 |
|---|---|
daily | 每天 00<00>00> |
hourly | 每小时 |
*-*-* 14:30:00 | 每天 14<30>30> |
Mon..Fri *-*-* 09:00:00 | 工作日上午 9 点 |
*/5:00 | 每 5 分钟 |
*:0/5 | 每 5 秒 |
[root@R11 sh]# systemctl list-timers# 查看所有的定时任务NEXT LEFT LAST PASSED UNIT.........Sun..03-15 00:00 6h 2026-03-14.. - log-time.timer| 列名(关键字) | 含义说明 |
|---|---|
| NEXT | 下一次定时器将触发的时间 |
| LEFT | 距离下一次触发还剩余的时间(例如 “6h” 表示还有 6 小时) |
| LAST | 上一次定时器实际触发的时间 |
| PASSED | 自上一次触发以来已经过去的时间(例如 “2min ago”)、若尚未触发过,则显示 - 或留空 |
| UNIT | 对应的定时器单元名称(以 .timer 结尾),它控制一个关联的 .service 单元 |
# 也可以通过修改时间进行触发!# 下一次触发的时间在03-15 00:00:00[root@R11 sh]# tail -1 /home/test.txtSat Mar 14 06:03:47 PM CST 2026: Hello from systemd timer![root@R11 sh]# dateSat Mar 14 06:10:50 PM CST 2026# 现在的时间⌚️[root@R11 sh]# date -s "2026-03-14 23:59:50"Sat Mar 14 11:59:50 PM CST 2026# 手动修改[root@R11 sh]# tail -1 /home/test.txtSat Mar 14 06:03:47 PM CST 2026: Hello from systemd timer![root@R11 sh]# tail -1 /home/test.txtSat Mar 14 06:03:47 PM CST 2026: Hello from systemd timer!# 我又查了几次,还是没有写入、此时我有点怀疑我自己了已经![root@R11 sh]# dateSun Mar 15 12:00:15 AM CST 2026# 又看了眼时间!已经过00:00:00了呀![root@R11 sh]# journalctl -u log-time.service | tail -3Mar 14 18:03:47 R11 systemd[1]: Starting log-time.service - time to /home/test.txt...Mar 14 18:03:47 R11 systemd[1]: log-time.service: Deactivated successfully.Mar 14 18:03:47 R11 systemd[1]: Finished log-time.service - time to /home/test.txt.# 又看了眼日志,还是上次的日志呀!![root@R11 sh]# systemctl list-timersNEXT LEFT LAST PASSED UNIT ACTIVATES....Mon 2026-03-16 00:00:00 CST 23h Sun 2026-03-15 00:00:27 CST 17s ago log-time.timer log-time.service# 但是你看下一次执行的时间已经变了!变成03-16了# 下一次执行触发的时间要23个小时# 上一次触发的时间为03-15 00:00:27'说明它是执行过的呀!'[root@R11 sh]# tail -1 /home/test.txtSun Mar 15 12:00:27 AM CST 2026: Hello from systemd timer!# 又cat了一次终于出来了![root@R11 sh]# journalctl -u log-time.service | tail -3Mar 15 00:00:27 R11 systemd[1]: Starting log-time.service - time to /home/test.txt...Mar 15 00:00:27 R11 systemd[1]: log-time.service: Deactivated successfully.Mar 15 00:00:27 R11 systemd[1]: Finished log-time.service - time to /home/test.txt.# 又看了一眼日志,也是成功运行了起来!'那么如何把时间改回✅️正确的呢?'[root@R11 sh]# dateSun Mar 15 12:09:07 AM CST 2026[root@R11 sh]# systemctl restart chronyd# 静静地等待一会ing.........[root@R11 sh]# dateSun Mar 15 12:09:27 AM CST 2026[root@R11 sh]# dateSat Mar 14 06:21:06 PM CST 2026# 变回来了,下午六点半Note
💡 手动改时间后,timer 触发有延迟
date -s 改到 00<00>00> 后,timer 直到 00:00<27>27> 才触发(journalctl 里时间戳是 00:00:27)
因为手动改时间后,systemd 需要先检测到时间跳变,timer 才会重新计算触发,不是立即触发
这是正常现象,稍等几十秒即可,别急着”怀疑自己”
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!
相关文章智能推荐
1
K8s故障排查 & 控制器与Service实战
Kubernetes故障排查三板斧describe/logs/exec与command&args,容器三种状态与pause基础架构容器,env环境变量部署WordPress,Deployment副本控制与滚动更新回滚,Service四类型ClusterIP/NodePort/LoadBalancer/ExternalName,kube-proxy+iptables底层实现,名称空间,CoreDNS服务发现与跨ns解析,deploy+svc部署WordPress及跨名称空间连库实战
2
K8s开篇 & kubeadm集群部署实战
KubernetesK8s核心概念与架构详解,基于kubeadm从零部署高可用集群,Flannel网络配置,Pod基础使用与YAML声明式管理
3
Prometheus 告警 && etcd 集群实战
Prometheus监控Alertmanager 告警路由/模板/静默/抑制 + 钉钉插件,etcd 3.7 TLS 高可用集群部署/备份恢复/Prometheus 监控,复用既有 kpyun CA 体系
4
Prometheus存储实战 && HTTPS认证 && 黑盒监控
Prometheus监控VictoriaMetrics单机部署+remote_write远端存储,Prometheus启用HTTPS+Basic Auth认证,node-exporter黑白名单,标签管理(relabel/metric_relabel),blackbox-exporter HTTP/ICMP/TCP黑盒探测,Grafana存储迁移到MySQL
5
Prometheus自定义监控 && 服务发现 && 联邦模式
Prometheus监控部署 pushgateway 实现短期任务/自定义指标的推送式监控(API 推送删除、honor_labels、TCP 12 状态、丢包率脚本),用 Go + client_golang 开发自定义 exporter(静态编译零依赖),落地 file_sd 与 consul 服务发现(consul 2.0.3 集群 + consul_exporter),最后用 3 台 Prometheus server 搭建联邦模式实现分布式采集汇总















