You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker容器执行含SSH的bash脚本后异常锁定问题求助

问题描述

在Windows本地运行的Docker容器用于Web应用开发测试,此前状态稳定。近期在容器内执行含SSH操作的自定义部署脚本deployment.sh后,容器出现异常:

  • 无法访问本地Web应用
  • 无法运行其他脚本
  • 重启容器时报错:Cannot restart container exampleWebapp: tried to kill container, but did not receive an exit event
  • 执行exit、停止/重建容器均无效,仅重启Docker引擎(99%情况恢复,偶尔失效)可临时解决,严重影响工作流程

该脚本在Apache服务器运行正常,仅在Docker Unix虚拟机环境中出现问题,脚本核心片段如下:

for target in $targets; do 
   rsync *checks differences between target and local*
   read -p "Deploying to $target on $server. Continue with Sync? " -n 1 -r
   if [[ $REPLY =~ ^[Yy]$ ]]; then
      rsync *commands to clone my changed webapp content and exclude desired files*
   else 
      exit 
   fi
done
可能的原因分析
  • 脚本exit命令终止容器主进程:Docker容器生命周期绑定主进程,若通过docker exec执行脚本时触发exit,且容器主进程为bash(或脚本意外继承主进程PID),会直接终止主进程导致容器僵死。
  • 资源耗尽导致WSL2虚拟机无响应:Docker Desktop依赖WSL2虚拟机,rsync同步大量文件时若占用过高CPU、内存或磁盘IO,会导致虚拟机进程无响应,Docker无法正常控制容器。
  • SSH连接未关闭引发资源泄漏:脚本中的SSH操作若未正确关闭连接,会残留僵尸进程或打开的文件描述符,耗尽容器内资源,导致容器无法响应。
  • 交互式read的终端异常:docker exec执行带read的脚本时,可能因TTY缺失、信号处理异常导致进程挂起,引发容器状态异常。
解决与恢复方案

临时恢复容器(无需重启Docker引擎)

  1. 执行docker inspect exampleWebapp获取容器的PID信息
  2. 在Windows命令行中运行wsl --exec kill -9 <容器PID>(针对WSL2后端),强制终止容器进程
  3. 之后即可正常执行docker rm exampleWebapp并重建容器

脚本与流程修复(根源解决)

  1. 避免终止容器主进程
    将脚本中的exit改为break,仅退出循环而非终止整个会话:

    for target in $targets; do 
       rsync *checks differences between target and local*
       read -p "Deploying to $target on $server. Continue with Sync? " -n 1 -r
       if [[ $REPLY =~ ^[Yy]$ ]]; then
          rsync *commands to clone my changed webapp content and exclude desired files*
       else 
          break  # 退出循环而非终止进程
       fi
    done
    
  2. 优化交互式执行
    执行docker exec时添加-it参数确保终端交互正常:

    docker exec -it exampleWebapp ./deployment.sh
    

    也可新增--force参数跳过确认,实现非交互式运行:

    force_sync=false
    if [[ "$1" == "--force" ]]; then
       force_sync=true
    fi
    
    for target in $targets; do 
       rsync *checks differences between target and local*
       if $force_sync || (read -p "Deploying to $target on $server. Continue with Sync? " -n 1 -r && [[ $REPLY =~ ^[Yy]$ ]]); then
          rsync *commands to clone my changed webapp content and exclude desired files*
       else 
          break
       fi
    done
    
  3. 优化rsync/SSH操作

    • rsync添加--partial参数避免传输中断残留临时文件
    • SSH连接添加超时参数:ssh -o ConnectTimeout=10 -o ServerAliveInterval=5,防止连接挂起
    • 用--bwlimit=1000限制rsync带宽(单位KB/s),避免耗尽WSL2资源
  4. 分离部署脚本与应用容器
    单独创建临时部署容器,挂载应用代码和SSH密钥,执行完成后销毁:

    docker run --rm -v /path/to/local/app:/app -v ~/.ssh:/root/.ssh alpine:latest sh -c "cd /app && ./deployment.sh"
    

内容的提问来源于stack exchange,提问作者Powermaster Prime

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 01:13:39