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

如何在并行LTO磁带迁移脚本中记录每个任务的起止时间?

问题描述

正在执行LTO-6到LTO-9的磁带迁移,使用GNU Parallel的sem命令实现2/4台磁带驱动器并行工作。脚本功能正常,但日志记录不符合预期:需要记录每个磁带迁移任务的启动和完成时间,但当前要么只能在循环结束后记录整个批次的完成时间,要么错误地把启动时间当成了结束时间(因为sem后台运行,脚本没等任务完成就写了结束日志)。

期望的日志格式:

>>> STARTED 000123 at 2025-06-14_07:43
!!! FINISHED 000123 at 2025-06-14_12:20
>>> STARTED 000437 at 2025-06-14_07:43
!!! FINISHED 000437 at 2025-06-14_13:05

或

>>> STARTED 000123 at 2025-06-14_07:43
>>> STARTED 000437 at 2025-06-14_07:43
!!! FINISHED 000123 at 2025-06-14_12:20
!!! FINISHED 000437 at 2025-06-14_13:05

当前使用的脚本片段:

function process1() {
   VAR1=( $(cat ${LIST1}) )
   if [[ ${VAR1[@]} ]]; then
      for i in "${VAR1[@]}"; do
         DATE=$(date +%Y-%m-%d_%R)
         echo ">>> STARTED" ${i} at $DATE >> /scratch/Migrate/job1.daily.progress 

         # 磁带转换命令
         sem -j${JOB} --id my_id1 fsmedcopy -T ANTF -s LTO6_Pool_a -v LTO9_Pool_4 -G y -r ${i}

          echo -e "Active tape ${i}"
      done
      sem --wait --id my_id1

      DATE=$(date +%Y-%m-%d_%R)
      echo "!!! FINISHED JOB" ${LIST1} at $DATE >> /scratch/Migrate/job1.daily.progress 
      echo "" >> /scratch/Migrate/job1.daily.progress
   fi
   exit
}

实际得到的错误日志:

>>> STARTED 000123 at 2025-06-14_07:43
>>> STARTED 000437 at 2025-06-14_07:43
!!! FINISHED 000123 at 2025-06-14_07:43
!!! FINISHED 000437 at 2025-06-14_07:43

核心问题:sem后台启动任务,原脚本的结束日志要么是批量写整个批次的时间,要么会立刻执行导致时间与启动时间一致。需要在保留并行的前提下,为每个任务单独记录真实的启动和完成时间。


解决方案

把单条磁带的迁移逻辑(含日志记录)封装成独立函数,让sem直接调用这个函数,这样每个任务的启动/结束日志会在任务实际执行的上下文里生成,时间完全准确。

修改后的脚本:

# 定义单磁带处理函数,包含日志记录
process_tape() {
    local tape_id=$1
    local log_file="/scratch/Migrate/job1.daily.progress"
    
    # 记录启动时间
    local start_time=$(date +%Y-%m-%d_%R)
    echo ">>> STARTED ${tape_id} at ${start_time}" >> "${log_file}"
    
    # 执行磁带迁移命令
    fsmedcopy -T ANTF -s LTO6_Pool_a -v LTO9_Pool_4 -G y -r "${tape_id}"
    
    # 记录完成时间(命令执行完才会走到这一步)
    local finish_time=$(date +%Y-%m-%d_%R)
    echo "!!! FINISHED ${tape_id} at ${finish_time}" >> "${log_file}"
    
    echo -e "Active tape ${tape_id} completed"
}

function process1() {
    # 读取磁带列表,避免原写法的分词问题(比如磁带ID含特殊字符的情况)
    local VAR1=()
    while IFS= read -r line; do
        VAR1+=("$line")
    done < "${LIST1}"
    
    if [[ ${#VAR1[@]} -gt 0 ]]; then
        # 用sem并行调用处理函数,-j指定并行数
        for i in "${VAR1[@]}"; do
            sem -j${JOB} --id my_id1 process_tape "${i}"
        done
        
        # 等待所有并行任务完成
        sem --wait --id my_id1
        
        # 可选:记录整个批次的完成时间
        local batch_finish=$(date +%Y-%m-%d_%R)
        echo "!!! FINISHED BATCH ${LIST1} at ${batch_finish}" >> /scratch/Migrate/job1.daily.progress 
        echo "" >> /scratch/Migrate/job1.daily.progress
    fi
    exit
}

关键改动说明

  • 封装单任务逻辑:把单磁带的日志记录和迁移命令放进process_tape函数,确保启动日志在迁移命令执行前生成,完成日志在命令执行完成后生成,时间完全对应真实任务周期。
  • 修正列表读取方式:用while read读取磁带列表,避免原cat+数组写法在磁带ID含空格/特殊字符时的分词错误。
  • 并行任务调度:sem直接调用封装后的函数,每个函数实例对应一个独立的磁带迁移任务,并行执行的同时保证日志的准确性。
  • 批次日志可选:保留了整个批次的完成日志(如果不需要可以删除),但每个任务的单独日志已经满足需求。

这样修改后,日志会按照任务实际的启动和完成时间生成,完全符合期望的格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 21:19:52