คำอธิบายค่าต่าง ๆ ที่เห็นบนหน้าจอ htop/top ของ Linux (2019)
(peteris.rocks)- เริ่มจาก หน้าจอ htop ของ Ubuntu Server 16.04 x64 แล้วไล่ตรวจสอบด้วย
/procและเอาต์พุตคำสั่งว่า uptime, load average, Tasks, PID, process tree, สถานะ, เวลา CPU, priority และตัวชี้วัดหน่วยความจำ หมายถึงอะไรจริง ๆ - ค่าจำนวนมากบนหน้าจอมาจากไฟล์ระบบอย่าง procfs และ
/etc/passwd,/etc/group,/etc/shadow,/etc/nsswitch.confและสามารถใช้straceตรวจสอบได้ว่าโปรแกรมอ่านไฟล์ใดบ้าง - Load average ไม่ใช่ค่าเดียวกับอัตราการใช้ CPU แต่เป็นค่าเฉลี่ยเคลื่อนที่แบบลดทอนเชิงเลขชี้กำลังที่รวมโปรเซสที่กำลังรัน·รอรัน และโปรเซสในสถานะ uninterruptible
- รหัสสถานะอย่าง
R,S,D,Z,T,tเชื่อมโยงกับการทำงานของ signal,kill,fork/exec/waitจึงเป็นเบาะแสในการตัดสินว่าโปรเซสหยุดหรือค้างอยู่เพราะอะไร VIRT,RES,SHR,MEM%แสดง หน่วยความจำเสมือน, หน่วยความจำจริง และหน่วยความจำที่แชร์ได้จากมุมมองต่างกัน จึงยากที่จะสรุปการใช้หน่วยความจำจริงจากตัวเลขเดียว
ค่าใน htop มาจากไหน
uptimeแสดงว่าระบบทำงานมานานแค่ไหนแล้ว และสามารถดูข้อมูลเดียวกันได้ด้วยคำสั่งuptime- โปรแกรม
uptimeอ่าน/proc/uptime- ตัวเลขแรกคือเวลารวมเป็นวินาทีที่ระบบเปิดอยู่
- ตัวเลขที่สองคือเวลารวมเป็นวินาทีที่ระบบอยู่ในสถานะ idle
- ในระบบแบบหลายคอร์ เวลา idle อาจถูกนำมารวมตามแต่ละคอร์ จึงอาจมากกว่า uptime รวมได้
- ใช้
strace uptime 2>&1 | grep openหรือstrace -e open uptimeเพื่อดูไฟล์ที่uptimeเปิด- เอาต์พุตตัวอย่างจะมี
/proc/uptime,/var/run/utmp,/proc/loadavg
- เอาต์พุตตัวอย่างจะมี
- ตัวเลขใน
/proc/uptimeเหมาะสำหรับใช้ในโปรแกรมหรือสคริปต์ ส่วนเอาต์พุตของuptimeถูกจัดรูปแบบให้อ่านง่ายสำหรับมนุษย์
Load average และอัตราการใช้ CPU
- ค่าสามตัวแรกของ
/proc/loadavgแสดง load average ของระบบในช่วง 1 นาที, 5 นาที, 15 นาที ล่าสุด - ค่าที่สี่แสดงจำนวนโปรเซสที่กำลังรันและจำนวนโปรเซสทั้งหมดในรูปแบบอย่าง
1/120และค่าสุดท้ายคือ PID ที่ถูกใช้ล่าสุด - เมื่อรันโปรเซสใหม่ จะมีการจัดสรร PID โดยปกติ PID จะเพิ่มขึ้นเรื่อย ๆ และเมื่อหมดจึงถูกนำกลับมาใช้ใหม่
- PID 1 เป็นของ
/sbin/initที่เริ่มทำงานตอนบูต
- PID 1 เป็นของ
- หากใน
htopเห็นโปรเซสที่กำลังรันเพียงตัวเดียว ตัวนั้นอาจเป็นhtopเอง sleep 30ไม่ได้อยู่ในสถานะกำลังรัน แต่เป็นสถานะ sleep จึงไม่เพิ่มจำนวน running process- งานที่ใช้ CPU ต่อเนื่องอย่าง
cat /dev/urandom > /dev/nullจะเพิ่มจำนวน running process และ load average - Load number คือค่าที่นับโปรเซสที่กำลังรันหรือรอรัน และโปรเซสในสถานะ uninterruptible
- load average ไม่ใช่ค่าเฉลี่ยธรรมดา แต่เป็น ค่าเฉลี่ยเคลื่อนที่แบบลดทอนเชิงเลขชี้กำลัง
- แม้แต่ load average แบบ 1 นาทีก็ไม่ได้สะท้อนเฉพาะ 60 วินาทีล่าสุดเท่านั้น แต่ให้น้ำหนักกับ 1 นาทีล่าสุดมากกว่า พร้อมรวมกิจกรรมก่อนหน้านั้นบางส่วนด้วย
- ในระบบ CPU เดียว หากมีโปรเซส CPU-bound หนึ่งตัว สามารถมองแบบง่าย ๆ ได้ว่า load average
1.00เท่ากับใช้ CPU 100%- ในระบบ 2 คอร์ สถานการณ์เดียวกันสามารถมองได้ว่าเป็นการใช้ CPU 50%
- load average ที่เทียบเท่าการใช้ CPU 100% บนระบบ 2 คอร์ สามารถทำให้ง่ายได้เป็น
2.00
- การทำให้ง่ายแบบนี้ไม่ถูกต้องเสมอไป เพราะโปรเซสสถานะ uninterruptible ถูกนับรวมใน load ด้วย
- จึงอาจเกิดสถานการณ์ที่ load average สูง แต่อัตราการใช้ CPU ไม่สูงได้
- อัตราการใช้ CPU ณ ขณะนั้นสามารถตรวจสอบได้ด้วย
mpstatsudo apt install sysstat -ympstat 1
Tasks, PID, process tree
- Tasks ที่มุมขวาบนของ
htopแสดงจำนวนโปรเซสทั้งหมดและจำนวนโปรเซสที่กำลังรัน - Linux kernel เรียกโปรเซสภายในว่า task และ
htopใช้คำว่า Tasks แทน Processes เพื่อลดพื้นที่บนหน้าจอ - ใช้
Shift+Hเพื่อสลับการแสดง thread- หากเห็นแบบ
Tasks: 23, 10 thrแปลว่ากำลังแสดง thread อยู่
- หากเห็นแบบ
- ใช้
Shift+Kเพื่อสลับการแสดง kernel thread- หากเห็นแบบ
Tasks: 23, 40 kthrแปลว่ากำลังแสดง kernel thread อยู่
- หากเห็นแบบ
- ทุกครั้งที่โปรเซสใหม่เริ่มทำงาน จะมีการจัดสรร PID
- หากรันแบบเบื้องหลังอย่าง
sleep 1000 &จะแสดงหมายเลข job และ PID $!ของbashจะขยายเป็น ID ของโปรเซสเบื้องหลังล่าสุด
- หากรันแบบเบื้องหลังอย่าง
- ข้อมูลเกี่ยวกับโปรเซสอยู่ใต้
/proc/<pid>//proc/<pid>/cmdlineเก็บคำสั่งที่ใช้รัน และอาร์กิวเมนต์ถูกคั่นด้วยไบต์\0- สามารถดูให้อ่านง่ายได้ด้วย
tr '\0' '\n' < /proc/<pid>/cmdlineหรือstrings /proc/<pid>/cmdline /proc/<pid>/cwdเป็นลิงก์ไปยังไดเรกทอรีทำงานปัจจุบัน และ/proc/<pid>/exeเป็นลิงก์ไปยังไบนารีที่ถูกเรียกใช้
- เครื่องมือวินิจฉัยอย่าง
htop,top,psอ่านรายละเอียดโปรเซสจาก/proc/<pid>/<file> - ฝั่งที่สร้างโปรเซสใหม่คือ parent process ส่วนฝั่งที่ถูกสร้างขึ้นใหม่คือ child process และความสัมพันธ์นี้ก่อให้เกิด process tree
- กด
F5ในhtopเพื่อดูโครงสร้างลำดับชั้นของโปรเซสps fและpstree -aก็แสดงความสัมพันธ์เดียวกัน
- เมื่อรัน
dateในbashตัวbashจะสร้างสำเนาของตัวเองด้วยforkจากนั้นโหลด/bin/dateเข้าในหน่วยความจำด้วยexecแล้วbashซึ่งเป็น parent จะรอให้ child จบการทำงาน /sbin/initเริ่มทำงานตอนบูตและเรียกsshdขึ้นมา เมื่อเชื่อมต่อผ่าน SSH ตัวsshdจะสร้างโปรเซสเซสชัน และเซสชันนั้นจะรัน shellbash
ผู้ใช้และสิทธิ์ของโปรเซส
- แต่ละโปรเซสมีเจ้าของเป็นผู้ใช้ และผู้ใช้จะแสดงด้วย ID แบบตัวเลข
- สามารถตรวจสอบ ID ผู้ใช้ของโปรเซสได้จากรายการ
Uidใน/proc/<pid>/status - คำสั่งอย่าง
id 1000จะแสดงชื่อผู้ใช้และกลุ่มที่ตรงกับ ID แบบตัวเลขนั้น idเลือกแหล่งที่ใช้แปลงชื่อ ตามการตั้งค่าใน/etc/nsswitch.conf- ในระบบตัวอย่าง จะอ่าน
/etc/passwdและ/etc/group compatคือ Compatibility mode ซึ่งเหมือนกับfilesแต่อนุญาตรายการพิเศษได้- ข้อมูลผู้ใช้อาจถูกเก็บไว้ในฐานข้อมูลหรือบริการอื่น เช่น LDAP ได้ด้วย
- ในระบบตัวอย่าง จะอ่าน
/etc/passwdและ/etc/groupเป็นไฟล์ข้อความธรรมดาที่แมป ID แบบตัวเลขให้เป็นชื่อที่มนุษย์อ่านได้- ข้อมูลรหัสผ่านจริงอยู่ใน
/etc/shadow$6$หมายถึงอัลกอริทึมแฮชsha512- ถัดจากนั้นจะเป็น salt แบบสุ่มเพื่อป้องกันการโจมตีแบบ rainbow table และ hash ของ password+salt
- โดยพื้นฐานแล้ว โปรแกรมจะรันด้วยสิทธิ์ของผู้ใช้ที่สั่งรัน
- แม้เจ้าของไฟล์ executable จะเป็นผู้ใช้อื่นก็ยังเป็นเช่นเดียวกัน
- หากต้องการรันเป็นผู้ใช้อื่นหรือเป็น
rootให้ใช้sudosudo idจะรันด้วย UID 0 ของroot- สามารถรันเป็นผู้ใช้ที่กำหนดได้ เช่น
sudo -u daemon id
- หากพยายามเขียนลง
/etc/sudoersโดยใช้ redirect โดยตรง อาจล้มเหลวได้ เพราะมีเพียงechoที่รันเป็น root ส่วน append ถูกทำโดยผู้ใช้ปัจจุบันecho "$USER ALL=(ALL) NOPASSWD: ALL" | sudo tee -a /etc/sudoerssudo bash -c "echo '$USER ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers"
- ควรแก้ไข
/etc/sudoersด้วยsudo visudo- จะตรวจสอบเนื้อหาก่อนบันทึก เพื่อป้องกันความผิดพลาดที่ทำให้ใช้
sudoไม่ได้
- จะตรวจสอบเนื้อหาก่อนบันทึก เพื่อป้องกันความผิดพลาดที่ทำให้ใช้
/usr/bin/passwdสามารถเขียนลง/etc/shadowได้ แม้ผู้ใช้ทั่วไปจะเป็นคนรัน- ในสิทธิ์ไฟล์มี
sจึงทำงานเป็นไฟล์ executable แบบ setuid - จะรันด้วยสิทธิ์ของ
rootซึ่งเป็นเจ้าของไฟล์ executable - สามารถหาไฟล์ executable แบบ setuid ที่เป็นของ root ได้ด้วย
find /bin -user root -perm -u+s
- ในสิทธิ์ไฟล์มี
โค้ดสถานะของโปรเซส
- คอลัมน์สถานะใน
htopแสดงชื่อเป็นSและค่าหลักมีดังนี้R: running หรือ runnable คือกำลังรันอยู่หรือรออยู่ใน run queueS: interruptible sleep คือรอให้อีเวนต์เสร็จสิ้นD: uninterruptible sleep โดยทั่วไปคือรอ I/OZ: defunct zombie คือจบการทำงานแล้วแต่ parent ยังไม่ได้ reapT: หยุดด้วย job control signalt: หยุดโดย debugger ระหว่าง tracingX: dead เป็นสถานะที่ไม่ควรปรากฏให้เห็น
psยังแสดง substate เช่นSs,R+,Ss+ด้วย-
R: กำลังรันหรือพร้อมรัน
- สถานะ
Rหมายถึงโปรเซสกำลังรันอยู่ในขณะนั้น หรือกำลังรอในคิวรัน - ซอร์สโค้ดของโปรแกรมเมื่อคอมไพล์แล้วจะกลายเป็นคำสั่ง CPU และเมื่อรันจะถูกโหลดเข้าเมโมรีเพื่อให้ CPU ประมวลผลคำสั่งเหล่านั้น
- การที่กำลังรันอยู่หมายความว่า CPU กำลังประมวลผลคำสั่งทางกายภาพจริง ๆ
- สถานะ
-
S: sleep ที่ interrupt ได้
- ในสถานะ
Sคำสั่งของโปรเซสจะไม่ถูกประมวลผลบน CPU แต่กำลังรออีเวนต์หรือเงื่อนไขบางอย่าง - เมื่ออีเวนต์เกิดขึ้น เคอร์เนลจะเปลี่ยนสถานะเป็น running
sleep 1000เป็นตัวอย่างของการรอเป็นเวลาที่กำหนด- สถานะนี้สามารถถูก interrupt ได้ด้วย signal
- ใน
htopสามารถกดF9เพื่อส่ง signal ได้ killคือ system call ที่ส่ง signal และ/bin/killคือโปรแกรมใน userland ที่เรียกใช้สิ่งนี้- signal เริ่มต้นคือ
TERMซึ่งร้องขอให้โปรเซสสิ้นสุดการทำงาน - signal เป็นตัวเลข และชื่อมักเขียนเป็นตัวพิมพ์ใหญ่ โดยอาจมี prefix
SIG - ตัวอย่าง:
INT,KILL,STOP,CONT,HUP kill -INT 10089,kill -2 10089,/bin/kill -2 10089ทำงานเหมือนกัน- เมื่อกด
CTRL+Cbashจะส่งSIGINTไปยัง foreground process - การส่ง
SIGINTหรือSIGTERMไม่ได้หมายความว่าโปรเซสจะต้องจบการทำงานเสมอไป - โปรแกรมสามารถตั้งค่า signal handler เพื่อจัดการ เช่น ทำงานเก็บกวาดก่อนแล้วจึงจบการทำงาน
SIGKILLหรือ9ทำให้เคอร์เนลบังคับจบโปรเซสโดยไม่ให้โอกาสโปรเซสตอบสนอง
- ในสถานะ
-
D: sleep ที่ interrupt ไม่ได้
- สถานะ
Dไม่สามารถปลุกด้วย signal ได้ และเนื่องจากSIGKILLก็เป็น signal จึงไม่สามารถ kill โปรเซสแบบนี้ได้ - สถานะนี้ใช้เมื่อโปรเซสจำเป็นต้องรอโดยไม่ถูกขัดจังหวะ หรือคาดว่าอีเวนต์จะเกิดขึ้นอย่างรวดเร็ว
- ตัวอย่าง: disk read/write
- uninterruptible process มักอาจเป็นสถานะที่รอ I/O หลังจาก page fault
- สถานะนี้อาจเกิดขึ้นจากความล่าช้าในการอ่าน·เขียน NFS
- อาจพบได้ในสถานการณ์ที่หน่วยความจำที่ใช้ได้มีน้อยเกินไปจนโปรเซสทำ swap จำนวนมาก
- ตัวอย่างเช่น หากรัน
sudo mount 8.8.8.8:/tmp /tmp &/sbin/mount.nfsจะอยู่ในสถานะD - เมื่อดูด้วย
straceจะเห็นว่า system callmountทำให้โปรเซสถูก block - หากใส่ออปชัน
intrให้กับmountจะทำให้รันแบบ interruptible ได้ sudo mount 8.8.8.8:/tmp /tmp -o intr
- สถานะ
-
Z: โปรเซสซอมบี้
- สถานะ
Zคือสถานะที่โปรเซสจบการทำงานแล้ว แต่ parent ยังไม่ได้ reap - โปรเซสซอมบี้ที่มีอยู่ช่วงสั้น ๆ อาจเป็นเรื่องปกติได้
- โปรเซสซอมบี้ที่ค้างอยู่นานอาจบ่งชี้ถึงบั๊กของโปรแกรม
- โปรเซสซอมบี้ไม่ใช้หน่วยความจำ และครอบครองเพียง PID เท่านั้น
- ไม่สามารถ
killโปรเซสซอมบี้โดยตรงได้ - สามารถส่ง
SIGCHLDไปยัง parent process เพื่อร้องขอให้ reap ซอมบี้ได้ - หาก kill parent process ก็สามารถลบ parent และซอมบี้ของมันได้
- สามารถจำลองสถานะซอมบี้ได้ด้วยโปรแกรม C ที่หลัง
forkแล้ว child เรียกexit(0)และ parent เรียกsleep(20) - เมื่อ parent จบลง ซอมบี้จะหายไป
- เหตุผลที่ซอมบี้ยังคงอยู่คือ parent ต้องสามารถตรวจสอบ exit code ของ child ได้ผ่าน system call
wait
- สถานะ
-
T และ t: โปรเซสที่หยุดอยู่
- สถานะ
Tคือสถานะที่ถูกหยุดด้วย job control signal - ระหว่างรัน
cat /dev/urandom > /dev/nullหากกดCTRL+Zจะเข้าสู่สถานะT - สามารถรันต่อได้ด้วย
fg - อาจหยุดด้วย signal
STOPและกลับมาทำงานต่อด้วย signalCONTได้เช่นกัน - สถานะ
tคือสถานะที่หยุดระหว่างที่ debugger กำลัง tracing - หาก attach ด้วย
sudo gdb -p <pid>ไปยังโปรเซสที่รันด้วยnc -l 1234 &จะเข้าสู่สถานะt
- สถานะ
เวลา CPU, niceness, priority
- Linux เป็นระบบปฏิบัติการแบบ multitasking จึงทำให้ดูเหมือนว่ามีหลาย process ทำงานพร้อมกันได้ แม้บน CPU เพียงตัวเดียว
- ในความเป็นจริง CPU ตัวเดียวสามารถรันคำสั่งได้ครั้งละหนึ่งคำสั่งเท่านั้น จึงใช้ time sharing
- process หนึ่งทำงานช่วงสั้น ๆ แล้วถูกหยุด
- process อื่นที่รอรันอยู่จะถูกนำมารันตามลำดับ
- ช่วงเวลาสั้น ๆ ที่ process หนึ่งได้รันเรียกว่า time slice
- โดยปกติ time slice มีความยาวเพียงไม่กี่มิลลิวินาที หาก system load ไม่สูงจึงแทบไม่รู้สึกถึงเรื่องนี้
- หาก load average บน single core เป็น
1.0ถือได้ว่า CPU ถูกใช้งาน 100%- หากสูงกว่า
1.0แปลว่าจำนวน process ที่ต้องการรันมีมากกว่าที่ CPU จะประมวลผลได้ จึงอาจเกิด slowdown หรือ delay - หากต่ำกว่า
1.0แปลว่า CPU อยู่ในสถานะ idle เป็นบางครั้ง
- หากสูงกว่า
- เหตุผลที่ running time ของ process อาจไม่เท่ากับเวลาที่ผ่านไปจริงอย่างแม่นยำ ก็อธิบายได้ด้วย time sharing
- หากมี task ที่ต้องรันมากกว่าจำนวน CPU core ที่ใช้งานได้ ต้องตัดสินใจว่า task ใดควรถูกรันก่อน
- scheduler ของ Linux kernel จะเลือก process ถัดไปจาก run queue โดยขึ้นอยู่กับอัลกอริทึม scheduler ของ kernel
- โดยทั่วไปเราไม่สามารถควบคุม scheduler ได้โดยตรง แต่สามารถบอกได้ว่า process ใดสำคัญกว่า
- niceness ที่แสดงเป็น
NIคือ priority ฝั่ง user-space- ช่วงค่าคือ
-20ถึง19 -20คือ priority สูงสุด และ19คือ priority ต่ำสุด- process ที่ nice มากกว่า อาจมองได้ว่ายอมหลีกทางให้ process ที่ nice น้อยกว่า
- ช่วงค่าคือ
PRIคือ priority ฝั่ง kernel-space ที่ Linux kernel ใช้- ช่วงค่าคือ
0ถึง139 0~99เป็น real time ส่วน100~139เป็นช่วงสำหรับ user
- ช่วงค่าคือ
- ความสัมพันธ์ระหว่างค่า nice กับ priority อธิบายได้ด้วย
PR = 20 + NI-20~+19ของNIจะกลายเป็น0~39ของPRและถูก map ไปยัง100~139
- niceness ก่อนเริ่มรันตั้งค่าได้ด้วย
nice -n niceness program - niceness ของ process ที่กำลังรันอยู่เปลี่ยนได้ด้วย
renice -n niceness -p PID - สีของอัตราการใช้ CPU มีดังนี้
- Blue: thread ที่มี priority ต่ำ,
nice > 0 - Green: thread ที่มี priority ปกติ
- Red: kernel thread
- Blue: thread ที่มี priority ต่ำ,
ตัวชี้วัดหน่วยความจำ: VIRT, RES, SHR, MEM%
- process ดูเหมือนว่ามีตัวเองอยู่ในหน่วยความจำเพียงลำพัง ซึ่งทำได้ด้วย virtual memory
- process ไม่ได้เข้าถึง physical memory โดยตรง แต่มี virtual address space ของตัวเอง
- kernel สามารถแปลง virtual memory address เป็น physical memory หรือ map บางส่วนไปยัง disk ได้
- ด้วยเหตุนี้จึงอาจดูเหมือนว่า process ใช้หน่วยความจำมากกว่าหน่วยความจำที่ติดตั้งอยู่ในคอมพิวเตอร์
- ปริมาณการใช้หน่วยความจำของ process จะแตกต่างกันตามว่าจะนับรายการต่อไปนี้รวมด้วยหรือไม่
- shared library
- disk-mapped memory
- swapped out memory
- สีของการใช้หน่วยความจำมีดังนี้
- Green: used memory
- Blue: buffers
- Orange: cache
-
VIRT/VSZ
VIRTคือปริมาณ virtual memory ทั้งหมดที่ task ใช้- รวมถึง code, data, shared library, swapped out page และ page ที่ถูก mapped แล้วแต่ยังไม่ได้ใช้
- แม้แอปพลิเคชันจะร้องขอ 1GB และใช้จริงเพียง 1MB ค่า
VIRTก็อาจแสดงเป็น 1GB ได้ - แม้จะ
mmapไฟล์ขนาด 1GB แล้วไม่ได้ใช้จริง ค่าVIRTก็อาจแสดงเป็น 1GB ได้ - ในกรณีส่วนใหญ่
VIRTไม่ใช่ตัวเลขที่มีประโยชน์
-
RES/RSS
RESคือ physical memory ที่ไม่ได้ถูก swapped out กล่าวคือปริมาณ resident memory ที่อยู่ใน physical memory ปัจจุบันRESอาจสะท้อนการใช้หน่วยความจำจริงได้ดีกว่าVIRTแต่ก็มีข้อจำกัด- ไม่รวม swapped out memory
- หน่วยความจำบางส่วนอาจถูกแชร์กับ process อื่น
- หาก process ใช้หน่วยความจำ 1GB แล้ว
fork()ค่าRESของ process ทั้งสองอาจดูเหมือนเป็น 1GB แต่ละตัว แต่จริง ๆ แล้วอาจใช้เพียง 1GB เนื่องจาก copy-on-write ของ Linux
-
SHR
SHRคือปริมาณ shared memory ที่ task ใช้- สะท้อนหน่วยความจำที่อาจแชร์กับ process อื่นได้
- ตัวอย่างโปรแกรม C แสดงให้เห็นว่าค่า
VIRT,RES,SHRเปลี่ยนไปอย่างไรผ่านขั้นตอนmalloc, การใช้หน่วยความจำบางส่วน,forkและการเขียนหน่วยความจำเพิ่มเติม - ส่วนตัวอย่างหน่วยความจำดังกล่าวยังคงถูกทิ้งไว้เป็น TODO
-
MEM%
MEM%คือสัดส่วนของ available physical memory ที่ task ใช้อยู่ในปัจจุบัน- เป็นค่าที่ได้จากการนำ
RESหารด้วย RAM ทั้งหมด - ตัวอย่าง: หาก
RESเป็น400Mและ RAM เป็น 8GB จะได้400/8192*100 = 4.88%
โปรเซสพื้นฐานของ Ubuntu Server 16.04
-
สำรวจโปรเซสที่เริ่มทำงานบน Ubuntu Server 16.04.1 LTS x64 ของ Digital Ocean droplet ใหม่เอี่ยม
-
/sbin/init/sbin/initทำหน้าที่ประสานงานส่วนที่เหลือของ boot process และตั้งค่าสภาพแวดล้อมของผู้ใช้- กลายเป็น parent หรือ grandparent ของโปรเซสที่เริ่มทำงานโดยอัตโนมัติ
- ผลลัพธ์ของ
dpkg -S /sbin/initคือsystemd-sysv: /sbin/initซึ่งในระบบนี้หมายถึง systemd - แม้จะ kill ก็ไม่เกิดอะไรขึ้น
-
/lib/systemd/systemd-journaldsystemd-journaldเป็น system service ที่รวบรวมและจัดเก็บ logging data- สร้างและดูแล structured, indexed journal จากข้อมูล log ที่ได้รับจากหลาย source
- ใช้รูปแบบไฟล์พิเศษที่ปรับให้เหมาะกับ log message แทนไฟล์ log แบบข้อความธรรมดา
- ดูได้ด้วย
journalctl journalctl _COMM=sshdjournalctl _COMM=sshd -o json-prettyjournalctl --since yesterdayjournalctl -bjournalctl -fjournalctl --disk-usagejournalctl --vacuum-size=1G- ดูเหมือนจะลบหรือปิดใช้งานไม่ได้ ทำได้เพียงปิด logging เท่านั้น
-
/sbin/lvmetad -flvmetadcache metadata ของ LVM เพื่อให้คำสั่ง LVM อ่าน metadata ได้โดยไม่ต้อง scan disk- การ scan disk ใช้เวลาและอาจรบกวนการทำงานปกติของระบบและ disk
- LVM มองได้ว่าเป็น “dynamic partitions” ที่สามารถสร้าง, resize และลบ logical volume ได้ขณะที่ Linux กำลังทำงาน
- สรุปว่าหากใช้งาน LVM อยู่ก็ควรเก็บไว้
-
/lib/systemd/udevdsystemd-udevdฟัง kernel uevent และรัน matching instruction ของ udev rules สำหรับแต่ละ event- udev เป็น device manager ของ Linux kernel และจัดการ device node ใน directory
/devเป็นหลัก - ไม่แน่ใจว่าจำเป็นสำหรับ virtual server หรือไม่
-
/lib/systemd/timesyncdsystemd-timesyncdเป็น system service ที่ซิงก์ local system clock กับ remote NTP server- ใช้แทน
ntpd - ในระบบตัวอย่าง
timedatectl statusแสดง network time และ NTP synchronized เป็นyes - ในผลลัพธ์
netstatเห็นเฉพาะ SSH port ที่อยู่ในสถานะ listening และไม่ได้เปิด UDP 123 port หลายพอร์ตเหมือนntpdของ Ubuntu 14.04
-
/usr/sbin/atd -fatdรัน job ที่ถูกใส่ไว้ใน queue เพื่อให้ทำงานในภายหลังatและbatchอ่านคำสั่งจาก stdin หรือไฟล์ แล้วนำไปรันภายหลัง- ต่างจาก cron ที่นัดหมายการทำงานซ้ำ ๆ
atจะรันครั้งเดียว ณ เวลาที่กำหนด - ในตัวอย่างใช้
echo "touch /tmp/yolo.txt" | at now + 1 minuteเพื่อสร้างไฟล์หลังจาก 1 นาที - หากไม่ใช้ ให้ลบด้วย
sudo apt remove at -y --purge
-
/usr/lib/snapd/snapd- Snappy Ubuntu Core ถูกแนะนำว่าเป็น Ubuntu rendition ที่ใช้ transactional update
- snap ถูกอธิบายว่าเป็น universal Linux package format ที่ทำให้ binary package เดียวทำงานได้บน Linux desktop, server, cloud และ device
- เข้าใจได้ว่าเป็น deb package แบบ simplified ที่รวม dependency ไว้ใน snap เดียวเพื่อแจกจ่าย
- เนื่องจากไม่เคย deploy หรือ distribute แอปพลิเคชันด้วย snappy บน server จึงลบด้วย
sudo apt remove snapd -y --purge
-
/usr/bin/dbus-daemon- D-Bus เป็นกลไก IPC และ RPC ระหว่างหลาย process ที่รันพร้อมกันบน machine เดียวกัน
- จำเป็นสำหรับ desktop environment แต่มีข้อสงสัยว่าจำเป็นสำหรับ server ที่รัน web app หรือไม่
- เมื่อลบ
dbusออกtimedatectl statusล้มเหลวด้วยข้อความFailed to create bus connection: No such file or directory - ดังนั้นจึงสรุปว่าควรเก็บไว้
-
/lib/systemd/systemd-logindsystemd-logindเป็น system service ที่จัดการ user login
-
/usr/sbin/cron -fcronเป็น daemon ที่รัน scheduled command-fหมายถึง foreground mode คือไม่ daemonize- งานที่ต้องรันเป็นระยะสามารถนัดหมายด้วย cron ได้
crontab -e- สรุปว่าใน Ubuntu มักใช้
/etc/cron.hourly,/etc/cron.dailyเป็นต้น - ดู log ได้ด้วยวิธีต่อไปนี้
grep cron /var/log/syslogjournalctl _COMM=cronjournalctl _COMM=cron --since="date" --until="date"- มีความเป็นไปได้สูงว่าจะเก็บ cron ไว้
- หากไม่ลบ สามารถหยุดและปิดใช้งานด้วย
sudo systemctl stop cron,sudo systemctl disable cron apt remove cronอาจพยายามติดตั้ง postfix เป็นต้น- เพราะ cron suggest mail transport agent
-
/usr/sbin/rsyslogd -nrsyslogdเป็น system utility ที่รองรับ message logging- ทำหน้าที่เติมไฟล์ log ใน
/var/log/เช่น/var/log/auth.log - ไฟล์ config อยู่ใน
/etc/rsyslog.d - สามารถส่ง log ไปยัง server ระยะไกลเพื่อทำ centralized logging ได้
- ใช้คำสั่ง
loggerเพื่อให้ background script เขียนข้อความลงใน/var/log/syslogได้ - แม้จะมี
systemd-journaldอยู่แล้ว แต่ rsyslog กับ journal มีคุณลักษณะต่างกัน จึงอาจมีกรณีที่ใช้ร่วมกันแล้วเป็นประโยชน์ - ดังนั้นตอนนี้จึงเก็บไว้ก่อน
-
/usr/sbin/acpidacpidเป็น ACPI event daemon- ออกแบบมาเพื่อแจ้ง ACPI event ให้ user-space program
- ACPI ใช้กับ hardware component discovery/configuration, power management, status monitoring เป็นต้น
- เนื่องจากไม่ได้ตั้งใจใช้ suspend/resume บน virtual server จึงลองลบออก
rebootสำเร็จ แต่หลังจากhaltแล้ว Digital Ocean ยังคงรับรู้ว่าเปิดอยู่ จึงต้อง Power Off จาก web interface- ดังนั้นจึงสรุปว่าควรเก็บไว้
-
/usr/bin/lxcfs /var/lib/lxcfs/lxcfsเป็น FUSE filesystem ที่ออกแบบมาสำหรับ LXC container- ให้ virtualized view ของไฟล์บางส่วนใน
/procและ filtered access ไปยัง host cgroup filesystem - ทำให้ uptime, top เป็นต้นภายใน container ให้ผลลัพธ์ที่ “ถูกต้อง” มากขึ้น
- หากไม่ได้ใช้ LXC container สามารถลบด้วย
sudo apt remove lxcfs -y --purge
-
/usr/lib/accountservice/accounts-daemon- AccountsService ให้ D-Bus interface และ implementation สำหรับ query และจัดการข้อมูล user account
- implementation อิงตามคำสั่ง
usermod(8),useradd(8),userdel(8)
-
หลังลบออกแล้ว อะไรจะพังบ้างนั้นปล่อยให้ “Time will tell”
-
/sbin/mdadmmdadmเป็นยูทิลิตีของ Linux สำหรับจัดการและมอนิเตอร์อุปกรณ์ software RAID- RAID คือวิธีใช้ hard drive หลายลูกให้เหมือนเป็นลูกเดียว
- RAID 0 ใช้เพื่อขยายความจุของ drive
- RAID 1, RAID 5, RAID 6, RAID 10 มีจุดประสงค์เพื่อป้องกัน data loss เมื่อ drive failure
- สามารถลบออกได้ด้วย
sudo apt remove mdadm -y --purge
-
/usr/lib/policykit-1/polkitd --no-debugpolkitdคือ PolicyKit daemon และ polkit เป็น Authorization Framework- เข้าใจได้ว่าเป็น sudo แบบ fine-grained
- สามารถให้สิทธิ์แก่ non-privileged user ในการทำ action บางอย่างในฐานะ root ได้
- ตัวอย่าง: อนุญาตให้ reboot บน desktop Linux
- สำหรับ server สรุปไว้ว่าสามารถลบออกได้ด้วย
sudo apt remove policykit-1 -y --purge - แต่อะไรจะพังบ้างยังคงเป็นคำถามอยู่
-
/usr/sbin/sshd -Dsshdคือ OpenSSH Daemon- ตัวเลือก
-Dทำให้ไม่ detach และไม่กลายเป็น daemon ช่วยให้ monitoring ได้ง่ายขึ้น
-
/sbin/iscsidiscsidเป็น background daemon ที่ทำงานตาม iSCSI configuration และจัดการ connection- iSCSI เป็นมาตรฐาน storage networking บน IP ที่ส่ง SCSI command ผ่าน IP network ทำให้ใช้ remote storage ได้เหมือน local disk
- สามารถลบออกได้ด้วย
sudo apt remove open-iscsi -y --purge
-
/sbin/agetty --noclear tty1 linuxagettyคือ alternative Linux getty- getty จัดการ physical หรือ virtual terminal และเมื่อพบการเชื่อมต่อจะเปิด username prompt จากนั้นรันโปรแกรม
login - บน Digital Ocean สามารถโต้ตอบกับ terminal นี้ผ่าน browser ได้จาก
Consoleใน droplet details - เมื่อลบไฟล์ที่เกี่ยวข้องกับ
getty@tty1.serviceแล้ว reboot ยังเชื่อมต่อ SSH ได้ แต่ไม่สามารถ login ผ่าน Digital Ocean web console ได้
-
เซสชัน SSH, bash, htop
sshd: root@pts/0หมายความว่า SSH session ของผู้ใช้rootถูกตั้งค่าไว้บน pseudoterminalpts/0- pseudoterminal จำลอง text terminal จริง
bashคือ shell ที่กำลังใช้งาน- ถ้ามี dash นำหน้าอย่าง
-bashแปลว่าเริ่มต้นเป็น login shell - shell ที่อักขระแรกของ argument zero เป็น
-หรือเริ่มด้วย option--loginคือ login shell - ในกรณีนี้จะอ่าน configuration file set อีกชุดหนึ่ง
htopคือ interactive process viewer ที่กำลังรันอยู่ใน screenshot
การทดลองลบบริการ
- รายการลบทั่วไปมีดังนี้
sudo apt remove lvm2 -y --purgesudo apt remove at -y --purgesudo apt remove snapd -y --purgesudo apt remove lxcfs -y --purgesudo apt remove mdadm -y --purgesudo apt remove open-iscsi -y --purgesudo apt remove accountsservice -y --purgesudo apt remove policykit-1 -y --purge
- Extreme edition รวมงานต่อไปนี้ด้วย
sudo apt remove dbus -y --purgesudo apt remove rsyslog -y --purgesudo apt remove acpid -y --purgesudo systemctl stop cron && sudo systemctl disable cronsudo rm /etc/systemd/system/getty.target.wants/getty@tty1.servicesudo rm /lib/systemd/system/getty@.service
- คอนฟิก nginx, PHP7, MySQL ที่ทำตามคำแนะนำ unattended installation of WordPress on Ubuntu Server ใช้งานได้
ภาคผนวก: เครื่องมือสำรวจและพฤติกรรมของ shell
-
การค้นหาซอร์สโค้ด
- เมื่อใช้แค่
straceยังไม่พอ สามารถดู source code ได้ - หา location ของ binary ด้วย
which uptimeแล้วหา Ubuntu package ด้วยdpkg -S /usr/bin/uptime - ในตัวอย่าง
uptimeอยู่ใน packageprocps - สามารถค้นหา package ที่ packages.ubuntu.com และหา link ไปยัง source repository ได้
- เมื่อใช้แค่
-
file descriptor และ redirection
- เมื่อต้อง redirect stderr ไปยัง stdout ให้ใช้
2>&1 echo something > fileคือการเขียน stdout ลง file และเหมือนกับecho something 1> fileecho something 2> fileเขียน stderr ลง fileecho something 2>1หมายถึง redirect stderr ไปยัง filename ชื่อ1- ใน
2>&1ที่มี&นั้น1ไม่ใช่ filename แต่เป็น stream ID
- เมื่อต้อง redirect stderr ไปยัง stdout ให้ใช้
-
ปัญหาสีของ PuTTY
- หากองค์ประกอบของ
htopดูเหมือนหายไปใน PuTTY สามารถแก้ได้ที่การตั้งค่า Window → Colours - คลิกขวาที่ title bar
- Change settings...
- Window → Colours
- เลือก Both radio button
- Apply
- หากองค์ประกอบของ
-
shell แบบง่ายที่เขียนด้วย C
- shell แบบง่ายที่เขียนด้วย C แสดงการใช้ system call
fork,exec,wait - หาก input เป็น
exitจะออกจากโปรแกรมด้วย shell built-in - คำสั่งอื่น ๆ จะ
forkแล้วให้ child รันด้วยexeclpส่วน parent รอสถานะการจบด้วยwaitpid - ตัวอย่างการรัน
date,true,falseจะแสดง child exit code ตามลำดับ - เหตุผลที่ข้อความจบของ background process อย่าง
sleep 1 &จะแสดงก็ต่อเมื่อกด Enter แล้ว คือ shell กำลังรอ input และจะตรวจสอบสถานะของ background process ตอนมีการป้อนคำสั่ง
- shell แบบง่ายที่เขียนด้วย C แสดงการใช้ system call
รายการที่เหลือต้องสำรวจและประวัติการแก้ไข
- รายการที่อยากศึกษาเพิ่มเติม ได้แก่ process state substatus, kernel thread,
/dev/pts, หน่วยความจำCODE·DATA·SWAP, ความยาว time slice, อัลกอริทึม Linux scheduler, core pinning, manual page, สีของ CPU/memory bar, process ID limit และ fork bomb,lsof,ionice,schedtoolเป็นต้น - การแก้ไข·อัปเดตหลักมีดังนี้
- idle time ของ
/proc/uptimeเป็นผลรวมของทุก core - แก้
printfของ parent/child ในตัวอย่าง zombie C - เพิ่มว่า
apt remove cronจะพยายามติดตั้งpostfixเนื่องจาก dependency ของ MTA idสามารถโหลดข้อมูลจาก source อื่นนอกจาก/etc/passwdผ่าน/etc/nsswitch.confได้- เพิ่มคำอธิบาย password hash format ของ
/etc/shadow - ควรแก้ไข
/etc/sudoersอย่างปลอดภัยด้วยvisudo - เพิ่มคำอธิบาย
MEM% - เขียนส่วน load average ใหม่
- แก้ไขว่า signal เริ่มต้นของ
kill 1234ไม่ใช่INTแต่เป็นTERM - เพิ่มคำอธิบาย CPU และ memory color bar
- idle time ของ
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
ช่วงหลังผมย้ายมาใช้ btop แล้ว อินเทอร์เฟซดูทันสมัยเท่าที่ต้องการ ใช้งานได้ดี และให้ข้อมูลมากพอ
อย่างที่คนอื่นพูดกัน ดูเหมือนจะแสดงการใช้พลังงาน (Watts) ด้วย และยังมีข้อมูลเครือข่าย, GPU, ดิสก์มาพร้อมกัน
https://github.com/aristocratos/btop
ปิดแถบการใช้งานดิสก์ไม่ได้ ทำให้ถ้าหน้าต่างคอนโซลไม่ใหญ่มาก กราฟความเร็ว I/O จะถูกบีบจนดูอึดอัดมาก
กราฟ CPU/GPU กินพื้นที่มากเกินไป และโดยรวมอยากให้ตารางไฟล์ที่เปิดอยู่ใช้พื้นที่มากกว่านี้
มีการตั้งค่า 2 อย่างที่ผมเปลี่ยนทุกครั้งเวลาใช้ htop และมันต่างกันมาก
อย่างแรก ปิด เธรดของผู้ใช้ โดยมากมันแค่ทำให้หน้าจอ htop รก และแทบไม่ให้ข้อมูลที่เป็นประโยชน์
อย่างที่สอง เปิด มุมมองต้นไม้ของโปรเซส บ่อยครั้งการรู้ว่าโปรเซสเริ่มมาจากไหนสำคัญกว่าข้อมูลอื่น ๆ และยังช่วยติดตามสิ่งอย่างโปรเซสคอมไพเลอร์ที่ประมวลผลไฟล์จำนวนมากและกิน CPU ได้ง่ายขึ้น
ส่วนตัวคิดว่าทั้งสองอย่างควรเป็นพฤติกรรมเริ่มต้นของ htop
ดีใจที่มีคำอธิบายว่าความจำเสมือนไม่น่าเชื่อถือเท่าไร วิธีที่ Windows Task Manager แสดงเป็นค่าเริ่มต้นก็ไปทางนี้เลย แย่มาก
Resident Set Size (RSS) เป็นตัวชี้วัดที่เชื่อถือได้ที่สุด และค่าอื่น ๆ อาจถูกขยายจนผิดเพี้ยนเพราะสิ่งอย่างไฟล์ที่แมปเข้าหน่วยความจำ ซึ่งในความเป็นจริงไม่ได้ก่อปัญหา
เช่น ต่อให้แมปไฟล์ล็อก 2GB เข้าหน่วยความจำ ส่วนนั้นจะถูกโหลดเป็นเพจเฉพาะตอนอ่านเท่านั้น ไม่ได้ใช้หน่วยความจำจริง ๆ แต่ผู้ใช้เห็นโปรเซสแล้วก็พูดว่า “ทำไมแอปนี้ใช้เมมเยอะขนาดนี้”
Chrome ก็เคยเจอปัญหานี้อยู่ช่วงหนึ่งจนลดการใช้ไฟล์ที่แมปเข้าหน่วยความจำ ไม่ใช่เพราะไฟล์ที่แมปเข้าหน่วยความจำไม่ดี แต่เพราะผู้ใช้เห็นค่าที่ไม่ใช่การใช้หน่วยความจำกายภาพจริงแล้วตอบสนองเกินเหตุ
บนเว็บยังมีไกด์ที่บอกให้ตัดสินการใช้งานจากปริมาณการจองหน่วยความจำเสมือนด้วย อย่างน้อยบทความนี้ก็ชี้ประเด็นส่วนนั้นได้ถูกต้อง
อ้างอิง: https://en.wikipedia.org/wiki/Proportional_set_size
ถ้าใช้ I/O ไฟล์แบบปกติจะไม่ถูกรวม ในคลัสเตอร์ HPC ที่คอยเฝ้าดูการใช้หน่วยความจำของแต่ละงานแล้วฆ่าทิ้งเมื่อเกินปริมาณที่ขอไว้ จึงเกิดผลลัพธ์ที่ค่อนข้างน่าสนุก
เมื่อเริ่มมีแรงกดดันด้านหน่วยความจำ มันก็ไม่เป็นตัวแทนที่ดีอีกต่อไป ผมเคยเห็นการตัดสินใจผิด ๆ หลายครั้งเพราะความเข้าใจผิดนี้ และเคยถึงขั้นเอาค่านี้ออกจากชาร์ตเพื่อกันไม่ให้สมาชิกทีมตีความกลับด้าน
ตามชื่อ มันแสดงเฉพาะส่วนที่แมปไปยังหน่วยความจำกายภาพซึ่งจัดสรรแบบส่วนตัวต่อโปรเซส และใกล้เคียงกับ Resident Set ของ Unix มากกว่า
เดาว่าน่าจะหมายถึงการใช้หน่วยความจำในแท็บ Performance แต่คนอาจเข้าใจผิดว่าเป็นรายการการใช้หน่วยความจำทั้งหมด เลยแยกไว้ให้ชัดเจน
ใน top ถ้าใช้ตัวอักษร
>จะเป็น การจัดเรียงตามการใช้หน่วยความจำใช้เป็นครั้งคราวเวลาไล่หาว่าทำไมโฮสต์ช้า และยังเห็นได้ด้วยว่า
swapdกิน CPU อยู่Mตัวใหญ่สำหรับหน่วยความจำ และPตัวใหญ่สำหรับ CPU มากกว่าเวลาอ่านบทความแบบนี้ก็ทำให้รู้ว่าแม้จะใช้ Linux ทุกวันมานานกว่า 20 ปีแล้ว ก็ยัง ใช้ศักยภาพได้แค่บางส่วน อยู่ดี เป็นบทความที่ดี
รู้สึกเหมือน HN กำลังฟื้นตัวกลับมา
หวังว่านี่จะไม่ใช่ช่วงซอมบี้เดินได้ของ HN
ใครไม่รู้จัก
nmonก็น่าลองดูเหมือนกันกด
hจะแสดงรายการมอนิเตอร์ที่ใช้ได้ กดอีกครั้งจะหายไป และออกด้วยqhttps://nmon.sourceforge.io/pmwiki.php
โดยเฉพาะ throughput ของดิสก์และ I/O ที่ดูด้วยปุ่ม
dและDค่อนข้างมีประโยชน์ชอบที่ กราฟการใช้ CPU แบบ Wide จัดการกับจำนวนคอร์มาก ๆ ได้ง่าย
ในแง่วิธีใช้งานที่ต่างจากพวก
*topผมเริ่มชอบรายงานแบบ diff สไตล์psที่นิ่ง ๆ และรายงานทั้งระบบแบบvmstatมากกว่าวิธีนี้ทำให้ทุกอย่างยังคงอยู่ในบัฟเฟอร์ scrollback ของเทอร์มินัล: https://github.com/c-blake/procs
เขียนด้วยภาษา Nim ซึ่งมีประสิทธิภาพและสื่อความหมายได้ดีอย่างไม่ค่อยพบ
บุ๊กมาร์กบทความนี้ไว้ตั้งแต่ปี 2016 และกลับมาอ้างอิงซ้ำหลายครั้งตลอดหลายปี