{"record":{"id":"51e98752da4cd2d4","repo":"docmirror/dev-sidecar","slug":"port-lsof-fuser-fusere","errorCode":null,"errorMessage":"终止占用端口 ${port} 的进程失败。\nlsof 方案失败\nfuser 方案: ${fuserError.message}","messagePattern":"终止占用端口 (.+?) 的进程失败。\nlsof 方案失败\nfuser 方案: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/shell/scripts/kill-by-port.js","lineNumber":72,"sourceCode":"          + `PowerShell 方案: ${psError.message}\\n`\n          + `CMD 方案: ${cmdError.message}`,\n        )\n      }\n    }\n  },\n\n  async linux (exec, { port }) {\n    // 主方案：lsof\n    try {\n      await exec(`kill $(lsof -i:${port} -t 2>/dev/null) 2>/dev/null || true`)\n      return true\n    } catch (_lsofError) {\n      // 备选方案：fuser\n      try {\n        await exec(`fuser -k ${port}/tcp 2>/dev/null || true`)\n        return true\n      } catch (fuserError) {\n        throw new Error(\n          `终止占用端口 ${port} 的进程失败。\\n`\n          + `lsof 方案失败\\n`\n          + `fuser 方案: ${fuserError.message}`,\n        )\n      }\n    }\n  },\n\n  async mac (exec, { port }) {\n    // macOS 与 Linux 采用相同策略\n    return executor.linux(exec, { port })\n  },\n}\n\nmodule.exports = async function (args) {\n  return execute(executor, args)\n}\n","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/docmirror/dev-sidecar/blob/7710cd56cce760c708f30b01d2d4056eb8c402d5/packages/core/src/shell/scripts/kill-by-port.js#L54-L90","documentation":"On Linux (and macOS, which delegates to the same code), kill-by-port tries `kill $(lsof -i:<port> -t)` first and falls back to `fuser -k <port>/tcp`. This error is thrown only when the fuser fallback itself throws — note both commands end with `|| true` so they mask 'no process found'; a genuine throw means the fuser binary is missing or execution of the shell command failed outright.","triggerScenarios":"Calling kill-by-port on Linux when lsof path threw (typically lsof not installed, since the `|| true` suppresses 'no process' cases) AND the fuser fallback also threw (fuser not installed — not part of default minimal images — or exec could not spawn a shell).","commonSituations":"Alpine/slim Docker containers or minimal distros where neither lsof nor fuser (psmisc) is installed; restricted containers lacking CAP_KILL; shells without /bin/sh fallback.","solutions":["Install the fallback tools: Debian/Ubuntu `apt-get install -y psmisc lsof`; Alpine `apk add psmisc lsof`; RHEL `dnf install psmisc lsof`.","Free the port manually: `ss -ltnp 'sport = :<port>'` to find the PID, then `kill -9 <pid>`.","If running in a container, ensure the container has CAP_KILL or perform the kill on the host.","Use `fuser -k -n tcp <port>` directly to confirm the tool works and see stderr without the 2>/dev/null suppression."],"exampleFix":"// before (both tools masked by || true, silent no-op when missing)\nawait exec(`kill $(lsof -i:${port} -t 2>/dev/null) 2>/dev/null || true`)\n// after (verify the tool exists and surface a clear message)\nawait exec(`command -v lsof >/dev/null || { echo 'lsof not installed'; exit 127; } && kill $(lsof -i:${port} -t)`, { printErrorLog: true })","handlingStrategy":"fallback","validationCode":"const { execSync } = require('child_process')\nfunction hasPortTools() {\n  for (const t of ['lsof', 'fuser']) {\n    try { execSync(`command -v ${t}`) } catch { return { ok: false, missing: t } }\n  }\n  return { ok: true }\n}\n// run before kill-by-port on Linux; if missing, install psmisc/lsof or use ss(8)","typeGuard":"null","tryCatchPattern":"try {\n  await killByPort({ port })\n} catch (e) {\n  if (e.message.includes('fuser')) {\n    // both lsof and fuser unavailable/failed\n    const out = execSync(`ss -ltnp 'sport = :${port}'`, { encoding: 'utf8' })\n    const pid = /pid=(\\d+)/.exec(out)?.[1]\n    if (pid) execSync(`kill -9 ${pid}`)\n  } else throw e\n}","preventionTips":["Install lsof and psmisc (fuser) in your image/Dockerfile when using dev-sidecar on Linux.","Use ss -ltnp as a dependency-free fallback on minimal systems.","Ensure the container has CAP_KILL for killing processes.","Verify the port is actually bound: ss -ltn | grep :<port> — if not, no kill is needed."],"tags":["linux","port","process-kill","lsof","fuser"],"backgroundTag":"port-already-in-use","analyzedSha":"7710cd56cce760c708f30b01d2d4056eb8c402d5","analyzedAt":"2026-08-31T22:07:07.234Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}