用 lsof 指令尋找佔用通訊埠的 Process
Posted on Dec 19, 2022 in Unix-like 命令列教學 by Amo Chen ‐ 2 min read
最近在開發 Next.js 相關的應用程式,無腦寫了無窮迴圈造成 dev server 關不掉,導致重啟 dev server 時會顯示以下警告訊息,該訊息顯示通訊埠(port) 3000 正在被其他 process 佔用:
warn - Port 3000 is in use, trying 3001 instead.
本文紀錄如何找到佔用 port 的 Process Id 並且停止其運作。
本文環境
- macOS
lsof 指令
lsof 指令是 macOS 與 Linux 都擁有的內建指令,用途為顯示開啟的檔案列表,由於 Unix-like 的作業系統設計哲學,一切都可視為檔案,所以連 service 所開啟的網路服務也是一個檔案,因此可用 lsof 列出。
如果要找出佔用 port 3000 的 TCP 服務,可以使用以下指令:
$ lsof -Pi tcp:3000 | grep LISTEN
上述指令結果如下,可以看到 PID 88627 正在監聽(LISTEN) port 3000:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
node 88627 user.name 23u IPv6 0xe2b29f4b29788c6f 0t0 TCP *:3000 (LISTEN)
前述指令 -P
參數會將 port 的名字轉成數字顯示,否則就會以 port 名稱顯示,例如 3000 可能會顯示成 hbci
(Home Banking Computer Interface), 如果不知道 port 名稱的人,會很有可能以為指令執行結果有問題,所以加上 -P
比較好。
-i
參數則是用以過濾網路相關的設定,其格式如下所示:
[46][protocol][@hostname|hostaddr][:service|port]
[46]
代表要濾出 IPv4 還是 IPv6, 如果只想顯示 IPv6 列表的話,可以指定 -i 4
[protocol]
則代表只顯示 TCP 或是 UDP 的列表,如果只想顯示 TCP 的列表,可以使用 -i tcp
, 也可以進一步使用 -i 4tcp
代表只顯示使用 IPv4 TCP 的列表。
[@hostname|hostaddr]
則可以用 IP 位址或 hostname 進行過濾,例如 -i @localhost
代表指顯示 listen 在 localhost 的列表,也可以寫成 -i @127.0.0.1
。
[:service|port]
則是用 port 或 port name 進行過濾(port name 可以在 /etc/services
中找到),例如前述指令只顯示 3000 port 的列表可表示為 -i :3000
。
這 4 種格式可以視需求搭配使用,例如指顯示執行在 0.0.0.0:3000
的 IPv4 TCP 列表,可以表示為 -i [email protected]:3000
。
找到之後,可以使用以下指令強制停止該 Process, 其中 88627 就是要被停止執行的 Process Id:
$ kill -9 88627
以上就是用 lsof
指令找到佔用通訊埠的 Process Id 的簡單介紹。
Happy Coding!