crontab命令定时同步shell,并在shell中执行docker-compose命令
背景
领导要求每天下班前同步开发环境到测试环境,这时我就想到了使用shell脚本,使用crontab 表达式进行定时同步 ,无需人工每天执行。
编写shell脚本
刚开始在网上查资料,因为需要使用spc进行远程复制,需要自动输入密码。此时需要检查是否安装了expect
# rpm -ql expect
如果没有安装,则使用yum命令安装一下
# yum install expect -y
安装好之后,思考自己的脚本该怎么写,如果不熟练,可以把每步操作先手动在linux上执行下。
我的脚本如下,其中使用expect自动输入密码是在网上参考的
#!/bin/sh
# 创建日志目录
mkdir -p /app/log
logDir=/app/log/
cd /app/log
logName=`date '+%Y%m%d'`
# 定时同步12环境,并启动当前环境gaea
# 使用cron表达式定时同步
# 先复制nginx配置
cd /app/gaea/nginx/conf.d
cp -p -f gaea-admin.conf /app/
cp -p -f gaea-portal.conf /app/
# 先停止当前环境的gaea容器
docker stop $(docker ps -a | grep "gaea-" |awk '{print$1}')
echo $(date "+%Y-%m-%d %H:%M:%S") +" docker stop gaea container" >> $logDir$logName.log
# 休眠5s
sleep 5s
# 再停止所有gaea容器
docker rm $(docker ps -a | grep "gaea-" |awk '{print$1}')
echo $(date "+%Y-%m-%d %H:%M:%S") +" docker rm gaea container" >> $logDir$logName.log
# 休眠5s
sleep 5s
# 删除/app目录下的gaea目录
rm -rf /app/gaea
echo $(date "+%Y-%m-%d %H:%M:%S") +" rm gaea directory" >> $logDir$logName.log
# 休眠5s
sleep 3s
rm -rf /app/portal
echo $(date "+%Y-%m-%d %H:%M:%S") +" rm portal directory" >> $logDir$logName.log
# 休眠5s
sleep 3s
# 复制12上的gaea到14的/app/目录下
expect -c "
set timeout 1200; ##设置拷贝的时间,根据目录大小决定,我这里是1200秒。
spawn /usr/bin/scp -r root@ip:/app/gaea /app/
expect {
\"*yes/no*\" {send \"yes\r\"; exp_continue}
\"*password*\" {send \"123456\r\";} ##远程IP的密码。
}
expect eof;"
# 休眠5s
sleep 5s
expect -c "
set timeout 1200; ##设置拷贝的时间,根据目录大小决定,我这里是1200秒。
spawn /usr/bin/scp -r root@ip:/app/portal /app/
expect {
\"*yes/no*\" {send \"yes\r\"; exp_continue}
\"*password*\" {send \"123456\r\";} ##远程IP的密码。
}
expect eof;"
# 休眠5s
sleep 5s
echo $(date "+%Y-%m-%d %H:%M:%S") +" copy gaea and portal directory to /app/" >> $logDir$logName.log
# 先启动gaea
cd /app/gaea
# 先启动admin的基础环境 使用全路径,可以让crontab 也能执行成功
docker-compose -p gaea -f docker-compose-base.yml up -d
# 休眠5s
sleep 5s
echo $(date "+%Y-%m-%d %H:%M:%S") +" start gaea base container" >> $logDir$logName.log
# 再启动admin的应用
docker-compose -p admin -f docker-compose.yml up -d
# 休眠5s
sleep 5s
echo $(date "+%Y-%m-%d %H:%M:%S") +" start gaea admin container" >> $logDir$logName.log
# 再启动portal
cd /app/portal/
# 休眠5s
sleep 5s
docker-compose -p portal -f docker-compose.yml up -d
echo $(date "+%Y-%m-%d %H:%M:%S") +" start gaea portal container" >> $logDir$logName.log
# 重新设置nginx内容
cp -f -p /app/*.conf /app/gaea/nginx/conf.d
# 需要重启下admin的nginx
docker start gaea-nginx
echo $(date "+%Y-%m-%d %H:%M:%S") +" start gaea-nginx" >> $logDir$logName.log
以上shell脚本命名为copy.sh,上传到/app目录下,修改权限
# chmod +x /app/copy.sh
再来设置定时任务
# crontab -e
39 20 * * * /app/copy.sh
关于crontab的命令大家可以自行百度,我这里设置是每天晚上8:39分执行app目录下的copy脚本。
出现的问题
但是执行完成后,日志也看到有打印,可用docker ps -a 查看容器,并没有起来一个与gaea相关的容器,但是之前的gaea容器全都删了。在使用crontab执行整个shell之前,我使用过bash 命令行执行copy.sh是正常的,可以使用docker-compose把服务启动。由此猜测是crontab并没有执行docker-compose命令。
解决办法
于是又在网上找资料,终于找到原因了。因为crontab执行命令是需要使用绝对路径的,而docker-compse命令的绝对路径是/usr/local/bin/docker-compose。因此,我们只需要在copy.sh中的docker-compose前面加上/usr/local/bin/。重新上传并修改权限即可。可以重新设置定时时间测试效果。最后可以看到所有容器全部起来,页面也能正常访问。
#!/bin/sh
# 创建日志目录
mkdir -p /app/log
logDir=/app/log/
cd /app/log
logName=`date '+%Y%m%d'`
# 定时同步12环境,并启动当前环境gaea
# 使用cron表达式定时同步
# 先复制nginx配置
cd /app/gaea/nginx/conf.d
cp -p -f gaea-admin.conf /app/
cp -p -f gaea-portal.conf /app/
# 先停止当前环境的gaea容器
docker stop $(docker ps -a | grep "gaea-" |awk '{print$1}')
echo $(date "+%Y-%m-%d %H:%M:%S") +" docker stop gaea container" >> $logDir$logName.log
# 休眠5s
sleep 5s
# 再停止所有gaea容器
docker rm $(docker ps -a | grep "gaea-" |awk '{print$1}')
echo $(date "+%Y-%m-%d %H:%M:%S") +" docker rm gaea container" >> $logDir$logName.log
# 休眠5s
sleep 5s
# 删除/app目录下的gaea目录
rm -rf /app/gaea
echo $(date "+%Y-%m-%d %H:%M:%S") +" rm gaea directory" >> $logDir$logName.log
# 休眠5s
sleep 3s
rm -rf /app/portal
echo $(date "+%Y-%m-%d %H:%M:%S") +" rm portal directory" >> $logDir$logName.log
# 休眠5s
sleep 3s
# 复制12上的gaea到14的/app/目录下
expect -c "
set timeout 1200; ##设置拷贝的时间,根据目录大小决定,我这里是1200秒。
spawn /usr/bin/scp -r root@ip:/app/gaea /app/
expect {
\"*yes/no*\" {send \"yes\r\"; exp_continue}
\"*password*\" {send \"123456\r\";} ##远程IP的密码。
}
expect eof;"
# 休眠5s
sleep 5s
expect -c "
set timeout 1200; ##设置拷贝的时间,根据目录大小决定,我这里是1200秒。
spawn /usr/bin/scp -r root@ip:/app/portal /app/
expect {
\"*yes/no*\" {send \"yes\r\"; exp_continue}
\"*password*\" {send \"123456\r\";} ##远程IP的密码。
}
expect eof;"
# 休眠5s
sleep 5s
echo $(date "+%Y-%m-%d %H:%M:%S") +" copy gaea and portal directory to /app/" >> $logDir$logName.log
# 先启动gaea
cd /app/gaea
# 先启动admin的基础环境 使用全路径,可以让crontab 也能执行成功
/usr/local/bin/docker-compose -p gaea -f docker-compose-base.yml up -d
# 休眠5s
sleep 5s
echo $(date "+%Y-%m-%d %H:%M:%S") +" start gaea base container" >> $logDir$logName.log
# 再启动admin的应用
/usr/local/bin/docker-compose -p admin -f docker-compose.yml up -d
# 休眠5s
sleep 5s
echo $(date "+%Y-%m-%d %H:%M:%S") +" start gaea admin container" >> $logDir$logName.log
# 再启动portal
cd /app/portal/
# 休眠5s
sleep 5s
/usr/local/bin/docker-compose -p portal -f docker-compose.yml up -d
echo $(date "+%Y-%m-%d %H:%M:%S") +" start gaea portal container" >> $logDir$logName.log
# 重新设置nginx内容
cp -f -p /app/*.conf /app/gaea/nginx/conf.d
# 需要重启下admin的nginx
docker start gaea-nginx
echo $(date "+%Y-%m-%d %H:%M:%S") +" start gaea-nginx" >> $logDir$logName.log