如您所知,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
浏览器现在应显示程序输出 -您好!