expect脚本终端运行正常但cron定时执行失败问题求助
故障排查及解决方案
常见故障原因
- 环境变量缺失:cron调度任务时使用的是最小化环境变量,PATH搜索路径和你手动登录终端的PATH不一致,可能导致
mysqldump命令无法被找到。 - 目录/权限异常:
- 确认
/home/user1/mysql目录已存在,不存在的话mysqldump的输出重定向会直接失败 - 确认cron任务的运行用户对两个脚本文件有执行权限,对
/home/user1/mysql目录有写入权限,可执行chmod +x /home/user1/*.sh /home/user1/*.exp添加执行权限
- 确认
- expect匹配失败:非交互式的cron环境下,
mysqldump的密码提示可能输出格式和终端下有细微差异(比如多余的控制字符、空格差异),你用的-exact精确匹配很容易匹配失败导致脚本卡住。
修复步骤
- 先给cron任务添加日志输出,方便定位具体错误,修改cron规则为:
* * * * * /usr/bin/expect -f /home/user1/script.exp >> /var/log/mysql_backup.log 2>&1
后续可查看/var/log/mysql_backup.log的内容定位具体报错。
2. 优化sql_backup.sh脚本,把mysqldump替换为绝对路径(可执行which mysqldump查询本地实际路径,常见为/usr/bin/mysqldump),修改后脚本如下:
#!/bin/bash # 提前创建输出目录避免不存在 mkdir -p /home/user1/mysql /usr/bin/mysqldump -u root -p --all-databases > /home/user1/mysql/mysql-bkp.sql
- 修改expect脚本的匹配规则,把精确匹配改为模糊匹配,避免格式差异导致匹配失败:
#!/usr/bin/expect -f set timeout -1 spawn /home/user1/sql_backup.sh match_max 100000 # 去掉-exact 用模糊匹配 expect "*Enter password:*" send -- "pass123\r" expect eof
更优替代方案
你这个场景完全不需要用expect脚本传递密码,反而会带来明文密码泄露、脚本复杂度提升的问题,直接用mysql配置文件存储密码即可:
- 给cron任务的运行用户home目录下新建
.my.cnf文件,写入以下内容:
[mysqldump] user=root password=pass123
如果你的cron任务配置在root用户的crontab中,需要把.my.cnf放到/root目录下。
2. 给该文件设置严格权限避免泄露:chmod 600 ~/.my.cnf
3. 修改sql_backup.sh去掉-p参数:
#!/bin/bash mkdir -p /home/user1/mysql /usr/bin/mysqldump -u root --all-databases > /home/user1/mysql/mysql-bkp.sql
- 直接把cron任务改成调度sql_backup.sh即可,不需要expect脚本:
* * * * * /bin/bash /home/user1/sql_backup.sh
内容的提问来源于stack exchange,提问作者Nitin Kumar
相关产品推荐
相关产品推荐

