كما تعلمون بالفعل ، يعد CGI ، واجهة البوابة الشائعة ، بروتوكولًا قياسيًا لخوادم الويب لتنفيذ البرامج عن طريق تمرير بيانات طلب HTTP إلى البرنامج عبر متغيرات الإدخال والبيئة القياسية ، وإعادة الإخراج القياسي للبرنامج كاستجابة HTTP. ما لم يتم استخدام FastCGI أو SCGI ، يتم تشغيل البرنامج القابل للتنفيذ كعملية منفصلة بواسطة خادم الويب لكل طلب وهدم في النهاية.
يستخدم 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 .
أخيرًا ، أعد تشغيل 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)
بعد ذلك ، تحتاج إلى الخروج من حلقة Infinite و 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
يجب أن يعرض المتصفح الآن إخراج البرنامج - مرحبًا!