1. 为什么需要定时关机?
作为一名长期使用Ubuntu系统的开发者,我经常遇到这样的场景:深夜跑完数据训练后忘记关机,结果机器连续运转好几天;或者作为服务器使用时,希望在业务低峰期自动关机节省能耗。定时关机看似是个小功能,但实际使用频率很高。
在Ubuntu系统中实现定时关机主要有三种主流方案:
- 使用shutdown命令配合cron定时任务(最通用)
- 使用systemd timer单元(新系统推荐)
- 编写自定义脚本配合at命令(临时性任务)
今天我们就重点讲解最经典可靠的cron方案,这也是我在生产环境使用多年的方法。相比其他方案,cron的优势在于:
- 配置简单直观,一条命令即可完成
- 支持复杂的定时规则(如每周特定几天)
- 系统原生支持,无需额外安装组件
- 日志记录完善,方便排查问题
2. 核心命令与参数解析
实现定时关机的核心是shutdown命令,我们先完整了解它的参数用法:
bash复制sudo shutdown -h 23:00 "系统将在23:00关机,请保存工作"
关键参数说明:
-h:halt的缩写,表示关机操作(对比-r是重启)23:00:24小时制的时间格式,也可以使用+m表示m分钟后- 引号内的消息:会广播给所有登录用户
常见时间格式示例:
22:30→ 晚上10点30分+30→ 30分钟后now→ 立即执行(等效于+0)
注意:直接使用shutdown命令是立即生效的一次性任务,要实现每天固定时间执行,需要结合cron使用。
3. Cron定时任务配置详解
3.1 认识Cron配置文件
Ubuntu系统默认安装了cron服务,配置文件主要有两种编辑方式:
- 用户级配置(推荐):
bash复制crontab -e
该命令会打开当前用户的cron配置,存储在/var/spool/cron/crontabs/目录下
- 系统级配置:
bash复制sudo nano /etc/crontab
需要root权限,适合系统级别的定时任务
对于定时关机这种需要root权限的操作,我建议直接使用sudo编辑root用户的cron:
bash复制sudo crontab -e
3.2 Cron时间表达式
定时关机的核心是编写正确的时间表达式,基本格式如下:
code复制* * * * * command_to_execute
| | | | |
| | | | +----- 星期几 (0 - 6) (周日=0)
| | | +------- 月份 (1 - 12)
| | +--------- 日 (1 - 31)
| +----------- 小时 (0 - 23)
+------------- 分钟 (0 - 59)
针对每天23点关机的需求,对应的表达式应该是:
code复制0 23 * * * /sbin/shutdown -h now
解释:
- 第1个0表示"整点"(23:00:00)
- 23表示23点(晚上11点)
- 星号表示"每天/每月/每周"都执行
3.3 完整配置步骤
- 打开root的cron配置:
bash复制sudo crontab -e
- 在文件末尾添加(建议放在最后一行):
bash复制# 每天23点自动关机
0 23 * * * /sbin/shutdown -h now
-
保存退出(nano编辑器按Ctrl+O保存,Ctrl+X退出)
-
验证配置:
bash复制sudo crontab -l
应该能看到刚才添加的那行配置
4. 高级配置与问题排查
4.1 关机前提醒用户
突然关机会导致其他用户数据丢失,更友好的做法是提前警告:
bash复制0 22 * * * /usr/bin/wall "服务器将在1小时后关机,请及时保存工作"
0 23 * * * /sbin/shutdown -h now
这里使用了wall命令向所有终端广播消息,两条任务分别设置在22点和23点。
4.2 日志验证
查看cron执行日志确认任务是否正常运行:
bash复制grep CRON /var/log/syslog
正常会看到类似记录:
code复制Jul 10 23:00:01 ubuntu CRON[1234]: (root) CMD (/sbin/shutdown -h now)
4.3 常见问题解决
问题1:关机命令没有执行
可能原因:
- cron服务未运行 → 检查状态
sudo service cron status - 命令路径错误 → 使用绝对路径
/sbin/shutdown - 权限不足 → 确保使用sudo crontab
问题2:关机被阻止
检查是否有其他服务阻止关机:
bash复制systemctl list-jobs
问题3:时区不正确
确保系统时区设置正确:
bash复制timedatectl
如果时区错误,修正为东八区:
bash复制sudo timedatectl set-timezone Asia/Shanghai
5. 替代方案对比
除了cron,还有几种实现定时关机的方法:
5.1 systemd timer(Ubuntu 16.04+)
- 创建服务单元:
bash复制sudo nano /etc/systemd/system/shutdown.timer
内容:
code复制[Unit]
Description=Daily shutdown
[Timer]
OnCalendar=*-*-* 23:00:00
Persistent=true
[Install]
WantedBy=timers.target
- 启用服务:
bash复制sudo systemctl enable --now shutdown.timer
5.2 at命令(单次任务)
示例:设置3小时后关机
bash复制echo "shutdown -h now" | at now + 3 hours
查看待处理任务:
bash复制atq
5.3 桌面环境方案
对于GUI用户,可以安装gnome-schedule:
bash复制sudo apt install gnome-schedule
然后在"应用程序 → 系统工具"中找到定时任务工具
6. 我的实践建议
经过多年运维经验,总结几个实用技巧:
-
双重确认机制:在关键生产环境,我会同时配置cron和systemd timer,互为备份
-
关机前清理:建议添加预处理脚本,例如:
bash复制0 22 * * * /usr/bin/docker stop $(docker ps -q)
0 23 * * * /sbin/shutdown -h now
- 节假日排除:通过cron的日期范围设置,避开节假日:
code复制# 工作日23点关机
0 23 * * 1-5 /sbin/shutdown -h now
- 网络唤醒配合:如果机器支持WOL,可以搭配使用:
bash复制# 每天8点开机,23点关机
0 8 * * * /usr/sbin/etherwake MAC地址
0 23 * * * /sbin/shutdown -h now
- 邮件通知:重要服务器关机前发送邮件提醒:
bash复制0 22 * * * echo "服务器将在23点关机" | mail -s "关机提醒" admin@example.com
