Linux crontab定时任务

参考资料

  1. 【図解】cronの仕組み
  2. 定时任务 - crontab
  3. 解决ubuntu下定时任务不执行问题
  4. crontab环境变量问题💥
  5. Linux定时任务功能详解:crontab与at命令应用指南

目录

  • [一. 环境准备](#一. 环境准备)
    • [1.1 wsl开启systemd](#1.1 wsl开启systemd)
    • [1.2 开启cron日志](#1.2 开启cron日志)
  • [二. cron服务管理相关命令](#二. cron服务管理相关命令)
    • [2.1 service 的方式](#2.1 service 的方式)
    • [2.2 systemctl 的方式](#2.2 systemctl 的方式)
  • [三. 简单使用crontab定时任务](#三. 简单使用crontab定时任务)
    • [3.1 编辑一个定时任务](#3.1 编辑一个定时任务)
      • [3.1.1 `crontab -e` 编辑定时任务](#3.1.1 crontab -e 编辑定时任务)
      • [3.1.2 通过命令行直接添加](#3.1.2 通过命令行直接添加)
    • [3.2 查看定时任务](#3.2 查看定时任务)
      • [3.2.1 `crontab -l` 查看既存的定时任务](#3.2.1 crontab -l 查看既存的定时任务)
      • [3.2.2 `/var/spool/cron/crontabs/用户名` 文件查看](#3.2.2 /var/spool/cron/crontabs/用户名 文件查看)
    • [3.3 删除定时任务](#3.3 删除定时任务)
      • [3.3.1 `crontab -e` 编辑删除定时任务](#3.3.1 crontab -e 编辑删除定时任务)
      • [3.3.2 按关键字在命令行删除](#3.3.2 按关键字在命令行删除)
      • [3.3.3 `crontab -r` 的方式删除](#3.3.3 crontab -r 的方式删除)
  • [四. 定时任务进阶](#四. 定时任务进阶)
    • [4.1 注意事项](#4.1 注意事项)
    • [4.2 定时任务的示例](#4.2 定时任务的示例)
      • [4.2.1 由于PATH引起问题的实例](#4.2.1 由于PATH引起问题的实例)
      • [4.2.2 其他定时任务示例](#4.2.2 其他定时任务示例)

一. 环境准备

1.1 wsl开启systemd

⏹笔者使用wsl来运行ubuntu,而 wsl 默认没有真正的 init 系统,无法使用现代 Linux 的标准服务管理工具:systemctl命令。

可通过修改/etc/wsl.conf的方式开启使用systemctl命令。如果使用的是VMware等虚拟机或者云服务器则默认会开启systemctl命令。

bash 复制代码
apluser@FengYeHong-HP:~$ ls -l /etc/wsl.conf
-rw-r--r-- 1 root root 43 Aug 14 20:50 /etc/wsl.conf
apluser@FengYeHong-HP:~$
apluser@FengYeHong-HP:~$ tail -n 2 /etc/wsl.conf
[boot]
systemd=true

⏹修改完毕/etc/wsl.conf之后,退出wsl,在PowerShell终端中执行关闭wsl的命令

powershell 复制代码
wsl --shutdown

⏹然后再一次进入wsl之后,systemd init 系统就已经被启用了

  • 可通过下面的命令进行验证
bash 复制代码
apluser@FengYeHong-HP:~$ ps -p 1 -o comm=
systemd

💥注意事项💥

  • wsl1无法启用systemd init 系统,wsl2才可以。
  • 启用 systemd 后,WSL 启动会比以前慢一些,因为它会启动一堆后台服务(dbus、journald、cron 等)

1.2 开启cron日志

⏹ubuntu默认没有开cron日志,可通过修改配置文件选择是否开启。去除#既可以开启cron日志。

bash 复制代码
apluser@FengYeHong-HP:~$ ls -l /etc/rsyslog.d/50-default.conf
-rw-r--r-- 1 root root 1123 Aug 13 09:00 /etc/rsyslog.d/50-default.conf
apluser@FengYeHong-HP:~$
apluser@FengYeHong-HP:~$ grep cron /etc/rsyslog.d/50-default.conf
cron.*                          /var/log/cron.log
#       cron,daemon.none;\

⏹配置文件修改完毕之后,还需要重启一下rsyslog服务,当定时任务开始执行后,就可以在/var/log/cron.log中看到日志了。

bash 复制代码
# 这两种方式都可以
sudo systemctl restart rsyslog
sudo  service rsyslog  restart

二. cron服务管理相关命令

特性 service systemctl
诞生时代 SysV init 时代(上世纪 90 年代) systemd 时代(2010 年以后)
依赖的 init 系统 SysV init / Upstart / systemd(兼容模式) 只能用于 systemd
底层调用 在旧系统调用 /etc/init.d/xxx 脚本,在新系统里会转到 systemctl 直接通过 systemd 的 D-Bus API 管理服务
功能范围 主要是启动、停止、重启、查看状态 除了服务管理,还能管理开机启动、目标(target)、挂载点、设备、电源等
输出信息 简单的状态行(旧模式),或 systemd 的详细状态(新模式) 详细的 systemd 状态、日志、依赖关系
是否未来主流 只是为了兼容旧脚本保留 现代 Linux 的标准,未来主流

2.1 service 的方式

bash 复制代码
# 查看crontab服务状态
ps -ef | grep '[c]ron'
service cron status            

sudo service cron start        # 启动服务
sudo service cron stop         # 关闭服务
sudo service cron restart      # 重启服务
sudo service cron reload       # 重新载入配置

2.2 systemctl 的方式

bash 复制代码
# 查看crontab服务状态
ps -ef | grep '[c]ron'
systemctl status cron

sudo systemctl start cron      # 启动
sudo systemctl stop cron       # 停止
sudo systemctl restart cron    # 重启
sudo systemctl enable cron     # 开机自启
sudo systemctl disable cron    # 禁用开机自启

三. 简单使用crontab定时任务

3.1 编辑一个定时任务

3.1.1 crontab -e 编辑定时任务

  • 直接在命令行输入crontab -e编辑定时任务
bash 复制代码
apluser@FengYeHong-HP:~$ crontab -e
  • 输入完成之后,会使用指定的文本编辑器(此处使用的是nano编辑器)打开定时任务编辑页面

3.1.2 通过命令行直接添加

⏹如果定时任务的命令长度不是十分长的话,可以直接通过命令行追加

  • crontab -l 2>/dev/null:读取现有任务,如果没有就忽略错误
  • echo '...':指定定时任务的内容
  • crontab -:覆盖回 crontab,添加定时任务
bash 复制代码
(crontab -l 2>/dev/null; echo '* * * * * echo "Hello world" >> /tmp/hello.log') | crontab -

3.2 查看定时任务

3.2.1 crontab -l 查看既存的定时任务

bash 复制代码
apluser@FengYeHong-HP:~$ crontab -l
* * * * * echo "Hello world" >> /tmp/hello.log

3.2.2 /var/spool/cron/crontabs/用户名 文件查看

  • 每个用户对应的定时任务都会保存到 /var/spool/cron/crontabs/用户名 文件中
bash 复制代码
apluser@FengYeHong-HP:~$ sudo ls -l /var/spool/cron/crontabs/apluser
-rw------- 1 apluser crontab 222 Aug 13 08:52 /var/spool/cron/crontabs/apluser
bash 复制代码
apluser@FengYeHong-HP:~$ sudo cat /var/spool/cron/crontabs/apluser
# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (- installed on Wed Aug 13 08:52:05 2025)
# (Cron version -- $Id: crontab.c,v 2.13 1994/01/17 03:20:37 vixie Exp $)
* * * * * echo "Hello world" >> /tmp/hello.log

3.3 删除定时任务

3.3.1 crontab -e 编辑删除定时任务

bash 复制代码
crontab -e

3.3.2 按关键字在命令行删除

bash 复制代码
# 可以先将既存的定时任务备份
crontab -l > mycron.bk
# 然后通过关键词的方式删除定时任务
crontab -l | grep -v 'Hello world'
crontab -l | grep -v 'Hello world' | crontab -

3.3.3 crontab -r 的方式删除

  • 💥注意:此种方式会删除当前用户的所有定时任务,慎用。
bash 复制代码
apluser@FengYeHong-HP:~$ crontab -ir
crontab: really delete apluser crontab? (y/n) y
apluser@FengYeHong-HP:~$
apluser@FengYeHong-HP:~$ crontab -l
no crontab for apluser
apluser@FengYeHong-HP:~$ sudo ls -l /var/spool/cron/crontabs/apluser
[sudo] password for apluser:
ls: cannot access '/var/spool/cron/crontabs/apluser': No such file or directory

四. 定时任务进阶

/etc/crontab 是 系统级别的 Cron 配置文件

  • 设置一些 系统维护任务(清理日志、同步时间等)
  • 启动时执行系统服务相关脚本
  • 运行需要 root 权限的定时任务
bash 复制代码
apluser@FengYeHong-HP:~$ cat /etc/crontab
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
# You can also override PATH, but by default, newer versions inherit it from the environment
#PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name command to be executed
17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
25 6    * * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6    * * 7   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6    1 * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
#

4.1 注意事项

  • PATH变量被精简

    • 🔷在交互式 shell 里,PATH 可能很长,例如
    bash 复制代码
    /usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:...
    • 🔷但 cron 里常常只有
    bash 复制代码
    /usr/bin:/bin
  • HOME变量可能不同

    • 交互 shell 下的 HOME 一般是当前用户的家目录,但 cron 可能会是 / 或其他值。
    • 如果脚本依赖 ~相对路径,建议使用绝对路径。
  • ⏹不会加载 ~/.bashrc~/.profile

    • cron 不会读取你时登录时加载的配置文件,所以环境变量、别名、函数都可能丢失。
    • 如果脚本依赖这些配置,可以在任务里手动加载
  • SHELL 变量可能不同

    • cron 默认使用 /bin/sh(在很多系统上是 dash),而不是 /bin/bash
    • 如果脚本里用了 bash 特性([[ ]]{1..5}source 等),除了在脚本内指定Shebang之外,还可以再定时任务编辑界面添加
    bash 复制代码
    SHELL=/bin/bash
  • %的特殊含义

    • 在 crontab 中 % ,表示换行(相当于把它后面的内容当作命令的标准输入 STDIN)。
    • 如果要在命令里用 %,必须写成 \% 才能被当作普通字符。
    bash 复制代码
    # 在终端执行会输出 Hello%World
    # 但是放进 crontab 里会变成
    #     命令:echo "Hello"
    #     标准输入:World
    * * * * * echo "Hello%World"

4.2 定时任务的示例

4.2.1 由于PATH引起问题的实例

  • PATH变量在交互式shell中,会输出很多内容
bash 复制代码
apluser@FengYeHong-HP:~$ echo "$PATH" | xargs -d ':' -L 1 | grep -v '威' | wc -l
48
apluser@FengYeHong-HP:~$ echo "$PATH" | xargs -d ':' -L 1 | grep -v '威' | head
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/usr/lib/wsl/lib
/mnt/c/Program Files (x86)/VMware/VMware Workstation/bin/
  • 但我们在corn定时任务中使用了PATH之后,只会输出很少的内容
bash 复制代码
apluser@FengYeHong-HP:~$ crontab -l
SHELL=/bin/bash
* * * * * /home/apluser/work/0815/bash_test.sh

apluser@FengYeHong-HP:~$ cat /home/apluser/work/0815/bash_test.sh
#!/usr/bin/env bash
echo "$PATH" | xargs -d ':' -L 1 | grep -v '威' >> /home/apluser/work/corn1.log

apluser@FengYeHong-HP:~$ tail /home/apluser/work/corn1.log
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/games
/usr/local/games
/snap/bin

apluser@FengYeHong-HP:~$

4.2.2 其他定时任务示例

bash 复制代码
# 实例1:每1分钟执行一次myCommand
* * * * * myCommand

# 实例2:每小时的第3和第15分钟执行
3,15 * * * * myCommand

# 实例3:在上午8点到11点的第3和第15分钟执行
3,15 8-11 * * * myCommand

# 实例4:每隔两天的上午8点到11点的第3和第15分钟执行
3,15 8-11 */2  *  * myCommand

# 实例5:每周一上午8点到11点的第3和第15分钟执行
3,15 8-11 * * 1 myCommand

# 实例6:每晚的21:30重启smb
30 21 * * * /etc/init.d/smb restart

# 实例7:每月1、10、22日的4 : 45重启smb
45 4 1,10,22 * * /etc/init.d/smb restart

# 实例8:每周六、周日的1 : 10重启smb
10 1 * * 6,0 /etc/init.d/smb restart

# 实例9:每天18 : 00至23 : 00之间每隔30分钟重启smb
0,30 18-23 * * * /etc/init.d/smb restart

# 实例10:每星期六的晚上11 : 00 pm重启smb
0 23 * * 6 /etc/init.d/smb restart

# 实例11:每一小时重启smb
* */1 * * * /etc/init.d/smb restart

# 实例12:晚上11点到早上7点之间,每隔一小时重启smb
0 23-7 * * * /etc/init.d/smb restart

⏹在 crontab 里,@reboot 是一种特殊的时间标记,表示系统启动完成后执行一次

  • 当系统启动(或 cron 服务启动)后,运行一次 script_a.py
  • >> /home/pi/cron.log 2>&1:把标准输出和错误输出都追加写入 /home/pi/cron.log
bash 复制代码
@reboot /usr/bin/python3 /home/pi/script_a.py >> /home/pi/cron.log 2>&1

⏹常见的特殊时间标记还有

语法 含义
@reboot 系统启动后运行一次
@yearly 每年运行一次(等同于 0 0 1 1 *
@monthly 每月运行一次(等同于 0 0 1 * *
@weekly 每周运行一次(等同于 0 0 * * 0
@daily 每天运行一次(等同于 0 0 * * *
@hourly 每小时运行一次(等同于 0 * * * *
相关推荐
嘻嘻嘻开心9 小时前
Collection接口
linux·windows·python
广东大榕树信息科技有限公司9 小时前
机房动环管理如何通过智能可视化实现高效运维?
运维·网络·物联网·国产动环监控系统·动环监控系统
广东大榕树信息科技有限公司9 小时前
当提升动力环境监控效率时,如何实现全面的数据集成与可视化?
运维·网络·物联网·国产动环监控系统·动环监控系统
喵叔哟9 小时前
11.容器化与 Docker
运维·docker·容器
Suchadar9 小时前
NAT网络地址转换
linux·服务器·网络
旺仔Sec10 小时前
2025年安徽省职业院校技能大赛(高职组)5G组网与运维赛项竞赛样题
运维·5g
凤凰战士芭比Q10 小时前
Jenkins(分布式、用户管理)
运维·分布式·jenkins
代码游侠10 小时前
复习——线程(pthread)
linux·运维·开发语言·网络·学习·算法
极地星光10 小时前
软件发布中.symbols文件夹单独发布全指南:从需求解析到自动化落地
运维·自动化
凯子坚持 c10 小时前
在家搭个私人云音乐库?用 Docker+cpolar 随时随地听歌
运维·docker·容器