1. 先搞清楚这套组合到底在解决什么问题
把vscode 远程连接和wget download failed这两件事放在同一个标题里,乍一看像是两个不相干的话题,但真正在服务器上干活的人都懂,它们其实是同一条流水线上的前后两站:先用 VSCode 把本地编辑体验搬到远程机器上,然后在远程终端里拉依赖、装环境、跑脚本,而wget恰好是这个环节里最容易掉链子的那个工具。我自己这几年维护过好几台开发机,绝大多数"环境装不上"的抱怨,最后追根溯源都不是代码问题,而是某一条wget命令在悄悄失败,然后被后面的脚本忽略掉了,等到编译报错的时候已经过了半小时,排查成本被放大好几倍。
这篇东西写给三类人看。第一类是刚接触远程开发、还在纠结要不要折腾 Remote-SSH 的朋友,我会把配置链路完整走一遍,包括那些官方文档写得含糊但实际会卡住你的细节。第二类是已经在用远程开发、但经常被download failed这类报错拦住的人,我会把wget的失败原因按链路拆开,给你一套可以照着敲的定位流程。第三类是负责给别人搭环境、需要写安装脚本的人,脚本里怎么处理下载失败、怎么降级、怎么避免"静默失败",这部分我会单独讲。
需要先说明一点:远程开发这件事没有标准答案,有人喜欢 VSCode Remote-SSH,有人习惯用终端里的 vim 加 tmux,也有人干脆在本地写代码再手动同步。我选 VSCode 这条路的理由是编辑体验和调试能力,尤其是远程解释器、远程终端、断点调试这几块,在纯终端工作流里要么没有,要么配置成本极高。所以下面的内容都围绕这个前提展开,如果你用的是别的方案,思路部分依然可以参考,具体命令需要自己替换。
1.1 远程开发的真实使用场景
很多人对"远程连接服务器"的理解还停留在"SSH 上去敲命令",其实现在说的远程开发,指的是编辑、运行、调试三个环节全部在远程完成,本地只承担显示和输入。这个区别很关键。传统做法是本地写代码,用 scp 或者 rsync 同步到服务器,再 SSH 上去跑;远程开发是把 VSCode 的界面留在本地,但文件系统、终端、语言服务、调试器全都跑在服务器上。
为什么这个改变值得折腾?举几个我自己遇到的场景。一是本地机器性能一般,但服务器上有几十核和几百 G 内存,跑编译、跑数据处理、跑模型训练都在服务器上,本地只是个瘦客户端。二是项目依赖的运行时版本和本地系统冲突,比如服务器是某个特定版本的 Linux 发行版,本地是 Windows 或者更新的桌面系统,装同一套依赖纯属自找麻烦。三是团队协作时环境要统一,代码放在共享的开发机上,谁都能连上去看同一份文件,避免"我这里能跑你那里不能跑"。
还有一种情况是硬件资源本身就在远端,比如需要访问特定的数据集、特定的网络位置、特定的内网服务。这时候本地开发根本没法复现,只能把工作区放在能访问这些资源的那台机器上。
理解这些场景之后,你会发现远程开发真正的价值不是"省事",而是让开发环境和运行环境尽可能重合,减少因为环境差异导致的偶发问题。至于wget为什么会出现在这个话题里,因为环境搭建的第一步几乎都是下载安装包、下载依赖源、下载脚本,而这些操作在远程终端里执行时,受网络路径、证书、DNS、防火墙的影响,失败率远比在本地浏览器里点一下高得多。
1.2 为什么 VSCode Remote-SSH 成了默认选项
市面上的远程方案不少,为什么大家最后都聚到 VSCode 这条路上?我总结下来是三个原因叠加。
第一个是插件生态。你在本地装了 Python 插件、C/C++ 插件、Go 插件,连上远程之后这些插件会自动在远程侧装一份对应的服务端组件,语法高亮、补全、跳转、格式化全都正常。这个体验是其他编辑器很难做到的,因为它需要插件作者愿意为远程模式单独适配。
第二个是配置文件足够简单。Remote-SSH 本质上就是帮你管理 SSH 连接,它读的是标准 SSH 配置,复用你已有的密钥和 config 文件。这意味着你不需要学一套新的认证体系,之前怎么连服务器,现在就怎么连。
第三个是调试链路完整。远程调试最麻烦的是把调试器和被调试进程对齐,VSCode 的方式是在远程侧启动一个调试适配器,本地界面通过通道跟它通信,你设的断点、看的变量、走的单步,都是真实的远程进程状态,不是模拟。
代价当然也有。远程连接会消耗一定的内存和 CPU,低配服务器上开远程窗口有时候会感觉编辑器"卡顿";网络质量差的时候输入延迟明显;还有就是初次配置的坑比较多,尤其是密钥、权限、配置文件这几块,新手很容易卡在第一步。但这些是一次性成本,配好之后每天都能省时间。
1.3 一个容易混淆的坑:flash download failed 不是一回事
搜索download failed的时候,你大概率会看到一堆error: flash download failed - target dll has been cancelled或者error: flash download failed - "cortex-m3"之类的结果。这里必须提醒一句:这类报错跟本文讲的wget下载失败完全是两码事。
flash download failed通常出现在嵌入式开发的烧录环节,指的是烧录器在往芯片写程序的时候失败,target dll has been cancelled是烧录算法动态库被取消或者加载失败,cortex-m3、cortex-m4是目标芯片内核型号。它的排查方向是烧录器连接、芯片供电、调试接口速率、Flash 算法选择、芯片是否被读保护,跟网络、跟 Linux 命令行、跟wget没有任何关系。
之所以要单独说这段,是因为很多人搜报错的时候只看关键词,看到download failed就一头扎进去,结果看了半天 Flash 烧录的帖子,问题还是没解决。分清报错所属的领域,是排查效率的第一道关口。本文只讨论命令行下载工具wget在远程 Linux 环境下报 download failed 这一类问题。
2. VSCode 远程连接服务器的落地步骤
这一章我把完整流程走一遍,从本地准备到服务端配置再到连接验证。每一段我都会说清楚"为什么这么做",因为照着敲命令容易,出了问题知道往哪查才是关键。
2.1 本地端准备:安装与插件选择
本地端要做的事情其实不多,但有几个细节容易忽略。
第一步是安装 VSCode。渠道上建议走官方渠道获取安装包,避免第三方打包版本夹带额外组件。Windows 用户注意选择适合自己的架构版本,现在不少机器是 ARM 架构,装错版本会跑不起来或者性能很差。macOS 用户直接下载对应芯片的版本即可。安装完成后,建议先在本地随便打开一个文件夹确认软件本身工作正常,再进入下一步。
第二步是装 Remote 相关插件。插件市场里搜索Remote - SSH,认准官方发布的那一个。装完之后左侧活动栏会出现一个远程连接的图标,这就是你的入口。有些人会顺手把Remote Development这个插件包也装上,它里面包含了 SSH、容器、WSL 几个子插件,如果你只连远程服务器,装单独的 SSH 插件就够了,装多了会拖慢启动。
第三步是确认本地有没有 SSH 客户端。Windows 10 之后的版本自带 OpenSSH 客户端,可以在 PowerShell 里敲ssh -V验证;如果没有,需要在系统设置的可选功能里手动添加。macOS 和大多数 Linux 桌面自带。这一步很关键,因为 Remote-SSH 插件本身不实现 SSH 协议,它调用的是系统的 SSH 客户端,本地没有客户端的话插件会提示找不到。
注意:不要把密钥文件的权限设得太开放。在 macOS 和 Linux 上,私钥文件如果被其他用户可读,SSH 客户端会直接拒绝使用它,报错信息通常写得比较隐晦,很多人会误以为是服务器的问题。
2.2 服务端准备:SSH 服务与账号
服务端要做的事情比本地多一些,核心就两件:保证 SSH 服务在跑,保证你的账号能登录。
先确认 SSH 服务状态。不同发行版的命令不一样,基于 systemd 的系统一般用systemctl status sshd或者systemctl status ssh查看。如果服务没启动,先启动再设置开机自启。这里有个常见误区:有些人改了配置文件之后忘了重启服务,然后一直以为配置没生效,白白折腾半天。
再说配置文件。/etc/ssh/sshd_config是服务端的配置文件,改之前一定要先备份,因为改错了会导致 SSH 服务起不来,如果此时你只有远程连接这一条路,那就彻底失联了,只能去机房或者找云平台的控制台救急。我自己的习惯是改之前先cp一份带时间戳的备份,改完先用sshd -t做语法检查,通过了再重启。
几个值得关注的配置项:Port决定监听端口,默认 22;PermitRootLogin控制是否允许 root 直接登录,出于安全考虑建议关掉,用普通账号登录后再提权;PasswordAuthentication控制是否允许密码登录,配置好密钥之后建议关掉;PubkeyAuthentication要确保是开启状态。这几个开关组合起来,决定了你能不能用密钥顺利连上。
用户和权限这块,确保你的账号有家目录、有可写的空间,否则远程服务端组件装不下去,连接会失败在一个很奇怪的地方。可以用df -h看一下家目录所在分区的剩余空间,几百兆以下就要留心了。
2.3 config 文件与密钥登录的写法
密钥登录是远程开发里最值得花时间配置的一环,配好之后每次连接都是一键完成,不用输密码。流程是本地生成密钥对,把公钥放到服务器上,然后配置本地的 SSH config 文件。
生成密钥的命令如下,-t指定算法,-C是备注,方便你以后在服务器上辨认这是哪台机器的公钥:
ssh-keygen -t ed25519 -C "dev-workstation-2024"生成过程中会问你保存路径和密码短语。路径默认在用户目录下的.ssh文件夹里,如果你有多台服务器,建议用不同的文件名区分。密码短语可以留空,也可以设一个,设了更安全但每次用都要输,配合本地的密钥管理工具会方便些。
把公钥传到服务器上,最省事的办法是用ssh-copy-id:
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@your-server-ip如果这个命令在你的系统上不可用,也可以手动把公钥内容追加到服务器的~/.ssh/authorized_keys文件里,注意文件权限要是 600,.ssh目录要是 700,权限不对的话 SSH 会忽略这个文件。
然后配置本地的 config 文件,路径是~/.ssh/config,写法大致是这样:
Host devbox HostName 192.0.2.10 User developer Port 22 IdentityFile ~/.ssh/id_ed25519 ServerAliveInterval 60 ServerAliveCountMax 3 TCPKeepAlive yes这里每一项都有用。Host是你自己起的别名,之后ssh devbox就能连上,VSCode 里也是填这个别名。ServerAliveInterval配合ServerAliveCountMax是心跳机制,每 60 秒发一次探测,连续 3 次没响应才断开。这个配置在远程开发里非常重要,因为有些网络设备会清理长时间没有数据流的连接,不配心跳的话你会在挂机一段时间后发现窗口卡死,只能重连。TCPKeepAlive是更底层的保活开关,两个一起开效果更好。
在 VSCode 里连接的时候,点远程图标,选择连接到主机,输入devbox这个别名即可。第一次连接会在服务器上安装服务端组件,需要几十秒到几分钟不等,取决于服务器到软件源的速度——这里就埋下了后面要讲的下载问题的伏笔。
2.4 连接上之后容易忽略的几件事
连上不等于用得舒服,有几个后续动作值得做。
第一是确认工作区的打开位置。远程窗口里打开文件夹,打开的是服务器的路径,不是本地的。有些人在本地和远程之间来回切,经常搞混自己在编辑哪一份文件,改了半天发现改的是本地副本,白忙一场。我的习惯是给远程窗口换个明显的主题色,一眼就能分辨。
第二是插件配置同步。有些插件在本地和远程都需要配置,比如代码格式化规则、调试器路径。远程侧的配置是独立的,不会自动继承本地的设置,需要你在远程窗口里单独配一遍。
第三是终端的工作目录。远程终端默认落在哪个目录,取决于你的配置。如果你习惯所有命令都在项目根目录执行,可以在项目下开终端,或者配置终端启动时自动切到工作区目录。
第四是文件监听的资源占用。大项目里文件数量多,远程侧的文件监听会消耗内存,如果服务器配置一般,可以在设置里排除掉不需要监听的目录,比如构建产物目录、依赖缓存目录、版本控制目录。这个优化在小项目里感觉不出来,在几十万文件的项目里能省下可观的资源。
3. wget download failed 到底在报什么
到了正题。wget的报错信息看起来五花八门,但其实有内在的分类逻辑,搞懂这个逻辑,你就能从报错文本快速判断该往哪个方向查。
3.1 报错文本的分类逻辑
wget的输出可以粗略分成三段:解析阶段、连接阶段、传输阶段。每一段的报错关键字都不一样。
解析阶段是域名转 IP 的过程,相关报错会提到Resolving或者Temporary failure in name resolution,说明 DNS 这块有问题。
连接阶段是建立 TCP 连接、协商加密层的过程,常见报错有Connection timed out、Connection refused、Unable to establish SSL connection、The certificate of ... is not trusted,说明目标不可达或者握手失败。
传输阶段是数据真正在流动的过程,报错可能是Read error at byte ...、Connection reset by peer、download failed because not enough bytes were received,说明连上了但数据没传完就断了。
还有一类是服务端返回的状态码,比如ERROR 403: Forbidden、ERROR 404: Not Found、ERROR 502,这类跟网络链路无关,是服务器明确告诉你请求不对或者资源不存在。
把报错归到这三四类里,排查范围立刻缩小一大半。下面逐个说。
3.2 从链路角度拆解失败点
从你的终端到目标文件之间,数据要经过好几跳:本机网络 → 网关 → 运营商网络 → 目标站点的入口 → 目标站点的回源。任何一跳出问题都会表现为下载失败,但排查手法完全不同。
本机侧常见的问题是 DNS 配置不对、路由表异常、系统时间不准。DNS 问题最典型,表现是域名解析不出来,但用 IP 直接访问是通的。系统时间不准会导致 TLS 握手失败,因为证书有效期校验依赖准确的时间,报错通常写得含糊,很多人根本想不到是时间问题。验证方法很简单,敲date看看时间对不对,偏差超过几分钟就要校准。
网络路径侧常见的问题是某些目标地址在当前网络环境下不可达,或者响应极慢。判断方法是换一个目标试试,如果换目标就正常,说明是特定地址的问题;如果换什么目标都慢,说明是整体链路的问题。
目标站点侧常见的问题是服务端限流、证书配置有问题、回源超时。这类问题的特征是你反复重试,有时成功有时失败,成功率大概在某个比例上下浮动。判断方法是拉长重试次数看成功率,如果一直失败就是硬性问题,如果偶发成功就是限流或者负载问题。
传输中断这类最容易被误判成网络问题,其实很多时候是对方在传输过程中主动断开,或者中间设备因为检测到长时间连接而清理了会话。特征是前面已经传了一部分数据,后面突然断掉。wget支持断点续传,可以加-c参数从断点继续,配合--tries重试次数,对这类问题有奇效:
wget -c --tries=5 --timeout=30 -O target-file.tar.gz "https://example.com/path/to/file"这里的-c是继续下载,--tries是最大尝试次数,--timeout是每次操作的超时秒数,-O是指定保存的文件名。这几个参数组合起来,对付偶发中断非常有效。
3.3 那些容易被误判的"看起来像网络"的问题
有几个问题表现得像网络故障,实际上根源在别处,踩过一次就会记住。
磁盘空间不足。下载到一半报错,看起来像连接被断,实际是磁盘写满了。远程机器上尤其常见,因为开发机上堆了各种镜像、缓存、日志。养成下载大文件之前先df -h看一眼的习惯,能省很多时间。如果家目录和临时目录在不同分区,还要分别看。
inode 耗尽。空间还有但 inode 用完了,表现也是写不进去。用df -i检查。这种情况在小文件特别多的目录里容易出现,比如缓存目录、依赖目录。
目标文件已存在且被占用。用-O覆盖一个正在被其他进程读写的文件,可能失败。检查一下有没有别的东西在用这个文件。
shell 的引号问题。URL 里带有&、?、=这类字符,不加引号会被 shell 解释成特殊含义,导致传给wget的地址被截断。表现是 404 或者下载到一个奇怪的文件。养成给 URL 加引号的习惯:
wget -O installer.sh "https://example.com/install.sh?version=1.2&arch=x86_64"重定向被当成失败。有些站点会返回 302 跳转,wget默认会跟随,但如果跳转链条很长或者跳到不同协议,可能出问题。用-v打开详细输出看看实际请求了什么地址,比瞎猜快得多。
提示:排查下载问题时,先加
-v看完整输出,再决定下一步动作。不要一上来就加各种跳过校验的参数,那只是把问题遮住,后面会在别的地方以更难查的形式冒出来。
4. 一套可复用的 wget 排错流程
前面讲了"是什么",这一章讲"怎么办"。我把自己常用的流程整理成五步,按顺序走基本能覆盖绝大多数情况。
4.1 五步定位法
第一步:确认 DNS 解析是否正常。
getent hosts example.com nslookup example.com两条命令能解析出 IP 就说明 DNS 没问题。如果解析不出来,看看/etc/resolv.conf里配的 DNS 地址是不是空的或者不可用。远程机器上这个文件被网络管理服务覆盖的情况很常见,你手动改了它,重启网络之后又变回去了,得从上层配置去改。
第二步:确认目标端口连通性。
curl -vI "https://example.com" --max-time 10这条命令会展示连接建立的全过程,包括 DNS、TCP 握手、TLS 握手、HTTP 响应头。哪一步卡住一目了然。用curl而不是wget做探测,是因为它的输出更结构化,更容易读。
第三步:确认是全局问题还是单点问题。
换一个已知可靠的地址做对比,比如同一网络下访问其他站点是否正常。如果所有目标都失败,问题在你的网络配置;如果只有目标站点失败,问题在目标侧或者你到目标侧的路径。
第四步:检查本地环境。
系统时间、磁盘空间、inode、环境变量里有没有影响 HTTPS 的配置、有没有全局的下载工具配置文件(比如~/.wgetrc)。这几项花两分钟检查完,能排除掉一大批"玄学问题"。
第五步:加参数重试并观察。
wget -c -v --tries=3 --timeout=20 --waitretry=5 -O output.file "https://example.com/file"--waitretry是重试之间的等待秒数,避免短时间内反复冲击对端。如果这样能成功,说明是偶发问题,把这套参数固化到脚本里即可。如果还是失败,把-v的输出完整看一遍,按前面讲的分类逻辑定位。
4.2 常见报错速查表
| 报错关键字 | 所属阶段 | 大概率原因 | 处理方向 |
|---|---|---|---|
Temporary failure in name resolution | 解析 | DNS 不可用或配置错误 | 检查 resolv.conf,换用可用的 DNS 服务 |
Connection timed out | 连接 | 目标端口不可达或被丢包 | 检查路由、防火墙规则、目标端口是否开放 |
Connection refused | 连接 | 目标端口没有服务在监听 | 确认端口号是否正确,服务是否在跑 |
Unable to establish SSL connection | 连接 | TLS 握手失败,协议或加密套件不匹配 | 检查系统时间、证书链、协议版本 |
certificate ... is not trusted | 连接 | 证书链不完整或系统根证书缺失 | 补装根证书,或在可信环境下手动指定证书 |
Read error at byte ... | 传输 | 传输中途被断开 | 加-c断点续传,加重试次数 |
not enough bytes were received | 传输 | 数据未传完,通常伴随连接重置 | 同上传,配合重试和续传 |
ERROR 403 | 服务端 | 权限不足,需要特定头部或来源 | 检查是否需要认证信息或请求头 |
ERROR 404 | 服务端 | 路径错误或资源已移除 | 核对 URL,注意引号和转义 |
ERROR 502 / 503 | 服务端 | 服务端本身异常或过载 | 稍后重试,或改用镜像地址 |
这张表基本上覆盖了我这些年遇到的大部分情况。需要说明的是,"处理方向"只是第一步,具体到某个报错还要结合当时的环境判断,不能生搬硬套。
4.3 降级与替代手段
当wget一时半会儿修不好的时候,不要死磕,换条路走往往更快。
换工具。curl是另一个选择,参数风格不同但能力接近:
curl -fL --retry 3 --retry-delay 5 --connect-timeout 10 -o output.file "https://example.com/file"-f表示 HTTP 错误码时返回失败,-L跟随重定向,--retry重试次数,--connect-timeout连接超时。脚本里我经常两个工具都留着,一个不通试另一个。
换源。很多软件包在多个位置有镜像,主源不通的时候换镜像往往立刻见效。比如系统包管理器的源配置,不同的镜像站点在连通性和速度上差异很大。脚本里最好把镜像地址做成变量,方便一处修改全局生效。
换协议。有些场景下同一份资源同时提供 HTTP 和 HTTPS,或者同时提供不同端口的访问方式。如果某个协议在当前网络下不稳定,另一个可能是通的。这属于应急手段,长期方案还是要解决根本问题。
本地下载再上传。如果远程机器的网络实在糟糕,而本地网络正常,可以在本地把文件下好,再用scp或者工具里的上传功能传上去。笨是笨了点,但在赶时间的时候非常好用。
5. 远程终端里跑下载脚本的那些细节
把 VSCode 远程开发和wget排错这两件事合在一起看,最典型的场景就是在远程终端里执行安装脚本,而脚本里往往藏着一串wget。这一章讲几个只有真正跑过才会注意到的细节。
5.1 长任务与断线保护
远程开发的连接虽然配了心跳,但也扛不住网络抖动和意外断开。而下载和安装这类任务动辄几分钟到几十分钟,一旦中途断线,跑了一半的任务会被挂断,运气不好还会留下半成品文件,让后续操作报莫名其妙的错。
解决办法是让任务脱离当前会话运行。最常用的是nohup配合后台执行:
nohup bash install.sh > install.log 2>&1 &或者用终端复用工具,把任务跑在一个可以随时挂载和卸载的会话里。这样即使你的远程窗口断了,服务器上的任务还在继续跑,重连之后接回去看日志就行。
判断任务是否还在跑,可以看日志文件的最后几行:
tail -f install.log注意tail -f本身会跟着会话走,会话断了它就停了,但被监控的任务不受影响。这是很多人误解的地方,以为tail断了任务也断了。
5.2 脚本里怎么处理下载失败
写安装脚本的时候,最忌讳的是"下载失败了但脚本继续往下跑",最后报出一个跟真实原因毫无关系的错误。我的做法是在关键下载环节加显式的检查。
一个比较简单可靠的写法是这样,下载之后立刻校验返回值,失败就退出并打印上下文:
#!/usr/bin/env bash set -euo pipefail URL="https://example.com/pkg.tar.gz" OUT="pkg.tar.gz" if ! wget -c --tries=3 --timeout=30 -O "$OUT" "$URL"; then echo "[下载失败] 目标: $URL" >&2 echo "[提示] 检查网络、DNS、磁盘空间后重试" >&2 exit 1 fi echo "[完成] 已保存到 $OUT"set -euo pipefail这一行很重要,它让脚本在遇到未定义变量、命令失败、管道中任一环节失败时立刻退出,而不是带着错误继续跑。很多脚本事故都是因为少了这一行。
下载完成之后,如果资源提供了校验值,最好做一次校验:
sha256sum -c pkg.tar.gz.sha256校验不过说明文件在传输过程中损坏了,这时候重下比继续用要靠谱得多。我第一次遇到"下载的文件解压报错"的时候愣了半天,后来才发现是下载不完整,加校验之后这类问题再没出现过。
5.3 几条踩过坑之后的经验
第一条经验是不要相信"下载成功了"这个表象。wget退出码为 0 只代表它认为请求完成了,不代表文件内容正确。中间设备返回一个错误页面、对端返回一个精简版文件,都有可能让wget认为成功。所以文件大小、校验值、解压测试这几步,能加就加。
第二条经验是把镜像地址集中管理。脚本里散落各处的下载地址,改起来是灾难。我的习惯是在脚本开头定义一组变量,所有下载都引用变量,需要切换的时候改一处就行。
第三条经验是关注远程机器的时间。这个坑我踩过不止一次,某台长期运行的虚拟机时间漂移了,导致所有 HTTPS 下载全部失败,报的错还都是证书相关的。校准时间之后一切正常。现在我把时间同步检查加进了环境自检脚本里。
第四条经验是区分"环境问题"和"临时问题"。前者需要改配置,后者只需要重试。判断方法很简单:同样的命令连续跑五次,五次都失败就是环境问题,偶尔成功就是临时问题。这个判断只需要一分钟,但能让你少走很多弯路。
第五条经验是日志要留全。远程环境下排查问题,你手上的信息就是命令行输出。把所有输出重定向到日志文件,包括标准输出和标准错误,出问题的时候翻日志比重新跑一遍高效得多。
最后分享一个小技巧:在 VSCode 远程窗口里,可以把常用的排查命令做成任务或者片段,一键执行。比如"检查 DNS + 检查磁盘 + 检查时间 + 测试目标连通性"这一套组合拳,配成一个任务之后,遇到下载失败点一下就跑完,省下的是每次手动敲五条命令的时间。这种小投入在长期使用里的回报率非常高。