macOS下Postinstall脚本执行docker command not found问题求助
问题分析与解决方案
核心问题原因
- Postinstall脚本的受限环境:macOS安装器(如.pkg)的Postinstall脚本运行在极简环境中,默认
PATH仅包含/usr/bin、/bin等少数系统路径,而Docker的可执行文件通常在/usr/local/bin或Docker app的资源目录中,不在默认PATH里,导致which docker返回空值。 - 变量与语法错误:脚本中
$Home应为大写的$HOME;使用反引号包裹$CheckVar load -i app.tar是错误的,反引号用于捕获命令输出,此处直接执行命令即可。 - Docker安装后未等待启动:Docker完成安装后,daemon不会立即启动,直接执行
docker load会失败。 - 架构不匹配:Apple Silicon芯片使用Intel架构的Docker安装包,会导致安装失败或无法正常运行。
- sudo的环境重置:sudo默认会重置环境变量,即使脚本中设置了PATH,sudo执行时也会丢失。
分步解决方案
1. 明确Docker的绝对路径
在macOS中,Docker的实际路径:
- Intel芯片:
/usr/local/bin/docker - Apple Silicon芯片:
/Applications/Docker.app/Contents/Resources/bin/docker(安装后会自动创建/usr/local/bin/docker的软链接,但Postinstall环境可能无法立即识别)
2. 修复脚本变量与语法
- 将
$Home改为$HOME - 移除命令执行时的反引号,直接使用
sudo "$DOCKER_PATH" load -i app.tar - 使用
sudo -E保留环境变量(如果需要传递PATH)
3. 等待Docker启动
安装Docker后,需要等待Docker daemon启动完成,可以通过循环检查docker info命令的返回值来实现。
4. 区分架构安装对应Docker包
为Apple Silicon芯片准备专门的Docker安装包(如AppleSiliconDocker.dmg),避免架构不兼容。
修改后的脚本
#!/bin/bash # 定义Docker的可能路径,优先检查实际安装位置 DOCKER_PATHS=( "/Applications/Docker.app/Contents/Resources/bin/docker" "/usr/local/bin/docker" ) # 查找可用的Docker路径 DOCKER_PATH="" for path in "${DOCKER_PATHS[@]}"; do if [ -x "$path" ]; then DOCKER_PATH="$path" break fi done # 检查芯片类型 CPU_BRAND=$(sysctl -n machdep.cpu.brand_string) WORK_DIR="$HOME/$DSTROOT/App" if [[ "$CPU_BRAND" == *"Intel"* ]]; then DOCKER_DMG="IntelDocker.dmg" else DOCKER_DMG="AppleSiliconDocker.dmg" fi # 确保工作目录存在 mkdir -p "$WORK_DIR" cd "$WORK_DIR" || exit 1 if [ -n "$DOCKER_PATH" ] && "$DOCKER_PATH" info &>/dev/null; then echo "Mac Chip is ${CPU_BRAND%% *}" echo "Docker found!" echo "Redirected to working dir.." sudo -E "$DOCKER_PATH" load -i app.tar if [ $? -eq 0 ]; then echo "Success" else echo "Failed to load Docker image" exit 1 fi else echo "Mac Chip is ${CPU_BRAND%% *}" echo "Docker not found, installing..." echo "Redirected to working dir.." # 挂载DMG并安装Docker sudo hdiutil attach "$DOCKER_DMG" -quiet sudo /Volumes/Docker/Docker.app/Contents/MacOS/install --accept-license --quiet sudo hdiutil detach /Volumes/Docker -quiet # 等待Docker启动并检查可用性 echo "Waiting for Docker to start..." MAX_WAIT=300 WAIT_COUNT=0 while [ $WAIT_COUNT -lt $MAX_WAIT ]; do # 重新查找Docker路径(安装后可能创建了软链接) for path in "${DOCKER_PATHS[@]}"; do if [ -x "$path" ]; then DOCKER_PATH="$path" break fi done if [ -n "$DOCKER_PATH" ] && "$DOCKER_PATH" info &>/dev/null; then break fi sleep 5 WAIT_COUNT=$((WAIT_COUNT + 5)) done if [ $WAIT_COUNT -ge $MAX_WAIT ]; then echo "Docker failed to start within 5 minutes" exit 1 fi # 加载镜像 sudo -E "$DOCKER_PATH" load -i app.tar if [ $? -eq 0 ]; then echo "Success" else echo "Failed to load Docker image" exit 1 fi fi
额外注意事项
- 确保Postinstall脚本拥有足够的权限,安装包的权限设置正确。
- Docker安装时使用
--accept-license --quiet参数实现静默安装,避免交互。 - 工作目录
$HOME/$DSTROOT/App需要确认$DSTROOT在Postinstall环境中是否正确传递,部分安装器环境中$DSTROOT是目标安装路径,可能需要调整为实际的镜像文件存放路径。
内容的提问来源于stack exchange,提问作者grLearn
相关产品推荐
相关产品推荐

