Como evito rm -rf / * acidental?

158

Acabei de executar rm -rf /* acidentalmente, mas quis dizer rm -rf ./* (observe a estrela após a barra).

alias rm='rm -i' e --preserve-root por padrão não me salvaram, então existem proteções automáticas para isso?

Eu não era root e cancelei o comando imediatamente, mas havia algumas permissões descontraídas em algum lugar ou algo assim, porque percebi que meu prompt do Bash já estava quebrado. Eu não quero depender de permissões e não ser root (eu poderia cometer o mesmo erro com sudo ), e eu não quero procurar por bugs misteriosos por causa de um arquivo ausente em algum lugar no sistema, então, backups e sudo são bons, mas gostaria de algo melhor para este caso específico.

Sobre pensar duas vezes e usar o cérebro. Eu estou usando isso na verdade! Mas eu estou usando isso para resolver algumas tarefas complexas de programação envolvendo 10 coisas diferentes. Eu estou imerso nessa tarefa profundamente o suficiente, não há nenhum poder mental para checar bandeiras e caminhos, eu nem sequer penso em termos de comandos e argumentos, eu penso em termos de ações como 'dir corrente vazia', parte diferente do meu cérebro traduz-los para comandos e, por vezes, comete erros. Quero que o computador os corrija, pelo menos os perigosos.

    
por Valentin Nemcev 02.12.2011 / 18:09

29 respostas

215

Um dos truques que eu sigo é colocar # no começo, usando o comando rm .

root@localhost:~# #rm -rf /

Isso evita a execução acidental de rm no arquivo / diretório incorreto. Depois de verificado, remova # do início. Esse truque funciona, porque no Bash uma palavra que começa com # faz com que essa palavra e todos os caracteres restantes nessa linha sejam ignorados. Então o comando é simplesmente ignorado.

OR

Se você quiser evitar algum diretório importante, há mais um truque.

Crie um arquivo chamado -i nesse diretório. Como um arquivo tão estranho pode ser criado? Usando touch -- -i ou touch ./-i

Agora, tente rm -rf * :

sachin@sachin-ThinkPad-T420:~$ touch {1..4}
sachin@sachin-ThinkPad-T420:~$ touch -- -i
sachin@sachin-ThinkPad-T420:~$ ls
1  2  3  4  -i
sachin@sachin-ThinkPad-T420:~$ rm -rf *
rm: remove regular empty file '1'? n
rm: remove regular empty file '2'? 

Aqui, o * expandirá -i para a linha de comando, de modo que seu comando se torne rm -rf -i . Assim, o comando solicitará antes da remoção. Você pode colocar esse arquivo em / , /home/ , /etc/ , etc.

OR

Use --preserve-root como uma opção para rm . No rm incluído nos pacotes coreutils mais recentes, essa opção é o padrão.

--preserve-root
              do not remove '/' (default)

OR

Use safe-rm

Trecho do site:

Safe-rm is a safety tool intended to prevent the accidental deletion of important files by replacing /bin/rm with a wrapper, which checks the given arguments against a configurable blacklist of files and directories that should never be removed.

Users who attempt to delete one of these protected files or directories will not be able to do so and will be shown a warning message instead:

$ rm -rf /usr
Skipping /usr
    
por 04.11.2014 / 06:07
42

Seu problema:

I just ran rm -rf /* accidentally, but I meant rm -rf ./* (notice the star after the slash).

A solução: Não faça isso! Por uma questão de prática, não use ./ no início de um caminho. As barras não adicionam valor ao comando e apenas causam confusão.

./* significa a mesma coisa que * , então o comando acima é melhor escrito como:

rm -rf *

Aqui está um problema relacionado. Eu vejo a seguinte expressão frequentemente, onde alguém assumiu que FOO está definido como algo como /home/puppies . Eu vi isso hoje, na verdade, na documentação de um grande fornecedor de software.

rm -rf $FOO/

Mas se FOO não estiver definido, isso será avaliado como rm -rf / , que tentará remover todos os arquivos em seu sistema. A barra final é desnecessária, então, na prática, não a use.

O que se segue faz o mesmo e é menos provável que corrompa o seu sistema:

rm -rf $FOO

Eu aprendi essas dicas da maneira mais difícil. Quando eu tive minha primeira conta de superusuário 14 anos atrás, eu acidentalmente executei rm -rf $FOO/ de dentro de um script de shell e destruí um sistema. Os outros 4 sysadmins olharam para isto e disseram: 'Sim. Todo mundo faz isso uma vez. Agora aqui está sua mídia de instalação (36 disquetes). Vá consertar. '

Outras pessoas aqui recomendam soluções como --preserve-root e safe-rm . No entanto, estas soluções não estão presentes para todos os Un * xe-varients e podem não funcionar no Solaris, FreeBSD & Mac OS X. Além disso, safe-rm requer que você instale pacotes adicionais em todos os sistemas Linux que você usa. Se você confia em safe-rm , o que acontece quando você inicia um novo trabalho e eles não têm safe-rm instalado? Essas ferramentas são uma muleta, e é muito melhor confiar nos padrões conhecidos e melhorar seus hábitos de trabalho.

    
por 03.12.2011 / 00:36
30

Como isso está em "Serverfault", eu gostaria de dizer isso:

Se você tiver dezenas ou mais servidores, com uma equipe maior de administradores / usuários, alguém irá para rm -rf ou chown do diretório errado.

Você deve ter um plano para recuperar o serviço afetado com o menor MTTR possível.

    
por 02.12.2011 / 19:58
23

As melhores soluções envolvem alterar seus hábitos para não usar rm diretamente.

Uma abordagem é executar echo rm -rf /stuff/with/wildcards* primeiro. Verifique se a saída dos curingas parece razoável e use o histórico do shell para executar o comando anterior sem o echo .

Outra abordagem é limitar o comando echo para casos em que é extremamente óbvio o que você estará excluindo. Em vez de remover todos os arquivos em um diretório, remova o diretório e crie um novo. Um bom método é renomear o diretório existente para DELETE-foo , criar um novo diretório foo com as permissões apropriadas e, finalmente, remover DELETE-foo . Um benefício colateral desse método é que o comando inserido em seu histórico é rm -rf DELETE-foo .

cd ..
mv somedir DELETE-somedir
mkdir somedir                 # or rsync -dgop DELETE-somedir somedir to preserve permissions
ls DELETE-somedir             # just to make sure we're deleting the right thing
rm -rf DELETE-somedir

Se você realmente insistir em excluir um monte de arquivos porque precisa que o diretório permaneça (porque ele deve sempre existir ou porque você não teria permissão para recriá-lo), mova os arquivos para um diretório diferente e exclua esse diretório.

mkdir ../DELETE_ME
mv * ../DELETE_ME
ls ../DELETE_ME
rm -rf ../DELETE_ME

(Pressione a tecla Alt + . .)

Excluir um diretório de dentro seria atraente, porque rm -rf . é curto, portanto, tem um baixo risco de erros de digitação. Sistemas típicos não permitem que você faça isso, infelizmente. Você pode usar rm -rf -- "$PWD" , com um risco maior de erros de digitação, mas a maioria deles não leva à remoção de nada. Tenha em atenção que isto deixa um comando perigoso na sua história da shell.

Sempre que possível, use o controle de versão. Você não rm , você cvs rm ou qualquer outra coisa, e isso é impossível de se desfazer.

O Zsh tem opções para avisar você antes de executar rm com um argumento que lista todos os arquivos em um diretório: rm_star_silent (ativado por padrão) solicita antes de executar rm whatever/* e rm_star_wait (desativado por padrão) adiciona um atraso de 10 segundos durante o qual você não pode confirmar. Isso é de uso limitado se você pretendia remover todos os arquivos em algum diretório, porque você já esperaria o prompt. Isso pode ajudar a evitar erros de digitação como rm foo * para rm foo* .

Existem muitas outras soluções flutuantes que envolvem a alteração do comando rm . Uma limitação dessa abordagem é que um dia você estará em uma máquina com o rm real e chamará automaticamente rm , seguro na expectativa de uma confirmação ... e, em seguida, estará restaurando os backups.

    
por 02.12.2011 / 21:42
18

Você sempre pode fazer um alias, como você mencionou:

what_the_hell_am_i_thinking() {
   echo "Stop." >&2
   echo "Seriously." >&2
   echo "You almost blew up your computer." >&2
   echo 'WHAT WERE YOU THINKING!?!?!' >&2
   echo "Please provide an excuse for yourself below: " 
   read 
   echo "I'm sorry, that's a pathetic excuse. You're fired."
   sleep 2
   telnet nyancat.dakko.us
}

alias rm -fr /*="what_the_hell_am_i_thinking"

Você também pode integrá-lo com um cliente twitter de linha de comando para alertar seus amigos sobre como você quase se humilhou limpando seu disco rígido com rm -fr /* como root.

    
por 02.12.2011 / 23:33
15

Sim: não trabalhe como root e sempre pense duas vezes antes de agir.

Além disso, dê uma olhada em algo como link .

    
por 02.12.2011 / 18:16
15

A maneira mais simples de evitar% acid_rm -rf /* é evitar todo o uso do comando rm ! Na verdade, sempre fui tentado a executar rm /bin/rm para me livrar do comando completamente! Não, não estou sendo faceta.

Em vez disso, use a opção -delete do comando find , mas antes de excluir os arquivos, recomendo a visualização de quais arquivos serão excluídos:

find | less

Note que, nas versões modernas de find , se você deixar de fora o nome de um diretório, implicitamente usará o diretório atual, portanto, o acima é o equivalente de:

find . | less

Quando tiver certeza de que esses são os arquivos que deseja excluir, adicione a opção -delete :

find path/to/files -delete

Portanto, não só o find é mais seguro de usar, como também é mais expressivo , por isso, se você quiser exclua apenas determinados arquivos em uma hierarquia de diretórios que correspondam a um padrão específico que você possa usar uma expressão como essa para visualizar e exclua os arquivos:

find path/to/files -name '*~' | less
find path/to/files -name '*~' -delete

Existem muitas boas razões para aprender e usar find além de apenas um rm mais seguro, então você se agradecerá mais tarde se aprender a usar find .

    
por 26.02.2012 / 06:50
14

Há alguns conselhos realmente ruins neste tópico, por sorte, a maioria deles foi rejeitada.

Primeiro de tudo, quando você precisa ser root, torne-se root-sudo e os vários truques de alias farão com que você fique fraco. E pior, eles farão você descuidado. Aprenda a fazer as coisas da maneira certa, pare de depender de aliases para protegê-lo. Um dia você terá raiz em uma caixa que não tem suas rodas de treinamento e explodir algo.

Segundo - quando você tem raiz, pense em si mesmo como dirigir um ônibus cheio de crianças em idade escolar. Às vezes você pode cantar a música no rádio, mas outras vezes você precisa olhar para os dois lados, desacelerar e checar todos os seus espelhos.

Terceiro - Você quase nunca realmente tem que rm -rf - mais provavelmente você deseja mv something something.bak ou mkdir _trash && mv something _trash/

Quarto - sempre ls do seu curinga antes de rm - Não há nada de louco em ver algo antes de destruí-lo para sempre.

    
por 03.12.2011 / 23:44
11

Este é um padrão meu especificamente para regexps no contexto de rm, mas teria salvado você neste caso.

Eu sempre faço echo foo*/[0-9]*{bar,baz}* primeiro, para ver o que o regexp vai corresponder. Depois que eu tiver a saída, voltarei com a edição da linha de comando e alterarei echo para rm -rf . Eu nunca usei rm -rf em um regexp não testado.     

por 02.12.2011 / 20:57
9

A solução para este problema é fazer backups regulares. Toda vez que você produz algo que não quer arriscar perder, faça o backup. Se você achar que fazer o backup regularmente é muito doloroso, simplifique o processo para que não seja doloroso.

Por exemplo, se você trabalha com código-fonte, use uma ferramenta como git para espelhar o código e manter o histórico em outra máquina. Se você trabalha em documentos, tenha um script que rsync s seus documentos para outra máquina.

    
por 02.12.2011 / 20:05
6

Parece que a melhor maneira de reduzir esse risco é ter uma exclusão de dois estágios, como a maioria das GUIs. Ou seja, substitua rm por algo que mova as coisas para um diretório de lixo (no mesmo volume). Em seguida, limpe o lixo depois que tiver passado tempo suficiente para perceber qualquer erro.

Um desses utilitários, trash-cli, é discutido no Unix StackExchange, aqui .

    
por 04.12.2011 / 00:02
3

Um fator-chave importante para evitar esse tipo de erro é não fazer login usando uma conta root. Quando você faz o login usando um usuário normal não privilegiado, você precisa usar sudo para cada comando. Então, você deve ter mais cuidado.

    
por 02.12.2011 / 18:15
3

Quando eu excluo um diretório recursivamente, coloco o -r e -f , se aplicável, no fim do comando, por exemplo %código%. Dessa forma, se eu acidentalmente pressionar Enter cedo demais, sem ter digitado o caminho inteiro ainda, o comando não é recursivo, então provavelmente é inofensivo. Se eu bato Enter ao tentar digitar a barra depois de rm /foo/bar -rf , eu escrevi /foo em vez de rm /foo .

Isso funciona muito bem em sistemas que usam o GNU coreutils, mas os utilitários em alguns outros Unixes não permitem que opções sejam colocadas no final dessa forma. Felizmente, não uso esses sistemas com muita frequência.

    
por 03.12.2011 / 15:00
2

Pode ser complicado, mas você pode configurar funções dentro do SELinux, de modo que, mesmo que o usuário se torne root via sudo su - (ou simples su), a capacidade de excluir arquivos pode ser limitada (você precisa fazer login diretamente como root para remover arquivos). Se você estiver usando o AppArmor, você pode fazer algo semelhante .

Naturalmente, a outra solução seria garantir que você tenha backups. :)

    
por 02.12.2011 / 18:37
2

Evite usar globbing . No Bash, você pode definir noglob . Mas, novamente, quando você move para um sistema em que noglob não está definido, você pode esquecer isso e proceder como se fosse.

Defina noclobber para evitar que mv e cp destruam arquivos também.

Use um navegador de arquivos para exclusão. Alguns navegadores de arquivos oferecem uma lixeira (por exemplo, Konqueror ).

Outra maneira de evitar globbing é a seguinte. Na linha de comando, eu echo filenamepattern >> xxx . Em seguida, edito o arquivo com o Vim ou vi para verificar quais arquivos devem ser excluídos (observe os caracteres de padrão de nome de arquivo em filenmates) e, em seguida, use %s/^/rm -f/ para transformar cada linha em um comando de exclusão. Fonte xxx. Dessa forma, você verá todos os arquivos que serão excluídos antes de fazer isso.

Mova os arquivos para um diretório 'sótão' ou tarball. Ou use o controle de versão (como foi dito antes de mim).

    
por 04.12.2011 / 06:47
2

O ZSH me pergunta (como padrão) antes de executar um rm -rf * .

    
por 25.05.2012 / 08:25
1

Fora de chattr , não há muitas salvaguardas de permitir que o root execute esse comando. É por isso que os grupos apropriados e os comandos cuidadosos são importantes na execução de privilégios.

Da próxima vez; Escaneie os arquivos que você planeja excluir - omita 'f' de rm -rf ou use find e passe para xargs rm

    
por 02.12.2011 / 18:17
1

Alguns alias de segurança para outros comandos, para evitar desastres semelhantes, encontraram aqui :

# safety features
alias cp='cp -i'
alias mv='mv -i'
alias rm='rm -I'                    # 'rm -i' prompts for every file
alias ln='ln -i'
alias chown='chown --preserve-root'
alias chmod='chmod --preserve-root'
alias chgrp='chgrp --preserve-root'

Observe as maiúsculas -I , é diferente de -i :

prompt once before removing more than three files, or when removing recursively. Less intrusive than -i, while still giving protection against most mistakes

    
por 03.12.2011 / 12:50
1

Normalmente, uso o sinal -v para ver o que está sendo excluído e tenho a chance de ^C rapidamente se tiver a menor dúvida. Não é realmente uma maneira de impedir bad rm , mas isso pode ser útil para limitar os danos caso algo dê errado.

    
por 04.12.2011 / 11:32
1

Meu processo de exclusão em máquinas baseadas em Unix é o seguinte.

  • Digite ls /path/to/intented/file_or_directory na janela do terminal e, em seguida, pressione return (ou Tab , conforme desejado) para ver a lista de arquivos.

Se tudo parece bom,

  • clique na tecla up arrow para trazer novamente ls /path/to/intented/file_or_directory do histórico do terminal.

  • substitua ls por rm ou rm -r ou rm -rf , conforme necessário. Eu pessoalmente não gosto de usar -f flag.

Este processo de validação também previne a execução prematura do comando rm , algo que aconteceu comigo, antes de eu começar a seguir este processo.

    
por 03.12.2011 / 21:26
1

Se você não estiver com disposição para adquirir novos hábitos agora, .bashrc/.profile é um bom lugar para adicionar alguns testes para verificar se você está prestes a fazer algo estúpido. Eu imaginei que em uma função Bash eu poderia encontrar um padrão que poderia arruinar o meu dia e descobrir isso:

alias rm='set -f; myrm' #set -f turns off wildcard expansion need to do it outside of           
                        #the function so that we get the "raw" string.
myrm() {
    ARGV="$*"
    set +f #opposite of set -f
    if echo "$ARGV" | grep -e '-rf /*' \
                           -e 'another scary pattern'
    then
        echo "Do Not Operate Heavy Machinery while under the influence of this medication"
        return 1
    else
        /bin/rm $@
    fi
}

A coisa boa é que é apenas Bash.

É claro que não é genérico o suficiente nessa forma, mas acho que tem potencial, por isso, poste algumas ideias ou comentários.

    
por 04.12.2011 / 06:16
1
Infelizmente, não posso deixar um comentário acima devido ao carma insuficiente, mas queria alertar os outros que a segurança não é uma panacéia para os pesadelos acidentais de exclusão em massa.

O seguinte foi testado em uma máquina virtual Linux Mint 17.1 (alertando para aqueles que não estão familiarizados com esses comandos: NÃO FAÇA ISSO! Na verdade, mesmo aqueles que estão familiarizados com esses comandos provavelmente nunca farão isso para evitar perda de dados catastrófica) :

Versão em texto (condensada):

$ cd /
$ sudo safe-rm -rf *
$ ls
bash: /bin/ls: No such file or directory

Versão da imagem (completa):

    
por 09.04.2015 / 06:30
1

Eu gosto da abordagem das janelas da lixeira.

Eu costumo criar um diretório chamado "/ tmp / recyclebin" para tudo o que eu preciso excluir:

mkdir /tmp/recyclebin

E nunca use rm -rf, eu sempre uso:

mv target_folder /tmp/recyclebin

Mais tarde, esvazio o recyclebin usando um script ou manualmente.

    
por 18.12.2015 / 14:45
0

Hehe (não testado e um pouco facetado!):

$ cat /usr/local/bin/saferm

#! /bin/bash

/bin/ls -- "$@"

echo "Those be the files you're about to delete."
echo "Do you want to proceed (y/N)?"

read userresponse

if [ "$userresponse" -eq "y" ]; then

  echo "Executing...."
  /bin/rm -- "$@"

fi

E então:

alias rm="/usr/local/bin/saferm"
Realisticamente, você deveria ter uma pausa mental antes de executar esse tipo de operação com um glob, se você está rodando como root, colocando "sudo" nele, etc. Você pode rodar um "ls" no mesmo glob, Mas, mentalmente, você deve parar por um segundo, ter certeza de que você digitou o que queria, ter certeza de que o que você quer é realmente o que você quer, etc. Suponho que isso é algo que é principalmente aprendido destruindo algo no primeiro ano como um Unix SA, da mesma forma que o queimador quente é um bom professor dizendo que algo no fogão pode estar quente.

E verifique se você tem bons backups!

    
por 02.12.2011 / 18:42
0

Além disso, não como uma proteção, mas como uma maneira de descobrir quais arquivos foram excluídos antes de você clicar em ^ C, você pode usar o banco de dados locate (claro que somente se ele foi instalado e sobreviveu rm )

Eu aprendi sobre isso com essa postagem no blog

    
por 03.12.2011 / 12:07
0

Basta usar o ZFS para armazenar os arquivos necessários para resistir à remoção acidental e ter um daemon que:

  • faz regularmente instantâneos deste sistema de arquivos
  • remove instantâneos antigos / desnecessários.

Os arquivos devem ser removidos, sobrescritos, corrompidos, o que for, apenas reverter o sistema de arquivos para um clone do último instantâneo bom e pronto.

    
por 03.12.2011 / 22:27
0

não tanto uma resposta, mas uma dica, eu sempre faço rm (dir) -rf não rm -rf (dir) ou seja: não vá nuclear até o último momento possível.

Ele ajuda a atenuar situações em que você digita o nome do dir de uma forma que ainda é uma exclusão válida, como escorregar e apertar a tecla enter.

    
por 09.04.2015 / 06:39
0

Acho que essa é uma dica poderosa de prevenção, com o atalho de expansão * no shell:

Primeiro, digite rm -rf * ou rm -rf your/path/* , NÃO digite Enter key. (claro, você deve ter o hábito de não pressionar Enter rapidamente / acidentalmente quando usar rm -rf )

Em seguida, pressione Alt-Shift-8 (ou seja, Alt-Shift-* ) para expandir o caractere curinga "*" explicitamente no bash. Isso também evita a reintrodução de um comando "rm -rf *" ao navegar no histórico.

Finalmente, depois de verificar se a expansão tem os arquivos / diretórios corretos, pressione Enter.

Feito.

    
por 22.11.2016 / 05:12
0

No caso de isso ajudar alguém no seu próprio caso:

1. Use rmsafe :

Ele move os arquivos para uma pasta "lixeira" e você sempre tem a chance de trazê-los de volta com um simples mv :

$ rmsafe /path/to/important/files

Fonte: link

2. Use safe :

Você pode definir um alias para rm usando seguro:

$ alias rm="safe rm"

Agora, se você executar rm /* , receba isso em resposta:

$ rm /*
Are you sure you want to 'rm /bin /boot /data /dev /etc /home /initrd.img /lib /lib64 /mnt /opt /proc /root /run /sbin /srv /sys /tmp /usr /var'? [y/n]

e acredito que você não digitará y !

Fonte: link

    
por 11.04.2018 / 14:39