วิธีติดตามการดำเนินการคำสั่งในเชลล์สคริปต์ด้วยการติดตามเชลล์
ในบทความชุดการดีบักเชลล์สคริปต์นี้ เราจะอธิบายโหมดการดีบักเชลล์สคริปต์ที่สาม นั่นคือการติดตามเชลล์ และดูตัวอย่างบางส่วนเพื่อสาธิตวิธีการทำงาน และวิธีการใช้งาน
ส่วนก่อนหน้าของซีรีส์นี้แสดงให้เห็นอย่างชัดเจนถึงโหมดการแก้ไขข้อบกพร่องของเชลล์สคริปต์อีกสองโหมด: โหมด โหมด verbose และ การตรวจสอบไวยากรณ์ พร้อมด้วยตัวอย่างวิธีเปิดใช้งานเชลล์ที่เข้าใจง่าย การดีบักสคริปต์ในโหมดเหล่านี้
- วิธีเปิดใช้งานโหมดดีบักสคริปต์เชลล์ใน Linux - ตอนที่ 1
- วิธีดำเนินการตรวจสอบไวยากรณ์โหมดดีบักในเชลล์สคริปต์ - ตอนที่ 2
การติดตามเชลล์หมายถึงการติดตามการดำเนินการคำสั่งในเชลล์สคริปต์ หากต้องการเปิดการติดตามเชลล์ ให้ใช้ตัวเลือกการดีบัก -x
นี่เป็นการสั่งให้เชลล์แสดงคำสั่งทั้งหมดและอาร์กิวเมนต์บนเทอร์มินัลในขณะที่ถูกดำเนินการ
เราจะใช้เชลล์สคริปต์ sys_info.sh
ด้านล่าง ซึ่งจะพิมพ์วันที่และเวลาของระบบของคุณ จำนวนผู้ใช้ที่เข้าสู่ระบบ และเวลาทำงานของระบบโดยย่อ อย่างไรก็ตาม มีข้อผิดพลาดทางไวยากรณ์ที่เราจำเป็นต้องค้นหาและแก้ไข
#!/bin/bash
#script to print brief system info
ROOT_ID="0"
DATE=`date`
NO_USERS=`who | wc -l`
UPTIME=`uptime`
check_root(){
if [ "$UID" -ne "$ROOT_ID" ]; then
echo "You are not allowed to execute this program!"
exit 1;
}
print_sys_info(){
echo "System Time : $DATE"
echo "Number of users: $NO_USERS"
echo "System Uptime : $UPTIME
}
check_root
print_sys_info
exit 0
บันทึกไฟล์และทำให้สคริปต์ทำงานได้ สคริปต์สามารถรันได้โดยรูทเท่านั้น ดังนั้นให้ใช้คำสั่ง sudo เพื่อรันสคริปต์ดังต่อไปนี้:
chmod +x sys_info.sh
sudo bash -x sys_info.sh
จากเอาต์พุตด้านบน เราสามารถสังเกตได้ว่า คำสั่งจะถูกดำเนินการก่อน ก่อนที่เอาต์พุตจะถูกแทนที่เป็นค่าของตัวแปร
ตัวอย่างเช่น วันที่ ถูกดำเนินการครั้งแรก และเอาต์พุตของมันถูกแทนที่เป็นค่าของตัวแปร DATE
เราสามารถตรวจสอบไวยากรณ์เพื่อแสดงเฉพาะข้อผิดพลาดทางไวยากรณ์ดังต่อไปนี้:
sudo bash -n sys_info.sh
หากเราพิจารณาเชลล์สคริปต์อย่างมีวิจารณญาณ เราจะพบว่าคำสั่ง if
ไม่มีคำปิดท้าย fi
ดังนั้นให้เราเพิ่มเข้าไปและสคริปต์ใหม่ควรมีลักษณะดังนี้:
#!/bin/bash
#script to print brief system info
ROOT_ID="0"
DATE=`date`
NO_USERS=`who | wc -l`
UPTIME=`uptime`
check_root(){
if [ "$UID" -ne "$ROOT_ID" ]; then
echo "You are not allowed to execute this program!"
exit 1;
fi
}
print_sys_info(){
echo "System Time : $DATE"
echo "Number of users: $NO_USERS"
echo "System Uptime : $UPTIME
}
check_root
print_sys_info
exit 0
บันทึกไฟล์อีกครั้งและเรียกใช้เป็นรูทและทำการตรวจสอบไวยากรณ์:
sudo bash -n sys_info.sh
ผลลัพธ์ของการดำเนินการตรวจสอบไวยากรณ์ของเราด้านบนยังคงแสดงให้เห็นว่ามีข้อบกพร่องอีกหนึ่งประการในสคริปต์ของเราบน บรรทัด 21 ดังนั้นเราจึงยังมีการแก้ไขไวยากรณ์ที่ต้องทำ
หากเราพิจารณาสคริปต์ในเชิงวิเคราะห์อีกครั้ง ข้อผิดพลาดใน บรรทัด 21 เกิดจากการไม่มีเครื่องหมายคำพูดคู่ปิด ( )
ในคำสั่ง echo สุดท้ายภายใน ฟังก์ชัน print_sys_info
เราจะเพิ่มเครื่องหมายคำพูดคู่ปิดในคำสั่ง echo และบันทึกไฟล์ สคริปต์ที่เปลี่ยนแปลงอยู่ด้านล่าง:
#!/bin/bash
#script to print brief system info
ROOT_ID="0"
DATE=`date`
NO_USERS=`who | wc -l`
UPTIME=`uptime`
check_root(){
if [ "$UID" -ne "$ROOT_ID" ]; then
echo "You are not allowed to execute this program!"
exit 1;
fi
}
print_sys_info(){
echo "System Time : $DATE"
echo "Number of users: $NO_USERS"
echo "System Uptime : $UPTIME"
}
check_root
print_sys_info
exit 0
ตอนนี้ตรวจสอบสคริปต์ทางวากยสัมพันธ์อีกครั้ง
sudo bash -n sys_info.sh
คำสั่งด้านบนจะไม่สร้างผลลัพธ์ใดๆ เนื่องจากสคริปต์ของเราตอนนี้มีไวยากรณ์ที่ถูกต้องแล้ว เราสามารถติดตามการทำงานของสคริปต์ทั้งหมดเป็นครั้งที่สองได้เช่นกัน และมันควรจะทำงานได้ดี:
sudo bash -x sys_info.sh
ตอนนี้รันสคริปต์
sudo ./sys_info.sh
ความสำคัญของการติดตามการดำเนินการเชลล์สคริปต์
การติดตามสคริปต์เชลล์ช่วยให้เราระบุข้อผิดพลาดทางไวยากรณ์และที่สำคัญกว่านั้นคือข้อผิดพลาดเชิงตรรกะ ยกตัวอย่างฟังก์ชัน check_root
ในเชลล์สคริปต์ sys_info.sh
ซึ่งมีจุดประสงค์เพื่อตรวจสอบว่าผู้ใช้เป็น root หรือไม่ เนื่องจากสคริปต์ได้รับอนุญาตให้ดำเนินการเท่านั้น โดยผู้ใช้ระดับสูง
check_root(){
if [ "$UID" -ne "$ROOT_ID" ]; then
echo "You are not allowed to execute this program!"
exit 1;
fi
}
ความมหัศจรรย์ที่นี่ถูกควบคุมโดยนิพจน์ if
[ "$UID" -ne "$ROOT_ID" ]
เมื่อเราไม่ใช้ตัวดำเนินการตัวเลขที่เหมาะสม ( -ne
ในกรณีนี้ ซึ่งหมายถึงไม่เท่ากับ ) เราจึงพบข้อผิดพลาดทางตรรกะที่เป็นไปได้
สมมติว่าเราใช้ -eq
( หมายถึง เท่ากับ) ซึ่งจะอนุญาตให้ผู้ใช้ระบบใดๆ รวมถึงผู้ใช้รูทสามารถรันสคริปต์ได้ ดังนั้นจึงเกิดข้อผิดพลาดเชิงตรรกะ
check_root(){
if [ "$UID" -eq "$ROOT_ID" ]; then
echo "You are not allowed to execute this program!"
exit 1;
fi
}
หมายเหตุ: ดังที่เราได้ดูไปก่อนหน้านี้เมื่อเริ่มซีรีส์นี้ คำสั่ง set shell ในตัวสามารถเปิดใช้งานการแก้ไขจุดบกพร่องในส่วนใดส่วนหนึ่งของเชลล์สคริปต์ได้
ดังนั้น บรรทัดด้านล่างจะช่วยเราค้นหาข้อผิดพลาดเชิงตรรกะในฟังก์ชันโดยการติดตามการดำเนินการ:
สคริปต์ที่มีข้อผิดพลาดเชิงตรรกะ:
#!/bin/bash
#script to print brief system info
ROOT_ID="0"
DATE=`date`
NO_USERS=`who | wc -l`
UPTIME=`uptime`
check_root(){
if [ "$UID" -eq "$ROOT_ID" ]; then
echo "You are not allowed to execute this program!"
exit 1;
fi
}
print_sys_info(){
echo "System Time : $DATE"
echo "Number of users: $NO_USERS"
echo "System Uptime : $UPTIME"
}
#turning on and off debugging of check_root function
set -x ; check_root; set +x ;
print_sys_info
exit 0
บันทึกไฟล์และเรียกใช้สคริปต์ เราจะเห็นว่าผู้ใช้ระบบทั่วไปสามารถเรียกใช้สคริปต์ได้โดยไม่ต้อง sudo ดังที่แสดงในผลลัพธ์ด้านล่าง เนื่องจากค่าของ USER_ID คือ 100 ซึ่งไม่เท่ากับราก ROOT_ID ซึ่งก็คือ 0
./sys_info.sh
ตอนนี้ก็มาถึงจุดสิ้นสุดของซีรีส์การดีบักเชลล์สคริปต์แล้ว แบบฟอร์มตอบกลับด้านล่างสามารถใช้เพื่อตอบคำถามหรือข้อเสนอแนะเกี่ยวกับคู่มือนี้หรือซีรีส์ทั้ง 3 ส่วน