Reset PHP cache through SQL query or from a gun on sparrows


Good time of day. Faced with such a task using an SQL query to reset PHP cache. Simply put, to remove multiple files in a specific directory. At the entrance there is:
the
    the
  • DBMS PostgreSQL 9.3
  • the
  • OS – Linux (Fedora, but not an essence important)

In the end, it turned out the decision to bundle python + C + bash (just a little). A little Unix-way, but maybe useful to someone.

Wrap the command to delete the PHP cache in a bash script, thinking about his further expansion of new functionality. Generally speaking, it would be nice to pass the desired command as a parameter. Here is the script:
the
#!/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

Here we declare the array that will contain the list of functions (i.e. commands) and before the call command that is sent (ie, functions), check whether it is in the list. Otherwise, a bad user can pass something like rm-rf ... as a parameter that will succeed in eval. Select the owner for this script as root (though apache will be enough, but think about extensibility, not forgetting the caution) and make the script execute:
the
chown root:root sysutils
chmod ugo+x sysutils

Execute this script from the DBMS is possible through C (a long way because of the need to bother with creating an extension to PostgreSQL) or via an unmanaged scripting language, which is plpython. But first, consider this script from the DBMS will be running as user postgres and delete the cache can only apache (at least). But do not worry, there is such a thing as SUID flag. Only here the problem is that in Linux you cannot set the SUID flag for scripts (read more — here). Actually, you can, but effective user ID will still be the same as the real one. Let's try to work around this limitation by writing a small C program that will call our script. Here is its code:
the
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

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

char command[255];

if (argc == 2)
{
snprintf(command, 255, "/usr/local/bin/sysutils %s", argv[1]);
system(command);
}
else
{
printf("USAGE: sysutils-core <command>\n");
}

return 0;
}

First, we set the effective user ID, then call the script and pass the parameter to the desired command. Compile the program and set the SUID flag:
the
gcc -o sysutils-core sysutils-core.c
chmod u+s sysutils-core

Check:
the
su postgres
./sysutils-core clear_cache

Now, on to the DBMS.

Install the extension plpython3 (pre-installed), by executing the following SQL command in the DB:
the
CREATE EXTENSION plpython3u;

Or using the console:
the
createlang plpython3u -h localhost -U postgres testdb

A function in the DBMS, through which will reset the cache:
the
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;

Then just call sysutils-core with clear_cache option. Check:
the
SELECT clear_cache ( );

If necessary, the function can be not only for postgres (that this user can create functions in unmanaged languages), in this case, the function when creating the option — SECURITY DEFINER (similar to SUID in the database).

That's all. If you want, you can add the transfer of arguments the new command and generally to manage linux server via a DBMS. Let this be a homework assignment.

UPD: a safer version of the C program (using execl):
Hidden text
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <error.h>
#include <sys/wait.h>
#include <errno.h>

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

if (argc == 2)
{
int status = 0;


switch (pid)
{
case -1:
printf("Fork sysutils process failed");
exit(1);
case 0:
execl("/bin/bash", "bash", "/usr/local/bin/sysutils", argv[1], NULL);
default:
wait(&status);
}
}
else
{
printf("USAGE: sysutils-core <command>\n");
}

return 0;
}

Article based on information from habrahabr.ru

Комментарии

Популярные сообщения из этого блога

Briefly on how to make your Qt geoservice plugin

Database replication PostgreSQL-based SymmetricDS

Yandex.Widget + adjustIFrameHeight + MooTools