chore: sync

This commit is contained in:
oneao committed 2026-10-08 11:34:12 +08:00
1 parent 8b1ec67609
commit ac65b75c73
6 files changed
+179 -10

No files matched your search

+49
View File
@@ -0,0 +1,49 @@
#!/usr/bin/env node
/**
* 启动文档站 dev server,启动前挑一个真正空闲的端口。
*
* 为什么不用 Nuxt 自带的端口回退:Nuxt 靠“试绑 host”判断端口是否空闲,而 Windows 上 Node
* 默认开启 SO_REUSEADDR,**允许多个进程绑定同一个 addr:port**,于是“能不能绑上”根本判断不出
* 冲突 —— 3000 已被别的服务占用时,探测仍然成功,Nuxt 就继续用 3000。
*
* 因此这里改用“实际建立 TCP 连接”来判断:只要 127.0.0.1 或 ::1 任一能连上,就说明该端口
* 正在被监听(可覆盖占用方绑在 0.0.0.0 / 127.0.0.1 / ::1 的所有常见情况),然后依次向上找。
*
* 起始端口:DOCS_PORT > PORT > 3000。
*/
import { spawn } from 'node:child_process'
import { connect } from 'node:net'
const start = Number(process.env.DOCS_PORT || process.env.PORT || 3000)
const MAX_TRIES = 100
/** 能否连接到 host:port(能连上即为“正在被监听”) */
function reachable(port, host) {
return new Promise((resolve) => {
const socket = connect({ port, host })
const done = (busy) => {
socket.destroy()
resolve(busy)
}
socket.setTimeout(400)
socket.once('connect', () => done(true))
socket.once('timeout', () => done(false))
socket.once('error', () => done(false))
})
}
async function isBusy(port) {
const [v4, v6] = await Promise.all([reachable(port, '127.0.0.1'), reachable(port, '::1')])
return v4 || v6
}
let port = start
while (port < start + MAX_TRIES && (await isBusy(port))) port++
if (port !== start) console.log(`端口 ${start} 已被占用,改用 ${port}`)
const child = spawn('nuxt', ['dev', '--port', String(port)], {
stdio: 'inherit',
shell: true,
})
child.on('exit', (code) => process.exit(code ?? 0))