UUCP 这套东西在 Linux 上属于活化石级别:命令还躺在/usr/bin里,man 手册也还能翻出来,但真让人说清楚 Linux uuto 命令和 uucp 到底差在哪,十个人里九个会卡壳。它要解决的问题其实特别朴素——把本机的文件传送到远端的 UUCP 主机上某个用户手里,而且不需要你知道对方家目录长什么样、权限怎么配、文件该落到哪个路径。早年没有 ssh、没有 scp、没有 rsync 的年代,跨机交换文件基本靠 UUCP 这一套,uuto 就是其中最"面向人"的那条命令。今天还会碰它的人大致三类:维护老工业设备或者老 Unix 小型机的运维、啃 Linux 常用命令大全和面试题的备考党、以及想搞明白"邮件和新闻组时代文件是怎么在机器之间跑的"这种底层问题的技术爱好者。这篇就把 uuto 从历史定位、环境准备、语法细节、完整的收发流程,一直到踩坑排查,按我实际折腾一遍的顺序讲透,能照着复现。
1. uuto 到底是什么:从 UUCP 的历史到今天的定位
UUCP 全称 Unix-to-Unix Copy,最早是贝尔实验室在上世纪七十年代末搞出来的一套机器间通信机制,它不只是传文件,还能在远端执行命令。整个套件里,uucp负责复制、uux负责远端执行、uucico是真正的传输守护、uuxqt负责在远端执行收到的请求,而uuto和uupick是一对,专门服务于"我发给你"这个场景。理解这一点非常关键:uuto 不是一条独立的传输协议实现,它本质上是 uucp 的外壳,帮你把文件放到远端的公共接收区,剩下的交给对方用 uupick 自己取。
1.1 一句话说清 uuto 和 uucp 的区别
uucp的目标是一个路径,写法是uucp 文件 远端主机!远端路径,你得知道对方机器上目录在哪、有没有写权限、uucp 用户能不能以你的身份写进去。uuto的目标是一个人,写法是uuto 文件 远端主机!用户名,你不需要知道路径,远端那一侧由 uupick 来完成最后一步落盘。举个生活化的例子:uucp 像是你自己上门把包裹塞进对方家门口,得先摸清门牌号还得保证门没锁;uuto 像是寄到小区快递柜,收件人收到通知后自己挑时间取件,双方都省心。这也是为什么很多人第一次看到 uuto 会觉得"这命令怎么这么简单"——因为它把复杂度推给了接收端。
1.2 为什么设计成"投递到用户"而不是"直接投递到路径"
这个设计选择背后是七十年代末的现实约束。当年机器之间是通过电话拨号加串口连接的,链路慢、费用高、随时可能断,而且不同站点归属于不同组织,权限管理非常粗糙。如果允许任意站点直接往别人家目录写文件,就意味着 uucp 这个运行账号必须在远端具备 impersonation 能力,能随意切换用户身份,这在多租户或者半开放的环境里完全不可接受。所以 uuto 的做法是"两段式投递":先把文件放到一个所有站点都能写、但权限被严格限制的公共目录,通常是/var/spool/uucppublic/receive/<用户名>/<来源主机>/,接收方再用 uupick 从公共区把文件搬进自己的目录。这样一来,发送端能做的只有"往信箱里塞信",接收端自己决定什么时候、以什么身份、把信拿到哪儿去,责任边界非常清楚。
1.3 uuto 今天还能在哪些场景派上用场
说实话,新建项目里用 uuto 是没道理的,scp、rsync over ssh、sftp 哪一个都比它强。但有几类现实场景绕不开它:一是老产线上的工控机或者嵌入式设备,系统还是老 Unix 或者早年定制的 Linux,上面只有 UUCP 套件,运维得靠它把日志和报表传出来;二是教学与考试环境,Linux 常用命令大全、面试题库里偶尔会考到这套命令族,你至少要知道它是干什么的、和 uucp 怎么区分;三是技术考古,想真正理解 Usenet 新闻组、UUCP 邮件网关那套东西是怎么运转的,亲手跑一遍 uuto 比看十篇文章都管用。下面所有的实操,我都会按"两台 Linux 通过 TCP 互联"来做,毕竟拨号猫和串口线现在不好找了。
2. 环境准备:把 UUCP 套件装起来并跑通基本链路
UUCP 在主流发行版仓库里几乎都还在,包名通常就叫uucp,内容来自 Taylor UUCP 这个维护得比较久的实现。GNU inetutils 里其实也带了一套 uucp 组件,但发行版一般不会两套同时装,避免二进制冲突。装之前建议先确认一下系统里有没有残留配置,尤其是/etc/uucp/这个目录,很多老镜像里是预置过的,直接覆盖可能把原有站点定义搞丢。
2.1 安装与版本确认
按发行版选命令,装完之后一定要确认二进制到底来自哪个实现,因为不同实现的选项会有差异:
# Debian / Ubuntu 系 apt-get update && apt-get install -y uucp # RHEL / CentOS 系,可能需要先启用额外仓库 yum install -y uucp # openSUSE zypper install uucp # 装完先看看到底有哪些命令进来了 dpkg -L uucp | grep -E 'bin|sbin' # Debian 系 rpm -ql uucp | grep -E 'bin|sbin' # RHEL 系 # 确认版本与手册可用 uuto --version man uuto | head -40装包的过程本身会创建一些东西,这些是后面能不能跑通的基础:系统里会多出uucp用户和uucp用户组,这个账号就是所有传输动作的运行身份;会创建/var/spool/uucp/作为队列工作区;还会创建/var/spool/uucppublic/作为公共收发区。有些发行版还会往 cron 里塞一条定时任务,周期性地拉起uucico处理积压队列,装完最好看一眼crontab -l -u uucp或者/etc/cron.d/uucp里有没有东西,避免后面手工调试时和定时任务互相干扰。
2.2 关键目录与账号,先摸清家底
上手之前花两分钟把这几个路径和账号搞清楚,能省掉后面一大半的排查时间:
| 路径 | 作用 | 常见权限 |
|---|---|---|
/etc/uucp/ | 主配置目录(Taylor UUCP 下含 config、sys、port、dial、passwd、call) | 0644,部分文件 0600 |
/usr/lib/uucp/ | 老版本配置位置,部分实现仍然读这里 | 0644 |
/var/spool/uucp/ | 队列与工作目录,临时文件、状态、日志都在里面 | 属主 uucp:uucp,0775 |
/var/spool/uucppublic/ | 公共目录,uuto 落文件的根 | 通常 0777 或 1777 |
/var/spool/uucp/.Log/ | 分系统、分类型的日志目录 | 属主 uucp:uucp |
/var/spool/uucp/.Status/ | 每个远端站点的通信状态记录 | 属主 uucp:uucp |
关于 uucp 这个账号,有个细节值得说:它的登录 shell 在不同发行版上可能是/usr/sbin/uucico、/bin/false或者/bin/bash。如果是uucico,说明这台机器允许别人拨进来做被动接收;如果是false,那它纯粹是个服务账号,只用于本地文件属主。你要做接收端测试的话,得确认这个 shell 配置和你的场景匹配,不然远端连上来会被直接踢掉。
2.3 最小可用配置:两台机器通过 TCP 互联
拨号时代过去了,现在最省事的做法是让 UUCP 走 TCP。Taylor UUCP 支持把 port 类型定义成tcp,协议用t,默认端口就是/etc/services里的uucp 540/tcp。下面这套配置我按"发送端 mynode(192.168.1.10)向接收端 remote(192.168.1.50)投递"来写,两边都要配。
发送端mynode的/etc/uucp/config:
# 本机在 UUCP 网络里的节点名,必须全局唯一 nodename mynode # 队列与工作目录 spool /var/spool/uucp # 调试级别,初期建议留 abnormal,排查时临时调高 debug abnormal发送端mynode的/etc/uucp/sys,描述"怎么连 remote":
system remote # 对方要求我们提供的登录名和口令,星号表示不限 call-login * call-password * # 允许通信的时间段,any 表示全天 time any # 使用名为 tcp 的 port 定义 port tcp # 使用 t 协议,适合 8 位干净链路 protocol t # 对方的地址 address 192.168.1.50发送端mynode的/etc/uucp/port,定义一条 TCP 链路:
port tcp type tcp # 服务名或端口号,对应 /etc/services 中的 uucp 540/tcp service 540接收端remote的/etc/uucp/config里把nodename改成remote,然后在/etc/uucp/sys里加一段表示"接受 mynode 的连接",再配一份相同的 port 定义,最后用监听模式把服务拉起来:
# 接收端启动监听,-l 表示 listen,前台运行便于观察 uucico -l # 只想临时跑一轮、处理完就退出,可以加 -x 提高调试级别 uucico -l -x 5注意:上面这些字段是基于 Taylor UUCP 的常见写法整理的示意配置,不同实现、不同发行版打包时的默认值会有出入,落盘前一定用
man uucp、man uucico对照一遍字段名,别直接复制到生产环境。
两边配置确认没问题后,先在发送端手工触发一次连接测试,不要急着发文件。uucico -s remote -x 5会尝试主动呼叫 remote,屏幕上会打印出完整的握手过程。看到类似"call complete""login successful"的日志再往下走,否则后面所有 uuto 都会静静地失败,你还以为是文件的问题。
3. uuto 命令语法与参数逐条拆解
uuto 的语法短得有点不真实,但它背后牵扯的东西不少。先把格式记住,再看每个参数为什么存在,最后搞明白你的文件在本地 spool 里经历了什么。
3.1 语法格式与地址写法
uuto [选项] 源文件... 远端用户这里的"远端用户"写法有几种变形,直接决定了文件会落到哪台机器的哪个收件箱:
主机名!用户名:最常见的形式,例如remote!zhangsan,表示投递到 remote 这台机器上 zhangsan 的公共接收区。中继主机!目标主机!用户名:UUCP 时代大量站点并非直连,需要经过中间节点转发,感叹号可以串联多级,例如gateway!remote!zhangsan。中间每一跳都得在各自的sys文件里有定义,否则队列会卡住一直重试。- 只写
用户名:不指定主机时,命令会按当前节点配置去解析,实际使用中很容易踩坑,建议永远把主机名写全。
几个真实可用的例子:
# 发送单个文件给 remote 主机上的 zhangsan uuto ./report.pdf remote!zhangsan # 一次发多个文件,接收端会逐个出现在 uupick 列表里 uuto ./a.log ./b.log ./c.log remote!ops # 传输完成后给自己发一封邮件通知 uuto -m ./monthly.csv remote!zhangsan # 先把源文件复制到 spool 再排队,源文件后续可以被安全删除 uuto -p ./snapshot.tar remote!backup3.2 常用选项与适用场景
uuto 的选项不多,但每一个都对应一个实际痛点,用错了要么传不过去,要么传过去之后对方一脸茫然。
| 选项 | 作用 | 什么时候用 |
|---|---|---|
-p | 传输前先把源文件复制到本地 spool 目录 | 源文件放在会被清理的临时目录,或者你希望发完立刻能删源文件 |
-m | 传输完成后给发送方发邮件通知 | 批量投递、无人值守场景,靠邮件确认结果 |
-n 用户 | 在远端额外通知指定用户 | 收件人平时不收信,需要提醒另一个人去 uupick |
-x 级别 | 设置调试输出级别,数值越大越啰嗦 | 排查连接、权限、路径类问题时临时打开 |
关于-p有个常见误解值得说清楚:很多人以为不加-p就是"直接流式传输不落盘",其实不是。uuto 无论如何都会在本地 spool 里建工作文件,区别在于源文件本身是被复制一份进去,还是被直接移动或者引用。加-p的好处是发送动作和源文件生命周期解耦,尤其是在 cron 里跑的时候,脚本后面就算执行了清理逻辑也不会影响已经在排队的任务。
-m依赖本机的邮件系统。如果你的机器上没装 MTA,或者邮件直接扔进黑洞,那这个选项开了也白开,通知会静默失败。测试环境里我一般直接看/var/spool/uucp/.Status/下的状态文件来判断成败,比等邮件靠谱。
3.3 本地 spool 里到底发生了什么
执行完 uuto 之后,文件并不是"已经发出去了",而是"已经排进队列了"。理解这一点是排查所有 UUCP 问题的前提。命令执行瞬间,本地 spool 里会出现这些东西:
/var/spool/uucp/<远端主机名>/目录下多出一个C.开头的工作文件,比如C.mynodeN0034。C代表 command,里面记录的是"要做什么",包括源文件路径、目标主机、目标用户、执行哪些后续动作。- 如果用了
-p,同一目录下还会出现D.开头的文件,D代表 data,就是真正要传的内容。 .Sequence文件里对应主机的序列号会加一,用来保证文件名不冲突。.Status文件里会记录该站点的最近通信状态,包括重试次数、上次成功时间。
真正的传输发生在uucico运行起来之后。它读sys配置、建链路、把D.文件发过去,然后在远端触发uuxqt执行随附的请求,由远端把这批文件搬进receive目录。所以在发送端敲完 uuto 立刻去远端找文件,大概率是找不到的,得等一次uucico跑完。默认情况下 UUCP 不是常驻服务,要么靠 cron 定时拉起,要么你手工执行uucico -s remote推一把,这一点和现代的文件传输工具差别很大,第一次用的人经常在这里犯迷糊。
4. 实操全流程:从本地发送到远端 uupick 取件
这一节把完整链路走一遍。我会把命令、现象、验证方式都写出来,你可以照着在两台虚拟机之间复现。
4.1 单文件与多文件发送
先在发送端准备测试文件,然后投递:
# 造两个测试文件 echo "hello uucp $(date)" > /tmp/hello.txt dd if=/dev/urandom of=/tmp/blob.bin bs=1k count=64 2>/dev/null # 投递单文件,指定远端主机和用户 uuto /tmp/hello.txt remote!zhangsan # 投递多个文件,一次排队 uuto /tmp/blob.bin /tmp/hello.txt remote!zhangsan # 观察本地队列,确认工作文件已经生成 ls -l /var/spool/uucp/remote/执行后如果没有报错,说明本地这一侧已经把任务排好了。接下来手工推一次传输:
uucico -s remote -x 5屏幕上的输出会显示连接、协商、传输、断开的过程。跑完之后到远端机器上,用 zhangsan 这个账号执行uupick,就能看到待取件的列表。如果远端还没有 zhangsan 这个系统账号,uuto 也传得过去,但 uupick 会因为找不到家目录而没法正常归档,所以测试前先确认用户存在。
4.2 通配符、目录与文件名陷阱
这一块是新手最容易翻车的地方,我自己也踩过好几次。
通配符是 shell 先展开的,不是 uuto 自己解析的。也就是说uuto *.log remote!ops在 shell 层面就变成了uuto a.log b.log c.log remote!ops,如果当前目录下匹配到的文件特别多,可能直接撞上命令行长度限制。更稳妥的做法是配合find或者分批处理。文件名里带空格或者特殊字符,必须用引号包起来,否则会被拆成多个参数,最后一个参数还被当成远端用户名,报出的错误信息会很莫名其妙。
目录不能直接传。uuto 不是 tar,给它一个目录路径它会直接拒绝。要传目录得自己先打包,到了远端再解开。
老实现对文件名长度有限制。System V 那一代的 UUCP 有 14 字符的文件名上限,超出部分会被截断,两个长名字前缀相同的文件就可能互相覆盖。Taylor UUCP 这一代放松了很多,但目标端如果是老设备,仍然可能被截断。最保险的办法是发送前把文件名改短,比如用日期加序号的方式重新命名。
非 ASCII 字符要小心。中文文件名能不能完整传过去,取决于链路协议和两端实现。用protocol t走 TCP 时一般没问题,但如果是老式的g协议且没开启 8 位支持,中文名和内容都可能变成乱码——这跟很多人遇到的"Linux 解压文件乱码"是同一类问题,根源都是编码协商没对齐。稳妥起见,跨机器传文件时文件名统一用 ASCII,内容里的编码问题在应用层解决。
4.3 接收端 uupick 的完整操作
接收端登录对应账号,直接敲uupick。如果积压的文件来自多个站点,可以用-s只看某一个来源:
# 处理所有站点的待收文件 uupick # 只处理来自 mynode 的文件 uupick -s mynode交互界面的典型样子是逐个文件询问,你输入一个字母决定怎么处置:
from mynode: file hello.txt ?可用的交互命令大致如下,具体以man uupick为准:
| 输入 | 含义 |
|---|---|
| 回车 | 跳过当前文件,看下一个 |
s [目录] | 保存到指定目录,不带目录则存到默认位置 |
m [目录] | 移动到指定目录,与保存的区别是源文件被移走 |
d | 删除当前文件 |
p | 把文件内容打印到终端,适合看小文本 |
q | 退出,未处理的文件留在原地 |
!命令 | 执行一条 shell 命令,比如!ls -l ~看一下当前目录 |
* | 对剩余所有文件重复上一个命令,批量保存时很好用 |
日常最常用的组合是:先用uupick扫一遍列表,确认来源都可信,然后s ~/inbox逐个保存;如果一次来了几十个日志文件,就在第一个文件上敲s ~/inbox,再敲*,剩下的全部按同样方式处理。
提示:uupick 默认的收件位置通常是用户家目录下的
receive结构,或者公共目录/var/spool/uucppublic/receive/<用户名>/。各家实现和打包配置不完全一样,第一次用建议先在一个文件上敲s不带目录,看它到底存到哪儿去了,再决定要不要指定路径。
4.4 用 uustat 观察队列与状态
发送端和接收端都可以用uustat看队列。这条命令在日常运维里比 uuto 本身还常用:
# 列出所有站点的队列任务 uustat -a # 只看发往 remote 的任务 uustat -s remote # 查看各站点的队列摘要 uustat -q # 删除某个卡住的任务(需要 jobid,从上面输出里拿) uustat -k mynodeN0034 # 重新触发某个任务的重试 uustat -r mynodeN0034uustat -a的输出里会带上任务编号、状态、重试次数和最后更新时间。重试次数一直涨但状态不变,基本可以断定是链路或者对端配置的问题,而不是文件的问题。这时候去看/var/spool/uucp/.Status/remote,里面记录的失败原因往往比屏幕上看到的详细得多。
5. 常见故障与排查实录
UUCP 最让人抓狂的地方在于它默认非常"安静"。命令返回 0,你以为成功了,其实任务正躺在队列里反复重试。下面这些是我实际遇到过、并且有明确解法的典型问题。
5.1 发送不报错但远端一直收不到
这个现象出现频率最高,原因几乎都集中在"uucico 没跑"上。UUCP 的传输不是实时的,uuto 只负责排队,真正干活的是 uucico。如果你装完没配 cron、也没手工执行,任务就会一直待在队列里。排查顺序建议这样走:
先看本地队列里有没有对应的工作文件,ls -l /var/spool/uucp/remote/。如果C.文件在,说明排队成功。接着看.Status里的重试次数和最后错误。再手工执行一次uucico -s remote -x 7,把详细过程打出来。最后确认接收端的uucico -l是不是还活着,防火墙有没有放行 540/tcp。这四步走完,绝大多数"神秘失踪"都能定位到具体环节。
5.2 权限与目录相关的报错
UUCP 涉及的文件属主和权限比较多,任何一个错了都会静默失败。几个高频点:
/var/spool/uucp/的属主必须是uucp:uucp。如果你手贱用 root 在里面创建过目录或者复制过文件,队列就可能因为权限不一致而写不进去。/var/spool/uucppublic/需要让远端站点能写入,通常是 0777 或者带 sticky 位的 1777,权限收紧到 0755 就会出现"能连上但传不进去"。
目标用户不存在也是常见原因。uuto 允许你发给一个远端不存在的用户名,文件会被放到公共目录的某个人名目录下,但那个用户登录后执行 uupick 时,如果家目录结构对不上,取件流程会失败。测试前先确认两端账号对齐,能省不少事。
还有一个容易被忽略的点:.Log和.Status目录如果被清理脚本误删,uucico 起不来或者起来就报错。有些发行版的打包脚本会在特定条件下重建这些目录,但别指望它,出问题了手工mkdir加chown uucp:uucp更直接。
5.3 日志的三个入口,按顺序看
排查 UUCP 一定要养成看日志的习惯,它的日志分散在几个地方,各管一段:
| 日志位置 | 内容 | 什么时候看 |
|---|---|---|
/var/spool/uucp/.Log/uucico/<主机> | 链路建立、登录、传输过程的细节 | 连接失败、传输中断 |
/var/spool/uucp/.Log/uucp/<主机> | uucp 命令层面的记录 | 排队阶段出问题 |
/var/spool/uucp/.Log/uuxqt/<主机> | 远端请求执行的记录 | 文件传过去了但没落到 receive 目录 |
/var/log/uucp/Log | 部分老实现的集中日志 | 找不到上面几个目录时来这里翻 |
journalctl -u uucp | systemd 环境下的服务日志 | 服务拉不起来 |
看日志之前先把调试级别调高。uucico -x 9 -s remote会把每一步协商都打出来,包括它尝试了哪个 port 定义、用了什么协议、对端回了什么。这类日志啰嗦是啰嗦,但定位问题比猜快十倍。定位完之后记得把级别调回去,不然日志会迅速把磁盘吃掉。
5.4 常见问题速查表
把上面这些整理成一张表,出问题的时候按症状查:
| 症状 | 可能原因 | 处理方向 |
|---|---|---|
| uuto 成功但队列不减少 | uucico 未运行 | 检查 cron 或手工执行uucico -s 主机 |
| 连接超时 | 地址错误、对端未监听、防火墙拦截 | 核对sys里的 address,确认uucico -l在跑,放行 540/tcp |
| 登录被拒绝 | 口令配置不匹配、uucp 账号 shell 被禁用 | 检查sys中的 call-login 与对端passwd配置 |
| 传输完成但远端没有文件 | 远端uuxqt未执行 | 查.Log/uuxqt/下的记录,确认目录权限 |
| 文件名被截断或覆盖 | 老实现的文件名长度限制 | 发送前重命名为短名,避免前缀重复 |
| 中文乱码 | 协议不支持 8 位或编码不一致 | 改用protocol t,文件名统一 ASCII |
| 任务反复重试 | 中间跳转节点配置缺失 | 检查多级地址里每一跳的sys定义 |
| 日志里提示磁盘满 | .Log或 spool 分区写满 | 清理历史日志,设置日志轮转 |
6. 注意事项与实操心得
这一节讲点手册上不会写、但实际折腾中最容易吃亏的东西。
6.1 安全与信任模型的坑
UUCP 的信任模型建立在一个现在完全不成立的前提上:网络里所有主机都是可信的。它默认允许远端站点通过配置里的账号登录,登录后能做的事情范围不小,历史上也确实因为这种宽松设计出过不少安全问题。所以有两条底线:第一,绝对不要把 UUCP 端口暴露在公网,哪怕只是测试;第二,如果只是为了在两台内网机器之间传文件,用 scp 或者 rsync 就够了,别为了"复古"特意去装 UUCP。这玩意儿现在更适合放在隔离的实验网段里玩。
配置层面还有个小习惯值得养成:能不用的功能就别开。远端执行请求(也就是uux那套)在很多场景下根本用不到,能关就关。sys文件里的时间和权限限制也尽量收紧,别一律time any,虽然调试方便,但也意味着任何时段都可能有人连上来。
6.2 时钟、编码与那些不起眼的细节
两台机器的系统时间要对齐。UUCP 会用时间戳判断任务是否超时、是否需要重试,时间差太大可能出现"刚发出去就被判定为过期"或者"永远不重试"这种诡异现象。用 chrony 或者 systemd-timesyncd 同步一下,比事后排查便宜得多。
编码问题前面提过,这里再强调一次:文件名保持 ASCII,内容编码在应用层处理。跨机器传输时不要指望两端对中文的处理完全一致,很多老实现内部还是按字节流处理的,遇到多字节字符就容易出问题。
还有一点是关于 spool 分区的。UUCP 的队列、日志、临时文件都堆在/var/spool/uucp/下,如果这个目录和根分区在一起,一次大批量投递就可能把根分区撑满,进而影响整个系统。做正式使用的话,把/var/spool/uucp/单独挂一个分区或者至少限制一下日志大小,是必要的。
6.3 现代替代方案该怎么选
如果你的目标只是"把文件可靠地送到另一台机器的某个用户手里",现在的选择比 uuto 好太多,直说结论:优先 ssh 体系。
# 单文件或少量文件,直接用 scp scp ./report.pdf zhangsan@192.168.1.50:/home/zhangsan/ # 大量文件、需要断点续传和增量同步,用 rsync over ssh rsync -avz --partial ./logs/ zhangsan@192.168.1.50:/home/zhangsan/logs/ # 需要接收方主动拉取、且机器不能直接互连时,用 ssh 反向隧道加 sftp # 或者干脆用经过认证的对象存储做中转这几条路都比 uuto 快、比 uuto 安全、比 uuto 好排查。uuto 唯一还值得学的地方,是它那套"投递到人、接收方自取"的模型——理解了它,你会更容易看懂早期邮件网关和新闻组转发为什么要设计成那个样子,也能更好地理解今天那些排队式消息系统的设计取舍。
最后分享一个我自己的使用习惯:每次在任何一台机器上用 uuto 之前,先跑一遍uustat -q和uucico -s 目标主机 -x 5的把链路确认一遍,确定连接是通的再发文件。就这么一个动作,能省掉至少一半"文件发出去了但对方没收到"的扯皮。链路不通的时候,你发多少个文件都是在给 spool 目录囤垃圾。