Processes, jobs, ports
คุม process ที่รันอยู่ Ctrl+C / Ctrl+Z / & / jobs / fg / bg และแก้ปัญหา port 3000 already in use ด้วย lsof + kill
จนถึงตอนนี้คำสั่งที่เรียนมาเสร็จทันทีแล้วคืน prompt แต่ในชีวิตจริงคุณจะเจอคำสั่งที่ ไม่ยอมจบ อย่าง npm run dev, ping google.com, tail -f log หรือเจอคำสั่งที่ค้าง กดอะไรก็ไม่ตอบสนอง
บทนี้เรียนการคุม process ที่กำลังรัน หยุดมันได้ ย้ายมันไปรันเงียบๆ ข้างหลัง รู้ว่าใครกำลังใช้ port อะไรอยู่ และเลิกเจอข้อความน่าหงุดหงิดว่า port 3000 already in use
Process คืออะไร
Process คือ คำสั่งที่กำลังรันอยู่ในเครื่อง ตั้งแต่ terminal, Chrome, Spotify, ไปจนถึง node app.js ที่เพิ่งสั่งรันของคุณ ทุก process มี PID (process ID) ที่ OS ใช้ระบุตัว และมี state ปัจจุบัน (running, stopped, sleeping)
$ ps # list process ของ shell ปัจจุบัน
$ ps aux # list ทุก process ในเครื่อง (เยอะมาก)
$ ps aux | grep node # กรองเฉพาะที่มี nodeForeground vs Background
เวลารันคำสั่ง shell จะ blocked รอจน process จบก่อนถึงคืน prompt ให้พิมพ์ต่อ นั่นเรียกว่ารันใน foreground
แต่บางคำสั่งเกิดมาเพื่อรันตลอดเช่น dev server ถ้ารันใน foreground คุณจะพิมพ์คำสั่งอื่นไม่ได้จนกว่าจะปิดเซิร์ฟเวอร์ ทางแก้คือส่งมันไปรันใน background แทน
4 วิธีจัดการ process ที่กำลังรัน
Ctrl + C= หยุด foreground process (ส่ง SIGINT ให้ตายอย่างสุภาพ) ใช้บ่อยสุดCtrl + Z= pause process ที่กำลังรัน (ส่ง SIGTSTP) ไม่ได้ฆ่า แค่หยุดชั่วคราว prompt กลับมาให้พิมพ์ต่อbg= เอา process ที่ pause ไปรันต่อใน backgroundfg= ดึง background process กลับมา foreground
สามารถใส่ & ท้ายคำสั่งให้รันใน background ตั้งแต่แรกก็ได้
$ npm run dev & # รันใน background ตั้งแต่แรก
[1] 12345 # shell บอก job number + PID
$ jobs # list jobs ที่อยู่ใน shell นี้
[1]+ Running npm run dev
$ fg %1 # เอา job 1 กลับมา foreground
$ sleep 30
^Z # Ctrl + Z → pause
[1]+ Stopped sleep 30
$ bg # resume ต่อใน background“Port already in use” ปัญหาคลาสสิคของ dev
ถ้าเคยรัน npm run dev แล้วเจอ error EADDRINUSE: address already in use :::3000 แปลว่ามีอีก process หนึ่งกำลัง “ฟัง” port 3000 อยู่แล้ว OS ไม่ยอมให้ 2 process ใช้ port เดียวกัน
เจอบ่อยที่สุดคือกด Ctrl + C แล้ว server ไม่ตายสนิท หรือปิด terminal ก่อนที่ server จะหยุด process เลยค้างอยู่ วิธีแก้คือหาว่าใครใช้ port นั้นอยู่ แล้ว kill ทิ้ง
$ lsof -i :3000 # ใคร listen port 3000
COMMAND PID USER NODE NAME
node 456 krish IPv4 *:3000 (LISTEN)
$ kill 456 # สุภาพ
$ kill -9 456 # force (ถ้า kill ธรรมดาไม่ได้ผล)Windows ใช้ netstat -ano | findstr :3000 แทน lsof หา PID แล้ว taskkill /PID 456 /F
ลองจำลองดู
Widget ข้างล่างจำลอง scenario ที่ทุก dev เจอ กด Start dev server ดูว่า error ยังไง แล้วใช้ lsof หา PID และ kill ให้ port ว่างก่อน Start ใหม่ สังเกต redis ที่ดื้อ ไม่ยอมตายด้วย kill ธรรมดา ต้อง kill -9
lsof -i :PORT)node app.js3000python -m http.server 80808080redis-server6379สรุป
- Process = คำสั่งที่กำลังรัน มี PID + state
Ctrl+Cหยุด,Ctrl+Zpause,bg/fgสลับ foreground/background,&รัน bg ตั้งแต่แรกjobslist background ใน shell,ps aux | grepหา process ใดๆ ในเครื่อง- Port busy →
lsof -i :PORTหา PID แล้วkill PID killสุภาพก่อน,kill -9เฉพาะถ้าไม่ได้ผล
คุม process ที่กำลังรันได้แล้ว คำถามต่อไปคือ เวลาพิมพ์ node หรือ git shell รู้ได้ยังไงว่าต้องไปรันไฟล์ไหน ทำไมบางเครื่องพิมพ์แล้วเจอ บางเครื่องขึ้น command not found บทต่อไปจะเรียน environment variables กับ $PATH กลไกเบื้องหลังการหา executable ของ shell