把新端口写在 launcher 的 flag 后面:dsh --profile web --port 3100。顺序有讲究,因为 --port 属于 app 而不是 launcher,launcher 遇到第一个不认识的 token 就停止解析。要找占用 3080 的进程用 lsof -nP -iTCP:3080 -sTCP:LISTEN。
dsh web 把网页端开在 http://127.0.0.1:3080。3080 这个端口足够常见——开发服务器、容器端口映射、
其它本地工具——撞车是常事。
找出占用端口的东西
macOS 与 Linux:
lsof -nP -iTCP:3080 -sTCP:LISTENWindows(PowerShell):
Get-NetTCPConnection -LocalPort 3080 -State Listen | Select-Object OwningProcess
Get-Process -Id <pid>如果查出来是上一次 dsh 没干净退出留下的 node 进程,杀掉重来。如果是你确实需要的服务,那就让
harness 让路。
换个端口
dsh --profile web --port 3100这也是为什么在边界情况下 dsh web --port 3100 和 dsh --profile web --port 3100 不总是等价。
行为奇怪的时候,用显式的 --profile 写法。
让它固化下来
每次启动都手敲 --port 很烦。端口属于 app 配置,所以可以写进 patch 层。先找到拥有它的那一行:
dsh --profile web --dump-config然后在 $DSH_HOME/profiles/web/cordis.patch.yml 里命中那一行。记住解析顺序——bundle、profile patch
文件、home 级的 $DSH_HOME/cordis.patch.yml、最后 --patch。home 级的设置会盖掉 profile 级的,改动
看起来没生效时先查这个。
一次性实验则完全不用碰文件:
dsh --profile web --patch ./tmp/alt-port.yml提示被占用,但没人监听
三个常见嫌疑。
容器发布了这个端口。 docker ps 看 PORTS 那一列。已发布的端口即使里面的进程闲着,也会占住宿主机
的绑定。
半死的进程。 上次运行丢了终端但没释放 socket。lsof 仍然能看到,按 PID 杀掉。
监听地址不匹配。 harness 绑的是 127.0.0.1,不是 0.0.0.0。绑在 0.0.0.0:3080 的进程会冲突,
绑在某个具体外部网卡上的可能不会。如果 lsof -iTCP:3080 看起来是空的,去掉 -sTCP:LISTEN 再跑一次,
能抓到 TIME_WAIT 之类其它状态的 socket。
换完之后验一下
别默认改动生效了,确认新端口真的在服务:
curl -sSI http://127.0.0.1:3100 | head -1有响应行说明起来了。connection refused 说明 flag 没落地——先查参数顺序,这比配置问题常见得多。
常见问题
为什么 dsh --port 3100 web 会失败,而 dsh --profile web --port 3100 可以?
launcher 先解析自己的 flag,遇到第一个不认识的 token 就把后面全部交给 app。把 --profile 这类 launcher flag 放在 --port 这类 app flag 前面。
能让局域网访问网页端吗?
默认绑 loopback,对一个能在你仓库里执行 shell 命令的工具来说这是刻意的。真需要远程访问,请走带认证的隧道,而不是把监听地址放宽。
提示端口被占,但看起来没人在监听。
通常是上次没干净退出的 dsh 进程,或者某个容器发布了这个端口。两边都查一下;macOS 上还要注意区分绑在 127.0.0.1 和绑在 0.0.0.0 的进程。