Evita que o usuário digite espaço acidental entre rm e curinga

29

Intenção:

rm -rf string*

Problema:

rm -rf string *

O primeiro caso é um uso legítimo e comum de rm, um pequeno erro de digitação pode causar muitos problemas no segundo caso. Existe uma maneira simples de proteger de forma inteligente contra um caractere curinga ou um caractere curinga acidental?

    
por bobdole 14.01.2015 / 05:58

11 respostas

37

Uma armadilha DEBUG pode ser escrita para cancelar comandos que pareçam suspeitos. O código a seguir, ou semelhante a ele, pode ser adicionado ao seu ~/.bashrc :

shopt -s extdebug
checkcommand() {
  if [[ $BASH_COMMAND = 'rm -r'*' *' ]]; then
    echo "Suppressing rm -r command ending in a wildcard" >&2
    return 1
  fi
  # check for other commands here, if you like
  return 0
}
trap checkcommand DEBUG

Ajuste a lógica a gosto.

(Na verdade, não espero que essa abordagem seja útil - muitas maneiras de atrapalhar um comando destrutivamente para encontrá-los testando um por um - mas fornece uma resposta literal à pergunta).

    
por 14.01.2015 / 17:35
47

Não há como criar um sistema totalmente à prova de balas. E adicionando "Tem certeza?" As sugestões para as coisas são contraproducentes e levam a "É claro que tenho certeza". reações de kneejerk.

Um truque que eu peguei de um livro em anos anteriores é primeiro fazer ls -R blah* , então rm -fr blah* se e somente se a listagem que eu encontrei atingiu o que eu queria atingir.

É muito fácil fazer o comando ls primeiro, depois , apagar o ls -R e substituir por rm -fr .

A pergunta final é: "Se a informação foi valiosa para você, onde está o seu backup?"

    
por 14.01.2015 / 06:37
8

Você pode se treinar para usar, digamos, rmrf no lugar de rm -rf ?

Se sim, esta função bash lhe dará a chance de ver o que realmente aconteceria antes de confirmar o comando:

rmrf() { echo rm -rf "$@"; read -p "Proceed (y/N)? "; [ "${REPLY,,}" = y ] && rm -rf "$@"; }

Para tornar esta função permanente, adicione esta linha ao arquivo ~/.bashrc em cada computador que você usa.

Comparação com o alias rm comum

É comum definir um alias:

alias rm='rm -i'

Isso tem duas limitações:

  1. Se você depender desse apelido, você terá um choque quando estiver em uma máquina ou em um ambiente que não o tenha. Por outro lado, tentar executar rmrf em uma máquina sem essa função retornará um command not found inofensivo.

  2. Esse alias não ajuda em seu caso porque a opção -f que você fornece na linha de comando substitui a opção -i no alias.

por 14.01.2015 / 06:05
6

Se eu estiver em uma situação em que excluir os arquivos incorretos é realmente importante, uma das coisas que fiz foi criar uma pasta da lixeira, como mkdir trashcan , e depois eu tenho um script rmTrashcan que tem um rm -rf trashcan/* ou rm -rf * ou similar, escrito com muito cuidado e verificado várias vezes.

Dessa forma, se eu cometer um erro, o erro estará no comando mv , não no comando rm . Depois que eu fizer um ls e tiver certeza de exatamente o que estou excluindo, um rmTrashcan realmente faz o trabalho sujo com segurança.

Também foi tremendamente conveniente para uma situação em que precisei excluir backups. Eu poderia mv um mês inteiro de backups na lixeira, mv os poucos que eu queria manter (1 º mês, 15 º mês) de volta para os backups, então rmTranshcan o resto. Fazer um comando similar é difícil de fazer com rm sozinho, e dessa forma deixe-me ls os backups estarem confiantes em quais arquivos eu estou deixando para trás (em vez de apenas enumerar os arquivos que pretendo excluir)

    
por 15.01.2015 / 08:08
4

Em vez de se preocupar com dois comandos ( ls e rm ), acho que uma maneira mais simples e fácil é usar find :

find . -maxdepth 1 -name "string*" -delete

Se você acidentalmente digitar "string *" , ele excluirá arquivos chamados string chars e string letters (que é o que você queria de qualquer maneira), mas não pegará todos os arquivos como * em um shell.

Além disso, você pode deixar o -delete para ver quais arquivos ele irá excluir, então pressione a seta para cima e digite -delete mais fácil do que digitar ^ls -R^rm -rf ou outras bobagens.

    
por 14.01.2015 / 18:12
3

Is there a simple way to smartly protect against an accidental trailing or leading wildcard?

Não realmente. Em outra resposta, você pode criar um comando personalizado para adicionar um prompt antes de executar uma tarefa. Mas o problema com esse comando personalizado é que ele deve ser instalado conscientemente nos sistemas em que você está trabalhando. E mesmo que esteja instalado, o problema é o seu reflexo para acertar y para que a tarefa seja executada.

Isso significa que tudo é um problema da interface do usuário, mesmo se estiver em um nível de linha de texto / comando. Quantas redes de segurança você espera que existam para protegê-lo de fazer algo que você não deveria? É como uma tesoura: se você é de alguma forma negligente e escorrega e corta a mão enquanto pretende cortar um pano ou papel, quem é a culpa? Ou mesmo semáforos e sinais de parada: não há realmente nada que impeça um motorista de acender uma luz ou ignorar sinais de trânsito além de uma percepção aguda do que pode acontecer se eles se envolverem em um comportamento de risco.

Dito isso, a melhor solução realista está nas permissões do sistema para usuários e grupos. Essa é a melhor / única rede de segurança real para proteger um usuário de si mesmo.

Se você está trabalhando em um sistema onde você é o único que o acessa, você pode ficar tentado a apenas chmod 777 de tudo, mas não é assim que um sistema racional é configurado. Em vez disso, as permissões devem ser algo como 755 para todos os diretórios e 644 para todos os arquivos não executáveis. Os arquivos executáveis devem ter no mínimo 755 , mas talvez até 744 se você quiser que outras pessoas leiam, mas não executem os arquivos.

    
por 14.01.2015 / 06:20
2

Tente compor seu comando rm inicial sem o sinal -f , mas com -i , tal que rm solicitará cada arquivo que ele deseja excluir. Para pequenas exclusões recursivas, você pode manter pressionada a tecla y , assim que tiver certeza de que o comando foi digitado corretamente. Para grandes exclusões, você pode cancelar a operação e usar o histórico de linha de comando para alterar cuidadosamente o -i para um -f .

    
por 14.01.2015 / 06:20
2

rm tem -i e -I sinalizadores para confirmar antes de cada remoção. No passado, algumas distribuições as ativaram por padrão. Essa é uma ideia terrível. Dê ao usuário muitos diálogos de confirmação para operações normais e eles começarão a confirmá-los habitualmente. Isso apenas muda a exigência de "ter cuidado" (sempre uma bandeira vermelha) para um novo e mais chato diálogo. "Sim. Sim. Sim. Sim! Sim! Deus, droga, computador idiota, apenas apague os arquivos SIMESESTIENSEYESYESYES - EXCREMENTO NÃO SIGNIFICADO! NOOOOOOO!" Este é o problema de diálogo "Sim, mas não quis dizer". Esta resposta fornece uma explicação visual de por que os diálogos de confirmação chegam na hora errada.

O tipo de erro que você descreve é um slip ," o desempenho de uma ação que não era o pretendido ". O usuário geralmente reconhece imediatamente o erro e sabe exatamente como corrigi-lo. Infelizmente, o Unix não dá ao usuário a oportunidade, o rm exclui o arquivo imediatamente. Todos os outros sistemas operacionais resolvem esse problema permitindo que as exclusões sejam desfeitas, pelo menos por um tempo, pelo uso da Lixeira.

Existem vários sistemas de lixo para o Unix, e esta resposta está cheia de sugestões .

A questão é alias rm ou não alias rm. Prós para aliasing rm ...

  1. Você não pode esquecer de usar a alternativa de rm.

Contras ao aliasing rm ...

  1. Você pode confiar em sistemas que não o possuem.
  2. Pode causar problemas quando o disco está quase cheio.
  3. Precisa de infraestrutura para esvaziar a lixeira periodicamente.
  4. Certifique-se de não interferir com o comportamento esperado de rm nos programas.
  5. Pode não ser totalmente emulado rm.

Se você seguir o primeiro argumento longe demais, acabará usando o vi (não vim, vi), csh (não tcsh, csh) e outros utilitários antiquados porque eles estão disponíveis universalmente. Ainda assim, existe o perigo de overcustomizing seu ambiente. Eu prefiro levar meus utilitários comigo e fazer isso o mais fácil possível. YMMV.

Dois e três são problemas técnicos. Eles podem ser resolvidos com um trabalho de reaper inteligente que verifica o tamanho do lixo e periodicamente limpa as coisas, semelhante a um tmpreaper . Este pode ser um cron job, ou uma versão mais inteligente pode fazer uso das várias infra-estruturas de eventos do sistema de arquivos disponíveis em muitas distribuições Linux de desktop. Isso não é simples e ainda mais difícil de ser feito com eficiência. É melhor encontrar um sistema existente do que tentar fazer o seu próprio.

O quarto pode ser resolvido tornando seu novo rm um alias de shell, alias rm='trash' , então ele não afetará os programas.

O quinto é um problema que deixo para o leitor resolver. rm não tem muitos switches.

    
por 14.01.2015 / 20:03
2

Eu ensino a todos sobre o !$ = last argument no último truque de comando:

% ls job[XYZ].*
jobX.out1
jobX.out2
[rest of the matches]

% rm !$

Isso permite uma inspeção da expansão de caractere curinga e, em seguida, o uso do mesmo padrão de glob sem a possibilidade de inserir um espaço antes do * .

Também sugiro que as pessoas nunca recortem e colem um padrão curinga globbing em uma linha de comando potencialmente destrutiva. Porque nas minhas próprias mãos isso tem sido um problema:)

Um técnico no meu laboratório acabou de cometer esse erro na semana passada (3 meses de trabalho) - e sim, tivemos um backup (1 dia atrás).

    
por 17.01.2015 / 17:41
0

Todos parecem estar dizendo: "Seja mais cuidadoso", "Não faça um apelido / pedido de confirmação porque ficará habituado a não prestar a devida atenção a ele".

Legal e tudo mais. Quero dizer, eu não acho que você deveria fazer um alias para rm (nem rmrf , já que você poderia facilmente estragar tudo e digitar o comando real).

Mas por que você não pode criar um alias / script e chamá-lo, digamos, remove e apenas alimentá-lo com um argumento (por exemplo, $ 1)? O curinga deve ser de $ 2, devido ao espaço inadvertido (direito?) E, portanto, seu script / wrapper / alias não será alimentado com o segundo. Sim, você só pode fazer um conjunto de exclusões (com um caractere curinga) por vez, mas esse é o preço que você pagaria.

Se eu estivesse escrevendo algo legal, talvez ele me dissesse o número de arquivos e diretórios que está planejando excluir e o tamanho total das coisas que eu estava excluindo e, em seguida, peça uma confirmação, mas isso pode impedir seu fluxo . Talvez faça disso uma opção de sinalização em remove ? (-Eu). Você também pode querer verificar $ 1 para ver se é apenas um único caractere curinga, pedir uma confirmação e listar em qual diretório você está.

Como um aparte, há um número de substituições de rm por aí. Muitos estão tentando ser compatíveis com a lixeira da área de trabalho da interface do usuário. Alguns desses podem valer a pena investigar.

    
por 14.01.2015 / 16:28
0

Um truque muito simples é colocar -rf no final: rm whatever* -rf
Isso reduz drasticamente a taxa de erro, porque você digita mais caracteres após o * , então você tem mais tempo para ver erros de digitação. Isso não resolve tudo. Apenas um simples truque cotidiano.

    
por 19.06.2017 / 17:35

Tags