Utilizou acidentalmente o redirecionamento de saída> em vez de um pipe |


21

Há um mês, escrevi um script Python para mapear endereços MAC e IP a partir do stdin. E dois dias atrás, lembrei-me e costumava filtrar a saída, tcpdumpmas deu errado por causa de um erro de digitação. Eu digitei

tcpdump -ne > ./mac_ip.py

e a saída não é nada. Mas a saída deve ser "Desconhecida" se não puder analisar a entrada, então eu fiz cat ./mac_ip.pye encontrei todos os tcpdumpdados em vez do programa. Então eu percebi que deveria usar

tcpdump -ne | ./mac_ip.py

Existe alguma maneira de recuperar meu programa? De qualquer forma, posso escrever meu programa novamente, mas se isso acontecer novamente com um programa mais importante, eu devo fazer alguma coisa. OU existe alguma maneira de dizer ao redirecionamento de saída para verificar o arquivo e avisar se é um executável?


18
Você pode recuperar seu programa do último backup antes de substituir, caso contrário não. BTW no shell, você pode especificar set -o noglobbere o bash não será mais redirecionado para os arquivos existentes. Veja aqui para detalhes: cyberciti.biz/tips/howto-keep-file-safe-from-overwriting.html
eckes

12
Você não deve ter permissão de gravação para executáveis importantes ...
Hagen von Eitzen

20
@eckesset -o noclobber
GnP

38
@HagenvonEitzen Eu odeio conselhos como esse, como se você tivesse definido a propriedade e as permissões apropriadas em todos os scripts shell e python únicos que você já escreveu antes de executá-lo (e, é claro, volte brevemente se precisar editá-lo ) É apenas marginalmente mais significativo do que "Você não deve digitar >quando quiser |". Não esqueça a realidade.
Jason C

30
Os repositórios Git são baratos. Confirme todo o seu código, não importa quão pequeno e sem sentido, e um erro como esse é uma solução rápida e fácil.
casey

Respostas:


22

Infelizmente, suspeito que você precisará reescrevê-lo. (Se você tiver backups, é a hora de liberá-los. Caso contrário, recomendo fortemente que você configure um regime de backup para o futuro. Muitas opções disponíveis, mas fora de tópico para esta resposta.)

Acho que colocar os executáveis ​​em um diretório separado e adicionar esse diretório ao PATHé útil. Dessa forma, não preciso fazer referência aos executáveis ​​por caminho explícito. Meu diretório de programas preferido para scripts pessoais (particulares) é "$HOME"/bine pode ser adicionado ao caminho de pesquisa do programa com PATH="$HOME/bin:$PATH". Normalmente, isso seria adicionado aos scripts de inicialização do shell .bash_profilee / ou .bashrc.

Por fim, nada impede que você remova a permissão de gravação em todos os programas executáveis:

touch some_executable.py
chmod a+x,a-w some_executable.py    # chmod 555, if you prefer

ls -l some_executable.py
-r-xr-xr-x+ 1 roaima roaima 0 Jun 25 18:33 some_executable.py

echo "The hunting of the Snark" > ./some_executable.py
-bash: ./some_executable.py: Permission denied

2
/usr/local/biné o local padrão para arquivos executáveis criados pelo usuário e scripts
gardenhead

4
@ Gardenhead Depende de como o sistema está configurado. /usr/localdestina-se a coisas específicas de host (em oposição a um diretório compartilhado entre hosts por meio de uma montagem de rede) e pode ou não ser gravável por usuários não-root.
chepner

4
@ Gardenhead é um local padrão, certamente. Uso /use/local/binpara scripts e programas instalados localmente que provavelmente serão usados ​​por várias contas de usuário e $HOME/binpara coisas pessoais de um único usuário. Há valor em ambos.
roaima

1
Note-se que o Fedora parece estar tentando empurrar usando$HOME/.local/bin
Zan Lynx

1
@Zan eeeww! Sério, obrigado. Parece que o RH está tentando empurrar tudo, ~/.localpois esse é outro item movido de seu lugar "tradicional".
roaima

38

Para impedir que arquivos existentes sejam substituídos pelo redirecionamento, >use a noclobberopção em bashqualquer shell semelhante ao POSIX (também (t)cshonde a funcionalidade realmente se originou, embora você faça isso em set noclobbervez de set -o noclobber/ set -Clá). Em seguida, se você precisar forçar a substituição de um arquivo, use o >|operador de redirecionamento ( >!in (t)csh).

Exemplo:

$ echo abc > file
$ set -o noclobber
$ echo xyz > file
bash: file: cannot overwrite existing file
$ echo xyz >| file
$ cat file
xyz

BTW, você pode verificar as configurações atuais com set -o:

$ set -o
...
monitor         on
noclobber       on
noexec          off
...

Embora isso responda perfeitamente à pergunta, eu não a recomendaria. 1. Digitar em >|vez de |não é muito menos provável que digitar >. 2. É fácil e altamente recomendável fazer backups (um editor que vale o nome pode salvar a última versão; há cronetc.). 3. Todo pedaço de código deve ser colocado sob controle de versão, mesmo pequenos scripts. YMMV.
Maaartinus

2
@maaartinus vamos lá, 1) digitar dois caracteres separados em vez de um é claramente menos provável. 2) Obviamente, os backups são essenciais, ninguém aconselhou o OP a não fazer backups, esta resposta não sugere backups, e os backups do editor pressupõem que você tenha editado o arquivo em um editor. 3) Novamente, você está pensando apenas no código que o OP escreveu, como neste exemplo em particular, mas a pergunta e esta resposta são aplicáveis ​​a qualquer arquivo na máquina, incluindo executáveis ​​do sistema.
terdon

8

Eu recomendo fortemente que os scripts importantes sob um repositório git sejam sincronizados remotamente (como uma plataforma auto-hospedada sofisticada ), como diz o comentário de @ casey.

Dessa forma, você está protegido contra erros humanos graves, como reverter o arquivo para o estado de trabalho anterior e executá-lo novamente.


4

O arquivo é recuperável?

Resposta curta: geralmente não.

O @Mark Plotnick aponta nos comentários, você pode recuperar .pyarquivos .pycusando o Uncompyle . Isso deve ser perfeito para a sua situação.

Em geral, porém, isso é muito mais difícil. Teoricamente, você pode usar ferramentas forenses para recuperar arquivos excluídos. Provavelmente, o mais fácil que já usei é testdisk(também conhecido como "PhotoRec"). Às vezes, funciona apenas e é um processo lento. Geralmente não vale a pena, então, sim, é possível , mas a resposta real é "não".

> Pode ser alterado para não sobrescrever executáveis?

Não. Não existe uma maneira padrão de dizer ao shell para nunca redirecionar apenas para arquivos marcados como executáveis. Há "noclobber" que impedirá o redirecionamento para arquivos existentes, executáveis ​​ou não, mas veja meus comentários sobre isso abaixo.

O que fazer no futuro?

  1. Isso pode parecer bobagem, mas para evitar erros futuros, você provavelmente não precisará fazer nada. Minha aposta é que você já aprendeu esta lição.

    Eu uso e ensino o Unix há muito tempo e, embora as pessoas cometam esse erro uma vez, raramente o repetem. Por que não? Provavelmente pela mesma razão que uma pessoa experiente com facas não se corta: os humanos são bons em aprender. Eventualmente, fazer a coisa certa se torna uma segunda natureza.

  2. Use um editor de texto que faça backups para você. Por exemplo, se você usar emacs, a versão anterior do seu programa será salva em mac_ip.py ~. Outros editores podem ser configurados para funcionar de maneira semelhante (por exemplo, "definir backup" em .nanorc). Para editores que não oferecem suporte a backups automáticos, você pode fazer uma função simplista no seu .bashrc:

    myeditor() { cp -p "$1" "$1~";  editor "$1"; }
    
  3. Facilite para você fazer cópias. Por exemplo, no diretório do projeto em que você está trabalhando, você pode ter um Makefile com um destino como este:

    # Use `make tar` to backup all files in this directory.
    # Tar filename will be ../<currentdirectory>-<date>.tar.gz 
    DIRNAME = $(shell basename `pwd`)
    TIMESTAMP = $(shell date +%s)
    tar:
        @echo "[Tarring up ${DIRNAME}.tar.gz]"
        (cd .. ; tar -zcvf "${DIRNAME}-${TIMESTAMP}.tar.gz" "${DIRNAME}")
    

    (Nota: stackexchange está processando incorretamente as TABs acima como 4 espaços.)

  4. Da mesma forma, você pode criar um destino Makefile que faz um rsynchost Unix remoto ao qual você tem sshacesso. (Use ssh-copy-idpara não ser solicitada sua senha repetidamente.)

  5. Use git. Existem muitos tutoriais excelentes para começar. Tente man gittutorial, man gittutorial-2e man giteveryday. Configurar seu próprio repositório git não é difícil, mas você também pode criar um repositório remoto sem nenhum custo no github.com

  6. Se as soluções acima forem muito pesadas, você pode salvar pequenos scripts no gist.github.com . Embora seja possível colar ou fazer upload de um navegador da Web, eu recomendo usar uma interface de essência da linha de comando para tornar as coisas super fáceis.

Eu desencorajo fortemente o uso de "noclobber".

Sim, se você escolher, set -o noclobberpoderá receber mensagens de erro sempre que tentar sobrescrever um arquivo existente. Esta é uma má ideia, na minha opinião. *

Faz com que o shell funcione de maneira não padrão, sem indicação visível se está ativado. Você precisa usar uma sintaxe diferente para fazer coisas normais. O pior de tudo é que, se você se acostumar com o noclobber, algum dia usará outra máquina Unix sem o noclobber e esse tipo de acidente poderá acontecer novamente.

Como você provavelmente sabe, o shell Unix foi projetado para ser uma ferramenta afiada para especialistas. É rápido de usar e não atrapalha o seu caminho - e vai te cortar se você esquecer qual extremidade é pontuda. Mas, quanto mais você o usa, mais eu acho que você apreciará que isso pode ser uma coisa boa.


* Nota de rodapé: talvez tome minhas opiniões com um grão de sal. Eu também sou o tipo de pessoa que acha que as rodas de treinamento de bicicleta são uma má idéia.


Eu também ensinei Unix por um tempo. Muitos dos meus alunos nunca aprenderam a apreciar a simplicidade direta do Unix; Digo a eles que não estão sozinhos, e que pelo menos ainda podem aprender enquanto lamentam o Manual do Unix Hater, que mapeia parte do campo minado para eles. simson.net/ref/ugh.pdf
Jason

Além disso: concordo - as rodas de bicicleta são úteis para quem aprende a andar de triciclo.
Jason

2

Talvez você tenha recuperado os dados após a ocorrência, se visualizou ou editou recentemente o script e ele ainda estava no buffer de memória. Caso contrário, você está praticamente sem sorte.

Se você procurou teegravar em um arquivo (e também STDOUT) em vez de >(ou em tee -avez de >>), poderia facilmente substituir teepor um alias, função ou link simbólico para um script que avisa o usuário se o arquivo que está prestes a gravar to é executável.

O que se segue não é de forma alguma ideal e pode ser melhorado muito , mas é um ponto de partida, apenas como um exemplo de como isso é possível:

wee.sh:

#!/bin/bash

if [ -n "${2}" ]; then
  if [ "$(ls -l "${2}" | awk '{print $1}' | grep x)" ]; then
    echo executable
  else
    tee -a "${2}"
  fi
elif [ "$(ls -l "${1}" | awk '{print $1}' | grep x)" ]; then
  echo executable
else
  tee "${1}"
fi

... então apenas echo 'alias tee="/path/to/wee.sh"' >> ~/.bashrcou algo semelhante.

Pelo lado positivo, pelo menos você terá mais prática e a segunda versão do seu script Python provavelmente será muito melhor que a primeira!


1

Você não especificou se está trabalhando em um PC ou servidor. Se seus arquivos estiverem armazenados em um servidor de arquivos dedicado, geralmente haverá backups automáticos ("snapshots") sendo mantidos pelo hardware do servidor de arquivos (OS no).

No Linux

O diretório virtual instantâneo oculto existe em todos os diretórios do seu sistema de arquivos.

Experimentar:

cd .snapshot   
ls -l

Se esse diretório existir, você poderá ter sorte. Você deve ver uma série de diretórios que mantêm os backups armazenados automaticamente em determinados momentos. Os nomes indicam o tempo relativo no passado em que o instantâneo foi armazenado. Por exemplo:

hourly.0
hourly.1
hourly.2
hourly.3
hourly.4
hourly.5
nightly.0
nightly.1
nightly.2
nightly.3
nightly.4
nightly.5
nightly.6
weekly.0
weekly.1
weekly.2

Vá para qualquer diretório de ponto no tempo que tenha idade suficiente (antes do erro de substituição de arquivo). Dentro do diretório do ponto no tempo, você deve ver o estado do ../..diretório (e todos os subdiretórios) daquele ponto no passado.

cd nightly.6
ls  # look around   
tee < mac_ip.py  # check for the correct content
cp mac_ip.py ~/safekeeping/mac_ip.py  # save the old file

Notas:

  1. ls -anão mostrará o .snapshotdiretório; você deve nomeá-lo explicitamente. É inserido virtualmente pelo servidor de arquivos. Ele não existe como um diretório real no seu sistema de arquivos.
  2. Esses instantâneos automáticos são um histórico contínuo. As mudanças antigas acabam caindo no final e são perdidas. Você precisa usar essa técnica o mais rápido possível depois de perceber que precisa de um arquivo de volta.

No Windows

O diretório oculto da captura instantânea pode ser nomeado ~ captura instantânea e existir apenas no nível raiz de uma determinada unidade.

Conselhos

Os instantâneos são uma rede de segurança que funciona na maioria das vezes, mas não sempre. Concordo com as outras recomendações para usar um sistema de controle de versão (como git) mesmo para arquivos triviais.


1

Já foi dito antes, e direi novamente. Use um sistema de controle de revisão.

Os backups são para recuperar uma falha de hardware. O controle de revisão é para situações como a sua (e tem muitos outros usos). As ferramentas de controle de revisão permitem manter um histórico de um arquivo e voltar a qualquer ponto desse histórico.

Exemplos de ferramentas de controle de revisão incluem subversão (SVN) (um pouco antiga agora, mas ainda boa), mercurial (hg) e git (git) (difícil de usar). O svn é bom para documentos de escritório e outras um-mescláveis, git e hg o superaram na maioria das outras funções. hg e git permitem trabalhar off-line e sincronizar com um servidor remoto, para distribuição e backup.

Leia o controle de revisão, depois distribua o controle de revisão e tente-o.


Concordo que o uso de controle de revisão é melhor para situações como a minha, mas dando as permissões corretas aos arquivos é igualmente importante
Bharat Teja
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.