如何编写Makefile实现本地操作后自动在SSH远程VM执行命令?
实现SCP上传+远程Docker命令全自动化的Makefile方案
方法1:直接在SSH命令中串联远程执行逻辑
不用单独建立交互式SSH连接,直接通过ssh命令的参数传递要执行的远程指令,和SCP步骤串联起来即可,整个流程会自动完成无需手动干预。
示例Makefile:
# 配置VM信息 VM_HOST = your-vm-ip VM_USER = vm-username REMOTE_WORKDIR = /opt/app/deploy deploy: # 打包本地构建产物(根据实际文件调整) tar -czf build.tar.gz ./dist ./Dockerfile # 上传压缩包到VM指定目录 scp build.tar.gz $(VM_USER)@$(VM_HOST):$(REMOTE_WORKDIR)/ # 远程执行Docker相关命令 ssh $(VM_USER)@$(VM_HOST) "\ cd $(REMOTE_WORKDIR) && \ # 加载镜像 docker load -i build.tar.gz && \ # 清理旧容器(容器不存在时不中断流程) docker stop flask-app-container || true && \ docker rm flask-app-container || true && \ # 启动新容器 docker run -d --name flask-app-container -p 5000:5000 your-flask-image:latest \ "
关键注意点:
- 用双引号包裹所有远程命令,换行用反斜杠
\保持格式清晰 - 用
&&串联命令,确保前一步成功才执行下一步 - 清理旧容器时加
|| true,避免容器不存在导致整个脚本中断
方法2:上传本地脚本到VM后执行
如果远程执行逻辑复杂,把命令写成单独的Shell脚本会更易维护。
- 本地创建
remote-deploy.sh脚本:
#!/bin/bash set -e # 遇到错误立即退出 WORKDIR="/opt/app/deploy" IMAGE_TAG="your-flask-image:latest" CONTAINER_NAME="flask-app-container" # 进入工作目录 cd $WORKDIR # 加载Docker镜像 docker load -i build.tar.gz # 停止并删除旧容器 docker stop $CONTAINER_NAME || true docker rm $CONTAINER_NAME || true # 启动新容器 docker run -d --name $CONTAINER_NAME -p 5000:5000 $IMAGE_TAG
- 修改Makefile,同时上传压缩包和脚本,然后远程执行:
VM_HOST = your-vm-ip VM_USER = vm-username REMOTE_WORKDIR = /opt/app/deploy deploy: tar -czf build.tar.gz ./dist ./Dockerfile # 同时上传压缩包和脚本 scp build.tar.gz remote-deploy.sh $(VM_USER)@$(VM_HOST):$(REMOTE_WORKDIR)/ # 远程赋予脚本执行权限并运行 ssh $(VM_USER)@$(VM_HOST) "\ chmod +x $(REMOTE_WORKDIR)/remote-deploy.sh && \ $(REMOTE_WORKDIR)/remote-deploy.sh \ "
常见问题处理
需要sudo权限执行Docker:
要么给VM用户添加Docker组(sudo usermod -aG docker $USER,需重新登录生效),要么在SSH命令中添加sudo并配合-t参数分配伪终端:ssh -t $(VM_USER)@$(VM_HOST) "sudo docker load -i build.tar.gz && ..."建议提前配置用户免密sudo,避免脚本执行时需要输入密码。
远程环境变量缺失:
远程非交互式Shell不会加载.bashrc或.profile,如果Docker命令不在默认PATH中,可使用绝对路径(比如/usr/bin/docker),或者在命令前手动加载配置:ssh $(VM_USER)@$(VM_HOST) "source ~/.bashrc && cd $(REMOTE_WORKDIR) && docker load ..."远程目录不存在:
在远程命令开头添加mkdir -p $(REMOTE_WORKDIR)确保目录存在。
内容的提问来源于stack exchange,提问作者charnould
相关产品推荐
相关产品推荐

