systemd定时器(推荐,适用于大多数场景)systemd是Ubuntu的初始化系统,其内置的定时器功能支持高精度、灵活配置,适用于周期性或单次任务。
/etc/systemd/system/myscript.service,内容如下(替换为实际脚本路径):[Unit]
Description=My Custom Script Service
[Service]
Type=oneshot # 单次任务(周期性任务可设为simple或其他类型)
ExecStart=/path/to/your/script.sh # 要执行的命令或脚本
/etc/systemd/system/myscript.timer,内容如下(以“每天8点执行”为例):[Unit]
Description=Run My Script daily at 8:00 AM
[Timer]
OnCalendar=*-*-* 08:00:00 # 每天8点触发(支持cron语法)
Persistent=true # 若错过计划时间,系统启动后会尽快补执行
[Install]
WantedBy=timers.target # 启用后随系统启动
sudo systemctl daemon-reload # 重新加载配置
sudo systemctl enable myscript.timer # 开机自启
sudo systemctl start myscript.timer # 立即启动
sudo systemctl status myscript.timer # 查看下一次触发时间
journalctl -u myscript.service -f # 实时查看执行日志
说明:
OnCalendar支持多种时间格式(如*-*-* 12:00:00表示每天中午12点,Mon *-*-* 09:00:00表示每周一9点)。OnCalendar改为OnUnitActiveSec(如OnUnitActiveSec=10sec表示每10秒触发一次)。timerfd(应用层定时器,适用于编程场景)timerfd是Linux提供的文件描述符定时器,可通过编程实现高精度超时控制(适用于C/C++等语言)。
#include <sys/timerfd.h>
#include <unistd.h>
#include <stdio.h>
#include <time.h>
int main() {
// 1. 创建定时器文件描述符
int fd = timerfd_create(CLOCK_MONOTONIC, 0); // CLOCK_MONOTONIC为单调时间(不受系统时间修改影响)
if (fd == -1) {
perror("timerfd_create failed");
return 1;
}
// 2. 设置定时器超时时间(第一次5秒,之后每3秒一次)
struct itimerspec new_timer;
new_timer.it_value.tv_sec = 5; // 第一次超时时间(秒)
new_timer.it_value.tv_nsec = 0; // 纳秒部分
new_timer.it_interval.tv_sec = 3; // 间隔时间(秒)
new_timer.it_interval.tv_nsec = 0;
if (timerfd_settime(fd, 0, &new_timer, NULL) == -1) {
perror("timerfd_settime failed");
close(fd);
return 1;
}
// 3. 循环读取超时事件(每次超时会返回8字节数据,表示超时次数)
uint64_t exp;
while (1) {
ssize_t s = read(fd, &exp, sizeof(exp));
if (s != sizeof(exp)) {
perror("read failed");
break;
}
printf("Timer expired %llu times\n", (unsigned long long)exp);
}
close(fd);
return 0;
}
gcc -o timerfd_example timerfd_example.c
./timerfd_example
输出示例:Timer expired 1 times # 5秒后
Timer expired 1 times # 3秒后(第二次)
Timer expired 1 times # 3秒后(第三次)
...
说明:
it_value:设置第一次超时时间(若为0则表示立即触发)。it_interval:设置间隔时间(若为0则表示一次性定时器)。CLOCK_MONOTONIC:推荐使用,避免系统时间修改影响定时精度。若需在内核模块中实现定时器(如驱动开发),可使用timer_list结构体。
#include <linux/module.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
struct timer_list my_timer;
void my_timer_callback(struct timer_list *timer) {
printk(KERN_INFO "Timer expired!\n");
// 重新设置定时器(实现周期性触发,若需一次性则无需此行)
mod_timer(timer, jiffies + msecs_to_jiffies(2000)); // 2秒后再次触发
}
static int __init my_init(void) {
printk(KERN_INFO "Module loaded\n");
timer_setup(&my_timer, my_timer_callback, 0); // 初始化定时器
mod_timer(&my_timer, jiffies + msecs_to_jiffies(5000)); // 5秒后首次触发
return 0;
}
static void __exit my_exit(void) {
del_timer(&my_timer); // 删除定时器
printk(KERN_INFO "Module unloaded\n");
}
module_init(my_init);
module_exit(my_exit);
MODULE_LICENSE("GPL");
Makefile编译模块,使用insmod加载,rmmod卸载。dmesg查看内核日志,会看到“Timer expired!”的输出(每2秒一次)。说明:
jiffies:内核时间单位(节拍数),msecs_to_jiffies()用于将毫秒转换为节拍数。mod_timer():用于修改定时器的超时时间(若定时器未激活则激活)。cron(仅适用于周期性任务)cron是Ubuntu的周期性任务调度工具,但最小时间间隔为1分钟,无法实现秒级超时。
crontab -e
0 8 * * * /path/to/your/script.sh
cron的语法为分钟 小时 日 月 周 命令,不支持秒级精度。systemd定时器(灵活、易管理)。timerfd(高精度、与应用层集成)。timer_list(底层驱动需求)。cron(仅适用于分钟级周期性任务)。根据具体需求选择合适的方法,即可实现Ubuntu系统中的定时器超时设置。