• Просто прекрасные чужие стихи

  • Чёрная Курица


  • Предлагаемый в OpenWrt по умолчанию вебсервер - uhttpd - позиционируется как "крошечный однопоточный вебсервер". В целом, так оно и есть. А это означает, что если использовать его для выкладывания файлов - одновременно доступ к файлам будет иметь только один пользователь, все остальные будут стоять в очереди. Так что для веб-интерфейса роутера этого вполне хватает, а вот для мини-файлохранилища - не особо. Поэтому выкидываем uhttpd на фиг и ставим nginx.

    Как подсказывает википедия, в nginx рабочие процессы обслуживают одновременно множество соединений, мультиплексируя их вызовами select, epoll или kqueue в зависимости от ОС. Поэтому здесь даже один рабочий процесс может обрабатывать несколько запросов асинхронно, как нам и хотелось. Причем одного рабочего процесса вполне хватит - плодить их нет смысла, только занимать оперативку. Кроме того, с nginx мы можем очень легко настроить несколько виртуальных хостов, и даже прицепить fastcgi-парсер для PHP-скриптов, хотя я пока так и не придумал, зачем он мне может пригодиться.

    Интерпретатор php-cgi я не стал вкомпилировать в саму прошивку и устанавливать как полагается; с одной стороны он довольно объемный, а с другой - я до сих пор не уверен, что он обязательно нужен. Поскольку по сути он представляет собой обычный бинарник, то мы можем просто положить его на флешку и, не мудрствуя лукаво, запускать оттуда. Нам понадобится только чуть изменить init-скрипт и организовать его автозапуск с помощью rc.local.

    Создаем где-нибудь скрипт php.init:

    #!/bin/sh /etc/rc.common
    # Copyright (C) 2010 OpenWrt.org
    START=50
    export PHP_FCGI_CHILDREN=''
    
    # порт, на котором будет слушать php-cgi
    PORT=1026
    
    # путь к интерпретатору
    BIN=/mnt/ext/php5/php-cgi
    
    # путь к файлу конфигурации
    CONFDIR=/mnt/ext/php5/php.ini
    
    # мы ведь не хотим и это запускать от имени root?
    USERN=nobody
    
    start() {
            su -s "/bin/sh" -c "$BIN -b $PORT -c $CONFDIR &" $USERN
    }
    
    stop() {
            kill `pidof php-cgi`
    }
    
    restart() {
            stop
            start
    }

    И дописываем в файл /etc/rc.local несколько строк для автозапуска:

    # следует немного подождать, пока инициализируется флешка
    sleep 5
    # проверим, подключена ли она и есть ли там init-скрипт
    if [ -e /mnt/ext/php5/php.init ]
    then
            /mnt/ext/php5/php.init start
    fi

    Теперь мы можем в nginx.conf добавить обработчик для .php-скриптов.

    Фрагмент nginx.conf:

            location ~ \.php$ {
                try_files   $uri @php404;
                include     fastcgi_params;
                fastcgi_pass        localhost:1026;
                fastcgi_param       SCRIPT_FILENAME $document_root$fastcgi_script_name;
            }
            location @php404 {
                return      404;
                break;
            }
    

    Директива try_files нужна для того, чтобы проверить существование запрашиваемых файлов. Можно написать и по-другому, но, как говорят, if_is_evil, - поэтому лучше возьмем try_files. В параметре fastcgi_pass указываем номер порта php-cgi из init-скрипта.

    Для счастья теперь не хватает только средства удаления старых логов nginx'а, чтобы они не скушали все свободное место на ramdisk'е раздела /tmp (он же /var). В принципе, можно вообще не писать никаких логов, но как-то правильнее и эстетичнее все-таки их вести. Поэтому устанавливаем logrotate и настраиваем /etc/logrotate.conf.

    Дописываем в logrotate.conf:

    /var/log/nginx/*.log {
            daily
            rotate 3
            missingok
            notifempty
            compress
            size 100k
            dateext
            sharedscripts
            postrotate
                [ ! -f /var/run/nginx.pid ] || kill -USR1 `cat /var/run/nginx.pid`
            endscript
    }

    Так мы получим ежедневную автоматическую архивацию логов в случае, если файл лога более 100кБ объемом.

    Теперь нужно только обеспечить ежедневный запуск logrotate, так как он процесс скромный и не демонический. Для этих средств служит crond из состава Busybox. Это обыкновенный и привычный crontab-менеджер. Файлы заданий он хранит в каталоге /etc/crontabs, поэтому создаем там файл root и дописываем в него строку следующего вида:

    20 02 * * * /usr/sbin/logrotate /etc/logrotate.conf >/dev/null 2>&1

    Таким образом logrotate будет запускаться каждый день в 02:20. Осталось только перезапустить crond, чтобы убедиться, что изменения точно вступили в силу.


  • Просто прекрасные чужие стихи

  • Чёрная Курица