之前我将博客的源代码放到了服务器上,并在服务器上运行了一个 code-server。这样我可以随时在任何电脑上编辑博客了。用着一直没有问题,直到有一天另一名同学想要在服务器上也运行一个 code-server。这时第二个 code-server 的运行就报错了。错误信息显示是

1
discarding socket connection: EACCES: permission denied, unlink '/tmp/code-server/tls-proxy'

这里的这个 tls-proxy 应该是 code-server 用来处理 ssl 的 socket 文件。那两个不同的进程之间的应该拥有各自 socket 文件,彼此不冲突。但是这里的这个错误信息显示第二个 code-server 没有尝试创建第二个 socket 文件,而是强行使用第一个进程的 socket 文件,因此导致错误。

因此我上 Github 下载了 code-server 的原代码进行研究。code-server 的代码是用 Typescript 写的,不是特别复杂。而且,直接全局搜索 "discarding socket connection" 只有一处。因此 bug 的位置很好确定。最终发现的出问题的地方在 socket.ts 文件的第 94 行:

1
2
3
4
5
6
7
8
public async findFreeSocketPath(basePath: string, maxTries = 100): Promise<string> {
let i = 0
let path = basePath
while ((await canConnect(path)) && i < maxTries) { // the line with bug
path = `${basePath}-${++i}`
}
return path
}

这里 await canConnect(path) 这个逻辑明显有问题。应该是尝试连接 path 中的 socket 文件失败以后尝试新的 socket 文件,而这里是连接成功以后创建新的 socket 文件。因此这段代码需要修改为:

1
2
3
4
5
6
7
8
public async findFreeSocketPath(basePath: string, maxTries = 100): Promise<string> {
let i = 0
let path = basePath
while (!(await canConnect(path)) && i < maxTries) { // fix the bug
path = `${basePath}-${++i}`
}
return path
}

这里的逻辑问题就算是解决了。不过除了代码的问题,还有 /tmp/code-server 这个文件夹的写入权限问题,以及 dist 包中部分文件会在前端报 404 的错误的问题。我把这些问题创建了一个 Issue,看开发团队什么时候解决吧。