Acidentalmente usou o redirecionamento de saída em vez de um pipe |

22

Um mês atrás eu escrevi um script Python para mapear os endereços MAC e IP do stdin. E há dois dias me lembrei disso e usei para filtrar a saída de tcpdump , mas 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.py e encontrei todos os tcpdump dados em vez do programa. Então percebi que deveria usar

tcpdump -ne | ./mac_ip.py

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

    
por Bharath Teja 24.06.2017 / 08:54

7 respostas

24

Infelizmente eu suspeito que você precisará reescrevê-lo. (Se você tem backups, esta é a hora de tirá-los. Se não, eu recomendo strongmente que você configure um regime de backup para o futuro. Muitas opções disponíveis, mas off topic para esta resposta.)

Acho que colocar executáveis em um diretório separado e adicionar esse diretório ao PATH é útil. Dessa forma, não preciso referenciar os executáveis por caminho explícito. Meu diretório de programas preferenciais para scripts pessoais (privados) é "$HOME"/bin e 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_profile e / ou .bashrc .

Por fim, não há nada que o impeça de remover a permissão de gravação para você mesmo 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
    
por 24.06.2017 / 09:28
39

Para evitar que arquivos existentes sejam substituídos pelo redirecionamento > use a opção noclobber em bash ou qualquer shell semelhante a POSIX (também em (t)csh onde o recurso realmente foi originado, embora você use set noclobber de set -o noclobber / set -C lá). 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
...
    
por 24.06.2017 / 13:04
10

Eu recomendo strongmente que os scripts importantes em um git repo , sejam sincronizados remotamente (a plataforma auto-hospedada fantasia vai fazer), como diz o comentário @ casey.

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

    
por 25.06.2017 / 11:08
5

O arquivo é recuperável?

Resposta curta: geralmente não.

@Mark Plotnick aponta nos comentários, você pode recuperar .py arquivos de .pyc usando Descompilar . Isso deve ser perfeito para sua situação.

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

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

Não. Não existe uma maneira padrão de dizer ao shell para nunca redirecionar apenas os arquivos marcados como executáveis. Existe o "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 bobo, mas para evitar erros futuros, você provavelmente não precisa fazer nada. Minha aposta é que você já aprendeu esta lição.

    Eu venho usando e ensinando o Unix há muito tempo e enquanto as pessoas frequentemente cometem esse erro uma vez, elas raramente o repetem. Por que não? Provavelmente pela mesma razão, 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 suportam backups automáticos, você poderia fazer uma função simplista em 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á enganando as TABs acima como 4 espaços.)

  4. Da mesma forma, você pode criar um destino Makefile que execute rsync para um host Unix remoto ao qual você tenha acesso ssh . (Use ssh-copy-id para que você não receba sua senha repetidamente.)

  5. Use git . Existem muitos excelentes tutoriais sobre como começar. Experimente man gittutorial , man gittutorial-2 e 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 em github.com

  6. Se as soluções acima forem muito pesadas, salve pequenos scripts em gist.github.com . Embora seja possível colar ou fazer o upload de um navegador da Web, recomendo usar uma interface de linha de comando para facilitar as coisas.

Desencorajo strongmente o uso de "noclobber".

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

Isso faz com que o shell funcione de maneira não padrão, sem indicação visível de que esteja habilitado. Você tem que usar uma sintaxe diferente para fazer coisas normais. Pior de tudo, se você se acostumar com o noclobber, algum dia usará outra máquina Unix sem 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 vai atrapalhar - e vai te cortar se você esquecer que final é pontudo. Mas, quanto mais você usa, mais eu acho que você vai perceber 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á ideia.

    
por 25.06.2017 / 16:16
3

Você pode ter recuperado os dados depois que eles ocorreram pela primeira vez se você 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ê canalizou para tee para gravar em um arquivo (assim como STDOUT ) em vez de > (ou tee -a em vez de >> ), pode facilmente substituir tee por um alias, função ou link simbólico para um script que avisa o usuário se o arquivo para o qual ele está prestes a gravar é executável.

O seguinte não é ideal e poderia ser melhorado em 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"' >> ~/.bashrc ou algo similar.

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!

    
por 24.06.2017 / 09:34
1

Você não especificou se está trabalhando em um PC ou em um servidor. Se os seus arquivos forem armazenados em um servidor de arquivos dedicado, geralmente há backups automáticos ("instantâneos") mantidos pelo (SO no hardware) do servidor de arquivos.

No Linux

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

Tente:

cd .snapshot   
ls -l

Se esse diretório existir, você pode estar com sorte. Você deve ver uma série de diretórios que armazenam backups automaticamente em determinados pontos no tempo. 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

Entre em qualquer diretório de ponto no tempo que tenha idade suficiente (antes do erro de sobrescrever o arquivo). Dentro do diretório timepoint, você deve ver o estado do diretório ../.. (e todos os subdiretórios) a partir desse 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 -a não mostrará o diretório .snapshot ; você deve nomear explicitamente. É inserido virtualmente pelo servidor de arquivos. Isso não existe como um diretório real em seu sistema de arquivos.
  2. Esses instantâneos automáticos são um histórico contínuo. Velhas mudanças eventualmente caem do fim e estão perdidos. Você precisa usar isso técnica logo que possível depois de perceber que você precisa de um arquivo de volta.

No Windows

O diretório de snapshot oculto pode ser chamado ~ snapshot e existe apenas no nível raiz de uma determinada unidade.

Conselhos

Os instantâneos são uma rede de segurança que funciona na maior parte do tempo, mas não o tempo todo. Eu concordo com as outras recomendações para usar um sistema de controle de versão (como git ) mesmo para arquivos triviais.

    
por 08.07.2017 / 00:52
1

Já foi dito antes, e eu vou dizer de novo. 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 outros um-mergables, git e hg o superaram para a maioria das outras funções. hg e git permitem que você trabalhe off-line e sincronize com um servidor remoto, para distribuição e backup.

Leia o controle de revisão, distribua o controle de revisão e, em seguida, experimente-o.

    
por 17.07.2017 / 22:58