shell 脚本执行无效
目录
遇到问题多思考,不能过度依赖度娘。此话时给自己的警钟。
希望此解决历程对各位猿友有所帮助。
背景:
在做数据同步脚本时,发现手动执行脚本,脚本有效。使用 crontab 脚本定时执行时,脚本无效。
非 root 用户执行脚本。
排查历程:
脚本内容如下:
将 docker 中数据库内容导出,上传至 sftp ,删除生成的数据库脚本。
#!/bin/bash
# 生成数据库脚本
echo `date` "开始生成数据库脚本"
sudo docker exec -i pg_test bash -c "pg_dump -U postgres -t user -d testdatabase > /var/lib/postgresql/data/user.sql"
sudo docker exec -i pg_test bash -c "pg_dump -U postgres -t role -d testdatabase > /var/lib/postgresql/data/role.sql"
echo `date` "开始生成数据库脚本 -- 成功"
# 将文件上传至 sftp
echo `date` "将文件上传至 sftp"
sudo lftp sftp://username:[email protected]:22 << EOF
cd /uploads/synchronized_data
lcd /var/lib/docker/volumes/7d41b8533d80f314d94baef587594e2c3092fc1bc1befb5b78bf59f61c0b125e/_data
put user.sql
put role.sql
bye
EOF
echo `date` "将文件上传至 sftp 成功"
# 删除本地文件
echo `date` "删除生成的 sql 文件"
sudo rm -f /var/lib/docker/volumes/7d41b8533d80f314d94baef587594e2c3092fc1bc1befb5b78bf59f61c0b125e/_data/user.sql
sudo rm -f /var/lib/docker/volumes/7d41b8533d80f314d94baef587594e2c3092fc1bc1befb5b78bf59f61c0b125e/_data/role.sql
echo `date` "删除生成的 sql 文件 -- 成功"
exit
crontab 配置:
每天凌晨执行一次脚本。
00 00 * * * /home/zhangll/data-sync/upload.sh >> /home/zhangll/data-sync/log/upload.log
问题:
已上配置,每次执行脚本后,并没又成功,并且也没有报错。
满脸懵逼。。。。。。。。。。。。。
排查节点一:
脚本也有可执行权限,该用户脚本操作的目录 /var/lib/docker/volumes/7d41b8533d80f314d94baef587594e2c3092fc1bc1befb5b78bf59f61c0b125e/_data/ 的操作权限。依旧不行。
我怎么才能看到错误信息呢?
crontab 配置只是将数据重定向到 /home/zhangll/data-sync/log/upload.log 文件,并没有将重定向错误信息。
在 Linux 系统中,
- /dev/null 表示空设备文件
- 0 表示stdin标准输入
- 1 表示stdout标准输出
- 2 表示stderr标准错误
因此,crontab 做如下配置。
00 00 * * * /home/zhangll/data-sync/upload.sh >> /home/zhangll/data-sync/log/upload.log 2>> /home/zhangll/data-sync/log/upload.log
配置过之后,错误如下:
sudo: sorry, you must have a tty to run sudo
大概意思是: 执行 sudo 命令需要一个终端。
参考: https://www.cnblogs.com/wjoyxt/archive/2004/01/13/6429215.html
方法一: 修改 /etc/sudoers 文件。由于服务器是客户服务器,及时有 sudo 权限,也不能随便修改。
方法二: 创建伪终端来执行命令: setsid head -c
节点二: 脚本修改如下:
#!/bin/bash
# 生成数据库脚本
echo `date` "开始生成数据库脚本"
setsid head -c "sudo docker exec -i pg_test bash -c 'pg_dump -U postgres -t user -d testdatabase > /var/lib/postgresql/data/user.sql'"
setsid head -c "sudo docker exec -i pg_test bash -c 'pg_dump -U postgres -t role -d testdatabase > /var/lib/postgresql/data/role.sql'"
echo `date` "开始生成数据库脚本 -- 成功"
# 将文件上传至 sftp
echo `date` "将文件上传至 sftp"
setsid head -c "sudo lftp sftp://bmwfiles:[email protected]:2222 << EOF"
cd /uploads/synchronized_data
lcd /var/lib/docker/volumes/7d41b8533d80f314d94baef587594e2c3092fc1bc1befb5b78bf59f61c0b125e/_data
put user.sql
put role.sql
bye
EOF
echo `date` "将文件上传至 sftp 成功"
# 删除本地文件
echo `date` "删除生成的 sql 文件"
setsid head -c "sudo rm -f /var/lib/docker/volumes/7d41b8533d80f314d94baef587594e2c3092fc1bc1befb5b78bf59f61c0b125e/_data/user.sql"
setsid head -c "sudo rm -f /var/lib/docker/volumes/7d41b8533d80f314d94baef587594e2c3092fc1bc1befb5b78bf59f61c0b125e/_data/role.sql"
echo `date` "删除生成的 sql 文件 -- 成功"
exit
确实有所进展,生成数据库脚本和删除数据库脚本没问题了,但是上传 sftp 时,报 put 、cd、bye 命令没找到。无奈,又回到到了远点。
节点三:问题解决
sudo 目的时获取 root 权限执行命令,如果使用 root 用户创建 crontab 任务,岂不是不需要加 sudo 了?,终于找到问题突破口,因此脚本修改如下。删除 sudo ,使用 root 用户创建定时任务。
#!/bin/bash
# 生成数据库脚本
echo `date` "开始生成数据库脚本"
docker exec -i pg_test bash -c "pg_dump -U postgres -t user -d testdatabase > /var/lib/postgresql/data/user.sql"
docker exec -i pg_test bash -c "pg_dump -U postgres -t role -d testdatabase > /var/lib/postgresql/data/role.sql"
echo `date` "开始生成数据库脚本 -- 成功"
# 将文件上传至 sftp
echo `date` "将文件上传至 sftp"
lftp sftp://bmwfiles:[email protected]:2222 << EOF
cd /uploads/synchronized_data
lcd /var/lib/docker/volumes/7d41b8533d80f314d94baef587594e2c3092fc1bc1befb5b78bf59f61c0b125e/_data
put audiences.sql
put media_contact_ratio.sql
bye
EOF
echo `date` "将文件上传至 sftp 成功"
# 删除本地文件
echo `date` "删除生成的 sql 文件"
rm -f /var/lib/docker/volumes/7d41b8533d80f314d94baef587594e2c3092fc1bc1befb5b78bf59f61c0b125e/_data/role.sql
rm -f /var/lib/docker/volumes/7d41b8533d80f314d94baef587594e2c3092fc1bc1befb5b78bf59f61c0b125e/_data/users.sql
echo `date` "删除生成的 sql 文件 -- 成功"
exit
至此,问题解决。兜兜转转,以最简单的方式简单的问题。
总结:
1: 度娘不是万能的,遇到问题先思考为什么,不要一味百度。
2: 对 sudo 命令的执行不是很了解