nginx и CGI скрипты

Jan 24, 2019 21:44

nginx, в отличие например от Apache httpd, не умеет сам запускать CGI-скрипты, ему нужен внешний сервер приложений, с которым nginx будет общаться по протоколу FastCGI или другому.

Если не нужна высокая производительность или фичи, а просто хочется эмулировать функционал апачевского mod_cgi, то проще всего поставить из портов демон www/fcgiwrap и передавать ему запросы через Unix socket. При запуске демона очень желательно указывать fcgiwrap_flags="-f", иначе ошибки fcgiwrap будут уходить в никуда (а при -f будут видны в nginx/error.log). И при необходимости перезапустить его вручную надо не забывать очистить переменные среды (например "env -i /usr/local/etc/rc.d/fcgiwrap restart"), иначе весь environment рута станет виден в CGI-скриптах).

Если CGI-скрипты планируется держать в /usr/local/www/cgi-bin/, а сокет для обмена между nginx и fcgiwrap в /tmp/fcgiwrap.socket, то секция nginx.conf должна выглядеть так:

location /cgi-bin/ {
root /usr/local/www;
include /usr/local/etc/nginx/fastcgi_params;
fastcgi_pass unix:/tmp/fcgiwrap.socket;
}

Обратите внимание, что в директиве root отсутствует "cgi-bin", хотя это реальный каталог на диске, в котором хранятся скрипты. Почему так?

Дело в том, что путь к скрипту задаётся (передаётся в fcgiwrap) склеиванием двух переменных: DOCUMENT_ROOT и SCRIPT_NAME, в которые мапятся (в fastcgi_params) nginx-овские переменные $document_root и $fastcgi_script_name соответственно. По умолчанию $fastcgi_script_name=$request_uri, то есть при обращении к
http://myserver.example/cgi-bin/myscript fcgiwrap получит команду найти на диске и выполнить "/usr/local/www"+"/cgi-bin/myscript". Естественно $fastcgi_script_name можно переопределить, например с помощью $fastcgi_split_path_info, но для простейшей эмуляции mod_cgi это не нужно.

Отлаживать скрипты вообще без веб-сервера можно как показано ниже, заодно это помогает лучше понять протокол обмена:

#!/bin/sh -x

DOCUMENT_ROOT=/usr/local/www/ ; export DOCUMENT_ROOT
REQUEST_URI=/cgi-bin/myscript ; export REQUEST_URI
SCRIPT_NAME=$REQUEST_URI; export SCRIPT_NAME
REQUEST_METHOD=GET ; export REQUEST_METHOD
su -m www -c '/usr/local/bin/cgi-fcgi -bind -connect /tmp/fcgiwrap.socket'

Оригинал сообщения находится по адресу https://victor-sudakov.dreamwidth.org/463780.html. Пожалуйста оставляйте комментарии там. Всего сейчас
комментариев.

копилка опыта, unix, shell, web

Previous post Next post
Up