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