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

Shell脚本并行处理文件异常:部分文件未执行的问题排查与修复

批量Docker并行处理文件脚本异常排查与修复

问题场景

需要批量处理指定文件夹内所有文件,限制最多15个Docker实例并行运行。编写脚本后出现异常:前15个文件正常处理,但后续仅能处理部分剩余文件(比如27个文件只处理了15+6个)。

原脚本代码:

# Path to the folder containing the files
INPUT_FILES_FOLDER="/mnt/data/INPUT"
OUTPUT_FILES_FOLDER="/mnt/data/OUTPUT"

# Path to the Docker image
DOCKER_IMAGE="your_docker_image"

# Number of parallel instances of Docker to run
MAX_PARALLEL=15

# Counter for the number of parallel instances
CURRENT_PARALLEL=0

# Function to process files
process_files() {
    for file in "$INPUT_FILES_FOLDER"/*; do
    input_file=`basename $file` 
    output_file="PROCESSED_${input_file}"

    input_folder_file="/data/INPUT/${input_file}"
    output_folder_file="/data/OUTPUT/${output_file}"

    echo "Input File: $input_file"
    echo "Output File: $output_file"

    echo "Input Folder + File: $input_folder_file"
    echo "Output Folder + File: $output_folder_file"


        # Check if the current number of parallel instances is less than the maximum allowed
        if [ "$CURRENT_PARALLEL" -lt "$MAX_PARALLEL" ]; then
            # Increment the counter for the number of parallel instances
            ((CURRENT_PARALLEL++))
            
            # Run Docker container in the background, passing the file as input
        # docker run hello-world
        docker run --rm -v /mnt/data/:/data my-docker-image:v5.1.0 -i $input_folder_file -o $output_folder_file &
            
            # Print a message indicating the file is being processed
            # echo "Processing $file"
        else
            # If the maximum number of parallel instances is reached, wait for one to finish
            wait -n && ((CURRENT_PARALLEL--))
        fi
    done
    
    # Wait for all remaining Docker instances to finish
    wait
}

# Call the function to process files
process_files

问题根源

核心问题是循环逻辑错误:当CURRENT_PARALLEL达到最大值时,脚本进入else分支执行wait -n && ((CURRENT_PARALLEL--)),但执行完这行后,当前循环迭代的文件并没有被处理——else分支里没有启动Docker容器的代码,这个文件直接被跳过了。

此外还有两个次要问题:

  1. 没有过滤非文件(如子目录),如果INPUT文件夹下有目录,会导致无效的Docker调用
  2. 使用反引号和未加引号的变量,存在文件名含空格时的崩溃风险

修正方案

方案一:修复原脚本逻辑

调整循环内的判断顺序,确保每个文件都会进入处理流程:

# Path to the folder containing the files
INPUT_FILES_FOLDER="/mnt/data/INPUT"
OUTPUT_FILES_FOLDER="/mnt/data/OUTPUT"

# Number of parallel instances of Docker to run
MAX_PARALLEL=15

# Counter for the number of parallel instances
CURRENT_PARALLEL=0

# Function to process files
process_files() {
    for file in "$INPUT_FILES_FOLDER"/*; do
        # 跳过非文件(比如子目录)
        [ -f "$file" ] || continue
        
        input_file=$(basename "$file") 
        output_file="PROCESSED_${input_file}"

        input_folder_file="/data/INPUT/${input_file}"
        output_folder_file="/data/OUTPUT/${output_file}"

        echo "准备处理文件: $input_file"

        # 若并行数已满,等待任意一个进程结束再释放槽位
        if [ "$CURRENT_PARALLEL" -ge "$MAX_PARALLEL" ]; then
            wait -n
            ((CURRENT_PARALLEL--))
        fi

        # 启动当前文件的Docker处理进程
        ((CURRENT_PARALLEL++))
        docker run --rm -v /mnt/data/:/data my-docker-image:v5.1.0 -i "$input_folder_file" -o "$output_folder_file" &
        echo "已启动进程,当前并行数: $CURRENT_PARALLEL"
    done
    
    # 等待所有剩余Docker实例完成
    wait
    echo "所有文件处理完成"
}

# 调用处理函数
process_files

修复要点:

  • 先检查并行数,满则等待释放槽位,之后再启动当前文件的处理,确保每个文件都不会被跳过
  • 增加非文件过滤逻辑,避免无效调用
  • 使用$(basename "$file")替代反引号,给变量加引号,兼容含空格的文件名

方案二:使用xargs简化并行逻辑

xargs原生支持并行数控制,逻辑更简洁可靠,无需手动维护计数器:

INPUT_FILES_FOLDER="/mnt/data/INPUT"
OUTPUT_FILES_FOLDER="/mnt/data/OUTPUT"
MAX_PARALLEL=15

# 定义单个文件的处理函数
process_single_file() {
    file="$1"
    input_file=$(basename "$file")
    output_file="PROCESSED_${input_file}"
    input_path="/data/INPUT/${input_file}"
    output_path="/data/OUTPUT/${output_file}"
    
    echo "处理文件: $input_file"
    docker run --rm -v /mnt/data/:/data my-docker-image:v5.1.0 -i "$input_path" -o "$output_path"
}

# 导出函数,让xargs可以调用
export -f process_single_file

# 遍历INPUT目录下的所有文件,用xargs并行处理
find "$INPUT_FILES_FOLDER" -maxdepth 1 -type f | xargs -I {} -P "$MAX_PARALLEL" bash -c 'process_single_file "$@"' _ {}

优势:

  • xargs -P直接控制并行数,无需手动维护计数器,逻辑不易出错
  • find确保只处理文件,自动跳过目录
  • 自动等待所有进程完成,无需额外wait命令

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 22:24:54