Utilizzato per errore il reindirizzamento dell'output> anziché una pipe |


21

Un mese fa ho scritto uno script Python per mappare gli indirizzi MAC e IP da stdin. E due giorni fa l'ho ricordato e usato per filtrare l'output di tcpdumpma è andato storto a causa di un errore di battitura. Ho scritto

tcpdump -ne > ./mac_ip.py

e l'output è nulla. Ma l'output dovrebbe essere "Sconosciuto" se non è in grado di analizzare l'input, quindi l'ho fatto cat ./mac_ip.pye ho trovato tutti i tcpdumpdati anziché il programma. Poi ho capito che avrei dovuto usare

tcpdump -ne | ./mac_ip.py

C'è un modo per riavere il mio programma? Comunque posso scrivere di nuovo il mio programma, ma se dovesse succedere di nuovo con un programma più importante, dovrei essere in grado di fare qualcosa. O c'è un modo per dire al reindirizzamento dell'output di controllare il file e avvisare se è un eseguibile?


18
È possibile recuperare il programma dall'ultimo backup prima della sovrascrittura, altrimenti no. A proposito in shell è possibile specificare set -o noglobbere bash non reindirizzerà più ai file esistenti. Vedi qui per i dettagli: cyberciti.biz/tips/howto-keep-file-safe-from-overwriting.html
eckes

12
Non dovresti avere il permesso di scrivere per importanti eseguibili ...
Hagen von Eitzen,

20
@eckesset -o noclobber
GnP,

38
@HagenvonEitzen Odio i consigli del genere, come se avessi impostato la proprietà e le autorizzazioni appropriate su ogni script una tantum di shell e python che avessi mai scritto prima di eseguirlo (e, naturalmente, torna di nuovo brevemente se devi modificarlo ). È solo leggermente più significativo di "Non dovresti scrivere >quando vuoi dire |". Non dimenticare la realtà.
Jason C,

30
I repository Git sono economici. Impegna tutto il tuo codice, non importa quanto piccolo e insignificante, quindi un errore del genere è una soluzione rapida e semplice.
Casey,

Risposte:


22

Purtroppo sospetto che dovrai riscriverlo. (Se si dispone di backup, questo è il momento di farli uscire. Altrimenti, consiglio vivamente di impostare un regime di backup per il futuro. Molte opzioni disponibili, ma fuori tema per questa risposta.)

Trovo che sia utile mettere gli eseguibili in una directory separata e aggiungere quella directory a PATH. In questo modo non ho bisogno di fare riferimento agli eseguibili per percorso esplicito. La mia directory di programmi preferita per gli script personali (privati) è "$HOME"/bine può essere aggiunta al percorso di ricerca del programma con PATH="$HOME/bin:$PATH". In genere questo viene aggiunto agli script di avvio della shell .bash_profilee / o .bashrc.

Infine, non c'è niente che ti impedisce di rimuovere l'autorizzazione di scrittura per te stesso su tutti i programmi eseguibili:

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è la posizione standard per gli eseguibili e gli script creati dall'utente
gardenhead,

4
@gardenhead Dipende da come è configurato il sistema. /usr/localè destinato a cose specifiche dell'host (al contrario di una directory condivisa tra host tramite un mount di rete) e può essere o meno scrivibile da utenti non root.
chepner,

4
@gardenhead è una posizione standard, certamente. Uso /use/local/binper script e programmi installati localmente che possono essere utilizzati da più account utente e $HOME/binper cose personali di un singolo utente. C'è valore in entrambi.
roaima,

1
Nota che Fedora sembra provare a spingere usando$HOME/.local/bin
Zan Lynx il

1
@Zan eeeww! Seriamente, grazie. Sembra che RH stia cercando di spingere tutto dentro, ~/.localvisto che è ancora un altro oggetto spostato dal suo posto "tradizionale".
roaima,

38

Per evitare che i file esistenti vengano sovrascritti dal reindirizzamento, >utilizzare l' noclobberopzione in basho qualsiasi shell simile a POSIX (anche nel (t)cshpunto in cui la funzionalità ha avuto origine, anche se set noclobberinvece di set -o noclobber/ set -Clì). Quindi, se è necessario forzare la sostituzione di un file, utilizzare l' >|operatore di reindirizzamento ( >!in (t)csh).

Esempio:

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

A proposito, puoi controllare le impostazioni correnti con set -o:

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

Mentre questo risponde perfettamente alla domanda, non lo consiglierei. 1. Digitare >|invece di |non è molto meno probabile che scrivere >. 2. È facile e altamente consigliabile eseguire backup (un editor degno del suo nome può salvare l'ultima versione; c'è cron, ecc.). 3. Ogni pezzo di codice dovrebbe essere messo sotto controllo della versione, anche piccoli script. YMMV.
Maaartinus,

2
@maaartinus dai, 1) digitando due caratteri separati anziché uno è chiaramente meno probabile. 2) Ovviamente i backup sono essenziali, nessuno ha consigliato all'OP di non effettuare backup, questa risposta non suggerisce in alcun modo di non avere backup e i backup dell'editor presuppongono che tu abbia modificato il file in un editor. 3) Ancora una volta, stai solo pensando al codice scritto dall'OP, come in questo esempio particolare, ma la domanda e questa risposta sono applicabili a qualsiasi file sulla macchina, inclusi gli eseguibili di sistema.
terdon

8

Consiglio vivamente di avere gli script importanti in un repository git , sincronizzati da remoto ( farà una piattaforma self-hosted di fantasia ), come dice il commento di @ casey.

In questo modo sei protetto da gravi errori umani come ripristinare il file allo stato di lavoro precedente ed eseguirlo di nuovo.


4

Il file è recuperabile?

Risposta breve: di solito no.

@Mark Plotnick sottolinea nei commenti, è possibile recuperare i .pyfile .pycdall'utilizzo di Uncompyle . Questo dovrebbe essere perfetto per la tua situazione.

In generale, tuttavia, questo è molto più difficile. Teoricamente puoi usare gli strumenti forensi per ripristinare i file. Probabilmente il più semplice che ho usato è testdisk(aka "PhotoRec"). Funziona solo a volte ed è un processo lento. Di solito non ne vale la pena, quindi sì, è possibile , ma la vera risposta è "no".

> Può essere modificato per non sovrascrivere gli eseguibili?

No. Non esiste un modo standard per dire alla shell di non reindirizzare mai solo per i file contrassegnati come eseguibili. C'è "noclobber" che impedirà il reindirizzamento in file esistenti, eseguibili o meno, ma vedere i miei commenti su quello qui sotto.

Cosa fare in futuro?

  1. Questo potrebbe sembrare sciocco, ma per prevenire errori futuri, probabilmente non devi fare nulla. La mia scommessa è che hai già imparato questa lezione.

    Ho usato e insegnato Unix per molto tempo e mentre le persone spesso commettono questo errore una volta, raramente lo ripetono. Perchè no? Probabilmente per lo stesso motivo per cui una persona esperta con i coltelli non si taglia da sola: gli umani sono bravi a imparare. Alla fine, fare la cosa giusta diventa una seconda natura.

  2. Utilizzare un editor di testo che esegua backup per te. Ad esempio, se si utilizza emacs, la versione precedente del programma viene salvata in mac_ip.py ~. Altri editor possono essere configurati per funzionare in modo simile (ad es. "Imposta backup" in .nanorc). Per gli editor che non supportano i backup automatici, puoi eseguire una funzione semplicistica nel tuo .bashrc:

    myeditor() { cp -p "$1" "$1~";  editor "$1"; }
    
  3. Semplifica la realizzazione di copie. Ad esempio, nella directory del progetto a cui stai lavorando, potresti avere un Makefile con una destinazione come questa:

    # 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 sta indurendo i TAB sopra come 4 spazi.)

  4. Allo stesso modo, è possibile creare una destinazione Makefile che fa un rsynca un host Unix remoto a cui si ha sshaccesso. (Utilizzalo in ssh-copy-idmodo che non ti venga richiesta ripetutamente la password.)

  5. Usa git. Ci sono molti tutorial eccellenti su come iniziare. Provate man gittutorial, man gittutorial-2e man giteveryday. Configurare il tuo repository git non è difficile, ma puoi anche creare un repository remoto gratuitamente su github.com

  6. Se le soluzioni di cui sopra sono troppo pesanti, è possibile salvare piccoli script su gist.github.com . Sebbene sia possibile incollare o caricare da un browser Web, ti consiglio di utilizzare un'interfaccia gist della riga di comando per semplificare le cose.

Sconsiglio vivamente di usare "noclobber".

Sì, se lo desideri, puoi farlo set -o noclobbere otterrai messaggi di errore ogni volta che provi a sovrascrivere un file esistente. Questa è una cattiva idea, secondo me. *

Fa funzionare la shell in modo non standard senza alcuna indicazione visibile se è abilitata. Devi usare una sintassi diversa per fare le cose normali. Peggio ancora, se ti abitui al noclobber, un giorno userai un'altra macchina Unix senza noclobber e questo tipo di incidente potrebbe accadere di nuovo.

Come probabilmente saprai, la shell Unix è stata progettata per essere uno strumento affilato per gli esperti. È veloce da usare e non ti ostacolerà - e ti taglierà se dimentichi quale estremità è appuntita. Ma più lo usi, più penso che apprezzerai che può essere una buona cosa.


* Nota in calce: forse prendi le mie opinioni con un granello di sale. Sono anche il tipo di persona che pensa che le ruote da allenamento per biciclette siano una cattiva idea.


Ho anche insegnato Unix per un po '. Molti dei miei studenti non hanno mai imparato ad apprezzare la semplicità diretta di Unix; Dico loro che non sono soli, e possono almeno imparare ancora mentre commiserano il Manuale di Unix Hater, che traccia per loro parte del campo minato. simson.net/ref/ugh.pdf
Jason

Inoltre: sono d'accordo - l'allenamento delle ruote su una bicicletta è utile per chiunque impari a guidare un triciclo.
Jason,

2

Potresti essere stato in grado di recuperare i dati dopo che si sono verificati per la prima volta se lo script è stato visualizzato o modificato di recente ed era ancora nel buffer di memoria. Altrimenti, sei praticamente sfortunato.

Se hai effettuato il piping per teescrivere su un file (oltre che STDOUT) anziché >(o tee -ainvece di >>), potresti facilmente sostituire teecon un alias, una funzione o un link simbolico a uno script che avvisa l'utente se il file che sta per scrivere to è eseguibile.

Quanto segue non è affatto l'ideale e potrebbe essere migliorato molto , ma è un punto di partenza, proprio come un esempio di come ciò sia possibile:

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

... quindi solo echo 'alias tee="/path/to/wee.sh"' >> ~/.bashrco qualcosa di simile.

Sul lato positivo, almeno avrai più pratica e la seconda versione del tuo script Python sarà probabilmente molto meglio della prima!


1

Non hai specificato se stai lavorando su un PC o un server. Se i tuoi file vengono archiviati su un file server dedicato, spesso ci sono backup automatici ("istantanee") che vengono conservati dall'hardware (OS sul) file server.

Sotto Linux

La directory di snapshot virtuale nascosta esiste in ogni directory del tuo file system.

Provare:

cd .snapshot   
ls -l

Se quella directory esiste, allora potresti essere fortunato. Dovresti vedere una serie di directory che contengono i backup archiviati automaticamente in determinati momenti nel tempo. I nomi indicano il tempo relativo nel passato in cui l'istantanea è stata memorizzata. Per esempio:

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

Vai in qualsiasi directory di punti temporale abbastanza vecchia (prima dell'errore di sovrascrittura dei file). All'interno della directory timepoint, dovresti vedere lo stato della ../..directory (e tutte le sottodirectory) a partire da quel punto in passato.

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

Gli appunti:

  1. ls -anon mostrerà la .snapshotdirectory; devi nominarlo esplicitamente. Viene inserito virtualmente dal file server. Non esiste come una vera directory nel tuo filesystem.
  2. Queste istantanee automatiche sono una cronologia continua. I vecchi cambiamenti alla fine cadono alla fine e si perdono. È necessario utilizzare questa tecnica il più presto possibile dopo aver realizzato che è necessario un file indietro.

Sotto Windows

La directory di snapshot nascosta può essere denominata ~ snapshot ed esiste solo al livello principale di una determinata unità.

Consigli

Le istantanee sono una rete di sicurezza che funziona il più delle volte, ma non sempre. Concordo con le altre raccomandazioni per utilizzare un sistema di controllo della versione (come git) anche per file banali.


1

È stato detto prima e lo dirò di nuovo. Utilizzare un sistema di controllo di revisione.

I backup servono per ripristinare un errore hardware. Il controllo delle revisioni è per situazioni come la tua (e ha molti altri usi). Gli strumenti di controllo delle revisioni consentono di conservare una cronologia di un file e di tornare a qualsiasi punto di tale cronologia.

Esempi di strumenti di controllo delle revisioni includono subversion (SVN) (un po 'vecchio ora, ma ancora buono), mercurial (hg) e git (git) (difficile da usare). svn è utile per i documenti di Office e altri tipi di fusibili, git e hg lo hanno superato per la maggior parte degli altri ruoli. hg e git ti consentono di lavorare offline e di sincronizzarti con un server remoto, per la distribuzione e il backup.

Leggi il controllo di revisione, quindi il controllo di revisione distribuito e quindi provali.


Concordo sul fatto che l'uso del controllo di revisione è la cosa migliore per situazioni come la mia, ma dare le giuste autorizzazioni ai file è altrettanto importante
Bharath Teja,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.