Skip to content

更新 ​

ThinkTerm 不会自行安装更新。它只负责检查、告诉你,然后等你决定。

检查更新 ​

桌面应用运行期间,会自己去 GitHub 检查有没有新版本:启动后大约十秒,如果记录里的上一次检查已经早于检查频率,就检查一次;之后每过一个这么长的时间再检查一次。命令行工具、TUI 和会话 server 从不自行检查。

设置 › 软件更新 里有两行控制这件事。自动检查更新 是一个开关,检查频率 提供 每 12 小时(默认)、每天 和 每周,开关关闭时它是灰的。改动在一分钟内生效。在你动用这两行之前,它们跟随配置文件里的 check_for_updates 和 check_for_updates_interval_seconds;两者怎么配合、一次检查何时到点,见配置页的更新检查。

设置 › 软件更新 显示的是检查的结果:当前运行的版本、是否已知有更新的版本,以及这个副本是怎么安装的。

  • 顶部那个按钮,在已知有新版本、且这个副本是 ThinkTerm 可以替换的那种时,是 安装更新,下面叠着一个 检查更新;其余情况下只有 检查更新。检查更新 会当场去问 GitHub,不论 自动检查更新 开着与否:请求进行期间按钮显示 正在检查…,之后短暂显示 已检查,上方的卡片显示返回的结果。请求失败时,卡片显示 无法检查更新。,原因打印在它下方。下面的 thinkterm update --check 在终端里做同样的事。
  • 上次检查 是只读的。它显示记录里最近一次检查是什么时候做的,不论是应用自己做的,还是用 检查更新 做的。
  • 更新内容 会在浏览器里打开待安装版本的发布说明。没有待安装的版本时,显示的是 查看全部版本,打开完整列表。
  • 下载来源 决定更新从哪里下载安装包,本机和远端 server 都用它。默认的 自动 先走 GitHub,GitHub 慢或连不上时改用镜像;直连 GitHub 从不使用镜像;也可以指定某一个镜像。不管从哪里下载,都要和 GitHub 记录的校验值一致才会安装。

检查到新版本时,窗口的角落里会浮出一枚胶囊,而不是弹窗抢占屏幕,见 更新胶囊。如果找到它的是自动检查,还会同时发一条通知 —— ThinkTerm 有新版本 —— 点击后会在浏览器里打开这个版本在 GitHub 上的页面。Check for Updates...(在 macOS 的 ThinkTerm 菜单和命令面板里,名称不翻译)会打开 设置 › 软件更新,绑定到按键上的 CheckForUpdates 动作也一样。

判断一个发布版是否更新,看版本号;唯一的例外是版本号相同。在 macOS 上,从源码检出自己打包的 ThinkTerm.app,可能带着一个后来才发布的版本号,而那个发布版是用更新的代码做的。遇到这种情况,ThinkTerm 会比较这个应用所基于的提交的时间和发布版所基于的提交的时间,用更新的代码做成的发布版会以 有新构建 提示出来。此时通知写的是 ThinkTerm 有新构建,设置 › 软件更新 写的是 ThinkTerm x.y.z 有比你这份更新的构建。查出发布版的提交时间要多发一个请求,发给 GitHub 的提交列表,只发一次,并和保存的检查结果存在一起。正式发布包从不这样比较,所以它不会被告知它自己就是的那个发布版。

除了上面那次查询,一次检查就是向 GitHub 的 release API 发一个请求,不带任何凭据。如果你自己设了 THINKTERM_UPDATE_TOKEN,它会被读取 —— 这能解除 GitHub 对匿名请求的限流,私有 fork 也需要它。它与安装脚本接受的 GITHUB_TOKEN 是两个变量,这是刻意的:ThinkTerm 自己的代码从不读取 GITHUB_TOKEN,所以你为别的工具导出的 token 不会被检查发出去。更新所运行的安装脚本会读取它,但只在必须自己下载归档时才会用到;见 安装更新。ThinkTerm 还会发送哪些东西,见 隐私与安全。

安装更新 ​

安装更新 会原地替换文件。替换期间你面前的窗口可以继续使用,而 ThinkTerm 仍然运行着启动时的那个版本。

最后这点最容易被误解,所以确认信息把话说明白了:ThinkTerm x.y.z 已安装。重启后开始使用新版本。 运行中的会话底下不会被偷偷换掉。

在找到眼前这个新版本之后,也许又发布了更新的版本,装旧的只会紧接着再更新一次。所以设置里的 安装更新 和更新胶囊会先向 GitHub 再问一次最新的发布版,装那一个,卡片和胶囊随后写的也是它。如果这第二次问不通 GitHub,就装原来提供的那个版本。

页面顶部的卡片会跟着安装进度变化。先是 正在准备安装 ThinkTerm x.y.z…,此时 ThinkTerm 在准备安装脚本;然后是 正在下载 ThinkTerm x.y.z…,带一条进度条和类似 63.1 MB / 80.0 MB · 79% 的一行,下载持续一秒之后会再加上 约 12 秒;接着是 正在安装 ThinkTerm x.y.z…。出了问题,卡片显示 更新安装失败。,原因出现在它下方;如果已经走到安装器那一步,还会附上安装器打印的内容。

ThinkTerm 会自己下载归档,并在安装脚本看到它之前,用 GitHub 在文件上传时记录的 SHA-256 核对。对不上的下载会被删除,什么都不会安装。如果 GitHub 没有这个归档的校验和,就由脚本自己获取并判断,和手动运行时一样,也没有进度条。

桌面应用通过系统代理下载,或者环境里指定的代理,SOCKS 也行。thinkterm update 用系统的 curl 下载,它读取环境里指定的代理。

安装完成后,卡片上会出现 重启 ThinkTerm,但只在重启不会结束任何终端时才有。由 ThinkTerm 自己运行的 shell —— 在应用自己的进程里的,或者经直接 SSH 连接的 —— 会随它一起结束,而放在会话 server 里的终端不会。只要还开着第一种 pane,就没有这个按钮,你可以在方便的时候自己退出再重新打开 ThinkTerm。Windows 也一样:安装器不会关掉 ThinkTerm,卡片会等安装器结束,然后给出同样的重启按钮。

更新前就在运行的会话 server,会在 ThinkTerm 下次启动时被移到新版本:运行中的 server 把 pane 交给新构建,里面的终端继续运行。如果 server 比正在启动的应用还新 —— 比如更新 server 时留在原地的旧应用 —— 它就不会被动,这个窗口先用自己的终端。server 里的那些终端还在;更新 ThinkTerm 后它们就回来了,要是改在设置里停掉会话 server,它们则会结束。

更新胶囊 ​

已知有新版本时,每个窗口终端区域的右下角都会浮着一枚圆角胶囊,写着 有新版本 和版本号。如果这个副本是 ThinkTerm 可以替换的,点一下就和 安装更新 做同样的事;其他副本则会打开 设置 › 软件更新,那里写明文件归谁管。胶囊会避开菜单、命令面板和对话框。

接着它代替卡片跟着安装走。先是 正在下载 和百分比,图标外转着一圈进度环,然后是 正在安装。装完之后,在重启不会结束任何终端时它写 重启以完成更新,点一下就重启 ThinkTerm。重启会结束终端时,它写 更新已安装,点一下打开设置页面。安装失败时写 更新失败 和 重试,点一下再试一次。更新下载或安装期间,点击没有任何作用。

指针停在胶囊上时,会展开一个关闭按钮。关掉后,胶囊收拢,飞进侧边栏设置按钮上的一个小圆点,一直留到下次启动;安装失败时圆点是红色的,这时点设置按钮打开的是 设置 › 软件更新,而不是设置。更新下载期间关掉胶囊,不会中止安装。

谁有权替换这些文件 ​

ThinkTerm 只更新它自己装的副本,也就是通过安装脚本装的那种。其他每一种安装方式都有各自的归属方:系统包管理器、Homebrew、Nix、AppImage 自己的更新器,或者那个运行了 cargo build 的人。对这些情况,ThinkTerm 会指出归属方,而不是覆盖它的文件。

这个副本的安装方式ThinkTerm 的处理
安装脚本安装更新,并保持原来的变体
手动放置的 ThinkTerm.app在原位置替换,并把命令行工具放到 ~/.local/bin
AppImage提示用 AppImageUpdate,或从发布页下载新的 AppImage
Homebrew提示运行 brew upgrade thinkterm。Homebrew 的 cask 不算在这里:它把 ThinkTerm.app 放进 /Applications,所以应用会把它当作手动放置的,在原位置替换
Nix提示通过你的 Nix 配置更新
系统包管理器提示用 apt、dnf 或原来的方式安装新包
Windows 安装器下载适合这台机器架构的新安装器并运行
从源码构建提示拉取仓库后重新构建
无法识别拒绝替换,并提示按原来的安装方式更新

在它不会替换文件的那些情况下,thinkterm update 做的不止是指出归属方:在 macOS 和 Linux 上,它还会打印一条出路 —— 跑一次安装脚本,就把这台机器纳入脚本管理的安装,之后每一次更新都回到按钮或那条命令。而如果安装器跑起来了却拒绝这台机器(glibc 太旧、musl、没有对应架构的构建),它会直说,并给出从源码构建这个版本的命令,而不是报一个没有原因的失败。

命令行 ​

thinkterm update 遵循与设置里那个按钮完全相同的规则。

bash
thinkterm update              # 检查,安装前询问
thinkterm update --check      # 只报告是否有新版本,不安装
thinkterm update -y           # 不询问直接安装
thinkterm update --version X  # 安装指定版本 X 而不是最新版,允许降级

两条路径都没有重新实现安装器,而是先下载发布归档,按 安装更新 里描述的方式核对,再把活交给 install.sh——只有这个脚本了解归档布局,以及桌面版和服务器版之间的切换。ThinkTerm 下载好的归档通过 --from 交给它,同时带上 --version 和这次安装所用的 --prefix。脚本是从默认分支拉取的,不是从要安装的那个 release 里取的:这样对安装器的修复能一次性覆盖所有已装机器,而不用等下一个版本发布。Windows 没有安装脚本,在那里两条路径都是下载新的安装器并运行它。

thinkterm update 让脚本直接写到你的终端,所以在服务器版安装上,脚本自己的交接会生效:运行中的 mux 服务端把会话交给新构建,见升级与卸载。设置里的 安装更新 则会捕获脚本的输出,桌面应用在下次启动时自己把会话 server 交接过去。

更新远端 server ​

客户端和 server 在协议发生变化后就无法通信。最常见的触发方式是:你的桌面端升级了,而某台主机上的 server 还跑着上个月的构建。

ThinkTerm 手上已经有到那台主机的 SSH 会话,所以它可以自己修复这个不匹配,而不是把你打发去手动登录。attach 时发现版本不匹配,它会先说明两边各运行哪个版本,接下来怎么做取决于那台主机。

有些不匹配它修不了,会在提问之前就说明。其中两种它从你自己的配置里就能知道:这个域被配置成从固定路径运行 ThinkTerm,以及客户端本身就是开发构建,没有对应的发布版。第三种是 server 比这个客户端还新:它会原样保留,因为它不会把会话交给更旧的构建,提示里会让你改为在这一端更新 ThinkTerm。

否则,ThinkTerm 会打开到该主机的 SSH 会话,读取那里装了什么。此时还没有向 GitHub 请求任何东西,主机上也没有任何改动。主机的 glibc 对要装的那个版本来说太旧(服务器版低于 2.31,桌面版低于 2.35)、主机用的是 musl、或者它的架构没有发布版,会在这一步、任何提问之前就被指出,并附上从源码构建的办法。glibc 为 2.31 到 2.33 的主机会装上内置 OpenSSL 的服务器构建。装哪个变体取决于主机上已有的东西:那里的桌面版安装会保留 GUI,在 Linux 上,发行版包装的桌面应用(它不写安装记录)也一样:它会得到装在 ~/.local 下的桌面版,启动器移到新的安装上,应用和服务器保持同一个版本。如果主机的 glibc 对桌面版来说太旧,提问里会说明只更新服务器,应用保持自己的版本。主机上的 macOS 应用包不动,因为它会自己更新。

然后它只问一次。这个问题会说明哪个版本、以哪个变体装到主机上,是以 SSH 用户的身份装到 ~/.local 下、不需要 root,通过 SSH 会发送什么,以及随带的东西,比如桌面应用。带有未提交源码改动的客户端不会因此被拒绝;提问里会带一条警告,说明发布版仍可能与它不匹配。回答 n,则哪里都没有改动:ThinkTerm 会打印出命令,供你自己在主机上运行。

只有回答 yes 之后,ThinkTerm 才会去 GitHub 查这个发布版。这是这个客户端正在运行的版本,不一定是最新版。查询失败时,它会说 Could not resolve release x.y.z,给出原因,然后停下。否则它通过这条 SSH 会话把安装脚本和这个发布版的校验值发给主机,由主机自己下载归档;下载不经过 ThinkTerm。脚本是联网取得的已签名副本(四秒内能验证就用它),不然用 ThinkTerm 内置的那一份,所以不会运行任何未经验证的东西。下载来源 同样适用,GitHub 慢时会让位给镜像,见安装。安装器的输出,以及下载的字节数和速率,会转发到连接窗口里。

之后运行中的会话会怎样,取决于一个设置,它同样在 设置 › 软件更新 页面上,默认开启:

更新远端 server 时保留会话 —— 运行中的 server 把 pane 交给新版本而不是停掉,里面跑的程序不会中断。

交接中途失败会重试,最多三次。太旧、无法交出 pane 的 server,会退回到下面这个询问。关闭该设置时,ThinkTerm 会在停止旧 server 前询问,因为停止它会结束它持有的所有会话。这件事从不会在未经询问的情况下执行;如果你拒绝,旧 server 会继续运行,直到你自己停掉它并重新连接。

交接本身用的就是 远程 里描述的那套机制——运行中的 server 把 pane 传给新的二进制,会话本身察觉不到。

相关 ​

  • 远程 —— 会话如何在断开、重启和升级后存活
  • 命令行 —— thinkterm 的其余子命令
  • 安装 —— 每次更新实际运行的安装脚本