脚本中SCP传输如何带进度条

wen 实用脚本 2

本文目录导读:

脚本中SCP传输如何带进度条

  1. 方法1:使用 pv 命令(推荐)
  2. 方法2:使用 rsync + 进度条
  3. 方法3:使用 bar 或 dialog 工具
  4. 方法4:使用 expect 脚本(高级)
  5. 方法5:使用 Python 脚本(最灵活)
  6. 安装必要工具
  7. 完整示例脚本
  8. 推荐方案

在 Shell 脚本中使用 SCP 传输并显示进度条,有几种常见方法,以下是完整的解决方案:

方法1:使用 pv 命令(推荐)

pv 是一个专门用于监控数据通过管道的工具,可以显示进度条。

#!/bin/bash
# 定义源文件和目标
SOURCE_FILE="/path/to/large/file.zip"
TARGET_USER="user"
TARGET_HOST="192.168.1.100"
TARGET_PATH="/home/user/"
# 使用 pv 显示进度
pv "$SOURCE_FILE" | ssh "$TARGET_USER@$TARGET_HOST" "cat > $TARGET_PATH$(basename $SOURCE_FILE)"
# 或者使用 scp + pv(需要知道文件大小)
FILE_SIZE=$(stat -c%s "$SOURCE_FILE")
pv -s "$FILE_SIZE" "$SOURCE_FILE" | ssh "$TARGET_USER@$TARGET_HOST" "cat > $TARGET_PATH$(basename $SOURCE_FILE)"

方法2:使用 rsync + 进度条

rsync 原生支持进度条显示:

#!/bin/bash
SOURCE_FILE="/path/to/large/file.zip"
TARGET="user@192.168.1.100:/home/user/"
# 使用 rsync 显示进度
rsync -P --progress "$SOURCE_FILE" "$TARGET"
# 参数说明:
# -P 等同于 --partial --progress
# --progress 显示传输进度

方法3:使用 bar 或 dialog 工具

创建一个自定义进度条函数:

#!/bin/bash
# 自定义进度条函数
show_progress() {
    local current=$1
    local total=$2
    local width=50
    # 计算百分比
    local percent=$((current * 100 / total))
    local completed=$((width * current / total))
    # 构建进度条
    printf "\r["
    for ((i=0; i<width; i++)); do
        if [ $i -lt $completed ]; then
            printf "="
        else
            printf " "
        fi
    done
    printf "] %d%%" $percent
}
# 模拟 SCP 传输(实际使用需要配合 expect 或其他工具)
# 这里仅演示进度条函数
for ((i=0; i<=100; i+=5)); do
    show_progress $i 100
    sleep 0.1
done
echo ""

方法4:使用 expect 脚本(高级)

对于需要完全自动化的场景:

#!/usr/bin/expect -f
set timeout -1
set source "/path/to/file.zip"
set target "user@192.168.1.100:/home/user/"
spawn scp -v "$source" "$target"
expect {
    "password:" {
        send "your_password\r"
        exp_continue
    }
    -re {(\d+)%} {
        set progress $expect_out(1,string)
        send_user "\rProgress: $progress%"
        exp_continue
    }
    eof
}

方法5:使用 Python 脚本(最灵活)

#!/usr/bin/env python3
import subprocess
import sys
import os
def scp_with_progress(source, target, password=None):
    # 获取文件大小
    file_size = os.path.getsize(source)
    # 构建 scp 命令
    cmd = ['scp', '-v', source, target]
    # 启动进程
    process = subprocess.Popen(
        cmd,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        universal_newlines=True
    )
    # 实时读取输出
    while True:
        output = process.stderr.readline()
        if output == '' and process.poll() is not None:
            break
        if output:
            # 解析百分比
            if '%' in output:
                try:
                    percent = output.split('%')[0].strip().split()[-1]
                    # 显示进度条
                    sys.stdout.write(f'\r传输进度: {percent}%')
                    sys.stdout.flush()
                except:
                    pass
    print("\n传输完成!")
# 使用示例
scp_with_progress('/path/to/file.zip', 'user@192.168.1.100:/home/user/')

安装必要工具

# Ubuntu/Debian
sudo apt-get install pv rsync
# CentOS/RHEL
sudo yum install pv rsync
# macOS
brew install pv rsync

完整示例脚本

这是一个完整的带进度条的 SCP 传输脚本:

#!/bin/bash
# 显示帮助信息
usage() {
    echo "用法: $0 <源文件> <目标>"
    echo "示例: $0 /path/to/file.zip user@host:/path/"
    exit 1
}
# 检查参数
if [ $# -ne 2 ]; then
    usage
fi
SOURCE="$1"
TARGET="$2"
# 检查源文件是否存在
if [ ! -f "$SOURCE" ]; then
    echo "错误: 文件 $SOURCE 不存在"
    exit 1
fi
# 获取文件大小
FILE_SIZE=$(stat -c%s "$SOURCE" 2>/dev/null || stat -f%z "$SOURCE" 2>/dev/null)
# 检查 pv 是否安装
if command -v pv &> /dev/null; then
    echo "使用 pv 显示进度条..."
    pv -s "$FILE_SIZE" "$SOURCE" | ssh "${TARGET%%:*}" "cat > ${TARGET#*:}/$(basename $SOURCE)"
elif command -v rsync &> /dev/null; then
    echo "使用 rsync 显示进度条..."
    rsync -P --progress "$SOURCE" "$TARGET"
else
    echo "使用 scp (无进度条)..."
    scp "$SOURCE" "$TARGET"
fi
echo "传输完成!"

推荐方案

  1. 最简单:使用 rsync -Prsync --progress
  2. 最灵活:使用 pv 工具
  3. 最可控:自定义 Python/Expect 脚本

选择哪种方法取决于你的具体需求和系统环境。

抱歉,评论功能暂时关闭!