在CentOS这类企业级Linux服务器的运维管理中,重启是一项看似简单却至关重要的操作,直接执行reboot
或shutdown -r now
命令虽然快捷,但在生产环境中,一个“干净”的重启过程往往需要在重启前执行一系列检查和清理工作,为此,创建一个自定义的reboot.sh
脚本,将预检查、清理、通知和重启操作流程化、自动化,是提升系统管理效率和稳定性的最佳实践,本文将深入探讨如何构建一个功能完善的reboot.sh
脚本。
为什么需要一个自定义重启脚本?
标准的重启命令会立即终止大部分进程并重启系统,这可能导致数据丢失或服务状态异常,一个精心设计的reboot.sh
脚本则可以扮演“重启管家”的角色,其核心价值在于:
- 执行预检查:在重启前验证关键服务的健康状况、磁盘空间是否充足、是否有重要用户在线等,避免在不当的时机重启。
- 进行环境清理:自动清理临时文件、过期日志,释放磁盘空间,确保系统以更“轻快”的状态启动。
- 实现优雅关闭:按照依赖关系有序停止服务,而非强制中断,保障数据的完整性。
- 发送通知告警:在重启前后向管理员发送邮件或其他形式的通知,确保操作的可追溯性。
如何创建一个基础的 reboot.sh
脚本?
创建脚本的第一步是确立其位置和权限,一个合理的做法是将其放置在系统管理员的PATH
路径下,如/usr/local/sbin/
。
创建脚本文件
sudo touch /usr/local/sbin/reboot.sh
赋予执行权限
sudo chmod +x /usr/local/sbin/reboot.sh
编写基本内容
使用文本编辑器(如vim
或nano
)打开文件,并写入最基础的结构:#!/bin/bash # 一个简单的CentOS重启脚本 echo "系统即将在5秒后重启..." sleep 5 /sbin/reboot
#!/bin/bash
:这是脚本的“Shebang”,告诉系统使用Bash来解释执行此脚本。/sbin/reboot
:使用reboot
命令的绝对路径,这是一个好习惯,可以避免因环境变量PATH
配置问题而找不到命令。
进阶功能与实践
一个真正有用的reboot.sh
脚本远不止于此,下面我们通过一个更复杂的示例,展示如何集成前述的进阶功能。
预检查与清理逻辑
在执行重启前,我们可以加入一系列判断和操作,为了结构清晰,可以使用一个表格来规划这些功能:
功能类别 | 命令示例 | 说明 |
---|---|---|
磁盘空间检查 | DISK_USAGE=$(df / | tail -1 | awk '{print $5}' | sed 's/%//') | 检查根分区使用率,超过阈值(如90%)则中止重启。 |
关键服务状态 | systemctl is-active nginx | 检查Nginx等核心服务是否正常运行,若未运行可记录警告。 |
在线用户提醒 | who | grep -vq '^root ' | 检查是否有非root用户在线,并向其发送重启警告消息。 |
清理临时文件 | find /tmp -type f -atime +7 -delete | 删除/tmp 目录下7天未访问的文件。 |
清理系统日志 | journalctl --vacuum-time=7d | 清理systemd 日志,只保留最近7天的记录。 |
一个完整的示例脚本
将上述逻辑整合,并加入日志记录和通知功能,我们可以构建一个相当健壮的reboot.sh
脚本。
#!/bin/bash # ================================================================= # 功能: CentOS 安全重启脚本 # 作者: System Administrator # 日期: 2025-10-27 # 描述: 在重启前执行系统检查、清理和通知操作 # ================================================================= # --- 配置区 --- LOG_FILE="/var/log/custom_reboot.log" ADMIN_EMAIL="admin@example.com" DISK_THRESHOLD=90 # 磁盘使用率告警阈值(%) # --- 函数定义 --- log_message() { echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE" } # --- 主执行流程 --- log_message "===== 开始执行安全重启脚本 =====" # 1. 磁盘空间检查 ROOT_USAGE=$(df / | tail -1 | awk '{print $5}' | sed 's/%//') if [ "$ROOT_USAGE" -gt "$DISK_THRESHOLD" ]; then log_message "错误: 根分区磁盘使用率 (${ROOT_USAGE}%) 超过阈值 (${DISK_THRESHOLD}%),中止重启。" # 可以在这里加入发送告警邮件的逻辑 exit 1 fi log_message "检查通过: 根分区磁盘使用率为 ${ROOT_USAGE}%。" # 2. 在线用户提醒 NON_ROOT_USERS=$(who | awk '{print $1}' | sort -u | grep -v '^root$') if [ -n "$NON_ROOT_USERS" ]; then log_message "检测到在线用户: $NON_ROOT_USERS" echo "系统管理员已发起重启操作,请尽快保存您的工作并注销登录。" | wall sleep 30 # 给用户30秒时间保存工作 fi # 3. 执行清理任务 log_message "开始执行系统清理..." # 清理/tmp目录下超过7天的文件 find /tmp -type f -atime +7 -delete log_message "清理 /tmp 目录完成。" # 清理systemd日志,保留7天 journalctl --vacuum-time=7d log_message "清理 journald 日志完成。" # 4. 发送通知 echo "服务器 $(hostname) 即将执行重启操作,原因:计划内维护,请关注系统启动状态。" | mail -s "服务器重启通知" "$ADMIN_EMAIL" log_message "已向管理员 ($ADMIN_EMAIL) 发送重启通知邮件。" # 5. 执行重启 log_message "所有检查和清理任务已完成,系统即将重启。" sleep 10 /sbin/reboot
安全与最佳实践
- 权限控制:此脚本涉及系统核心操作,应仅允许
root
用户或有sudo
权限的管理员执行。 - 测试先行:在任何生产环境应用前,务必在测试环境中充分验证脚本的每一个逻辑分支。
- 绝对路径:脚本中调用的所有命令(如
reboot
,systemctl
,find
)都应使用绝对路径,可通过which command
命令查询。 - 日志记录:像示例中一样,将脚本的关键操作和结果记录到日志文件,便于事后审计和故障排查。
相关问答FAQs
我将 reboot.sh
脚本放在了 cron 中计划重启,但任务执行后系统并没有重启,为什么?
解答:这是一个非常常见的问题,主要原因在于,reboot
和 shutdown
这类命令为了安全,默认需要一个交互式的终端(TTY)环境才能执行,而 cron
任务在后台运行,并没有分配TTY,解决方法有两种:
- 修改命令:在脚本中使用
shutdown -r now
而不是reboot
,并为其添加--no-wall
参数,但这通常仍需特殊权限。 - 配置 sudoers(推荐):编辑
/etc/sudoers
文件(使用visudo
命令),为执行该脚本的用户(或cron服务,如root
)添加无密码执行重启命令的权限,在文件末尾添加一行:username ALL=(ALL) NOPASSWD: /sbin/shutdown, /sbin/reboot
然后将脚本中的
/sbin/reboot
修改为sudo /sbin/reboot
,这样,cron在执行脚本时调用sudo
就不需要输入密码了。
我的脚本在执行时卡住了,没有任何输出,也不继续往下走,可能是什么原因?
解答:脚本卡住通常是因为某个命令进入了等待状态或阻塞状态,请检查以下几点:
- 交互式命令:检查脚本中是否包含了需要用户输入的命令,如
read
,yes/no
确认等,在自动化脚本中应绝对避免这类命令。 - 后台进程与管道:如果脚本启动了后台进程但没有正确管理,或者某个管道命令的下游进程没有正常结束,都可能导致主脚本挂起。
- 网络相关操作:如果脚本中有
wget
,curl
,ssh
等网络请求,可能因网络问题导致长时间无响应,建议为这些命令设置超时参数,如curl --max-time 10 ...
。 - 调试:在脚本的开头加入
set -x
,这会让Shell在执行每一行命令前都将其打印到标准输出,从而精确定位是哪一行命令导致了卡顿,排查完成后记得将其移除。
【版权声明】:本站所有内容均来自网络,若无意侵犯到您的权利,请及时与我们联系将尽快删除相关内容!
发表回复