卸载 dsh 前要先停进程吗?DeepSeek Harness 后台进程、端口占用与 DSH plugin 残留排查
卸载 dsh 前要先停掉后台进程,因为 DeepSeek Harness 会留下几类常驻或半常驻进程:命令行 dsh web 起的 profile 进程、dsh --profile headless 跑完即退的会话进程,以及桌面端的 Host 进程。它们占着运行时、profile 与文件句柄,逐级清理时会被挡在门外。
这篇按「要停哪些进程 → 端口为什么还被占 → 残留进程与端口怎么定位收尾」三步讲。卸载命令本身与各平台路径见《卸载 dsh 的方法汇总》。
卸载 dsh 前要先停哪些进程
卸载前要退三类进程:dsh web 起的常驻 Web profile 进程、dsh --profile headless 的会话进程(任务跑完即退),以及桌面端的 Host 进程(来源)。
先用命令把三类进程找齐:
- 查 dsh 与 Node 进程 — macOS / Linux 跑
pgrep -fl dsh或ps aux | grep -i deepseek;Windows 跑tasklist | findstr /i "dsh node"。预期:列出所有相关进程及 PID。 - 分辨常驻与一次性的 — 看命令行里是
dsh web(常驻、监听端口)还是dsh --profile headless "..."(跑完即退)。预期:能区分出哪个是长期占用、哪个可以放过。 - 查桌面端 Host 进程 — 桌面端未退出时会有 Host 在跑。预期:退出桌面端后该进程消失,
profiles/desktop的单实例锁释放。 - 逐一结束常驻进程 — macOS / Linux 用
kill <pid>,Windows 用taskkill /F /PID <pid>;能正常退出的优先正常退出。预期:进程列表里相关项消失,运行时与句柄释放。
第 2 步是省事的关键:headless 会话进程跑完任务就自己退了,通常不用手动处理;真正需要动手的是常驻的 dsh web 与桌面 Host。别把一次性的当成常驻,也别把常驻的当成不会占资源。
卸载后端口为什么还被占:桌面端不开端口,dsh web 才开
官方说明桌面端应用不打开 Web 端口;监听端口的只有命令行的 dsh web 所起的 profile 进程。所以「卸载 DeepSeek Harness 后端口还被占」几乎都是 dsh web 的进程没退,而不是卸载没卸干净(来源)。
用命令确认端口归属:
- 列监听中的端口 — macOS / Linux 跑
lsof -i -P | grep LISTEN;Windows 跑netstat -ano | findstr LISTENING。预期:列出端口与对应 PID。 - 把 PID 对应回进程 — macOS / Linux 用
ps -p <pid> -o pid,command;Windows 用任务管理器「详细信息」按 PID 找。预期:确认该 PID 是不是 Node / dsh 进程。 - 确认是不是 dsh web — 看进程命令行里有没有
dsh web或--profile web。预期:命中说明是命令行起的常驻进程,与桌面端无关。 - 结束该进程再复查端口 — 结束进程后重跑第 1 步。预期:端口从监听列表消失,说明占用已解除。
第 3 步能直接解释一个常见误判:“我明明卸载了桌面端,端口怎么还在?” 因为那个端口从来不是桌面端开的——桌面端不开 Web 端口,是并存的 dsh web 进程在监听。认清归属,才不会反复卸载。
卸载后进程与端口残留的定位与收尾
收尾顺序是「先按名字找进程 → 再按端口找 PID → 匹配两者 → 优先正常退出」,只有进程无响应时才强制结束,避免中断正在写包的进程(来源)。
按顺序执行,每步都有可核对预期:
- 再查一遍残留进程 — macOS / Linux 跑
pgrep -fl dsh;Windows 跑tasklist | findstr /i node。预期:确认还有没有 dsh / Node 进程没退。 - 再查一遍端口 —
lsof -i -P | grep LISTEN/netstat -ano | findstr LISTENING。预期:确认端口是否已放开。 - 桌面端看有没有待重启提醒 — 打开 DSH Plugin Hub 的通知中心。预期:有「待重启」说明进程需退出才算完成,退出桌面端后再核对。
- 正常退出优先 — 能通过界面退出或发送常规终止信号的就正常退。预期:进程收尾时释放 profile 与锁,不会留下半成品状态;无响应才强制结束。
第 4 步的顺序值得强调:强制结束正在写包的进程,官方说明插件变更失败时只保留部分修改、不回滚,所以能用正常退出解决的,不要一上来就强杀。进程退了、端口放了,卸载与清理才不会互相打架。
卸载 dsh 前停进程的注意事项
- headless 一般不用管:任务跑完即退,只有卡住不退时才需要处理。
- 桌面端不开端口:端口被占是
dsh web进程的事,别归因到桌面端卸载。 - 先认归属再动手:按端口找到 PID、对应回进程,确认是 dsh / Node 再结束。
- 正常退出优先:强制结束可能中断写包事务,留下不可回滚的部分状态。
- 退出后再卸载:进程释放运行时与句柄后,卸载与目录清理才顺畅。
卸载前后想确认哪些任务还在跑、有没有待重启,DSH Plugin Hub 的通知中心会把进度与提醒列在一起,想核对某个 DSH插件是否真的卸载了也一目了然,比在终端里翻进程更直观。

来源:DeepSeek Harness 命令行 README(官方仓库)、DeepSeek Harness 桌面端 README(官方仓库)、DeepSeek Harness 源码仓库
常见问题
卸载 dsh 前必须先停掉后台进程。DeepSeek Harness 的 dsh web 会起一个常驻 profile 进程并监听端口,桌面端也会有一个 Host 进程在跑;这些进程占着运行时、profile 与相关文件,逐级清理时会被挡住。先退出它们再卸载,卸载过程才不会出现文件被占用或端口仍被监听的情况。
卸载 DeepSeek Harness 后端口还被占,几乎都是 dsh web 起的进程没退。官方说明桌面端应用不打开 Web 端口,所以监听端口的是命令行的 dsh web 所起的 profile 进程;应用卸载或删除目录不会自动结束一个还在运行的 Node 进程,端口会继续被它监听。用进程与端口命令找到它并结束即可。
dsh web 会起一个常驻的 Web profile 进程并监听端口,适合持续使用;dsh --profile headless 是在 headless profile 里跑一个任务,任务跑完进程即退出,不会长期占端口。收拾进程时先看有没有 dsh web 这类常驻进程,headless 一般不需要手动处理,除非任务卡住没退。
先按名字找进程,再按端口找到对应 PID。macOS 与 Linux 用 pgrep -fl dsh 或 ps aux | grep -i deepseek 列进程,用 lsof -i -P | grep LISTEN 看监听中的端口;Windows 用 tasklist | findstr /i node 找进程,用 netstat -ano | findstr LISTENING 看端口与 PID,再回到任务管理器核对。两端都要确认进程与端口是否一一对应。
优先正常退出,实在不退再强制结束。能通过界面退出或发送终止信号时,进程有机会收尾、释放 profile 与锁;只有进程无响应时才用强制结束。强制结束正在写包的进程可能留下半成品状态,而官方说明插件变更失败时只保留部分修改、不回滚,所以能不强制就不强制。
相关术语
- dsh web
- dsh web 是 DeepSeek Harness 命令行的一个入口模式(等价于 --profile web),它会起一个常驻的 Web profile 进程并监听端口,是卸载后端口仍被占用的主要来源。— DeepSeek Harness 命令行 README
- dsh --profile headless
- dsh --profile headless 是 DeepSeek Harness 命令行在 headless profile 里执行一次任务的入口模式,任务跑完进程即退出,一般不会长期占用端口。— DeepSeek Harness 命令行 README
- Host 进程
- Host 进程是 DeepSeek Harness 桌面端的后端进程,桌面端在插件变更与运行时会启动或停止它;它参与独占 profiles/desktop,卸载或重置前要先退出。— DeepSeek Harness 桌面端 README
- profile
- profile 是 DeepSeek Harness 中一套独立的运行环境,命令行按入口模式使用不同 profile,每个 profile 自带 package.json 与 node_modules;进程常按 profile 归属,定位进程时要连 profile 一起看。— DeepSeek Harness 命令行 README
来源
- DeepSeek Harness 命令行 README· deepseek-ai
- DeepSeek Harness 桌面端 README· deepseek-ai
- DeepSeek Harness 源码仓库· GitHub