Co je to CGI skript?

CGI skript je vámi vytvořený program, který umožní generovat dynamické WWW stránky, tj. stránky, které mohou vypadat při každém jejich otevření jinak. Obsah může být závislý na aktuálním času, obsahu různých souborů, adrese počítače, ze kterého je stránka navštívena atd.

Jak vytvořit CGI skript

CGI skript je jakýkoliv (na straně serveru) spustitelný soubor (obvykle však skript – odtud pojmenování), který po spuštění na standardní výstup vypíše HTTP hlavičku stránky (nezaměňujte s HTML hlavičkou) a poté její vlastní obsah. Může jít o klasický text v HTML, ale také jakékoli jiný typ dat.

Skript by měl vygenerovat minimálně hlavičku Content-Type: následovanou prázdným řádkem, který denotuje konec hlavičky. Příklad jednoduchého shellového CGI skriptu:

 
#!/bin/bash
#
echo "Content-Type: text/html"
echo
echo "<body>"
echo "prvni pokusna stranka"
echo "<pre>"
date
echo "</pre>"
echo "</body>"

/bin/bash je celá cesta k interpretu, který má na serveru skript spustit. Může to být Bash, Perl, PHP nebo leccos jiného. Dejte si však pozor, pokud své stránky a skripty píšete v editorech či na systémech, kde se vám na konec řádků ukládá i znak CR (Ctrl-M, ^M) – typicky windowsové programy. Pak by se hledal nikoliv program bash v adresáři /bin, ale jakýsi program bash^M, který samozřejmě neexistuje.

Content-Type: je v tomto případě text/html, což pro WWW server znamená, že CGI skript generuje HTML stránku. Pokud by skript generoval např. obrázek, Content-Type by byl, řekněme, image/gif.

CGI skript musí být spustitelný na Aise. Aby WWW server rozpoznal, že jde o CGI skript, musí mít skript příponu .cgi. Programátoři v Perlu jistě uvítají modul CGI.pm, který zpříjemňuje tvorbu a parsování formulářů.

Uživatelské CGI skripty dostupné pod /~uzivatel/

CGI skript musí být spustitelný vlastníkem. Pokud se nejedná o binární program, ale o skutečně o skript, je potřeba také nastavit právo pro čtení vlastníkem.

Skripty jsou spouštěny pomocí mechanismu suexec, který umožní provádění skriptu pod identitou vlastníka. Zároveň také kontroluje některé bezpečnostní podmínky. Základem je: skript musí patřit uživateli, který je uvedený v URL (http://www.fi.muni.cz/~uzivatel/) a skupině, kterou má tento uživatel jako primární (lze zjistit příkazem id). Skript ani nadřazený adresář nesmějí mít povolen zápis pro skupinu a ostatní.

CGI skripty uložené mimo strom /~uzivatel/

Tyto CGI skripty musí být spustitelné (oprávnění x) uživatelem apachefi; pokud se nejedná o binární program, ale o skript, je potřeba mít nastaveno i právo pro čtení (r) uživatelem apaechefi. To lze dosáhnout příkazem setfacl -m u:apachefi:r-x skript.cgi. Spouštěné CGI skripty běží pod identitou uživatele apachefi, a tomu je tedy potřeba přizpůsobit i chování skriptu. Typicky například tento uživatel může zapisovat pouze do adresáře /tmp.

Speciální proměnné v CGI skriptech, práce s parametry v URL

WWW server nastaví několik nových proměnných, se kterými můžete v CGI skriptu pracovat. Které to jsou, můžete zjistit podle příkladu uvedeného v sekci o ladění CGI skriptů. Speciálně, pokud předáváte CGI skriptu parametry (metodou GET), budou dostupné v proměnné QUERY_STRING. V shellovém CGI skriptu může zpracování parametrů vypadat třeba takto:

#!/bin/bash
. /packages/run.64/bashlib-0.4/bin

echo Content-type: text/plain
echo

STROJ=$(param stroj)

/usr/bin/host $STROJ

Tento program uloží do proměnné STROJ hodnotu parametru stroj. Pokud tedy program zavoláte pomocí URL http://www.fi.muni.cz/~uzivatel/tento_skript.cgi?stroj=aisa, bude jeho výstupem výstup příkazu host aisa. (Více o bashlib na bashlib.)

Pokud parametry předáváte metodou POST, jsou data předána na standardní vstup CGI skriptu.

CGI skripty a bezpečnost

Je důležité si uvědomit, že pokud je spouštěný CGI skript vyvolán v podstromu /~uzivatel/, běží pod vaší identitou. Pokud tedy uděláte ve skriptu nějakou bezpečnostní chybu, může dojít i ke ztrátě/změně vašich dat na serveru či jinému zneužití vaší identity. Proto si před uveřejněním skript vždy důkladně zkontrolujte a počítejte s tím, že se možná někdo bude snažit robustnost a odolnost vašeho skriptu vlastnoručně prověřit. To se týká obzvlášť zpracování parametrů.

Rovněž mějte na paměti, že příklady uváděné na této stránce jsou pouze ilustrační (byť funkční) a nemusí být napsány bezpečně. Než začnete psát CGI skripty, doporučujeme přečíst si o této problematice něco na webu.

Ladění CGI skriptů

Doporučujeme předně zkusit CGI skript spustit z příkazové řádky přímo na Aise. Zde můžete odchytit např. chybová hlášení interpretu. Je velice pravděpodobné, že po spuštění pod uživatelem apachefi nebude mít skript nastavené některé proměnné prostředí (typicky PATH, LD_LIBRARY_PATH, ...). Aktuální stav proměnných při běhu CGI skriptu vám zjistí například tento kód:
#!/bin/bash

echo "Content-type: text/plain"
echo
set

Ladění Perlových skriptů:

  • Používejte use CGI, což umožní ladit skripty i na příkazové řádce, včetně parametrů.
  • Používejte use CGI::Carp qw(fatalsToBrowser), což zobrazí chybové hlášky do browseru.

Ladění shell skriptů:

  • Hned za úvodní #!/cesta/k/interpretu (např. #!/bin/bash) přidejte řádek exec 2>/home/uzivatel/public_html/stderr.log, který přesměruje chybový výstup do souboru.
  • Používáte-li moduly, je potřeba je nejdříve inicializovat. Více podrobností najdete na stránce o modulech.
Co dělat, když to stále nefunguje:
  • Znovu si přečíst tuto stránku.
  • Znovu překontrolovat, jestli máte správně nastavená přístupová práva na adresáři ~/public_html a vnořených (pro detaily viz stránku o uživatelských HTML stránkách.
  • Znovu překontrolovat, jestli má CGI skript příponu .cgi.
  • Znovu překontrolovat přístupová práva na CGI skriptu a jeho relevantním okolí.
  • Znovu si zkusit CGI skript spustit ručně na Aise z příkazové řádky.
  • Pokud skript funguje na příkazové řádce, ale ne při přístupu přes WWW, podívat se do logů WWW serveru po možné příčině. Logy najdete v adresáři /var/log/httpd v souborech error_log, access_log a suexec.apachefi.log.
  • Poradit se se zkušenějšími kolegy.
  • Poradit se se správci.