如您所知,CGI,Common Gateway接口是Web服務器通過標準輸入和環境變量將HTTP請求數據傳遞到程序中,並將程序的標準輸出作為HTTP響應返回程序的標準協議。除非使用FastCGI或SCGI,否則Web服務器針對每個請求啟動可執行程序作為單獨的過程啟動,並在末尾拆除。
GDB是GNU調試器,通常用於調試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 Gateway超時響應。
最後,重新啟動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的Curses Frontend,它為熟悉的GDB文本接口提供了拆分屏幕,顯示源在執行時。
您可以使用pgrep找到CGI流程ID:
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
瀏覽器現在應顯示程序輸出 -您好!