คำสั่ง nohup: วิธีใช้ nohup.out และการให้งานทำงานต่อแม้ปิดเทอร์มินัล
หากต้องการให้งานทำงานต่อแม้คุณปิดเทอร์มินัลหรือการเชื่อมต่อ SSH หลุด ให้รันด้วยคำสั่ง nohup โดย nohup จะรันคำสั่งโดยให้ไม่สนใจสัญญาณตัดการเชื่อมต่อ (SIGHUP) ที่ส่งมาตอนปิดเทอร์มินัล เมื่อรัน sleep ที่ใส่ nohup กับ sleep ที่ไม่ใส่พร้อมกันบนเซิร์ฟเวอร์ AlmaLinux 9 แล้วปิดเทอร์มินัล มีเพียงตัวที่รันด้วย nohup เท่านั้นที่ยังทำงานต่อ
ผลลัพธ์ด้านล่างได้จากเซิร์ฟเวอร์ AlmaLinux 9.8 (บัญชี root) และเซิร์ฟเวอร์ Debian 12 (บัญชีทั่วไป) ใช้ sleep แทนงานที่ทำงานนาน และตอนหยุดระบุเฉพาะ PID ที่ได้รับตอนรัน เวลาแสดงเป็น UTC
1️⃣ วิธีใช้คำสั่ง nohup
ใส่ nohup ไว้หน้าคำสั่งที่จะรัน และใช้ & ท้ายคำสั่งเพื่อกำหนด การรันเบื้องหลัง ตามคู่มือทางการของ GNU ตัว nohup เองไม่ได้ส่งคำสั่งไปทำงานเบื้องหลัง ดังนั้นถ้าไม่ใส่ & พรอมต์จะไม่กลับมาจนกว่าคำสั่งจะทำงานเสร็จ
nohup sleep 300 &[1] 3431609
nohup: ignoring input and appending output to 'nohup.out'[1] คือหมายเลขงาน และ 3431609 คือ PID ของโปรเซสที่รัน ข้อความที่ตามมาแจ้งว่าจะไม่รับอินพุตจากแป้นพิมพ์ และจะเขียนเอาต์พุตต่อท้ายไฟล์ nohup.out
PID ของงานที่เพิ่งรันจะเก็บอยู่ใน $! จึงควรตรวจด้วย [echo $!] ทันทีหลังรันแล้วจดไว้ เมื่อจะดูสถานะหรือหยุดงานก็ใช้หมายเลขนั้นได้เลย
echo $!3431609เมื่อปิดเทอร์มินัล เชลล์จะได้รับสัญญาณตัดการเชื่อมต่อ และส่งสัญญาณเดียวกันไปยังงานที่เชลล์นั้นรันไว้ (ตามคู่มือทางการของ Bash) เพื่อยืนยันพฤติกรรมนี้ จึงรัน [nohup sleep 300 &] และ [sleep 301 &] ที่ไม่มี nohup พร้อมกันในเทอร์มินัลใหม่
sleep 301 &[2] 3432892jobs -l[1]- 3432883 Running nohup sleep 300 &
[2]+ 3432892 Running sleep 301 &ขณะที่งานทั้งสองอยู่ในสถานะ Running ได้ปิดหน้าต่างเทอร์มินัล แล้วตรวจ PID ทั้งสองด้วย ps จากเชลล์อื่น
ps -p 3432883,3432892 -o pid,stat,etime,cmd PID STAT ELAPSED CMD
3432883 S 00:05 sleep 300เหลือเพียง sleep 300 ที่รันด้วย nohup ส่วน sleep 301 ที่รันโดยไม่มี nohup จบไปพร้อมกับการปิดเทอร์มินัล
โปรเซสที่รันด้วย nohup ก็เหมือนโทรศัพท์ที่เปิดโหมดห้ามรบกวนไว้
nohup เป็นคำสั่งในแพ็กเกจ coreutils ดูเวอร์ชันที่ติดตั้งได้จากบรรทัดแรกของ --version เซิร์ฟเวอร์ AlmaLinux 9.8 เป็น 8.32 และเซิร์ฟเวอร์ Debian 12 เป็น 9.1
nohup --version | head -1nohup (GNU coreutils) 8.32nohup --version | head -1nohup (GNU coreutils) 9.12️⃣ nohup.out และการเปลี่ยนทิศทางเอาต์พุต
ถ้าไม่ได้กำหนดว่าเอาต์พุตจะไปที่ใด nohup จะเขียนเอาต์พุตของคำสั่งต่อท้าย nohup.out ในโฟลเดอร์ปัจจุบัน nohup.out ที่สร้างขึ้นครั้งแรกมีขนาด 0 และมีสิทธิ์ -rw------- ซึ่งอ่านและเขียนได้เฉพาะผู้ใช้ที่สร้างไฟล์
ls -l nohup.out-rw------- 1 root root 0 Oct 28 23:04 nohup.outคู่มือทางการของ GNU อธิบายว่า nohup สร้าง nohup.out ให้อ่านและเขียนได้เฉพาะผู้ใช้ที่สร้างไฟล์ ไม่ว่าจะตั้งค่า umask ไว้อย่างไร ถ้าเขียนลงโฟลเดอร์ปัจจุบันไม่ได้ จะเขียนลง $HOME/nohup.out ในโฮมโฟลเดอร์ และถ้าเขียนที่นั่นไม่ได้อีก ก็จะไม่รันคำสั่ง
เมื่อรันคำสั่งที่มีเอาต์พุตด้วย nohup เอาต์พุตยังคงอยู่ใน nohup.out หลังคำสั่งทำงานเสร็จ
nohup sh -c 'echo start; sleep 2; echo end' &[1] 3431985
nohup: ignoring input and appending output to 'nohup.out'cat nohup.outstart
end
[1]+ Done nohup sh -c 'echo start; sleep 2; echo end'Done ในบรรทัดสุดท้ายคือการแจ้งเตือนของเชลล์ว่างานเสร็จแล้ว nohup.out ไม่ได้สร้างใหม่ทุกครั้งที่รัน แต่เขียนต่อท้ายไฟล์เดิม ดังนั้นถ้ารันหลายงานจากโฟลเดอร์เดียวกัน เอาต์พุตจะปนกันอยู่ในไฟล์เดียว
ถ้าต้องการแยกล็อกของแต่ละงาน ให้กำหนดไฟล์เอาต์พุตด้วย > และส่งเอาต์พุตข้อผิดพลาดไปยังไฟล์เดียวกันด้วย 2>&1
nohup sh -c 'echo start; sleep 300' > job.log 2>&1 &[1] 3432059cat job.lognohup: ignoring input
startเมื่อใส่ 2>&1 ด้วย เทอร์มินัลแสดงเพียงหมายเลขงานและ PID ส่วนข้อความแจ้งของ nohup [nohup: ignoring input] ถูกบันทึกไว้ในบรรทัดแรกของไฟล์ล็อก
ถ้าใส่เพียง > แต่ไม่ใส่ 2>&1 เทอร์มินัลจะแสดงข้อความแจ้งว่าเอาต์พุตข้อผิดพลาดถูกส่งไปยังไฟล์ของเอาต์พุตมาตรฐาน
nohup sleep 300 > job2.log &[2] 3432097
nohup: ignoring input and redirecting stderr to stdoutงานที่ไม่ต้องเก็บเอาต์พุตไว้ให้ส่งไปที่ /dev/null กรณีนี้เทอร์มินัลก็แสดงเพียงหมายเลขงานและ PID เช่นกัน
nohup sleep 300 > /dev/null 2>&1 &[3] 3432137ตารางด้านล่างแสดงที่ที่เอาต์พุตไปและข้อความที่ปรากฏในเทอร์มินัลของการรันทั้งสี่แบบ
| รูปแบบการรัน | เอาต์พุตไปที่ | ข้อความในเทอร์มินัล |
|---|---|---|
| nohup คำสั่ง & | nohup.out ในโฟลเดอร์ปัจจุบัน | nohup: ignoring input and appending output to 'nohup.out' |
| nohup คำสั่ง > ไฟล์ & | ไฟล์ที่กำหนด (รวมเอาต์พุตข้อผิดพลาด) | nohup: ignoring input and redirecting stderr to stdout |
| nohup คำสั่ง > ไฟล์ 2>&1 & | ไฟล์ที่กำหนด | ไม่มี (ข้อความแจ้งอยู่บรรทัดแรกของไฟล์) |
| nohup คำสั่ง > /dev/null 2>&1 & | ทิ้ง | ไม่มี |
3️⃣ การตรวจสอบและหยุดโปรเซส nohup
รายการ jobs แสดงเฉพาะงานที่รันจากเชลล์ปัจจุบัน ดังนั้นหลังปิดเทอร์มินัลแล้วเชื่อมต่อใหม่ ให้ตรวจโปรเซส nohup ด้วย ps -p โดยระบุ PID ระหว่างที่ยังอยู่ในเชลล์เดิม jobs -l จะแสดงหมายเลขงาน PID และสถานะพร้อมกัน
jobs -l[1]+ 3431609 Running nohup sleep 300 &เมื่อใส่ PID หลัง ps -p และเลือกคอลัมน์ด้วย -o จะแสดงเพียงบรรทัดของโปรเซสนั้น S ใน STAT หมายถึงสถานะหลับเพื่อรอเหตุการณ์ และ ELAPSED คือเวลาที่ผ่านไปตั้งแต่เริ่มทำงาน
ps -p 3431609 -o pid,stat,etime,cmd PID STAT ELAPSED CMD
3431609 S 00:03 sleep 300เมื่อต้องการหยุด ให้ใส่ PID ต่อท้าย kill ได้เลย
kill 3431609kill ไม่แสดงอะไรออกมา และเมื่อรัน jobs ต่อ งานนั้นแสดงเป็น Terminated แล้วหายไปจากรายการ
jobs[1]+ Terminated nohup sleep 300เมื่อรัน ps อีกครั้งด้วย PID เดิม แสดงเพียงหัวตาราง จึงยืนยันได้ว่าโปรเซสจบแล้ว
ps -p 3431609 -o pid,stat,etime,cmd PID STAT ELAPSED CMDnohup ไม่สนใจเฉพาะสัญญาณตัดการเชื่อมต่อ จึงแม้จะส่งสัญญาณเดียวกันโดยตรงด้วย [kill -HUP] ก็ไม่จบ ได้ส่ง kill -HUP ไปยัง sleep 305 ที่รันด้วย nohup และ sleep 306 ที่รันโดยไม่มี nohup
kill -HUP 3437119 3437128เมื่อตรวจด้วย jobs -l ต่อ เหลือเพียงฝั่ง nohup ที่ยังเป็น Running ส่วน sleep 306 จบด้วย Hangup
jobs -l[1]- 3437119 Running nohup sleep 305 &
[2]+ 3437128 Hangup sleep 306ถ้าไม่ระบุสัญญาณให้ kill จะส่ง SIGTERM ดังนั้นงานที่รันด้วย nohup ก็หยุดได้ด้วย [kill PID]
4️⃣ เปรียบเทียบคำสั่ง nohup กับ disown และตัวเลือก
🔲 เปรียบเทียบ nohup กับ disown
disown เป็นคำสั่งในตัวของ bash ที่ใช้กับงานที่รันไปแล้ว ใช้เมื่อต้องการแยกงานที่รันด้วย & โดยไม่มี nohup ออกจากสัญญาณตัดการเชื่อมต่อของเทอร์มินัลภายหลัง disown ไม่เปลี่ยนเอาต์พุตไปที่ nohup.out ดังนั้นงานที่มีเอาต์พุตควรกำหนดที่เก็บเอาต์พุตด้วย > ไฟล์ ตั้งแต่ตอนรัน
ตามคู่มือทางการของ Bash ถ้าใช้ disown โดยไม่มีตัวเลือก งานนั้นจะหายไปจากรายการ jobs ส่วน disown -h จะเก็บงานไว้ในรายการแต่ไม่ส่งสัญญาณตัดการเชื่อมต่อให้ ขั้นแรกรัน sleep 302 แล้วรัน disown
sleep 302 &[1] 3433230disowndisown ไม่แสดงอะไรออกมา และ jobs -l ที่รันต่อก็ได้ผลว่างเปล่า
jobs -lต่อมารัน sleep 303 แล้วรัน disown -h กับงานหมายเลข %1
sleep 303 &[1] 3433343disown -h %1เมื่อตรวจด้วย jobs -l งานยังคงอยู่ในรายการ
jobs -l[1]+ 3433343 Running sleep 303 &จากนั้นรัน sleep 304 อีกหนึ่งตัวโดยไม่ทำอะไรเพิ่ม ปิดเทอร์มินัล แล้วตรวจ PID ทั้งสามจากเชลล์อื่น
sleep 304 &[2] 3433474ps -p 3433230,3433343,3433474 -o pid,stat,etime,cmd PID STAT ELAPSED CMD
3433230 S 00:11 sleep 302
3433343 S 00:08 sleep 303งานสองตัวที่ใช้ disown และ disown -h ยังอยู่ มีเพียง sleep 304 ที่ไม่ได้ทำอะไรเพิ่มที่จบไป เมื่อเทียบทั้งสี่วิธีจะเป็นดังนี้
| วิธี | ใช้เมื่อ | รายการ jobs | หลังปิดเทอร์มินัล | เอาต์พุต |
|---|---|---|---|---|
| nohup คำสั่ง & | ตอนรัน | ยังอยู่ | ยังอยู่ | nohup.out หรือไฟล์ที่กำหนด |
| คำสั่ง & แล้ว disown | หลังรัน | ข้าม | ยังอยู่ | ไม่เปลี่ยน |
| คำสั่ง & แล้ว disown -h | หลังรัน | ยังอยู่ | ยังอยู่ | ไม่เปลี่ยน |
| คำสั่ง & อย่างเดียว | — | ยังอยู่ | สิ้นสุดแล้ว | ไม่เปลี่ยน |
งานที่ต้องเรียกหน้าจอเซสชันกลับมาแล้วพิมพ์ต่อ เหมาะกับเทอร์มินัลมัลติเพล็กเซอร์อย่าง tmux ส่วนงานที่รันครั้งเดียวแล้วรับเพียงผลลัพธ์เป็นไฟล์ ใช้ nohup ก็เพียงพอ
🔲 ตัวเลือกของคำสั่ง nohup
📌 ตัวเลือกหลัก: ผลที่รันในบทความนี้
| ตัวเลือก | หน้าที่ | ผลที่เห็นในบทความนี้ | |
|---|---|---|---|
| --version | แสดงข้อมูลเวอร์ชันแล้วจบ | เซิร์ฟเวอร์ AlmaLinux 9.8 เป็น nohup (GNU coreutils) 8.32 และเซิร์ฟเวอร์ Debian 12 เป็น nohup (GNU coreutils) 9.1 |
📎 ตัวเลือกอื่น: ตามคู่มือทางการ
| ตัวเลือก | หน้าที่ | |
|---|---|---|
| --help | แสดงวิธีใช้แล้วจบ |
🔲 ตัวจำลองคำสั่ง nohup
ในตัวจำลองด้านล่าง คุณสามารถรันงานด้วย nohup ปิดเทอร์มินัลแล้วเชื่อมต่อใหม่ด้วยชิป 🔌 และดูด้วยตัวเองว่าโปรเซสใดยังเหลืออยู่
🔢 FAQ & เนื้อหาแนะนำ
ตั้งเวลางาน
Linux: ตั้งค่า crontab
การตั้งค่า crontab ตัวตั้งเวลาของลินุกซ์ ที่ใช้ลงทะเบียนงานให้ทำซ้ำตามเวลาที่กำหนด เช่น การสำรองข้อมูลหรือการล้างล็อก
โปรเซส
คำสั่ง top ของ Linux (ตรวจการใช้ CPU และหน่วยความจำ)
คำสั่ง top สำหรับดูการใช้ CPU และหน่วยความจำของแต่ละโปรเซสแบบเรียลไทม์
ℹ️ ประกาศเรื่องลิงก์แอฟฟิลิเอต
เนื้อหาของเว็บไซต์นี้มีลิงก์แอฟฟิลิเอต หากผู้เข้าชมซื้อสินค้าหรือบริการผ่านลิงก์เหล่านี้ เว็บไซต์นี้จะได้รับค่าคอมมิชชันจากผู้ขาย ในกระบวนการนี้ ราคาที่ผู้ซื้อจ่าย(ราคาจะลดลงเมื่อมีโปรโมชัน↓)จะไม่สูงขึ้นแต่อย่างใด ราคา ส่วนลด และข้อมูลสต็อกที่แสดงเป็นข้อมูล ณ เวลาที่เขียนและอาจต่างจากความเป็นจริง โปรดตรวจสอบกับผู้ขายอีกครั้งก่อนซื้อ การเลือกและการประเมินสินค้าเขียนตามเกณฑ์ของเราเอง และการได้รับค่าคอมมิชชันหรือไม่ไม่มีผลต่อลำดับการแนะนำหรือเนื้อหาการประเมิน