返回资讯中心
外部精选
软件工程
#开发者实时流

开发者通过修改让 Zed 远程服务器在 FreeBSD 上运行

来源标题:Lying to Zed to get its remote server running on FreeBSD

一位开发者通过非官方方式让 Zed 编辑器的远程服务器功能在 FreeBSD 上跑了起来,并公开呼吁 Zed 团队正式支持 FreeBSD。该开发者表示愿免费协助 CI 等工作。其改用 Zed 的原因是 VS Code 近期变得缓慢且被 AI 功能拖累,而 Zed 提供原生开关可彻底关闭 AI 功能。

Hacker News 最新arch1e2026/11/13 · 今天15 分钟阅读

以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。

如果 Zed 团队有人看到这篇文章:请原生支持 FreeBSD 远程服务器。我很乐意无偿帮忙做 CI 或其他任何事情,随时联系我:hayzam@alchemilla.io。

我从 16 岁左右开始用 VS Code,到现在快十年了,说实话大部分时候它还凑合。但最近它变得让人难以忍受:又慢,又被越来越多的 AI 垃圾拖得越来越重。另一方面,Zed 很快,而且它有一个原生开关可以关掉所有 AI 功能,这一点我太喜欢了。(在设置里有个开关,或者在设置文件里写 "disable_ai": true。)

这不是因为我要避开 LLM。我只是不想让它们试图编辑我写的每一行,或者蹲在角落里阴森森地评判我。我大部分 FOSS 代码还是自己写:这让我保持清醒,而且我觉得 FOSS 开发者有责任保持代码干净,好让 LLM 去抄,哈哈。我交出去的是那些累人的部分:回归测试、边界情况,以及超出我这颗 20 瓦小脑瓜所能容纳范围的探索。为此我用那些和模型配合良好的 harness,比如 OpenCode。至于自动补全之外……我一直觉得 claude code 之类的整套 harness 在编辑器里非常笨重。

Zed 目前没有 FreeBSD 远程服务器的方案,但 FreeBSD 可以大量运行 Linux 二进制文件,所以我们用 Zed 的 Linux 版本。你只需要一台能 SSH 登录的 FreeBSD 服务器。

sudo sysrc linux_enable=YES
sudo service linux start
sudo pkg install linux_base-rl9
kldstat -m linux64 # should print a module
  1. 让 Zed 选择 Linux 服务器

Zed 会询问主机运行的是什么平台。FreeBSD 回答 FreeBSD amd64,而 Zed 没有对应的服务器,于是它就放弃了。这个 wrapper 只对那一个问题回答 Linux x86_64,其余全部转交给真正的 uname。把它保存为 ~/.local/bin/uname 并赋予可执行权限:

#!/bin/sh
case "$#:$*" in
 1:-sm|1:-ms) printf 'Linux x86_64\n' ;;
 *) exec /usr/bin/uname "$@" ;;
esac

把 ~/.local/bin 加入非交互式 SSH 会话的 PATH。对于 zsh,在 ~/.zshenv 里加上这段(用你所用 shell 的对应写法):

export PATH="$HOME/.local/bin:$PATH"

这是个小小的谎言,但是可控的,也是我很想早日退休掉的那部分。

从 Zed 通过 SSH 连接并打开一个文件夹。首次连接会把 Linux 服务器上传到 ~/.zed_server/。想观察的话,运行 tail -f ~/.local/share/zed/logs/server-workspace-*.log。

没有这个修复的话,你能正常连接,但会得到一个空的项目树,服务器日志里会有:

error processing entry failed to read directory entry
Caused by:
 Invalid argument (os error 22)

修复是 ec6629628cb,在 main、stable/15 和 releng/15.2 中,所以 15.2-RELEASE 会包含它。如果错误仍然存在,用 uname -v 检查你是否启动了新内核。

更想要原生服务器?editors/zed port 也会构建一个并上传到 ~/.zed_server/(见其安装信息),但它必须与你的 Zed 版本完全匹配,而且可能落后于 Zed 频繁的更新。Linux 这条路线则始终跟随 Zed 自己的下载。

为了展示你的项目,Zed 会向服务器询问每个文件夹中文件的名称,一次问几个。Zed 为每一批预留了一小块空间。

想象一位老师给一个学生念班级名单,学生把名字写在便利贴上(我想不出更好的比喻了,请包涵)。老师每念一个名字就划掉一个,而且再也不会念划掉的名字。学生的便利贴上能写下 6 个名字。老师按每 4 个一组来念,这是个合理的习惯,几乎每次都没问题。但 6 不是组的整数倍,所以她会念 8 个名字并划掉全部 8 个。而便利贴上只放得下 6 个。

现在她陷入了困境。她的疏忽在于,在检查之前就抓取了超过能放下的数量。她不能把放得下的 6 个交出去、把另外 2 个留到以后,因为它们已经被划掉了,她再也不会念它们了。于是她改为报错,至少这很响亮。当我尝试安静的方式时,我的 1,002 个文件中有 112 个(从列表中)无声无息地消失了。我相当确定,响亮的错误胜过安静的丢失。Zed 看到错误后判定它无法读取该文件夹,于是把它显示为空。

修复很小:读取的名字不要超过便利贴上放得下的数量。读 6 个,划掉 6 个,回来再读下 6 个,直到名单念完。在真实的 bug 中,老师是 FreeBSD 的 Linux 翻译层(Linuxulator),便利贴是 768 字节的缓冲区,一组 4 个名字是一个 512 字节的块。

这是一个回归。2026 年 2 月针对 NFS 目录返回虚假条目的修复(110f2567cb51,PR 292282)改变了 sys/compat/linux/linux_file.c 在 linux_getdents() 和 linux_getdents64() 中计算原生读取大小的方式:

/* before February 2026 */
buflen = min(args->count, MAXBSIZE);
/* after: every request rounded up to a 512-byte block */
buflen = min(roundup2(args->count, DEV_BSIZE), MAXBSIZE);

如果调用方的缓冲区不是 512 字节的整数倍,原生批次就可能超出它。模拟层会一直转换记录,直到某条放不下,然后返回 EINVAL,但 kern_getdirentries() 已经把目录偏移推进过了整个批次。这就是为什么仅返回部分批次还不够。

修复(ec6629628cb,在 D60760 中评审):

if (args->count >= DEV_BSIZE)
 buflen = min(args->count, MAXBSIZE);
else
 buflen = roundup2(args->count, DEV_BSIZE);

这是安全的,因为 Linux 的目录记录永远不会比 FreeBSD 的大:对于 dirent64,头部是 19 字节对 24 字节,而且两者都把每条记录向上取整到 8 的倍数。能放进调用方缓冲区的原生批次,转换后也放得下。

旧版的 getdents 对 32 位和 64 位调用方有同样的 bug。我的第一个补丁只修复了 getdents64;两个都修复后,测试矩阵从 86 个失败降到了零。

(原文较长,此处译出前 6000 字,完整内容请点「打开原文」。)

正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。

打开原文
去社区讨论 →