
Я работаю над веб-приложением LAMP, и где-то есть запланированный процесс, который постоянно создает папку, называемую shop
в корне сайта. Каждый раз, когда это появляется, это вызывает конфликты с правилами перезаписи в приложении, что нехорошо.
Пока я не найду скрипт, вызывающий проблемы, есть ли способ предотвратить shop
создание любой папки, которая называется в корне? Я знаю, что я могу изменить разрешения для папки, чтобы предотвратить изменение ее содержимого, но я не нашел способа предотвратить создание папки с определенным именем.
решение1
Это невозможно, поскольку пользователь, создавший каталог, имеет достаточные права на запись в родительский каталог.
Вместо этого вы можете использовать inotify
семейство системных вызовов, предоставляемых ядром Linux, для отслеживания создания (и, при необходимости, mv
-редактирования) каталога shop
в указанном каталоге, если каталог создан (или, при необходимости, mv
-редактирован) .rm
В этом случае вам понадобится следующая программа пользовательского пространства inotifywait
(входит в комплект inotify-tools
, при необходимости сначала установите ее).
Предполагая, что каталог shop
будет находиться в /foo/bar
каталоге, давайте установим мониторинг для /foo/bar/shop
его создания и rm
немедленно, если он создан:
inotifywait -qme create /foo/bar | \
awk '/,ISDIR shop$/ { system("rm -r -- /foo/bar/shop") }'
inotifywait -qme create /foo/bar
отслеживает/foo/bar
каталог на предмет любого файла/каталога, который может быть создан, т.е. отслеживает любоеcreate
событиеЕсли файл создан,
awk '/,ISDIR shop$/ { system("rm -r -- /foo/bar/shop") }'
проверяет, является ли он каталогом и имеет ли его имяshop
(/,ISDIR shop$/
), если да, тоrm
каталогом (system("rm -r -- /foo/bar/shop")
)
/foo/bar
Для удаления shop
из каталога команду необходимо выполнить от имени пользователя, имеющего разрешение на запись в каталог .
Если вы также хотите отслеживать mv
операции -ing, добавьте moved_to
также наблюдение за событием:
inotifywait -qme create,moved_to /foo/bar | \
awk '/,ISDIR shop$/ { system("rm -r -- /foo/bar/shop") }'
Обратите внимание, если вы ищете файл, а не каталог, с именем shop
:
inotifywait -qme create /foo/bar | \
awk '$NF == "shop" { system("rm -- /foo/bar/shop") }'
inotifywait -qme create,moved_to /foo/bar | \
awk '$NF == "shop" { system("rm -- /foo/bar/shop") }'
решение2
Чтобы ответить буквально, основываясь на вопросе предотвращенияпапкаопределенного имени, которое будет создано.
touch shop
Вы не можете создать каталог, если файл с таким же именем уже существует.
mkdir: cannot create directory ‘shop’: File exists
решение3
А как насчет перехвата mkdir
системного вызова с помощью LD_PRELOAD
...?
$ ls
test.c
$ cat test.c
#define _GNU_SOURCE
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dlfcn.h>
typedef int (*orig_mkdir_func_type)(const char *path, mode_t mode);
int mkdir(const char *path, mode_t mode) {
if(!strcmp(path, "shop")) return 1;
orig_mkdir_func_type orig_func;
orig_func = (orig_mkdir_func_type)dlsym(RTLD_NEXT, "mkdir");
return orig_func(path, mode);
}
$ gcc -shared -fPIC test.c -o test.so
$ LD_PRELOAD='./test.so' mkdir test
$ LD_PRELOAD='./test.so' mkdir shop
mkdir: cannot create directory ‘shop’: No such file or directory
$ ls
test test.c test.so
Обратите внимание, что внутри этого обработчика вы можете вместо этого регистрировать PID процесса, который хочет создать этот каталог:
$ cat test.c
#define _GNU_SOURCE
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dlfcn.h>
typedef int (*orig_mkdir_func_type)(const char *path, mode_t mode);
int mkdir(const char *path, mode_t mode) {
if(!strcmp(path, "shop")) {
FILE* fp = fopen("/tmp/log.txt", "w");
fprintf(fp, "PID of evil script: %d\n", (int)getpid());
fclose(fp);
}
orig_mkdir_func_type orig_func;
orig_func = (orig_mkdir_func_type)dlsym(RTLD_NEXT, "mkdir");
return orig_func(path, mode);
}
$ gcc -shared -fPIC test.c -o test.so
$ LD_PRELOAD='./test.so' mkdir shop
$ cat /tmp/log.txt
PID of evil script: 8706
Вам необходимо поместить это в ~/.bashrc
root (или в тот, кто запускает ваше приложение), чтобы гарантировать, что это будет использоваться:
export LD_PRELOAD=/path/to/test.so
решение4
Создайте символическую ссылку, указывающую на несуществующее местоположение внутри несуществующего каталога. Это имеет некоторые забавные последствия:
$ ln -s non-existent/foobar foo
$ ls -ln
total 0
lrwxrwxrwx 1 1000 1000 19 Okt 4 17:17 foo -> non-existent/foobar
$ mkdir foo
mkdir: cannot create directory ‘foo’: File exists
$ cat foo
cat: foo: No such file or directory
$ echo foo > foo
zsh: no such file or directory: foo
- mkdir, link и другие завершатся ошибкой
EEXIST
(Файл существует). - Попытка открыть путь для чтения, записи или добавления завершится ошибкой
ENOENT
(Нет такого файла или каталога) - Использование stat(2) (а не lstat(2) или stat(1)) для определения местоположения также не даст результата
ENOENT
. lstat, конечно же, вернет информацию о символической ссылке.
Это имеет два преимущества по сравнению с некоторыми другими предлагаемыми здесь решениями: (а) вам не нужна запущенная служба, отслеживающая создание каталога, и (б) для большинства команд имя кажется несуществующим.
Вам придется попробовать, но я подозреваю, что какие бы правила перезаписи у вас ни были, они не используют lstat или другие команды, не допускающие разыменования, что приводит к их сбою.