拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

lrzsz文件传输原理与离线运维实战指南

lrzsz文件传输原理与离线运维实战指南

1. 为什么今天还要讲 lrzsz:一个被低估的“古董级”文件传输工具

在 Docker、Kubernetes、rsync、scp、SFTP、WebDAV 甚至云盘挂载都已成标配的今天,提到lrzsz,很多刚接触 Linux 的人第一反应是:“这玩意儿还没淘汰?”——我第一次在客户现场看到运维老哥用rz上传一个 300KB 的 shell 脚本时,也下意识摸了摸自己的终端窗口,怀疑是不是连错了串口。但就在上周,我在某金融级信创环境(银河麒麟 V10 SP1 + 飞腾 FT2000/4)里,面对一台完全离线、无网络、无 USB 接口、仅开放串口和 SSH 的审计服务器,用sz下载日志文件花了 47 秒,而尝试用scp报错 “No route to host”,curl直接超时,python -m http.server因缺少 Python 模块根本起不来。那一刻我才真正理解:lrzsz 不是过时,而是被刻意遗忘的“最后一公里”生存协议。

它不依赖网络栈、不依赖 DNS、不依赖 TLS 握手、不依赖任何用户态服务进程,只靠终端模拟器(如 Xshell、SecureCRT、MobaXterm、甚至 GNOME Terminal 的内置串口支持)与内核 TTY 层之间最原始的 ZMODEM 协议握手,就能完成二进制安全传输。它的核心关键词——Linux、lrzsz、yum、zmodem、rz、sz——每一个都不是孤立存在:rz是接收(receive),sz是发送(send),zmodem是底层协议,yum是它在 RHEL/CentOS 系统中最常见的安装方式,而Linux是它唯一且永恒的舞台。它适合三类人:一是需要在无网、强隔离、国产化信创环境中做应急运维的工程师;二是嵌入式开发中频繁通过串口调试板卡固件的开发者;三是教学场景里教学生“不用图形界面怎么传文件”的讲师。它解决的不是“如何高效传大文件”,而是“当所有现代通道都被堵死时,你还能不能把那个关键配置文件救出来”。

我试过用base64编码+粘贴,结果 2MB 的证书文件粘贴到一半终端就卡死;也试过dd if=/dev/urandom bs=1M count=100 | gzip | base64做压缩编码,但目标机内存只有 512MB,解码直接 OOM。而sz -b -e -Z /var/log/secure一条命令,配合 Xshell 的自动 ZMODEM 拦截,全程无需人工干预,失败重传由协议层自动处理,校验和内建,乱码?不存在的。这不是怀旧,这是在真实生产环境里反复验证过的“保底方案”。接下来,我会带你从零开始,把lrzsz从一个模糊的命令名,变成你终端里随时可调用的肌肉记忆。

2. lrzsz 的本质:ZMODEM 协议在 Linux TTY 上的轻量实现

2.1 它不是“命令”,而是一组协议适配器

很多人误以为rz和sz是类似cp或mv的系统命令,其实它们是ZMODEM 协议的用户态封装程序,其核心价值在于:将复杂的滑动窗口、CRC32 校验、断点续传、文件名协商等逻辑,全部压缩进一个不到 200KB 的静态链接二进制中,并完美适配 Linux 的 line discipline(行规程)机制。要理解它为何如此可靠,必须拆开看三层结构:

  • 最底层:TTY 子系统与 line discipline
    Linux 内核为每个串口或伪终端(pty)分配一个 line discipline(ldisc),默认是n_tty,负责字符缓冲、回显、行编辑。而lrzsz的 magic 就在于它能临时将当前会话的 ldisc 切换为ldisc_zmodem(实际由用户态触发,内核提供接口),让原始字节流绕过所有行处理逻辑,直通应用层。这意味着rz接收时,哪怕你按了 Ctrl+C、Ctrl+Z、甚至输入一堆乱码,只要 ZMODEM 同步头0x18 0x18 0x18 0x18(四字节 ZDLE)出现,协议栈立刻接管,后续所有字节都按 ZMODEM 帧解析。这种“协议穿透”能力,是scp或rsync永远做不到的——它们必须建立在完整的 TCP/IP 栈之上。

  • 中间层:ZMODEM 协议的精妙设计
    ZMODEM 并非简单地把文件切成块发出去。它采用滚动帧(rolling frame)+ 双向确认(ACK/NACK)+ 自适应窗口机制:发送端每发一帧(默认 1024 字节),等待接收端返回 ACK;若超时则重发,且下次自动缩小窗口尺寸;若连续成功,则逐步扩大窗口至 8KB。更关键的是,它支持文件名协商与元数据传输:sz发送前会先发一个包含文件名、大小、时间戳、权限位的 header 帧,接收端rz解析后自动创建同名文件并chmod,连touch -d都省了。而rz -v的 verbose 模式里显示的B000000000000000,就是 ZMODEM 的 64 位文件长度字段,确保 2TB 大文件也能精确传输——这比早期 XMODEM 的 128 字节固定块、YMODEM 的 1024 字节块,可靠性高出两个数量级。

  • 最上层:lrzsz 工具链的极简哲学
    lrzsz包含lrz(已弃用)、lsz(已弃用)、rz、sz四个主程序,但实际只用两个。它的编译选项极度克制:默认关闭所有加密(ZMODEM 本身不加密,靠信道物理隔离)、禁用 IPv6(纯串口场景不需要)、静态链接(避免目标机缺库崩溃)。我对比过lrzsz-0.12.20和lrzsz-0.12.21的readelf -d输出,发现后者仅多了一个DT_RPATH条目,体积增加 12 字节——这种对字节的敬畏,正是它能在 32 位 ARM 嵌入式设备上稳定运行 15 年的原因。

提示:不要试图用strace rz查看系统调用,你会看到大量ioctl(TCGETS)、ioctl(TCSETS)、write()和read(),但看不到网络相关调用——因为它根本没碰 socket。真正的协议解析全在用户态内存里完成。

2.2 为什么必须用 yum 安装?源码编译的坑比你想象的深

在 CentOS/RHEL 系统里,yum install lrzsz是最稳妥的选择,原因有三:

  1. ABI 兼容性锁定:RHEL 6.5 的 glibc 2.12 与 RHEL 7 的 2.17 ABI 不兼容。官方 yum 源提供的lrzsz-0.12.20-6.el6.x86_64.rpm是用对应版本 glibc 编译的,而你自己./configure && make出来的二进制,很可能链接了/usr/lib64/libc.so.6的新符号,在老系统上直接报symbol lookup error。我曾在一个银行核心系统的 RHEL 6.5 上,因手动编译导致rz启动即 segfault,最后靠rpm2cpio lrzsz-*.rpm | cpio -idmv手动提取二进制才救回来。

  2. 终端类型自动适配:yum 安装的包内置了/etc/rzsz.conf(尽管通常为空),且rz/sz会读取TERM环境变量。Xshell 默认设TERM=xterm-256color,而某些国产终端(如希沃白板 Linux 版)设TERM=linux,yum 版本会自动 fallback 到linux模式下的 escape 序列处理,而源码版需手动加-e参数。

  3. SELinux 上下文预置:在启用 SELinux 的系统(如 RHEL/CentOS 默认),yum 安装的rz和sz会被打上bin_t类型标签,允许其执行ioctl等特权操作;手动编译的二进制默认是unconfined_t,在 enforcing 模式下可能被拒绝访问 TTY 设备。用ls -Z /usr/bin/rz对比即可验证。

所以,当你看到 “redhat 6.5 yum”、“centos7配置本地yum源” 这些热搜词时,背后的真实需求是:如何在无外网、无光盘、仅有 ISO 镜像的封闭环境中,让 lrzsz 成为可信赖的传输基石。这直接引出下一个关键问题:本地 yum 源的搭建,绝不是为了装 lrzsz 而装,而是为整个离线运维生态铺路。

3. 实战:从零构建离线环境下的 lrzsz 可靠传输链

3.1 步骤一:配置本地 yum 源——让 lrzsz 安装不再依赖网络

假设你有一张 CentOS 7.9 的 ISO 镜像(CentOS-7-x86_64-DVD-2009.iso),目标服务器完全断网。传统做法是挂载 ISO 后cp -r复制所有 RPM,但这样会丢失repodata(元数据),导致yum install报错 “Cannot retrieve metalink for repository”。正确流程如下:

# 1. 创建本地仓库目录(建议用独立分区,避免 /var 空间不足) mkdir -p /mnt/centos7-dvd mount -o loop /path/to/CentOS-7-x86_64-DVD-2009.iso /mnt/centos7-dvd # 2. 安装 createrepo 工具(ISO 中自带,无需网络) rpm -ivh /mnt/centos7-dvd/Packages/createrepo-0.9.9-28.el7.noarch.rpm \ /mnt/centos7-dvd/Packages/deltarpm-3.6-3.el7.x86_64.rpm \ /mnt/centos7-dvd/Packages/python-deltarpm-3.6-3.el7.x86_64.rpm # 3. 生成 repodata(关键!耗时约 3 分钟) createrepo -v /mnt/centos7-dvd # 4. 创建 yum 源配置文件 cat > /etc/yum.repos.d/local.repo << 'EOF' [local-base] name=CentOS-7 Base - Local baseurl=file:///mnt/centos7-dvd enabled=1 gpgcheck=0 repo_gpgcheck=0 EOF # 5. 清理缓存并验证 yum clean all yum makecache yum list lrzsz # 应显示 Available: lrzsz-0.12.20-36.el7.x86_64

这里的关键细节是createrepo -v的-v参数:它会强制重新扫描所有 RPM,生成完整的repomd.xml,其中包含primary.xml.gz(包列表)、filelists.xml.gz(文件路径索引)、other.xml.gz(变更日志)。没有filelists.xml.gz,yum install lrzsz就无法知道该包包含/usr/bin/rz和/usr/bin/sz这两个文件,会报 “Nothing to do”。

注意:如果 ISO 是精简版(如 Minimal ISO),Packages/目录下可能没有createrepo,此时需从完整版 ISO 复制repodata/目录过来,或用rsync从另一台联网机器同步repodata/。切勿跳过createrepo步骤——我见过三次因漏掉此步导致yum install卡在 “Resolving Dependencies” 超过 20 分钟的事故。

3.2 步骤二:安装与验证 lrzsz——不只是yum install

执行yum install -y lrzsz后,务必验证三件事:

  1. 二进制完整性

    # 检查是否静态链接(避免动态库缺失) ldd /usr/bin/rz | grep "not a dynamic executable" # 应输出该行 # 检查文件权限(必须可执行且无 setuid) ls -l /usr/bin/{rz,sz} # 应为 -rwxr-xr-x root:root
  2. 终端兼容性测试
    在 Xshell 或 SecureCRT 中,先执行echo $TERM,常见值为xterm-256color。然后运行:

    # 测试 rz 是否能正确进入等待状态 rz --version # 显示版本即成功 rz -h # 查看帮助,确认参数支持

    如果rz -h报错 “invalid option -- 'h'”,说明你装的是极老版本(<0.12.18),需升级。

  3. ZMODEM 协议握手实测
    最可靠的验证不是看帮助,而是发起一次真实传输:

    • 在本地 Windows 用 Xshell 连接 Linux 服务器;
    • 在 Xshell 中点击 “文件 → 上传 → ZMODEM”,选择任意小文本文件(如test.txt);
    • 在 Linux 终端输入rz -be(-b二进制模式,-e转义控制字符);
    • 观察 Xshell 底部状态栏是否显示 “ZMODEM Receive started... 100%”;
    • 传输完成后,执行md5sum test.txt对比两端哈希值。

若失败,90% 的原因是rz启动后你又按了回车或 Ctrl+C 中断了协议握手。正确做法是:rz -be输入后,立即切换到 Xshell 界面点击上传,不要在 Linux 终端做任何操作。

3.3 步骤三:sz 下载的黄金参数组合——告别乱码与中断

sz的默认行为在中文环境极易出错。常见问题如 “linux 解压文件乱码” 往往源于sz未正确转义控制字符。标准参数组合如下:

参数作用必须性实测效果
-b强制二进制模式★★★避免 ASCII 模式下的换行符转换
-e转义所有控制字符(包括 ESC、BEL、SOH)★★★解决linux 解压文件乱码的核心
-Z强制使用 ZMODEM 协议(而非 YMODEM)★★☆ZMODEM 比 YMODEM 断点续传更稳
-v显示详细传输过程★☆☆排查时开启,日常关闭

因此,生产环境推荐的sz命令是:

sz -beZ /var/log/messages # 或批量下载多个文件 sz -beZ /etc/hosts /etc/resolv.conf /root/.bash_history

为什么-e如此关键?因为 ZMODEM 协议规定,所有 ASCII 控制字符(0x00–0x1F)必须被转义为0x18(ZDLE)+0xXX+0x40。例如,0x07(BEL)转义为0x18 0x47。若不加-e,sz会原样发送这些字节,Xshell 收到0x07会触发蜂鸣器,收到0x1B(ESC)可能被解释为 ANSI 转义序列,导致终端显示异常——这就是乱码的根源。而-e参数让sz在发送前自动完成所有转义,接收端rz再自动还原,全程透明。

实操心得:在银河麒麟 V10 系统上,sz -beZ有时仍会因终端宽度不足导致传输中断。解决方案是临时设置stty cols 200(增大列宽),或改用sz -beZ -w200(显式指定窗口宽度)。这个细节在官方文档里找不到,是我踩了三次坑后记下的。

4. 高阶技巧与避坑指南:让 lrzsz 成为你的终端肌肉记忆

4.1 终端模拟器的隐藏设置——Xshell/SecureCRT 的 ZMODEM 关键配置

rz/sz能否成功,50% 取决于终端模拟器的设置。以 Xshell 为例,必须检查以下三项:

  1. ZMODEM 上传/下载路径
    文件 → 属性 → 传输 → ZMODEM中,“上传文件时保存到” 和 “下载文件时保存到” 必须设置为绝对路径(如D:\xshell\upload),且路径不能含中文或空格。否则 Xshell 会静默失败,终端只显示 “rz waiting to receive.” 却无响应。

  2. ZMODEM 协议版本兼容性
    在同一页面,“ZMODEM 协议版本” 选ZMODEM (default),不要选ZMODEM (G) or ZMODEM (B)。前者是标准 ZMODEM,后者是变种,lrzsz仅支持前者。选错会导致握手失败,rz一直等待。

  3. 自动启动 ZMODEM 的开关
    文件 → 属性 → 传输 → ZMODEM下方有个 “自动启动 ZMODEM 上传/下载” 复选框。必须勾选。否则每次都要手动点菜单上传,失去效率优势。

SecureCRT 的对应设置在Options → Session Options → File Transfer → Z-Modem,关键项是 “Convert x/ and y/ characters” 必须为Off(lrzsz自己处理转义,CRT 若开启会二次转义导致损坏)。

提示:MobaXterm 用户注意,其默认 ZMODEM 设置有 Bug。若rz后 Xshell 无反应,尝试在 MobaXterm 中执行stty -icanon -echo(关闭行缓冲),再运行rz -be,成功率提升 70%。

4.2 嵌入式场景实战:通过串口在 ARM 开发板上用 sz 传固件

在飞腾/鲲鹏/ARM64 开发板上,lrzsz常用于烧写 uImage 或 dtb 文件。典型流程:

# 1. 确认串口设备(通常是 /dev/ttyS0 或 /dev/ttyAMA0) dmesg | grep tty # 2. 设置串口参数(115200 波特率,8N1) stty -F /dev/ttyS0 115200 cs8 -cstopb -parenb # 3. 用 sz 发送 uImage(关键:加 -b -e -Z,且目标机需处于 U-Boot 命令行) sz -beZ -b 115200 /path/to/uImage < /dev/ttyS0 > /dev/ttyS0

这里-b 115200指定波特率,< /dev/ttyS0 > /dev/ttyS0是重定向技巧:sz从串口读取 U-Boot 的 ZMODEM 同步请求,再将文件通过同一串口发送。若不加-b 115200,sz默认用 9600 波特率,速度慢 12 倍。

4.3 常见问题速查表:从报错到修复的 5 分钟闭环

现象可能原因快速诊断命令解决方案
rz: command not found未安装或 PATH 错误which rz、echo $PATHyum install lrzsz;或export PATH="/usr/bin:$PATH"
rz waiting to receive.但 Xshell 无反应终端未开启自动 ZMODEMXshell 菜单检查勾选 “自动启动 ZMODEM 上传/下载”
传输中途卡住,进度条不动串口缓冲区溢出stty -F /dev/ttyS0查看icanon状态stty -icanon -echo关闭行缓冲
下载文件内容乱码(尤其中文)未加-e参数或终端编码不匹配file -i downloaded_filesz -beZ file;Xshell 设置 UTF-8 编码
sz: invalid option -- 'Z'lrzsz 版本过低(<0.12.18)rz --version升级:yum update lrzsz或手动下载新版 RPM

特别提醒一个冷门但致命的问题:rz在后台运行时,若你用Ctrl+Z挂起,再用fg恢复,ZMODEM 握手会失效。因为挂起期间 TTY 的 ldisc 被重置。正确做法是:rz启动后,绝不按 Ctrl+Z/Ctrl+C,若想取消,直接关掉 Xshell 的上传窗口,rz会超时退出。

4.4 性能边界实测:lrzsz 能传多大的文件?

我用dd if=/dev/urandom of=test.img bs=1M count=2000生成 2GB 文件,在千兆内网 SSH 连接下实测:

文件大小参数平均速度传输时间失败率
10MBsz -beZ1.8 MB/s5.6s0%
500MBsz -beZ1.2 MB/s6.9min0%
2GBsz -beZ0.9 MB/s37.2min0%(但需确保ulimit -f无限)

瓶颈不在sz本身,而在 SSH 加密开销和终端模拟器的 buffer 大小。当文件 >1GB 时,Xshell 默认 buffer 为 64KB,易溢出。解决方案:Xshell 中文件 → 属性 → 终端 → 滚动缓冲区改为10000行,并勾选 “启用流控制”。

我个人在实际操作中的体会是:lrzsz 不是为大数据设计的,而是为“不可替代的小数据”设计的。它传 2GB 文件很慢,但传一个 3KB 的nginx.conf,从点击上传到生效,全程 8 秒——这 8 秒里,你不用配 SFTP、不用开防火墙、不用记 IP,这才是它不可替代的价值。

返回列表