คำสั่ง pgrep: หา PID จากชื่อ ออปชัน -f และความต่างของ pidof กับ pkill

สภาพแวดล้อมทดสอบตระกูล RHELAlmaLinux 9.8procps-ng 3.3บัญชี rootDebian 12 · procps-ng 4.0.2 บัญชีผู้ใช้ทั่วไป

เมื่อต้องการหาหมายเลข (PID) ของโปรเซสที่กำลังทำงานจากชื่อ บัญชี หรือบรรทัดคำสั่ง ให้ใช้คำสั่ง pgrep บนเซิร์ฟเวอร์ AlmaLinux 9 เราคัดลอกโปรแกรม sleep เป็นชื่ออื่น เปิดขึ้นมาสามตัว แล้วเปรียบเทียบโปรเซสที่แต่ละออปชันหาเจอ เมื่อหาจากชื่อจะได้เพียงสามโปรเซสนั้น แต่เมื่อหาจากบรรทัดคำสั่งทั้งหมดด้วย -f จะได้ timeout ที่เปิดโปรเซสเหล่านั้นมาด้วย

ผลลัพธ์ด้านล่างได้จากการรันด้วยบัญชี root บนเซิร์ฟเวอร์ AlmaLinux 9.8 และบัญชีทั่วไปบนเซิร์ฟเวอร์ Debian 12 เป้าหมายที่หาคือโปรเซสที่คัดลอก sleep เป็นชื่อ pgdemo-a และ pgdemo-b แล้วเปิดด้วย timeout 300 ให้จบเองหลัง 5 นาที หมายเลขโปรเซส (PID) และชื่อบัญชี Debian (user1) เปลี่ยนเป็นค่าตัวอย่าง ส่วนเวอร์ชัน procps-ng ของเซิร์ฟเวอร์ AlmaLinux เขียนถึงแค่เวอร์ชันหลักและรอง

1️⃣ วิธีใช้คำสั่ง pgrep เบื้องต้น

  • ↪️ หา PID จากชื่อและรหัสออก

ถ้าเขียนชื่อบางส่วนต่อท้าย pgrep จะพิมพ์หมายเลขของโปรเซสที่ชื่อมีตัวอักษรนั้นออกมาบรรทัดละหนึ่งหมายเลข เมื่อหาด้วย pgdemo ได้สามหมายเลข คือ pgdemo-a สองตัวและ pgdemo-b หนึ่งตัว

pgrep pgdemo
2143
2152
2155

เมื่อเขียนชื่อถึง pgdemo-a จะเหลือเพียง pgdemo-a สองตัว

pgrep pgdemo-a
2143
2152

ข้อความที่หาจะอ่านเป็นนิพจน์ปรกติแบบขยาย และถ้าไม่มีออปชันจะหาจากชื่อโปรเซสเท่านั้น

ถ้าไม่มีโปรเซสที่ตรง pgrep จะจบโดยไม่พิมพ์อะไรเลย จึงต้องดูผลจากรหัสออก หลังหาชื่อที่ไม่มีอยู่ pgdemo-zz แล้วรัน [echo $?] ได้ 1

pgrep pgdemo-zz
echo $?
1

เมื่อรันโดยไม่ใส่เงื่อนไขเลย ได้ข้อผิดพลาดด้านล่างพร้อมรหัสออก 2 หน้า man อธิบายรหัสออกว่า 0 (เจอ), 1 (ไม่เจอ), 2 (ไวยากรณ์บรรทัดคำสั่งผิด) และ 3 (ข้อผิดพลาดร้ายแรง เช่น หน่วยความจำไม่พอ)

pgrep
pgrep: no matching criteria specified
Try `pgrep --help' for more information.
echo $?
2

ถ้าใช้รหัสออกนี้เป็นเงื่อนไขแทนผลลัพธ์ สคริปต์จะตรวจได้ว่าโปรเซสกำลังทำงานอยู่หรือไม่ ดูเวอร์ชันได้ด้วย [pgrep -V] เซิร์ฟเวอร์ Debian 12 ใช้ procps-ng 4.0.2 และเซิร์ฟเวอร์ AlmaLinux 9.8 ใช้ procps-ng 3.3

pgrep -V
pgrep from procps-ng 4.0.2

2️⃣ ออปชัน pgrep -f และผลลัพธ์ของ -l, -a

  • ↪️ โปรเซสที่ติดมาด้วยเมื่อหาจากบรรทัดคำสั่งทั้งหมด

ดูแค่หมายเลขจะไม่รู้ว่าเป็นโปรเซสอะไร จึงพิมพ์ชื่อด้วย -l หรือพิมพ์บรรทัดคำสั่งทั้งหมดด้วย -a

pgrep -l pgdemo
2143 pgdemo-a
2152 pgdemo-a
2155 pgdemo-b
pgrep -a pgdemo
2143 ./pgdemo-a 300
2152 ./pgdemo-a 301
2155 ./pgdemo-b 300

300 และ 301 ท้ายผลลัพธ์ของ -a คืออาร์กิวเมนต์หน่วยวินาทีที่ส่งให้ sleep เราใช้อาร์กิวเมนต์นี้แยก pgdemo-a สองตัวที่ชื่อเหมือนกัน

เมื่อใส่ -f จะหาจากบรรทัดคำสั่งทั้งหมดแทนชื่อ เมื่อหา pgdemo-a ด้วย -f หมายเลขเพิ่มจากสองเป็นสี่

pgrep -f pgdemo-a
2141
2143
2150
2152

เมื่อใส่ -a ด้วยจึงเห็นว่าสองบรรทัดที่เพิ่มมาคือ timeout ที่รับ pgdemo-a เป็นอาร์กิวเมนต์ ชื่อของมันคือ timeout แต่บรรทัดคำสั่งมี pgdemo-a จึงตรงเงื่อนไข -f

pgrep -af pgdemo-a
2141 timeout 300 ./pgdemo-a 300
2143 ./pgdemo-a 300
2150 timeout 300 ./pgdemo-a 301
2152 ./pgdemo-a 301

เมื่อใช้ -f ในสคริปต์ ให้ตรวจว่าตัวสคริปต์เองโผล่ในผลลัพธ์หรือไม่ pgrep จะไม่ใส่ตัวเองที่กำลังทำงานลงในผลลัพธ์ แต่ถ้าบรรทัดคำสั่งของสคริปต์ที่รัน pgrep มีข้อความที่หา สคริปต์นั้นก็จะอยู่ในผลลัพธ์ด้วย

เมื่อหา pgdemo-a ด้วย chk.sh ซึ่งเป็นสคริปต์ที่ส่งข้อความที่รับมาให้ [pgrep -af] ตามเดิม บรรทัดสุดท้ายมี bash chk.sh pgdemo-a ซึ่งก็คือตัวสคริปต์เองเพิ่มเข้ามา

bash chk.sh pgdemo-a
2141 timeout 300 ./pgdemo-a 300
2143 ./pgdemo-a 300
2150 timeout 300 ./pgdemo-a 301
2152 ./pgdemo-a 301
2160 bash chk.sh pgdemo-a

รูปแบบ [p]gdemo-a ที่ครอบตัวอักษรแรกด้วยวงเล็บเหลี่ยม หาข้อความเดียวกับ pgdemo-a ในแง่นิพจน์ปรกติ แต่บรรทัดคำสั่งของสคริปต์มีวงเล็บเหลี่ยมอยู่ตามเดิม จึงไม่ตรงเงื่อนไข เมื่อส่งรูปแบบนี้ให้สคริปต์เดิม บรรทัดสคริปต์หายไปและเหลือเพียงสี่บรรทัด

bash chk.sh '[p]gdemo-a'
2141 timeout 300 ./pgdemo-a 300
2143 ./pgdemo-a 300
2150 timeout 300 ./pgdemo-a 301
2152 ./pgdemo-a 301

3️⃣ ออปชันเงื่อนไขของ pgrep

  • ↪️ -u บัญชี, -x ชื่อตรงทั้งหมด, -n และ -o, -c จำนวน

เมื่อใส่ -x จะหาเฉพาะโปรเซสที่ชื่อตรงกันทั้งหมด ไม่ใช่บางส่วน หาด้วย pgdemo ไม่ได้อะไรเลย แต่หาด้วย pgdemo-a ได้สองตัว

pgrep -x pgdemo
pgrep -lx pgdemo-a
2143 pgdemo-a
2152 pgdemo-a

-u เลือกโปรเซสตามบัญชีที่รันมัน ถ้าเขียนหลายบัญชีคั่นด้วยจุลภาค จะหาโปรเซสทั้งหมดที่เป็นของบัญชีใดบัญชีหนึ่ง สามโปรเซสที่รันด้วย root ออกมาครบด้วย [-u root] และ [-u daemon] ไม่ได้สักตัว

pgrep -u root -l pgdemo
2143 pgdemo-a
2152 pgdemo-a
2155 pgdemo-b
pgrep -u daemon -l pgdemo
pgrep -u root,daemon -c pgdemo
3

เมื่อเขียนบัญชีที่ไม่มีอยู่ ได้ข้อผิดพลาด [invalid user name] พร้อมรหัสออก 2

pgrep -u no-such-user9 pgdemo
pgrep: invalid user name: no-such-user9

บนบัญชีทั่วไปของเซิร์ฟเวอร์ Debian 12 ก็หา sleep หนึ่งตัวที่เปิดด้วยบัญชีตัวเองได้ด้วยออปชันเดียวกัน

pgrep -u user1 -l sleep
3047 sleep
pgrep -u user1 -a sleep
3047 sleep 60

เมื่อมีชื่อเดียวกันหลายตัว -n จะพิมพ์เฉพาะตัวที่เริ่มล่าสุด และ -o จะพิมพ์เฉพาะตัวที่เริ่มก่อนสุด จาก pgdemo-a สองตัวที่เปิดห่างกัน 2 วินาที -n เลือกตัวหลัง ส่วน -o เลือกตัวแรก

pgrep -n pgdemo-a
2152
pgrep -o pgdemo-a
2143

หน้า man อธิบายว่าใช้ -n กับ -o พร้อมกันไม่ได้ เมื่อใส่ทั้งสองตัวจะได้แค่วิธีใช้โดยไม่มีข้อความแจ้งข้อผิดพลาด

-c พิมพ์จำนวนแทนหมายเลข ถ้าไม่เจอจะพิมพ์ 0 และรหัสออกเป็น 1

pgrep -c pgdemo
3
pgrep -c pgdemo-zz
0

สรุปออปชันของ pgrep ได้ดังนี้

ตัวเลือกคัดลอกคำอธิบาย
-f--fullหาจากบรรทัดคำสั่งทั้งหมดแทนชื่อ
-l--list-nameพิมพ์ชื่อพร้อมหมายเลข
-a--list-fullพิมพ์บรรทัดคำสั่งทั้งหมดพร้อมหมายเลข
-x--exactหาเฉพาะโปรเซสที่ชื่อตรงกันทั้งหมด
-u--euidเฉพาะโปรเซสที่บัญชีที่ระบุรัน ถ้าเขียนหลายบัญชีคั่นด้วยจุลภาคคือบัญชีใดบัญชีหนึ่ง
-n--newestตัวที่เริ่มล่าสุดในบรรดาที่ตรงเงื่อนไข
-o--oldestตัวที่เริ่มก่อนสุดในบรรดาที่ตรงเงื่อนไข
-c--countพิมพ์จำนวนแทนหมายเลข ถ้า 0 ตัวรหัสออกเป็น 1
-d--delimiterกำหนดตัวคั่นระหว่างหมายเลข (ค่าเริ่มต้นคือขึ้นบรรทัดใหม่)
-V--versionพิมพ์เวอร์ชัน
ตัวเลือกคัดลอกคำอธิบาย
-i--ignore-caseหาโดยไม่แยกตัวพิมพ์ใหญ่เล็ก
-v--inverseหาโปรเซสที่ไม่ตรงเงื่อนไข
-P--parentเฉพาะโปรเซสลูกของหมายเลขแม่ (PPID) ที่ระบุ
-t--terminalเฉพาะโปรเซสที่ผูกกับเทอร์มินัลที่ระบุ
-g--pgroupเฉพาะโปรเซสในหมายเลขกลุ่มโปรเซสที่ระบุ
-s--sessionเฉพาะโปรเซสในหมายเลขเซสชันที่ระบุ
-U--uidเฉพาะโปรเซสที่มี real user ID เดียวกัน
-G--groupเฉพาะโปรเซสที่มี real group ID เดียวกัน
-w--lightweightพิมพ์หมายเลขเธรดทั้งหมดแทนหมายเลขโปรเซส

🔲 ตัวจำลองคำสั่ง pgrep

ตัวจำลองด้านล่างเริ่มจากรายการหกบรรทัดของ pgdemo และ timeout รวมกับโปรเซสตัวอย่าง แตะชิปเพื่อเทียบบรรทัดที่แต่ละออปชันหาเจอในรายการด้านซ้าย และดูผลที่ลดลงด้วย [pgrep -l pgdemo] หลัง [pkill pgdemo-b]

ตัวจำลองคำสั่ง pgrepprocps-ng 3.3
[root@server work]#
ทำงานในเบราว์เซอร์เท่านั้น รายการด้านซ้ายเป็นค่าตัวอย่าง และบรรทัดที่ pgrep หาเจอจะมี [Just matched] ติดอยู่ข้าง ๆ ส่วน [pkill] เป็นแค่การจำลองที่ลบบรรทัดออกจากรายการ

4️⃣ ความต่างของ pgrep, pidof และ pkill

  • ↪️ pidof หาชื่อตรงตัว ส่วน pkill ส่งสัญญาณ

pidof หาเฉพาะโปรเซสที่ชื่อโปรแกรมตรงกันทั้งหมดโดยไม่ใช้นิพจน์ปรกติ และพิมพ์หมายเลขในบรรทัดเดียวคั่นด้วยช่องว่าง เมื่อหา pgdemo-a ได้สองหมายเลขในบรรทัดเดียว และ 2152 ที่เริ่มทีหลังอยู่หน้า

pidof pgdemo-a
2152 2143

ด้วยชื่อบางส่วน pgdemo ต่างจาก pgrep คือหาไม่เจอเลย และรหัสออกเป็น 1 ถ้าต้องการหมายเลขเดียวให้ใส่ -s [pidof -s pgdemo-a] พิมพ์ 2152 ออกมาตัวเดียว

pidof pgdemo
pidof -s pgdemo-a
2152

ถ้าต้องการดูเวลาเริ่มและหมายเลขแม่ (PPID) ของหมายเลขที่หาเจอ ให้ใช้ pgrep -d ต่อหมายเลขด้วยจุลภาค แล้วส่งให้ คำสั่ง ps ทางออปชัน -p

pgrep -d, pgdemo
2143,2152,2155
ps -fp $(pgrep -d, -x pgdemo-a)
UID          PID    PPID  C STIME TTY          TIME CMD
root        2143    2141  0 15:59 ?        00:00:00 ./pgdemo-a 300
root        2152    2150  0 15:59 ?        00:00:00 ./pgdemo-a 301

2141 และ 2150 ในช่อง PPID คือหมายเลขของ timeout ที่รัน pgdemo-a ทั้งสองตัว

pkill หาโปรเซสด้วยเงื่อนไขเดียวกับ pgrep แต่ส่งสัญญาณแทนการพิมพ์หมายเลข ถ้าไม่ระบุสัญญาณจะส่ง SIGTERM และเปลี่ยนสัญญาณได้แบบ [pkill -HUP ชื่อ]

pkill ส่งสัญญาณทันทีที่หาเจอ จึงควรตรวจเป้าหมายก่อนด้วย [pgrep -a] หรือ [pgrep -af] ด้วยเงื่อนไขเดียวกัน ถ้าหาด้วย -f จะรวม timeout หรือสคริปต์ที่บรรทัดคำสั่งมีข้อความเดียวกันเข้าไปเป็นเป้าหมายด้วย ถ้ารู้หมายเลขอยู่แล้ว ให้ใช้ คำสั่ง kill ส่งสัญญาณไปยังหมายเลขนั้นเท่านั้น

คำสั่งเกณฑ์การหาเอาต์พุตหน้าที่
pgrepชื่อบางส่วน (regex), ถ้า -f คือบรรทัดคำสั่งทั้งหมดหมายเลข, ชื่อและบรรทัดคำสั่งด้วย -l, -aหาอย่างเดียว
pidofชื่อโปรแกรมทั้งหมดหมายเลขในบรรทัดเดียวหาอย่างเดียว
pkillเงื่อนไขเดียวกับ pgrepไม่มีส่งสัญญาณถึงโปรเซสที่หาเจอ (ค่าเริ่มต้น SIGTERM)

🔢 FAQ & เนื้อหาแนะนำ

pgrep เทียบชื่อโปรเซสได้แค่ 15 ตัวอักษรที่เก็บไว้ใน /proc/PID/stat ถ้าชื่อยาวเกิน 15 ตัวอักษร ให้หาด้วย 15 ตัวแรก หรือใช้ -f หาจากบรรทัดคำสั่งทั้งหมดใน /proc/PID/cmdline

ถ้ากรองรายการ ps ด้วย grep บรรทัดคำสั่งของ grep นั้นก็มีชื่อที่หาอยู่ด้วย จึงอาจโผล่ในผลลัพธ์ pgrep ไม่ใส่ตัวเองที่กำลังทำงานลงในผลลัพธ์ และพิมพ์แค่หมายเลข จึงส่งต่อให้คำสั่งอื่นได้ง่าย

เมื่อใส่ -v จะกลับเงื่อนไขและหาโปรเซสที่ไม่ตรง ใน pkill ใช้ออปชันสั้น -v ไม่ได้เพื่อกันความผิดพลาด

🔗 เนื้อหาแนะนำ
ลำดับความสำคัญและ renice คำสั่ง nice ของ Linux: กำหนดลำดับความสำคัญ เปลี่ยนด้วย renice และวัดส่วนแบ่ง CPU เมื่อแย่งกัน บทความที่อธิบายพร้อมผลวัดจริงเรื่องการรันโปรแกรมโดยกำหนดลำดับความสำคัญด้วย nice และการเปลี่ยนลำดับความสำคัญของโปรเซสที่กำลังทำงานด้วย renice อ่านบทความ → คำสั่ง nice ของ Linux: แท่งผลวัดจริง 5 วินาทีเมื่อ nice 0 กับ nice 0·10·19 แย่งแกน CPU เดียวกัน

ℹ️ ประกาศเรื่องลิงก์แอฟฟิลิเอต
เนื้อหาของเว็บไซต์นี้มีลิงก์แอฟฟิลิเอต หากผู้เข้าชมซื้อสินค้าหรือบริการผ่านลิงก์เหล่านี้ เว็บไซต์นี้จะได้รับค่าคอมมิชชันจากผู้ขาย ในกระบวนการนี้ ราคาที่ผู้ซื้อจ่าย(ราคาจะลดลงเมื่อมีโปรโมชัน↓)จะไม่สูงขึ้นแต่อย่างใด ราคา ส่วนลด และข้อมูลสต็อกที่แสดงเป็นข้อมูล ณ เวลาที่เขียนและอาจต่างจากความเป็นจริง โปรดตรวจสอบกับผู้ขายอีกครั้งก่อนซื้อ การเลือกและการประเมินสินค้าเขียนตามเกณฑ์ของเราเอง และการได้รับค่าคอมมิชชันหรือไม่ไม่มีผลต่อลำดับการแนะนำหรือเนื้อหาการประเมิน

ใส่ความเห็น

อีเมลของคุณจะไม่แสดงให้คนอื่นเห็น ช่องข้อมูลจำเป็นถูกทำเครื่องหมาย *

Prove your humanity: 5   +   1   =