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

Bash脚本中wait命令未生效的原因及修复方案

问题原因

核心问题是管道中的while read会创建子shell,你在while循环里向PIDS数组添加PID的操作仅在子shell中生效,父shell无法获取到更新后的PIDS值。这导致后续的wait循环遍历的是空数组,直接跳过等待步骤,脚本立刻进入sleep 10后重复执行,看起来就像wait完全没生效。

修复方案

解决关键是让while read在当前shell环境中执行,避免子shell隔离变量,最常用的方法是用进程替换替代管道。

修改后的完整脚本
#!/bin/bash

# GitHub repository details
REPO="RiceKX/Hydra"            # Format: owner/repo, e.g., "octocat/Hello-World"
BRANCH="development"           # The branch you want to check for the latest build
GITHUB_TOKEN="${GITHUB_TOKEN:-$(cat /path/to/your/token)}"  # GitHub token with necessary permissions
GITHUB_API="https://api.github.com"
ARTIFACTS_DIR="latest_dev_build"    # Directory to store downloaded artifacts

# Ensure the artifacts directory exists
mkdir -p "$ARTIFACTS_DIR"

# Run the script in an infinite loop
while true; do
    # Check if repository, branch, and GitHub token are provided
    if [ -z "$REPO" ] || [ -z "$BRANCH" ] || [ -z "$GITHUB_TOKEN" ]; then
      echo "Please set the repository, branch, and GitHub token in the script."
      exit 1
    fi

    # Step 1: Fetch the latest successful run for the specified branch
    echo "Fetching the latest successful build for branch '$BRANCH'..."

    RUN_ID=$(curl -s \
      -H "Authorization: token $GITHUB_TOKEN" \
      "$GITHUB_API/repos/$REPO/actions/runs?branch=$BRANCH&status=success&per_page=1" | \
      jq -r '.workflow_runs[0].id')

    if [ "$RUN_ID" == "null" ] || [ -z "$RUN_ID" ]; then
      echo "No successful builds found for branch '$BRANCH'."
      exit 1
    fi

    echo "Latest successful run ID: $RUN_ID"

    # Step 2: Fetch the artifacts associated with this run
    echo "Fetching artifacts for the latest run..."

    ARTIFACTS=$(curl -s \
      -H "Authorization: token $GITHUB_TOKEN" \
      "$GITHUB_API/repos/$REPO/actions/runs/$RUN_ID/artifacts")

    # Check if we successfully got the artifacts
    if [ -z "$ARTIFACTS" ] || [ "$(echo "$ARTIFACTS" | jq '.artifacts | length')" -eq 0 ]; then
      echo "No artifacts found for this run."
      exit 1
    fi

    # Step 3: Extract artifact details and download them in parallel
    PIDS=()  # Store background process PIDs to wait for them later
    # 使用进程替换替代管道,避免子shell隔离变量
    while read ARTIFACT_NAME ARTIFACT_DOWNLOAD_URL ARTIFACT_DIGEST; do
        if [ -z "$ARTIFACT_NAME" ] || [ -z "$ARTIFACT_DOWNLOAD_URL" ] || [ -z "$ARTIFACT_DIGEST" ]; then
          echo "Error: Artifact name, download URL, or digest missing for artifact."
          continue
        fi

        ARTIFACT_PATH="$ARTIFACTS_DIR/$ARTIFACT_NAME.zip"

        # Check if the artifact already exists
        if [ -f "$ARTIFACT_PATH" ]; then
            # Calculate the local digest of the downloaded artifact
            LOCAL_DIGEST=$(sha256sum "$ARTIFACT_PATH" | cut -d' ' -f1)

            # If the local digest matches the GitHub digest, skip downloading
            if [ "$LOCAL_DIGEST" == "$ARTIFACT_DIGEST" ]; then
                echo "Artifact $ARTIFACT_NAME is already up to date (digest matches), skipping download."
                continue
            else
                echo "Artifact $ARTIFACT_NAME exists but the digest does not match. Re-downloading..."
            fi
        fi

        # Download and extract each artifact in parallel
        (
            echo "Downloading and extracting artifact: $ARTIFACT_NAME from $ARTIFACT_DOWNLOAD_URL"

            curl -L -o "$ARTIFACT_PATH" \
              -H "Authorization: token $GITHUB_TOKEN" \
              "$ARTIFACT_DOWNLOAD_URL"
            
            if [ $? -eq 0 ]; then
                echo "Artifact $ARTIFACT_NAME downloaded successfully."

                # Extract the downloaded artifact
                unzip -o "$ARTIFACT_PATH" -d "$HOME"
                echo "Artifact $ARTIFACT_NAME extracted to $HOME."
            else
                echo "Failed to download $ARTIFACT_NAME."
            fi
        ) &  # Run this process in the background

        PIDS+=($!)
    done < <(echo "$ARTIFACTS" | jq -r '.artifacts[] | "\(.name) \(.archive_download_url) \(.digest)"')

    # Wait for all background processes to finish before continuing
    echo "Waiting for background processes to finish..."
    for PID in "${PIDS[@]}"; do
        wait "$PID"
    done

    echo "All artifacts downloaded and extracted successfully."

    # Sleep for 10 seconds before running the script again
    echo "Waiting for 10 seconds before checking again..."
    sleep 10
done
额外优化提示
  • 可以在wait后检查每个进程的退出状态,确保下载和提取操作都执行成功
  • 若需要持久化日志,可将关键输出定向到日志文件,方便后续排查问题

内容的提问来源于stack exchange,提问作者Kris Rice

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 05:10:53