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

如何用分块实现文件流式传输到tar?SSH备份场景问题求助

问题分析与修复方案

你的核心需求是通过SSH流式备份远程主机内容(含目录和服务逻辑转储),但受限于远程主机磁盘空间,只能通过split分块临时存储转储内容,再交给tar归档后删除临时块。脚本的不稳定源于时序逻辑错误和事件监听不准确,以下是具体修复方案:

故障原因拆解

  1. tar进程挂起:原脚本用close_nowrite触发文件删除,此时tar可能仍在读取已删除的文件(Linux下文件删除后,持有描述符的进程仍可读取),加上FIFO写端关闭时机与tar文件处理的时序冲突,导致tar无法正常接收EOF信号退出。
  2. 0字节文件条目:close_nowrite事件在tee写完文件就触发,此时tar可能还未打开该文件,删除后tar尝试读取不存在的文件,最终生成0字节归档条目。

修复后的脚本

#!/bin/bash
set -euo pipefail

# 创建权限受限的FIFO,避免外部干扰
mkfifo -m 600 filenames

# 启动tar进程,从FIFO读取待归档文件列表,输出到标准输出
tar --files-from filenames -cf - &
TAR_PID=$!

# 打开FIFO的写文件描述符
exec 100>filenames

# 先添加主机级目录/文件到归档列表
echo "/etc" >&100
echo "/root" >&100

# 定义split过滤函数:处理转储分块,确保tar读完后再删除临时文件
splitfilter() {
    local temp_file="$1"
    # 将转储内容写入临时文件
    tee "$temp_file"
    # 强制刷盘,确保内容完全写入磁盘
    sync "$temp_file"
    # 向tar发送当前临时文件名,触发归档
    echo "$temp_file" >&100
    # 等待所有进程(含tar)关闭该文件后再删除
    inotifywait -qq -e close "$temp_file"
    # 删除临时文件
    rm -f "$temp_file"
}

# 导出函数,供split的子shell调用
export -f splitfilter

# 执行服务逻辑转储,分块处理后传入归档流程
dump_program_1 | split -b 4K /var/backup/PREFIX_DUMP_1_ --filter 'splitfilter "$FILE"'
dump_program_2 | split -b 4K /var/backup/PREFIX_DUMP_2_ --filter 'splitfilter "$FILE"'

# 关闭FIFO写端,向tar发送EOF,告知无更多文件需要归档
exec 100>&-

# 等待tar完成所有归档操作
wait $TAR_PID

# 清理FIFO文件
rm -f filenames

关键修复点

  1. 调整事件监听逻辑:用inotifywait -e close替代close_nowrite,只有当所有打开该文件的进程(包括tar)都关闭描述符后,才删除临时文件,彻底避免tar读取不完整或不存在的文件。
  2. 确保文件写入完整性:添加sync命令强制刷盘,避免tar读取到未完全写入磁盘的内容。
  3. 严格模式开启:set -euo pipefail提前捕获脚本中的错误(如变量未定义、命令执行失败),减少隐性问题。
  4. FIFO权限控制:mkfifo -m 600限制FIFO的访问权限,防止外部进程意外写入干扰归档流程。
  5. 变量安全包裹:用引号包裹所有变量,避免文件名含特殊字符时出现解析错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 03:37:55