Создание каталога, защищенного от 'комнаты-rf'

На Unix/Linux имя файла является последовательностью любых байтов за исключением наклонной черты или NUL. Наклонная черта разделяет компоненты контура, и NUL завершает путь.

Так, можно использовать любое кодирование, Вы хотите для имен файлов. Некоторые приложения могут испытать затруднения из-за некоторой кодировки, если они наивны о том, чем символы могут быть в именах файлов - например, плохо записанные сценарии оболочки часто не обрабатывают имена файлов с пробелами.

Современные среды Unix/Linux обрабатывают закодированные имена файлов UTF-8 очень хорошо.

9
02.06.2013, 02:14
5 ответов

В исследовании Вашего вопроса я столкнулся с этой техникой, которая могла бы помочь Вам в будущем.

Можно, по-видимому, коснуться файла в каталоге как так:

touch -- -i

Теперь, когда Вы выполняете команду rm -fr * в каталоге, где -i присутствует Вам подарят интерактивную подсказку от rm.

$ ls
file1  file2  file3  file4  file5  -i

$ rm -fr *
rm: remove regular empty file `file1'? n
rm: remove regular empty file `file2'? n
rm: remove regular empty file `file3'? n
rm: remove regular empty file `file4'? n
rm: remove regular empty file `file5'? n

То же самое может быть достигнуто, просто оставив псевдоним на месте для rm всегда делать rm -i. Это может стать раздражающим. Так часто то, что я видел сделанный, должно иметь в распоряжении этот псевдоним, и затем отключить его, когда Вы действительно хотите удалить без того, чтобы быть запрошенным.

alias rm='rm -i'

Теперь в каталогах Вас встретят как это:

$ ls
file1  file2  file3  file4  file5

$ rm -r *
rm: remove regular empty file `file1'?

Переопределять псевдоним:

$ \rm -r *

Это все еще не останавливает a rm -fr как бы то ни было. Но это действительно предоставляет Вам некоторую защиту.

Ссылки

14
27.01.2020, 20:05
  • 1
    Это - хорошее, изящное решение, которое работает хорошо, если Вы только хотите/нуждаетесь защитить маленький набор каталогов. И я могу быть старомодным, но я все еще живу под впечатлением это, если Вы говорите --force к чему-то Вы действительно имеете в виду это. –  a CVn 02.06.2013, 00:18
  • 2
    Также отметьте это rm -I (верхний регистр i) могло бы быть полезным в псевдониме, поскольку это немного менее навязчиво (согласно странице справочника, только подсказки при удалении больше чем трех файлов или рекурсивно). спасибо –  a CVn 02.06.2013, 00:20
  • 3
    Обратите внимание что touch ./-i обманите только работы с GNU rm и только если переменная POSIXLY_CORRECT не установлена (команды POSIX не распознают опции после аргументов). –  Stéphane Chazelas 04.06.2013, 01:03

Много возможностей:

  • alias rm='rm -i' - комната спросит - если Вы не укажете -f...
  • chmod -w dir - защищает файлы непосредственно в том каталоге.
  • chattr +i если Вы действительно имеете в виду это
  • запишите свою собственную обертку вокруг комнаты
  • и т.д...

Но лучший путь состоит в том, чтобы, вероятно, иметь хорошее резервное копирование и сохранить важные данные в некотором управлении версиями (как git), который приносит много других преимуществ, также.

5
27.01.2020, 20:05
  • 1
    Прибыл сюда для упоминания этого. Я предложил бы, чтобы болтовня +i сделала это совершенно безопасным. –  JZeolla 01.06.2013, 17:09
  • 2
    , мне уже исказили комнату к rm -i но поскольку можно было бы ожидать, это не работает с -f опция. Я использую мерзавца для многих другая цель, но что, если я случайно делаю rm -rf * в мерзавце также? –  Dilawar 03.06.2013, 10:02
  • 3
    С мерзавцем при удалении просто подкаталога, можно легко восстановить его от локального репозитория. При удалении целого репозитория, можно просто клонироваться, он снова - учитывая Вас продвинул его к некоторому другому месту прежде. –  michas 03.06.2013, 10:42

Используйте программное обеспечение управления версиями как git инкапсулировать Ваши проекты.

Пока Вы не удаляете целый проект, необходимо было бы целеустремленно ввести rm -rf .* удалить .git каталог и теряет все данные, необходимые для отката.

Это обладает дополнительным преимуществом, что можно продвинуть резервные копии материала к удаленному серверу как GitHub или битоприемник.

1
27.01.2020, 20:05

Вот то, как rm -rf dir работы:

  1. Это открывается dir, и перечислите его содержание.
  2. Для каждой записи, если это - каталог, повторяют тот же процесс для него, если это не, звонить unlink на нем.

Если Вы, для списка каталогов, могли бы возвратить специальное имя файла сначала, и если Вы могли бы вызвать процесс, делающий unlink на том файле для смерти, который решил бы проблему. Это могло быть сделано с помощью файловой системы предохранителя.

Например, Вы могли адаптироваться loopback.pl пример от модуля Предохранителя жемчуга, который просто реализует фиктивную файловую систему, которая является просто передачей к реальной файловой системе внизу как так (см. также патч ниже):

  • при списке каталога, если это содержит названную запись .{{do-not-delete}}., предварительно ожидайте список записей с двумя файлами: .{{do-not-delete}}!error и .{{do-not-delete}}!kill
  • при попытке к unlink первый, возвратитесь EPERM код так, чтобы rm отображает сообщение об ошибке
  • при попытке к unlink второй, процесс уничтожается.

$ ls -Ff dir/test
./  .{{do-not-delete}}.  foo/  ../  bar
$ ./rm-rf-killer dir
$ ls -Ff dir/test
.{{do-not-delete}}!error  .{{do-not-delete}}!kill  ./  .{{do-not-delete}}.   foo/  ../  bar
$ rm -rf dir/test
rm: cannot remove `dir/test/.{{do-not-delete}}!error': Operation not permitted
zsh: terminated  rm -rf dir/test
$ ls -Ff dir/test
.{{do-not-delete}}!error  .{{do-not-delete}}!kill  ./  .{{do-not-delete}}.   foo/  ../  bar

Здесь патч для применения к тому же loopback.pl пример как подтверждение концепции:

--- loopback.pl 2013-06-03 22:35:00.577316063 +0100
+++ rm-rf-killer    2013-06-03 22:33:41.523328427 +0100
@@ -7,2 +7,4 @@
 my $has_threads = 0;
+my $flag = ".{{do-not-delete}}";
+
 eval {
@@ -42,3 +44,4 @@

-use blib;
+#use blib;
+use File::Basename;
 use Fuse;
@@ -49,3 +52,3 @@

-my %extraopts = ( 'threaded' => 0, 'debug' => 0 );
+my %extraopts = ( 'threaded' => 0, 'debug' => 0, 'mountopts' => 'nonempty' );
 my($use_real_statfs, $pidfile);
@@ -64,3 +67,7 @@

-sub fixup { return "/tmp/fusetest-" . $ENV{LOGNAME} . shift }
+sub fixup {
+    my $f = shift;
+    $f =~ s#(/\Q$flag\E)!(error|kill)$#$1.#s;
+    return ".$f";
+}

@@ -78,3 +85,9 @@
 }
-    my (@files) = readdir(DIRHANDLE);
+    my @files;
+    
+    while (my $f = readdir(DIRHANDLE)) {
+        unshift @files, "$flag!error", "$flag!kill"
+            if ($f eq "$flag.");
+        push @files, $f;
+    }
 closedir(DIRHANDLE);
@@ -121,3 +134,12 @@
 sub x_readlink { return readlink(fixup(shift));         }
-sub x_unlink   { return unlink(fixup(shift)) ? 0 : -$!; }
+sub x_unlink   {
+    my $f = shift;
+    if (basename($f) eq "$flag!error") {return -EPERM()}
+    if (basename($f) eq "$flag!kill") {
+        my $caller_pid = Fuse::fuse_get_context()->{"pid"};
+        kill("TERM", $caller_pid);
+        return -EPERM();
+    }
+    return unlink(".$f") ? 0 : -$!;
+}

@@ -203,3 +225,2 @@
 sub daemonize {
-    chdir("/") || die "can't chdir to /: $!";
 open(STDIN, "< /dev/null") || die "can't read /dev/null: $!";
@@ -236,2 +257,3 @@

+chdir($mountpoint) or die("chdir: $!");
 daemonize();
@@ -239,3 +261,3 @@
 Fuse::main(
-    'mountpoint'    => $mountpoint,
+    'mountpoint'    => '.',
 'getattr'       => 'main::x_getattr',
1
27.01.2020, 20:05

Я создал сценарий для создания этой задачи легче. Сценарий оболочки изменяет разрешение чтения-записи и флаг болтовни данного списка папок в интерактивном режиме, не спрашивая пароль root. Можно загрузить zip-файл со ссылки, данной ниже.

https://drive.google.com/file/d/0B_3UYBZy2FVsMVpBSWdSWnFBYk0/edit? usp=sharing

Я также включал сценарий установки для создания установки легче. Инструкции включаются в zip-файл.

-1
27.01.2020, 20:05

Теги

Похожие вопросы