再见 Crontab!Linux 定时任务的新选择!

news2025/2/24 15:42:35

引言

说到 Linux 下定时执行任务,大多数人可能会想到 crontab?没错,它的确是 Linux 下比较通用和方便的方式,但是今天我来介绍一种新的方法来创建定时任务并且支持更多更强大的功能。

Systemd

很多小伙伴应该听说过 Systemd,它是 Linux 自带的系统工具,已经成为大多数发行版的标准配置。它是用来代替 initd 进程的,解决了 initd 进程的一些问题,成为了系统的1 号进程(PID=1)。

Systemd 相比于 crontab,有很多优点:

  • 一个任务可以拆分成多个任务,任务之间可以有依赖关系

  • 方便的查询日志,自带日志工具和命令

  • 可以对任务启用资源限制,例如限制 CPU 和内存的使用

关于 Systemd 的使用和介绍,这里不讲太多,后面再详细讲。今天分享通过 Systemd 来实现定时任务的方法。

一个小例子

先来准备一个小例子:

echo `date` >> /tmp/data.txt

执行脚本,脚本会在 tmp 目录的 data 文件中输出当前的时间,正好可以验证脚本是否在正常运行,别忘了给脚本加可执行权限(chmod +x hello.sh)。

先执行脚本看下效果:

image-20250120224144129

脚本可以正常运行了。

Systemd unit

想要使用 Systemd 实现定时任务,要先创建一个Systemd 单元,Systemd 的单元是 Systemd 中最小功能单位,可以理解为一个进程的描述。一个任务就是一个单元,单元之间可以相互依赖也可以相互调用,多个单元可以组成一个大的任务管理系统。

Systemd 单元有很多种类,最常见的 Service 负责后台服务,Slice 负责资源分配,mount 负责挂载文件系统,Timer 负责定时任务等等。

单元描述符一般在系统中的三个目录中保存,分别是:

  • /usr/lib/systemd/system:用户自己定义的单元描述符文件
  • /etc/systemd/system:用户安装的软件所对应的单元描述符文件
  • /lib/systemd/system:系统自带的单元描述符文件

可以使用 systemctl 命令查看所有的单元描述符文件,也可以单独查看某一个分类的文件。

# 查看所有 Service 单元
systemctl list-unit-files --type service
# 查看所有的 timer 单元
systemctl list-unit-files --type timer
# 查看所有 mount 单元
systemctl list-unit-files --type mount
# 查看所有的单元
systemctl list-unit-files

管理命令

现在有了单元描述符文件后,我们还需要通过 systemctl 命令来管理进程。

常用的命令有:

# 启动进程
systemctl start 单元名
# 停止进程
systemctl stop 单元名
# 查看单元状态
systemctl status 单元名
# 开机自启
systemctl enable 单元名
# 关闭开机自启
systemctl disable 单元名

Service 单元

要想使用 Systemd 来实现定时任务,还需要新建两个文件,一个用来描述单元的基本信息,例如启动命令,执行的路径,单元依赖等等。还有一个文件是用来定时执行任务,类似于 crontab,用来定义什么时候执行任务。

先说 Service 单元,新建一个单元,例如 demo.service,放到 /usr/lib/systemd/system 目录下,内容如下:

[Unit]
Description=my hello.sh

[Service]
ExecStart=/bin/bash /root/hello.sh

先查看一下刚才新建的单元状态:

root@debian:~# systemctl status hello.service 
○ hello.service - hello.sh
     Loaded: loaded (/lib/systemd/system/hello.service; static)
     Active: inactive (dead)

现在是停止的状态,因为我们还没有启动它。执行命令 systemctl start hello.service 启动它。

root@debian:~# systemctl status hello.service 
○ hello.service - hello.sh
     Loaded: loaded (/lib/systemd/system/hello.service; static)
     Active: inactive (dead)
root@debian:~# systemctl start hello.service 
root@debian:~# systemctl status hello.service 
○ hello.service - hello.sh
     Loaded: loaded (/lib/systemd/system/hello.service; static)
     Active: inactive (dead)

Jan 21 08:41:43 debian systemd[1]: Started hello.service - hello.sh.
Jan 21 08:41:43 debian systemd[1]: hello.service: Deactivated successfully.

可以看到, 程序正常启动了,但是后来又停止了,因为它只有一行代码,执行了 echo 之后就停止了,符合预期,下面我们让它来定时执行。

注意:在 ExecStart 字段中的命令要写绝对路径,因为 Systemd 不会自动加载环境变量,不写绝对路径会找不到可执行文件。

Timer 单元

为了可以定时执行任务,还需要新建一个 timer 单元来定义如何定时执行刚才创建的单元。新建一个 hello.timer,还是放到刚才的目录中,内容为:

[Timer]
OnUnitActiveSec=5s # 每隔多久执行任务
AccuracySec=1ms #设置时间精度,如果不设置的话,具体的执行时间就不一定了
Unit=hello.service # 要执行哪个任务

[Install]
WantedBy=multi-user.target

有一个 Install 字段,这个字段在几乎每个单元中都会有,可以说是很常用或者说比较基本的一个字段,它的意思是多用户模式,可以简单理解为只要系统是以多用户模式启动的,那么这个任务就会被定时执行。

现在我们启动定时器看看:

# 别忘了编辑了单元文件后先执行下面的命令重载单元文件,不然可能会不生效
systemctl daemon-reload
# 启动定时器
systemctl start hello.timer

查看一下命令是否正常执行,看下输出的日志:

root@debian:~# cat /tmp/data.txt 

Tue Jan 21 09:17:13 AM EST 2025
Tue Jan 21 09:17:18 AM EST 2025
Tue Jan 21 09:17:23 AM EST 2025
Tue Jan 21 09:17:28 AM EST 2025

发现日志可以正常输出,说明我们新建的单元被正常的定时调度执行了。

开机自启

上面的配置只能保证系统不重启的情况下定时执行,如果要想实现开机自启的话,要记得执行命令:

root@debian:~# systemctl enable hello.timer
Created symlink /etc/systemd/system/multi-user.target.wants/hello.timer → /lib/systemd/system/hello.timer.

它会创建一个软连接到 user.target.wants 目录中,在系统启动的时候自动加载并执行这些任务。

如果想要关闭开机自启的话,执行 systemctl disable hello.timer 命令即可。

查看日志

Systemd 和 crontab 最大的优点我觉得是日志,crontab 只能通过程序打印的日志才能知道它到底有没有执行,Systemd 自带完善的日志系统可以很方便的查看日志。

因为刚才的脚本只输出了时间到文件中,没有打印日志到控制台,所以我们加一行 echo,然后再来查看日志。

echo `date` >> /tmp/data.txt
echo `date`

查看日志使用 journalctl 命令:

journalctl -u hello.service

image-20250121223941914

总结

使用 Systemd 来设置定时任务,虽然上面说了那么多,其实就两件事,写两个文件,一个文件定义需要执行什么命令,另一个文件定义什么时候执行命令,然后记得重载单元文件,然后启动定时器并且设置开机自启即可。

本文章首发于个人博客 LLLibra146’s blog

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2280747.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity入门1

安装之后无法获得许可证,可以考虑重装 新建项目 单击空白处生成脚本 双击c#文件 会自动打开vstudio 检查引用 如果没有引用,重开vstu,或者重新加载项目 hierarchy层级 scenes场景 assets资产 inspector督察 icon图标 资源链接&…

【二叉树】遍历总结!

在很多问题中,熟练掌握二叉树的遍历方法,能够轻松解决很多问题。 新建一棵二叉树root[1,null,2,3] 1、前序遍历 前序遍历的顺序为根节点->左子树->右子树,按照以上二叉树,遍历顺序为[1,2,3]。代码为…

(2)STM32 USB设备开发-USB虚拟串口

例程:STM32USBdevice: 基于STM32的USB设备例子程序 - Gitee.com 本篇为USB虚拟串口教程,没有知识,全是实操,按照步骤就能获得一个STM32的USB虚拟串口。本例子是在野火F103MINI开发板上验证的,如果代码中出现一些外设的…

ASP .NET Core 学习(.NET9)部署(一)windows

在windows部署 ASP .NET Core 的时候IIS是不二选择 一、IIS安装 不论是在window7 、w10还是Windows Server,都是十分简单的,下面以Windows10为例 打开控制面版—程序—启用或关闭Windows功能 勾选图中的两项,其中的子项看需求自行勾选&am…

Java并发编程面试题:线程池Fork/Join(19题)

🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…

fyne 选项卡设计

用户界面的设计至关重要,它直接影响着用户体验。选卡设计作为一种常见的界面布局方式,能够有效地组织和展示信息,使用户能够方便快捷地浏览和操作。 Fyne 是一个用 Go 语言编写的跨平台 GUI 框架,它提供了丰富的组件和功能&#…

MySQL——主从同步

提醒:进行配置时,需要确保一主两从的操作系统、MySQL版本一致,否则将出现问题 环境介绍 服务器IP主服务器172.25.254.10从服务器-1172.25.254.11从服务器-2172.25.254.12 配置 # 快速配置,选择多重执行,确保版本一…

IDEA中Maven使用的踩坑与最佳实践

文章目录 IDEA中Maven使用的踩坑与最佳实践一、环境配置类问题1. Maven环境配置2. IDEA中Maven配置建议 二、常见问题与解决方案1. 依赖下载失败2. 依赖冲突解决3. 编译问题修复 三、效率提升技巧1. IDEA Maven Helper插件使用2. 常用Maven命令配置3. 多模块项目配置4. 资源文件…

VIVADO-block desgn 中时钟连线报错

问题描述 1.自定义的IP核由于封装不规范,输出的时钟引脚缺少该时钟的相关信息 正常时钟引脚属性 异常的时钟引脚属性 2.run connection automation 中无法找到这种缺少信息的时钟源 3.axi_clk与axi interconnect时钟频率不匹配 解决方案: 1.用BUFG将缺少…

CSDN 博客之星 2024:默语的技术进阶与社区耕耘之旅

CSDN 博客之星 2024:默语的技术进阶与社区耕耘之旅 🌟 默语,是一位在技术分享与社区建设中坚持深耕的博客作者。今年,我有幸再次入围成为 CSDN 博客之星TOP300 的一员,这既是对过往努力的肯定,也是对未来探…

BUUCTF_Web(UPLOAD COURSE 1)

打开靶机,发现需要上传文件,尝试一句话木马蚁剑链接 一句话木马 【基本原理】利用文件上传漏洞,往目标网站中上传一句话木马,然后你就可以在本地通过中国菜刀chopper.exe即可获取和控制整个网站目录。表示后面即使执行错误&#…

车载软件架构 --- CP和AP作为中央计算平台的软件架构双核心

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 简单,单纯,喜欢独处,独来独往,不易合同频过着接地气的生活…

docker ubuntu:20.04构建c++ grpc环境

由c grpc必须源码编译,ubuntu版本不同可能出现的问题也不同,这里分享下我的构建过程。 我是vscode结合docker去安装c虚拟环境,我不想污染本机环境。 vscode的插件Dev Containers Dockerfile如下(如果单纯是ubuntu环境构建,可忽略该…

PV-RCNN、PV-RCNN++ 网络结构

paper: PV-RCNN https://arxiv.org/abs/1912.13192PV-RCNN https://arxiv.org/abs/2102.00463 github:使用OpenPCDet进行训练测试 https://github.com/open-mmlab/OpenPCDet PV-RCNN 简介 PV-RCNN的提出是想要综合 point-based 和 voxel-based 3D目…

认识c++

文章目录 1namespace 写博客 ,做作业 笔记很关键 1namespace ::域作用限定域 局部域>全局域>命名空间域(展开了命名空间域or指定访问命名空间域) 不要轻易展开 可以这样解决 方案一 方案二 using namespace std; 直接展开会有风…

接口 V2 完善:基于责任链模式、Canal 监听 Binlog 实现数据库、缓存的库存最终一致性

🎯 本文介绍了一种使用Canal监听MySQL Binlog实现数据库与缓存最终一致性的方案。文章首先讲解了如何修改Canal配置以适应订单表和时间段表的变化,然后详细描述了通过责任链模式优化消息处理逻辑的方法,确保能够灵活应对不同数据表的更新需求…

内容中台实施最佳实践解析与应用指南

内容概要 内容中台是一个旨在提升企业内容管理与分发能力的战略性平台,其实施最佳实践对于企业在数字化转型中尤为重要。内容中台的建设,不仅涉及技术层面的架构设计,还需结合组织变革、业务流程优化等多个方面,以实现高效、灵活…

顺序表和链表(详解)

线性表 线性表( linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构,也就说是连续的一条直线。…

TCP全连接队列

1. 理解 int listen(int sockfd, int backlog) 第二个参数的作用 backlog:表示tcp全连接队列的连接个数1。 如果连接个数等于backlog1,后续连接就会失败,假设tcp连接个数为0,最大连接个数就为1,并且不accept获取连接…

C语言程序环境与预处理—从源文件到执行程序,这里面有怎么的工序?绝对0基础!

正文开始前,我们简单聊上一聊! 众所周知!编译器的功能非常强大的,我们在编译软件上敲的每一行代码,点击执行,就会输出结果,从代码-->输出结果,这中间经历了怎样的一个过程&#…