Сброс PHP-кеша через SQL-запрос или из пушки по воробьям

ecfc5a39a62506cd2052bbd89f7e9e06.pngДоброго времени суток. Столкнулся с такой вот задачей — через SQL запрос сбросить PHP-кеш. Проще говоря, удалить несколько файлов в определённом каталоге. На входе имеется: СУБД — PostgreSQL 9.3 ОС — Linux (Fedora, но не суть важно) В итоге, получилось решение в связке python + C + bash (всего понемногу). Немного не Unix-way, но может кому-то пригодится.Обернём команду удаления PHP-кеша в bash-скрипт, подумав про его дальнейшее расширение новым функционалом. Вообще говоря, было бы неплохо передавать нужную команду в виде параметра. Вот этот скрипт: #!/bin/bash

function __clear_cache () { rm /var/www/html/cache/*.php }

FUNCS=() FUNCS+=(»__clear_cache»)

function function_exists () { local e for e in »${@:2}»; do [[ »$e» == »$1» ]] && return 0; done return 1 }

if function_exists »$1» »${FUNCS[@]}»; then eval »$1» else echo «Function $1 does not exists» exit 1 fi Тут мы объявляем массив, который будет содержать список функций (т.е команд) и, перед вызовом переданной команды (т.е функции), проверяем, есть ли она в списке. Иначе нехороший пользователь может передать что-то типа rm -rf … в качестве параметра, что успешно выполнится в eval. Установим владельца для этого скрипта root (хотя и apache хватит, но думаем про расширяемость, не забывая про осторожность) и сделаем скрипт выполняемым: chown root: root sysutils chmod ugo+x sysutils Выполнять этот скрипт из СУБД можно через C (долгий путь, так как необходимо заморачиваться с созданием расширения к PostgreSQL) или через неуправляемый скриптовый язык, коим является plpython. Но для начала задумаемся — скрипт из СУБД будет выполняется с правами пользователя postgres, а удалить кеш может только apache (как минимум). Но не беда, есть же такая штука, как SUID флаг. Только вот проблема в том, что в Linux нельзя установить SUID флаг для скриптов (подробнее — тут). Вернее, можно, но эффективный user ID всё равно будет таким же как и реальный. Попробуем обойти это ограничение, написав небольшую программу на C, в которой будет вызов нашего скрипта. Вот её код: #include #include #include #include

int main (int argc, char *argv[]) { setuid (0);

char command[255];

if (argc == 2) { sprintf (command,»/usr/local/bin/sysutils %s», argv[1]); system (command); } else { printf («USAGE: sysutils-core \n»); }

return 0; } Сперва мы устанавливаем эффективный user ID, затем вызываем скрипт, передав ему параметр — требуемую команду. Скомпилируем программу и установим SUID-флаг: gcc -o sysutils-core sysutils-core.c chmod u+s sysutils-core Проверяем: su postgres ./sysutils-core clear_cache Теперь перейдём к СУБД-части.Установим расширение plpython3 (предварительно установленное в систему), выполнив SQL-команду в соответствующей БД:

CREATE EXTENSION plpython3u; Или используя консоль: createlang plpython3u -h localhost -U postgres testdb Функция в СУБД, через которую будет сбрасываться кеш имеет вид: CREATE OR REPLACE FUNCTION clear_cache () RETURNS void AS $BODY$ import os os.system (»/usr/local/bin/sysutils-core clear_cache») $BODY$ LANGUAGE plpython3u VOLATILE; Тут просто вызов sysutils-core с параметром clear_cache. Проверяем: SELECT clear_cache (); При необходимости, вызов функции может быть не только под postgres (именно этот пользователь может создавать функции на неуправляемых языках), в таком случае функции при создании необходимо указать опцию — SECURITY DEFINER (аналог SUID в СУБД).Вот и всё. При желании, можно добавить передачу аргументов, новые команды да и вообще управлять linux-сервером через СУБД. Пусть это будет домашним заданием.

© Habrahabr.ru