iterm2的上传下载无法经跳板机使用

~/.ssh/config中配置了如下的跳板机连接,能实现scp -r target:<path> <local-path>scp -r <local-path> target:<path> 正常上传/下载文件和文件夹(测试版本scp/ssh:OpenSSH_8.1p1, LibreSSL 2.7.3)

# 跳板机
Host jumpserver
    Hostname <host-ip/url>
    User <username>
    IdentityFile ~/.ssh/id_rsa
    # 转发密钥
    ForwardAgent yes
    
Host target
    HostName <内网ip>
    User <username>
    IdentityFile ~/.ssh/id_rsa
    ProxyJump jumpserver
    # ProxyJump jumpserver 等价于 ProxyCommand ssh jumpserver -W %h:%p

但是即便在~/.ssh/config中做了如上配置,iterm2(我测试过的version:Build 3.5.10),其自带的下载(cmd+点击)/上传(opt+拖拽)功能,仍不支持经过跳板机连接的服务器,会弹出如下报错

image-20241202000700917

我初步猜测:是因为iterm2用来支持此功能的内置scp版本过老,无法经过跳板机上传/下载。在2018年的某帖子和2021年的某帖子都表示,scp无法用于有跳板机的情况。

注:ssh 、 scp、 sftp 的安装版本都来自于OpenSSH的同一版本,ssh -V即可查看OpenSSH的版本。

法一:scp trigger【推荐】

优点:

  • 在ssh远程终端下就能直接上传/下载文件,方便快捷

  • 依赖少(只需要本地安装iterm2、ssh、scp),该方法无需在服务器和本机上安装其他软件,直接使用本地的scp来传输文件

  • 可以传输文件夹

  • 一次可以上传/下载多个文件/文件夹

  • 传输过程中有error才弹出错误提示,否则弹出成功提示

缺点:

  • 只适合小文件的传输,大文件建议单独开一个终端,使用 rsync/scp 等

安装bash脚本

在服务器上~/.bashrc~/.zshrc中添加如下代码:

# down/up: ssh登陆服务器后,在远程的终端下输入down/up命令,实现下载/上传文件或文件夹
down() {
    local dirs=
    local arg
    for arg in $@; do
        if [ -e $arg ]; then
            local path_arg=$(abspath $arg)
            dirs="$dirs,'\"$path_arg\"'"
        else
            echo not exist: $arg
        fi
    done
    # 去掉dirs字符串开头的'; '
    if [ "${dirs:0:1}" = "," ]; then
        dirs=${dirs:1}
    fi
    if [[ "$dirs" =~ , ]]; then
        dirs="{${dirs}}"
    fi
    if [ "$dirs" != '' ]; then
        echo -e "\033[38;5;8m[\U000026A1RUNCOMMAND\U000026A1]scp -r $USER@`hostname`:$dirs ~/Downloads && osascript -e 'display notification \"Download finished successfully.\" with title \"Download Finished\"'[\U000026A1RUNCOMMANDEND\U000026A1]\033[0m"
    fi
}

up(){
    local dirs=$(printf "'%s' " "$@")
    dirs=${dirs:0:${#dirs}-1}
    echo -e "\033[38;5;8m[\U000026A1RUNCOMMAND\U000026A1]scp -r $dirs $USER@`hostname`:`pwd` && osascript -e 'display notification \"Upload finished successfully.\" with title \"Upload Finished\"'[\U000026A1RUNCOMMANDEND\U000026A1]\033[0m"
}

添加iTerm2 Triggers规则

Preference/Profiles/Advanced/Triggers 添加新规则:

Regular Expression: \[⚡RUNCOMMAND⚡\](.+?)\[⚡RUNCOMMANDEND⚡\]
Action: Run Command
Parameters: \1
Instant: ✓
Enable: ✓

Preference/Advanced/Number of screen lines to match against trigger regular expressions: 设置为10,或者别的较大的数字,它表示Trigger能匹配最多多少行(以当前终端分屏窗口的行计算)。该数字越大,则一次能上传/下载文件就越多、文件路径就越长。

使用

将文件夹/文件从本地上传到服务器:

up  本地路径 [本地路径 [本地路径...]]
  • 本地路径必需是绝对路径,要获得本地绝对路径,可以在Finder中选中文件/文件夹后,cmd+C然后在iterm2中cmd+V,或者直接拖拽到iterm2中

将文件夹/文件从服务器下载到本地:

down 远程路径 [远程路径 [远程路径...]]
  • 远程路径可以是绝对路径、或对于当前位置的相对路径

法二:lszrz【不推荐】

参考

优缺缺点

优点:

  • 在ssh远程终端下就能直接上传/下载文件,方便快捷

缺点:

  • 依赖多:需要本地和服务器都安装了lrzsz

  • sz/rz只能传输文件,不能传输文件夹,文件夹建议压缩后传输

  • rz一次只能上传单个文件

  • sz/rz只适合小文件的传输,大文件建议单独开一个终端,使用 rsync/scp 等

  • sz/rz只有支持 zmodem 协议的软件(如iterm2)才可以使用

  • sz/rz执行完后,不论是否无error,都会触发iterm2的错误通知,还会输出乱码(如下图)

    image-20241202004302133

安装lrzsz

lrzsz 是一个提供 rzsz 命令的工具,用于通过 zmodem 协议进行文件传输。

mac上安装lrzsz

brew install lrzsz

服务器(Linux)上安装lrzsz

# 若有sudo权限
sudo apt install -y lrzsz # 对于基于 Debian 的系统(如 Ubuntu)
sudo yum install lrzsz # 对于基于 Red Hat 的系统(如 CentOS 或 Fedora)
# 若无sudo权限
conda install -c conda-forge lrzsz

从原码安装

wget https://ohse.de/uwe/releases/lrzsz-0.12.20.tar.gz
tar -xvzf lrzsz-0.12.20.tar.gz
cd lrzsz-0.12.20

./configure --prefix=<安装路径> # 比如 /usr/local/lrzsz
make
make install

检查是否安装成功

rz --version
sz --version

创建脚本

然后安装脚本到 $PATH 或者其它目录,并使其可执行。

sudo wget -O /usr/local/bin/iterm2-zmodem https://gist.githubusercontent.com/islishude/716c59c2529cbd87babbb2fdaf49f3ae/raw/e642bbed611fa607335e9a9edf5a1609be3567dd/iterm2-zmodem

sudo chmod +x /usr/local/bin/iterm2-zmodem

添加iTerm2 Triggers规则

设置Iterm2的Tirgger特性,profiles->default->editProfiles->Advanced中的Tirgger配置:

Regular expression: \*\*B0100
Action:             Run Coprocess
Parameters:         /usr/local/bin/iterm2-zmodem sz
instant: true
enable: true

Regular expression: \*\*B00000000000000
Action:             Run Coprocess
Parameters:         /usr/local/bin/iterm2-zmodem rz
instant: true
enable: true

使用方法

参考

在远程服务器运行 rz -be :本地就会弹出窗口要求选择要上传的文件(一次只能选择一个文件,不能选文件夹),选择后即上传

image

在远程服务器运行 sz -be filename1 filename2 … filenameN (都只能是文件、不能是文件夹):本地就会弹出窗口要求保存文件的本地路径,选择后即下载

image

参数:

-+, --append
  将文件内容追加到已存在的同名文件
-a, --ascii
  以文本方式传输
-b, --binary
  以二进制方式传输,推荐使用
--delay-startup N
  等待 N 秒
-e, --escape
  对所有控制字符转义,建议使用
-E, --rename
  已存在同名文件则重命名新上传的文件,以点和数字作为后缀
-p, --protect
  对 ZMODEM 协议有效,如果目标文件已存在则跳过
-q, --quiet
  安静执行,不输出提示信息
-v, --verbose
  输出传输过程中的提示信息
-y, --overwrite
  存在同名文件则替换
-X, --xmodem
  使用 XMODEM 协议
--ymodem
  使用 YMODEM 协议
-Z, --zmodem
  使用 ZMODEM 协议
--version
  显示版本信息
--h, --help
  显示帮助信息