特定の名前のフォルダーが作成されないようにすることはできますか?

特定の名前のフォルダーが作成されないようにすることはできますか?

私は LAMP Web アプリで作業していますが、サイトのルートにというフォルダーを作成し続けるスケジュールされたプロセスがどこかにありますshop。これが表示されるたびに、アプリ内の書き換えルールとの競合が発生します。これは好ましくありません。

問題のあるスクリプトが見つかるまで、shopルートに というフォルダーが作成されないようにする方法はありますか? フォルダーの権限を変更して、その内容が変更されないようにできることはわかっていますが、特定の名前のフォルダーが作成されないようにする方法が見つかりませんでした。

答え1

ディレクトリを作成するユーザーが親ディレクトリに書き込むための十分な権限を持っている場合は、それはできません。

inotify代わりに、Linux カーネルによって提供されるシステム コール ファミリを活用して、指定されたディレクトリ内のmvディレクトリの作成 (およびオプションで -ing)を監視することができます。ディレクトリが作成された (またはオプションで-ed)場合。shopmvrm

この場合に必要なユーザー空間プログラムは ですinotifywait( に付属していますinotify-tools。必要な場合は最初にインストールしてください)。


ディレクトリがディレクトリshop内に存在すると仮定して/foo/bar、作成の監視を設定し/foo/bar/shoprm作成されたらすぐに実行します。

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を使用して syscallをハイジャックするとどうなるでしょうか?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これが確実に使用されるようにするには、これをルート (またはアプリを実行しているユーザー) に配置する必要があります。

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
  1. mkdir、link などはEEXIST(ファイルが存在します) で失敗します。
  2. パスを読み取り、書き込み、または追加のために開こうとすると、ENOENT「(そのようなファイルまたはディレクトリはありません)」というエラーで失敗します。
  3. stat(2) (lstat(2) や stat(1) ではない) をその場所で使用しても失敗しますENOENT。lstat は当然、シンボリックリンクに関する情報を返します。

これには、ここで提案されている他のソリューションに比べて 2 つの利点があります。(a) ディレクトリの作成を追跡するサービスを実行する必要がないこと、(b) ほとんどのコマンドでは名前が存在しないように見えることです。

試してみる必要がありますが、どのような書き換えルールを使用しても、lstat やその他の非参照コマンドが使用されないため、失敗するのではないかと思います。

関連情報