Асинхронный дочерний процесс в скрипте FastCGI

Асинхронный дочерний процесс в скрипте FastCGI

Предположим, я хочу, чтобы мой сервер переходил в спящий режим при любом HTTP-запросе к пути /sleep(т. е. http://hostname/sleep), но также перед переходом в спящий режим отправлял полный ответ ( HTTP 200).

С использованиемnginxсFastCGI, я настроил путь вnginxконфигурация:

location /sleep {
    fastcgi_pass unix:/path/to/fcgiwrap.socket;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME /path/to/script.sh;
}

Это вызывает следующий скрипт ( /path/to/script.sh):

#!/bin/sh
# -*- coding: utf-8 -*-
cat << EOF
Content-Type: text/html

<html><head><title>Sleep</title><meta charset="UTF-8"></head>
<body><p>Sleep: $(date)</p></body></html>
EOF
sleep 1 && sudo systemctl suspend < /dev/null > /dev/null 2>&1 &

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

решение1

Вы можете разделить cgi и приостановку, вставив файл, используемый как триггер systemd. Смотрите man systemd.pathдля этой активации на основе пути юнита. Это имеет преимущество в том, что не нужно использовать sudo из cgi.

Создать файл блока/etc/systemd/system/mycgitrigger.path

[Path]
PathModified=/some/writeable/file
[Install]
WantedBy=multi-user.target

и включите его. Измените скрипт cgi, чтобы он просто записывал что-либо в файл /some/writeable/fileдля запуска выключения. Поместите команду короткого тайм-аута и выключения в файл юнита /etc/systemd/system/mycgitrigger.service(который не нужно включать).

решение2

Очевидным решением было бы

echo "sleep 1 && sudo systemctl suspend" | at now

Связанный контент