อย่างที่คุณอาจทราบอยู่แล้ว CGI อินเตอร์เฟส Gateway Common เป็นโปรโตคอลมาตรฐานสำหรับเว็บเซิร์ฟเวอร์ในการดำเนินการโปรแกรมโดยผ่านข้อมูลการร้องขอ HTTP ไปยังโปรแกรมผ่านตัวแปรอินพุตมาตรฐานและตัวแปรสภาพแวดล้อมและส่งคืนเอาต์พุตมาตรฐานของโปรแกรมเป็นการตอบกลับ HTTP เว้นแต่จะใช้ FastCGI หรือ SCGI โปรแกรมที่เรียกใช้งานได้จะเริ่มเป็นกระบวนการแยกต่างหากโดยเว็บเซิร์ฟเวอร์สำหรับแต่ละคำขอและขาดในตอนท้าย
GDB, GNU debugger มักใช้ในการดีบักโปรแกรม C และ C ++ และรองรับการแนบกับกระบวนการที่กำลังทำงานอยู่ เนื่องจากกระบวนการ CGI มีอายุสั้นคุณต้องชะลอการออกเพื่อให้มีเวลาเพียงพอในการแนบดีบักในขณะที่กระบวนการยังคงทำงานอยู่ สำหรับการดีบักแบบไม่เป็นทางการตัวเลือกที่ง่ายที่สุดคือใช้ sleep() ในวงวนที่ไม่มีที่สิ้นสุดที่ตำแหน่งเบรกพอยต์และออกจากลูปด้วยดีบักเกอร์เมื่อติดอยู่กับโปรแกรม มีตัวเลือกอื่น ๆ ที่ซับซ้อนกว่าที่ฉันไม่ได้กล่าวถึงที่นี่
ตัวอย่างต่อไปนี้ถือว่า Ubuntu Linux และ Apache
ก่อนอื่นติดตั้งและเปิดใช้งานโมดูล CGI:
sudo a2enmod cgi
จากนั้นกำหนดค่าโฮสต์เสมือนจริงที่เปิดใช้งาน CGI:
<VirtualHost *:80>
ServerName cgi-test.example.com
DocumentRoot /var/www/cgi-test/htdocs
CustomLog /var/log/apache2/cgi-test.access.log combined
ErrorLog /var/log/apache2/cgi-test.error.log
TimeOut 600
ScriptAlias /cgi-bin/ /var/www/cgi-test/cgi-bin/
<Directory "/var/www/cgi-test/cgi-bin">
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
หมายเหตุพารามิเตอร์ TimeOut - ขอสงวน 10 นาทีสำหรับการดีบักแทนค่าเริ่มต้นหนึ่งนาที หลังจากหมดเวลาแล้ว Apache จะฆ่ากระบวนการ CGI และส่งคืนการตอบ กลับหมดเวลา 504 เกตเวย์
ในที่สุดรีสตาร์ท Apache:
sudo service apache2 restart
ติดตั้งเครื่องมือสร้าง:
sudo apt-get install build-essentials cmake cgdb
โคลนและรวบรวมแอปพลิเคชัน:
git clone https://github.com/mrts/debugging-cgi-applications-with-gdb.git
cd debugging-cgi-applications-with-gdb
cmake .
make
คัดลอกแอปพลิเคชันไปยังไดเรกทอรี cgi-bin :
cp cgi-debugging-example /var/www/cgi-test/cgi-bin
เปิด URL ที่เรียกใช้แอปพลิเคชันในเบราว์เซอร์:
http://cgi-test.example.com/cgi-bin/cgi-debugging-example
เบราว์เซอร์จะแสดงไอคอนการโหลดเป็นแอปพลิเคชันเข้าสู่ลูปที่ไม่มีที่สิ้นสุดและสามารถแนบกับ GDB ได้
ขอแนะนำให้ใช้ CGDB แทน GDB ธรรมดา CGDB เป็นคำสาปส่วนหน้าไปยัง GDB ที่ให้อินเทอร์เฟซข้อความ GDB ที่คุ้นเคยพร้อมหน้าจอแยกที่แสดงแหล่งที่มาในขณะที่ดำเนินการ
คุณสามารถค้นหารหัสกระบวนการ CGI ด้วย pgrep :
pgrep -l cgi-debugging
แนบ CGDB เข้ากับกระบวนการ (กระบวนการถูกหยุดเมื่อดีบักเกอร์ติด):
sudo cgdb cgi-debugging-example $(pgrep cgi-debugging)
ถัดไปคุณจะต้องออกจากฟังก์ชั่นลูปอนันต์และ wait_for_gdb_to_attach() ฟังก์ชั่นเพื่อไปถึง "เบรกพอยต์" ในแอปพลิเคชันของคุณ เคล็ดลับที่นี่คือการก้าวออกจาก sleep() จนกว่าคุณจะไปถึง wait_for_gdb_to_attach() และตั้งค่าของตัวแปร is_waiting ด้วยดีบักเกอร์เพื่อให้ while (is_waiting) ออก:
(gdb) finish
Run till exit from 0x8a0920 __nanosleep_nocancel () at syscall-template.S:81
0x8a07d4 in __sleep (seconds=0) at sleep.c:137
(gdb) finish
Run till exit from 0x8a07d4 in __sleep (seconds=0) at sleep.c:137
wait_for_gdb_to_attach () at cgi-debugging-example.c:6
Value returned is $1 = 0
(gdb) set is_waiting = 0 # <- to exit while
(gdb) finish
Run till exit from wait_for_gdb_to_attach () cgi-debugging-example.c:6
main () at cgi-debugging-example.c:13
นอกจากนี้คุณยังสามารถบังคับผลตอบแทนด้วย return แต่นั่นอาจทำให้สถานะแอปพลิเคชันยุ่งเหยิงและทำให้เกิดปัญหา หรือคุณสามารถใช้ next เพื่อก้าวออกจากฟังก์ชั่นแทนที่จะ finish
เมื่อคุณออกจาก wait_for_gdb_to_attach() คุณสามารถทำการดีบักโปรแกรมต่อไปหรือปล่อยให้มันเสร็จสมบูรณ์:
(gdb) next
(gdb) continue
Continuing.
[Inferior 1 (process 1005) exited normally]
(gdb) quit
ตอนนี้เบราว์เซอร์ควรแสดงเอาต์พุตโปรแกรม - สวัสดี!