Проблемы со сценариями cgi-bin, использующими uWSGI и nginx.

Я пытаюсь запустить сценарии cgi-bin в системе nginx с использованием uWSGI, и у меня возникают проблемы с этим и с отладкой, чтобы выяснить, что происходит не так. Система представляет собой Raspberry Pi, на которой работает книжный червь Rasbian, и я добавил блок местоположения nginx для cgi-bin на сайт по умолчанию вследующее...

      location ^~ /cgi-bin/ {
   root /var/www/cgi-bin;
   include uwsgi_params;
   uwsgi_pass unix:/tmp/uwsgi.sock;
}

Насколько я понимаю, этот блок местоположения определяет выражение, поэтому все, что начинается с cgi-bin, затем обрабатывается внутри. Базовая конфигурация uWSGI включает в себя файл, поставляемый с моей системой, который устанавливает некоторые значения по умолчанию:что здесь...

      uwsgi_param  QUERY_STRING       $query_string;
uwsgi_param  REQUEST_METHOD     $request_method;
uwsgi_param  CONTENT_TYPE       $content_type;
uwsgi_param  CONTENT_LENGTH     $content_length;

uwsgi_param  REQUEST_URI        $request_uri;
uwsgi_param  PATH_INFO          $document_uri;
uwsgi_param  DOCUMENT_ROOT      $document_root;
uwsgi_param  SERVER_PROTOCOL    $server_protocol;
uwsgi_param  REQUEST_SCHEME     $scheme;
uwsgi_param  HTTPS              $https if_not_empty;

uwsgi_param  REMOTE_ADDR        $remote_addr;
uwsgi_param  REMOTE_PORT        $remote_port;
uwsgi_param  SERVER_PORT        $server_port;
uwsgi_param  SERVER_NAME        $server_name;

Вышеописанное достаточно просто, и при этом я поэкспериментировал с несколькими вещами. Я создал модуль systemd, который запускает uWSGI с определенной конфигурацией, которую вы можете увидеть здесь...

      [uwsgi]
uid = uwsgi
gid = uwsgi
plugins = cgi,logfile
socket = /tmp/uwsgi.sock
cgi = /cgi-bin=/var/www/cgi-bin
chmod-socket = 666
chown-socket = www-data:www-data
req-logger = file:/var/log/uwsgi/errors.log
logger = file:/var/log/uwsgi/errors.log
chdir = /var/www/cgi-bin

Я пробовал некоторые другие варианты с приведенной выше конфигурацией путей. Именно после того, как я взглянул на вещи с помощью приведенных ниже методов, я решил отказаться от моего интереса к этим путям и такого рода деталям.

Все запускается, разрешения для каталога установлены правильно, и у меня все работает нормально. Когда я пытаюсь запустить скрипт с URL-адресомЯ получаю ошибку 502 в nginx, а затем эта ошибка появляется в журнале, который я установил для uWSGI...

      -- unavailable modifier requested: 0 --

В журнале не содержится подробностей о том, что здесь пошло не так, и это моя главная проблема. Я не смог найти способа получить более подробные журналы или дополнительную информацию об этой ошибке, поэтому я провел дальнейшее расследование. Было несколько тем, в которых у некоторых пользователей Django возникали проблемы из-за отсутствия плагинов. Я проверил, что плагины для CGI и эти журналы ошибок существуют и загружаются.

Это соответствует этой ошибке для запроса в журнале ошибок nginx...

      2023/07/24 18:02:18 [error] 32579#32579: *5 upstream prematurely closed connection while reading response header from upstream, client: 192.168.1.4, server: _, request: "GET /cgi-bin/test.cgi HTTP/1.1", upstream: "uwsgi://unix:/tmp/uwsgi.sock:", host: "redacted.home"

Поскольку возможности получить более подробные логи не было, я решил поискать другие способы. Первым было получить экземпляр GPT-4, который дал мне друг, для создания простого сценария CGI Perl, который просто создает файл при запуске и записывает в него переменные среды...

      #!/usr/bin/perl

use CGI;
my $cgi = CGI->new;

# Open the debug file
open(my $fh, '>', '/var/www/cgi-bin/test.log') or die "Could not open file 'debug_file.txt' $!";

# Print the environment variables to the file
foreach my $key (sort keys %ENV) {
    print $fh "$key=$ENV{$key}\n";
}

# Close the file
close $fh;

# Generate a simple HTTP response
print $cgi->header('text/plain');
print "Debug information written to '/path/to/debug_file.txt'.\n";

exit;

Этот простой сценарий Perl никогда не создавал ни одного файла, поэтому я решил попробовать еще пару вещей, чтобы посмотреть, что происходит.

Я решил использовать инструмент socat с командойпрослушивать сокет, который использует uWSGI, чтобы самому видеть запросы. Вывод был слегка искажен, и его нельзя было вставить здесь, но я смог увидеть некоторые детали, которые nginx передавал в этом запросе...

      SERVER_PROTOCO HTTP/1.1
REQUEST_SCHEME http
REQUEST_URI /cgi-bin/test.cgi
PATH_INFO /cgi-bin/test.cgi

Здесь были и другие вещи в выводе socat, но в целом здесь не было ничего особенного: ни того, что было очевидно, ни того, что я мог бы изменить. Однако я подумал, что виноваты могут быть пути, которые здесь предоставляет nginx. Изменение путей и тому подобное ничего не изменило, как показывают мои следующие исследования происходящего.

Еще я решил использовать для мониторинга рабочего процесса uWSGI,позволяет просмотреть системные вызовы, выполняемые процессом, что, хотя и немного ограничивает, но может дать некоторую информацию. Я получил идентификатор процесса из файла журнала при запуске службы. Я использовал эту команду straceкоторый следует за любыми ответвлениями, очень многословен и не обрезает строки длиной менее 9999 байт. После запуска он ждет вот так...

      strace: Process 32699 attached
epoll_wait(10,

Когда я отправляю HTTP-запрос к nginx для моего тестового сценария вкаталоге, мы видим, как рабочий процесс выполняет некоторую работу. Здесь мы видим, как рабочий uWSGI запрашивает у операционной системы запрос и некоторую информацию о нем. Далее скрипт должен выполнить системный вызов, связанный с записью ошибки в журнал.

      epoll_wait(10, [{EPOLLIN, {u32=9, u64=9}}], 1, -1) = 1
accept4(9, {sa_family=AF_UNIX}, [110->2], SOCK_NONBLOCK) = 12
read(12, "\0v\1\0\f\0QUERY_STRING\0\0\16\0REQUEST_METHOD\3\0GET\f\0CONTENT_TYPE\0\0\16\0CONTENT_LENGTH\0\0\v\0REQUEST_URI\26\0/cgi-bin/nph-proxy.cgi\t\0PATH_INFO\26\0/cgi-bin/nph-proxy.cgi\r\0DOCUMENT_ROOT\20\0/var/www/cgi-bin\17\0SERVER_PROTOCOL\10\0HTTP/1.1\16\0REQUEST_SCHEME\4\0http\v\0REMOTE_ADDR\v\000192.168.1.4\v\0REMOTE_PORT\5\00040434\v\0SERVER_PORT\2\080\v\0SERVER_NAME\1\0_\t\0HTTP_HOST\n\0pidns.home\17\0HTTP_USER_AGENT\n\0curl/8.0.1\v\0HTTP_ACCEPT\3\0*/*", 4100) = 378
write(2, "-- unavailable modifier requested: 0 --\n", 40) = 40
close(12)                               = 0

Здесь я разбиваю вышеизложенное на что-то более легкое для чтения...

      REQUEST_URI /cgi-bin/nph-proxy.cgi
PATH_INFO /cgi-bin/nph-proxy.cgi
DOCUMENT_ROOT /var/www/cgi-bin
SERVER_PROTOCOL HTTP/1.1
REQUEST_SCHEME http
SERVER_PORT 80
SERVER_NAME (possibly empty)

Я обращаю внимание, что некоторые пути в запросе выглядят не совсем правильно, как это видно по strace. Файловая система proc также указала на некоторые проблемы с используемым рабочим каталогом, для которого было установлено значение- который я исправил, а также обновил в файлах конфигурации, показанных выше, как для nginx, так и для uWSGI.

Я думаю, здесь много говорится о том, что strace нам здесь не показывает , а именно файловые операции или любые системные вызовы для запуска сценария. Несмотря на различные настройки nginx и настройки службы uWSGI, никогда не было попыток открыть какие-либо файлы или что-либо выполнить.

Документация показывает, что пользователям, столкнувшимся с этой ошибкой, пришлось установить и включить определенные плагины, чтобы ошибка исчезла. Однако эти люди использовали приложения Python/Django, а я просто использую CGI и расширение файлов журналов. В документации по запуску приложений CGI не упоминается ничего, кроме включения плагина CGI и наличияпеременная в файле конфигурации.

Учитывая, что ошибка возникает, когда процесс не делает ничего, кроме получения запроса, процесс никогда не пытается ничего сделать с подробностями в запросе, и что некоторые пользователи получают эту ошибку, когда плагины и тому подобное отсутствуют - я думаю, можно предположить, чтоПо сути, это переменные, предоставляемые nginx. Значения по умолчанию здесь будут иметь все необходимое для современных веб-приложений, например, чистые URL-адреса и другие вещи, которых нет в CGI.

Я подозреваю, что это может исправить некоторое сокращение того, что передается здесь nginx, но я не могу найти ничего об этом в документации. Если кто-то более знаком с работой CGI, возможно, что-то в моей конфигурации или отладке выше выделяется.

0 ответов

Другие вопросы по тегам