crontab调用mysql失败主因是环境变量缺失、密码明文、连接验证不充分、时间格式错误及脚本路径/日志处理不当;应使用绝对路径、.my.cnf配置、三层健康检查、标准五段式定时、显式日志重定向和固定工作目录。

crontab 调用 mysql 命令连不上数据库?先看环境变量
crontab 默认不加载用户 shell 的环境变量(比如 PATH、HOME),所以直接写 mysql -u root -p123 test -e "SELECT 1" 很可能报错 command not found: mysql 或 Access denied(因为找不到 ~/.my.cnf)。
实操建议:
- 用绝对路径调用
mysql,例如/usr/bin/mysql(可用which mysql确认) - 显式指定配置文件:
/usr/bin/mysql --defaults-file=/home/user/.my.cnf -e "SELECT 1",避免依赖HOME - 不要在 crontab 里用
-p明文传密码;改用.my.cnf(权限必须是600) - 测试前先手动运行完整命令,再复制进 crontab
检查数据库是否存活,别只靠 ping 或端口探测
只执行 nc -z localhost 3306 或 mysqladmin ping 容易误判:MySQL 进程活着,但 mysqld 可能卡在 recovery、连接数打满、或某个表被锁死,实际无法响应查询。
实操建议:
- 用轻量级 SQL 真实触发一次查询:
/usr/bin/mysql --defaults-file=/home/user/.my.cnf -e "SELECT 1" information_schema 2>/dev/null - 加超时控制,防止 hang 住:
timeout 5 /usr/bin/mysql ... - 检查返回值:
$?为 0 才算通过;非零需记录日志或告警 - 避免查业务库,优先用
information_schema或performance_schema,减少干扰
crontab 时间格式写错导致任务从不执行
常见错误包括:把「分 时 日 月 周」顺序记反、周和月的数字范围混淆(周是 0–7,0 和 7 都是周日;月是 1–12)、使用了系统不支持的扩展语法(如 @hourly 在某些旧版 cron 里不可靠)。
实操建议:
- 坚持用标准五段式:
0 2 * * * /path/to/check.sh表示每天 2:00 执行 - 周和日不能同时设为非
*(否则 cron 会要求两者都满足,极难触发) - 调试时先设成每分钟跑一次:
* * * * * ...,确认逻辑正确后再调回正式周期 - 日志重定向要明确:
> /var/log/mysql_health.log 2>&1,否则看不到错误输出
脚本里没处理 mysqld 没启动就执行 mysql 命令的情况
如果 MySQL 实例本身已崩溃,脚本仍尝试连接,会失败并可能掩盖真正问题(比如磁盘满、OOM kill)。更糟的是,有些监控脚本失败后不做任何标记,导致“假阳性”静默。
实操建议:
- 先检查进程:
pgrep -f "mysqld" > /dev/null || { echo "$(date) mysqld not running" >> /var/log/mysql_health.log; exit 1; } - 再检查端口监听:
ss -tln | grep ":3306" > /dev/null || { ... } - 最后才执行
mysql查询;三层检查缺一不可 - 所有失败分支都要写日志、返回非零退出码,让 crontab 或外部监控能捕获
最容易被忽略的是:脚本里用了相对路径、没设 cd 到固定目录,或者日志路径不存在却没做 mkdir -p。cron 下的当前工作目录不一定是家目录,出错时连日志都写不进去。











