เข้าใจ $$ vs $BASHPID: ตัวแปร Process ID ใน Bash
เมื่อเร็วๆ นี้ผมทำงาน Shell Script พบความแตกต่างสำคัญในพฤติกรรมของ Bash Special Variable $$ และ $BASHPID ทุก Process ใน Linux จะได้รับ Process ID นั่นคือวิธีที่ OS จัดการ Process
Related Read: Learn Difference Between Sourcing and Forking in Bash
Terminal Session ของคุณก็ได้รับ Process ID เหมือนกัน มี Special Variable ชื่อ $$ และ $BASHPID เก็บ Process ID ของ Current Shell
รันคำสั่งด้านล่างดู Process ID ของ Shell ปัจจุบัน ทั้ง $$ และ $BASHPID
จะคืนค่าเดียวกัน
$ echo $$ # Printing special variable $$
$ echo $BASHPID # Printing the variable $BASHPID
ใน Bash เมื่อเรียก External Program จาก Shell จะสร้าง Child Process/Subshell และ Program จะ Submit ใน Child Process เท่านั้น ดูตัวอย่าง ใส่ Process Monitor Command ใน Script sample.sh Demo Parent Shell สร้าง Subprocess รัน Program
#!/usr/bin/env bash
ps -ef --forest | grep -i bash
รัน Script นี้ได้ Process ID ของ Bash จากรูปด้านล่าง เข้าใจได้ว่าเรียก Script Bash สร้าง Child Process รัน Script
$ ./sample.sh
ตอนนี้ใช้ทั้ง $$ และ $BASHPID ภายใน Script ดูคืนค่าอะไร
#!/usr/bin/env bash
echo "============================"
ps -ef --forest | grep -i bash
echo "============================"
echo "PID USING $$ FOR SCRIPT $0 ==> $$"
echo "PID USING BASHPID FOR SCRIPT $0 ==> $BASHPID"
echo
รัน Script อีกครั้ง
$ ./sample.sh
คืนค่า Process ID เดียวกัน นี่คือความแตกต่างจริง สร้าง Child Process อีกตัวใน Script ด้วยการรัน Command ใน Parentheses()
# STORING THE PID INTO A VARIABLE...
VAR_HASH=$(echo $$)
VAR_BASHPID=$(echo $BASHPID)
echo "VALUE OF VAR_HASH ==> $VAR_HASH"
echo "VALUE OF VAR_BASHPID ==> $VAR_BASHPID"
ใน Bash Parentheses จะ Invoke Child Process รันสิ่งภายใน Parentheses ในกรณีนี้ ทั้ง $$ และ $BASHPID ควรเก็บ Child Process ID ใหม่ แต่จากรูปเห็นความแตกต่าง $$ เก็บ 382 ซึ่งเป็น Parent ID (Process ID ของ Script sample.sh) และ $BASHPID เก็บ Child Process ID ที่สร้างโดย Parentheses
มาเข้าใจพฤติกรรมนี้ ดู Man Page:
$ man bash
เมื่อใช้ $$ แม้ใน Subshell มันเก็บ Process ID ของ Parent Process ที่มันถูกสร้างขึ้น แต่ BASHPID จะเก็บ Current Process ID กล่าวคือ เมื่อเรียกใน Parentheses จะเก็บ Child Process ID
เราไม่สามารถ Assign หรือ Modify Variable $$ ได้ แต่ BASHPID Reassign ได้แต่ No Effect
$ $$=10
$ BASHPID=10
$ echo $BASHPID
Unset BASHPID ได้ เมื่อ Unset มันสูญเสีย Special State และใช้เป็น Normal Variable ได้
$ unset BASHPID
$ echo $BASHPID
$ BASHPID="Tecmint"
$ echo $BASHPID
แม้พยายาม Assign Process ID ของ Shell จะถือเป็น User-defined Variable เพราะสูญเสีย Special State แล้ว
$ BASHPID=$(echo $$)
$ echo $$;echo $BASHPID
กรณีนี้ ต้องใช้ Terminal Session ใหม่สำหรับ BASHPID ให้กลับมาเป็น Special State
ขอจบเท่านี้ บทความนี้เห็นความแตกต่างระหว่าง $$ และ BASHPID และพฤติกรรม อ่านและแชร์ Feedback ได้เลย