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

排查FIFO容量限制:S3对象迁移脚本仅处理7000个任务

环境信息
  • 操作系统:CentOS 7.9
  • Bash版本:GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)

背景

通过Shell脚本(调用curl访问本地MinIO端点)进行S3对象迁移。脚本通过后台进程&启动多个工作进程,使用FIFO作为任务队列,借助flock控制队列读取,完成对象的下载、上传等操作。脚本部分代码如下:

# ...
# 读取参数、显示信息 ...
# 设置锁、FIFO ...
# 定义工作进程执行的job()函数。
#
# ...

# FIFO(任务队列)为文件描述符3
# FIFO锁为文件描述符4


function work () {
  wid=$1  
  # 设置文件描述符和锁
  # ...

  while true; do
    flock 4                          # 获取FIFO锁
    read -r -su 3 job_id obj
    read_status=$?
    flock -u 4                       # 释放FIFO锁
    
    if [[ $read_status -eq 0 ]]; then
      # 若从队列读取到任务,在子进程中执行
    fi
  done
  
  # 清理文件描述符
}

echo "启动工作进程..."
for ((i=1;i<="${WORKERS:-4}";i++)); do
  printf "%s" "_"
  work $i &
done
echo


function append_job() {
  job_id=$1
  target_object=$2
  printf "\r(%d s) 添加任务 [# %s] %.110s\e[K" "$(( $(date +%s) - ts_start ))" "${job_id}" "${target_object}"
  echo "${job_id}" "${target_object}" 1>&3 
}


while read -r obj_name ; do
  append_job $i "${obj_name}"
  i=$((i+1))
done < <(the_function_that_list_all_objects_from_bucket ${TARGET_BUCKET})
echo

遇到的问题

脚本处理对象数少于7000的存储桶时正常,但当存储桶对象超过7000个时,仅能添加恰好7000个任务,工作进程仅迁移7000个对象就结束。

预期结果与初步猜想

脚本应无问题完成全部(超过7000个)迁移任务,初步猜想:

  • 传入while循环的标准输入(<(the_function_that_list_all_objects_from_bucket ${TARGET_BUCKET}))会将所有对象列表存储在内存中,暂时与FIFO无关。
  • 即使FIFO存在最大容量限制,当工作进程从FIFO读取任务后,FIFO容量应会减少,循环可继续添加任务。
  • 即使标准输入非常庞大(如<(gen_huge_result),超过16GB),操作系统会处理,循环仍能运行,仅耗时更长。

已尝试的操作

检查对象列表的长度和大小:

# the_function_that_list_all_objects_from_bucket ${TARGET_BUCKET} | wc -l 
8043

# the_function_that_list_all_objects_from_bucket ${TARGET_BUCKET} | wc -c
434387

通过命令查看管道最大容量:

# cat /proc/sys/fs/pipe-max-size
1048576

8043个对象的迁移理论上不存在问题,还尝试强制减慢任务添加速度,但仍在7000个任务时停止,猜测是任务添加时达到了FIFO的最大容量,但不清楚具体原因。


更新

1. 部分实验

根据建议进行以下实验:

  • 是字节限制还是行数限制?
    将任务参数增加至4倍:
work() {
  # ...
  while true; do
    ## 尝试读取队列
    flock 4                          # 获取FIFO锁
    read -r -su 3 work_id work_item tmp1 tmp2 tmp3 tmp4 tmp5 tmp6 # 读取到work_id和work_item
    read_status=$?                   # 保存read的退出状态
    # ...
}


append_job() {
  # ...
  echo "${work_id}" "$work_item" "${work_id}" "$work_item" "${work_id}" "$work_item" "${work_id}" "$work_item" 1>&3 ## FIFO为文件描述符3
}

结果任务数超过了2000,手动执行CTRL+C终止。如果是行数限制,任务数应在约1750(7000/4)时停止。

  • 是否存在异常任务?
    未发现异常任务,任务执行无标准错误输出,甚至将任务设置为仅执行true,问题仍存在,认为是任务发送环节存在某些限制。

2. 今日无法复现该问题

使用“移动”方式(复制后删除)代替仅“复制”完成了昨日的迁移工作。请求运维团队恢复了迁移开始前的虚拟机快照,再次运行相同脚本,发现任务添加数达到了8043个。推测是重启(恢复镜像)清除了操作系统的某些限制,目前无法复现问题,若再次遇到将尝试相关脚本排查根因。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 19:13:21