Versehentlich wurde die Ausgabeumleitung> anstelle einer Pipe | verwendet

21

Vor einem Monat habe ich ein Python-Skript geschrieben, um MAC- und IP-Adressen von stdin abzubilden. Und vor zwei Tagen habe ich mich daran erinnert und die Ausgabe von gefiltert, tcpdumpaber es ist wegen eines Tippfehlers schiefgegangen. Ich tippte

tcpdump -ne > ./mac_ip.py

und die Ausgabe ist nichts. Aber die Ausgabe sollte "Unbekannt" sein, wenn die Eingabe nicht analysiert werden kann, also habe ich cat ./mac_ip.pyalle tcpdumpDaten anstelle des Programms gefunden. Dann wurde mir klar, dass ich verwenden sollte

tcpdump -ne | ./mac_ip.py

Gibt es eine Möglichkeit, mein Programm zurückzubekommen? Wie auch immer, ich kann mein Programm wieder schreiben, aber wenn es mit einem wichtigeren Programm erneut passiert, sollte ich in der Lage sein, etwas zu tun. ODER gibt es eine Möglichkeit, die Ausgabeumleitung anzuweisen, nach der Datei zu suchen und zu warnen, ob es sich um eine ausführbare Datei handelt?

Bharath Teja
quelle
18
Sie können Ihr Programm von der letzten Sicherung vor dem Überschreiben wiederherstellen, andernfalls nicht. Übrigens können Sie in der Shell festlegen, dass set -o noglobberBash nicht mehr in vorhandene Dateien umgeleitet wird. Weitere Informationen finden Sie hier: cyberciti.biz/tips/howto-keep-file-safe-from-overwriting.html
24.
12
Sie sollten keine Schreibberechtigung für wichtige ausführbare Dateien haben ...
Hagen von Eitzen
20
@eckesset -o noclobber
GNP
38
@HagenvonEitzen Ich hasse solche Ratschläge, als ob Sie für jedes einzelne Shell- und Python-Skript, das Sie jemals geschrieben haben, bevor Sie es ausführen, die richtigen Eigentumsrechte und Berechtigungen festgelegt haben (und natürlich kurz zurück, wenn Sie es bearbeiten müssen) ). Es ist nur unwesentlich aussagekräftiger als "Sie sollten nicht tippen, >wenn Sie meinen |." Vergiss die Realität nicht.
Jason C
30
Git-Repos sind billig. Übernehmen Sie Ihren gesamten Code, egal wie klein und bedeutungslos er ist, und ein Fehler wie dieser ist eine schnelle und einfache Lösung.
Casey

Antworten:

22

Leider vermute ich, dass Sie es umschreiben müssen. (Wenn Sie Backups haben, ist dies die Zeit, um sie herauszubekommen. Wenn nicht, würde ich Ihnen dringend empfehlen, ein Backup-Regime für die Zukunft einzurichten. Viele Optionen verfügbar, aber nicht thematisch für diese Antwort.)

Ich finde, dass PATHes hilfreich ist , ausführbare Dateien in einem separaten Verzeichnis abzulegen und dieses Verzeichnis dem hinzuzufügen . Auf diese Weise muss ich nicht explizit auf die ausführbaren Dateien verweisen. Mein bevorzugtes Programmverzeichnis für persönliche (private) Skripte ist "$HOME"/binund es kann mit dem Programmsuchpfad hinzugefügt werden PATH="$HOME/bin:$PATH". Normalerweise wird dies zu den Shell-Startskripten .bash_profileund / oder hinzugefügt .bashrc.

Schließlich hindert nichts Sie daran, die Schreibberechtigung für alle ausführbaren Programme selbst zu entfernen:

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
Roaima
quelle
2
/usr/local/bin
Dies
4
@gardenhead Es hängt davon ab, wie das System eingerichtet ist. /usr/localist für hostspezifische Dinge gedacht (im Gegensatz zu einem Verzeichnis, das über einen Netzwerk-Mount von mehreren Hosts gemeinsam genutzt wird) und kann von Nicht-Root-Benutzern beschrieben werden oder auch nicht.
Chepner
4
@gardenhead ist sicherlich ein Standardstandort. Ich verwende /use/local/binfür lokal installierte Skripte und Programme, die wahrscheinlich von mehreren Benutzerkonten verwendet werden, und $HOME/binfür Dinge, die für einen einzelnen Benutzer persönlich sind. In beiden steckt Wert.
Roaima
1
Beachten Sie, dass Fedora anscheinend versucht, mit$HOME/.local/bin
Zan Lynx
1
@Zan eeeww! Im Ernst, danke. Es sieht so aus, als würde RH versuchen, alles in den Griff zu bekommen, ~/.localda dies ein weiterer Gegenstand ist, der von seinem "traditionellen" Platz verdrängt wurde.
Roaima
38

Um zu verhindern, dass vorhandene Dateien durch Umleitung überschrieben werden, >verwenden Sie die noclobberOption in bashoder eine POSIX-ähnliche Shell (auch dort, (t)cshwo das Feature ursprünglich erstellt wurde, obwohl Sie dies set noclobberanstelle von set -o noclobber/ set -Cdort tun ). Wenn Sie das Ersetzen einer Datei erzwingen müssen, verwenden Sie den >|Umleitungsoperator ( >!in (t)csh).

Beispiel:

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

Übrigens können Sie die aktuellen Einstellungen überprüfen mit set -o:

$ set -o
...
monitor         on
noclobber       on
noexec          off
...
jimmij
quelle
Obwohl dies die Frage perfekt beantwortet, würde ich es nicht empfehlen. 1. Tippen >|statt |ist nicht viel weniger wahrscheinlich als Tippen >. 2. Es ist einfach und sehr ratsam, Backups zu erstellen (ein Editor, der seinen Namen verdient, kann die letzte Version speichern; es gibt cronusw.). 3. Jeder Code sollte unter Versionskontrolle gestellt werden, auch winzige Skripte. YMMV.
Maaartinus
2
@maaartinus komm schon, 1) die Eingabe von zwei getrennten Zeichen anstelle von einem ist eindeutig weniger wahrscheinlich. 2) Offensichtlich sind Backups unerlässlich, niemand hat dem OP geraten, keine Backups zu erstellen. Diese Antwort deutet in keiner Weise darauf hin, dass keine Backups erstellt wurden, und Editor-Backups setzen voraus, dass Sie die Datei in einem Editor bearbeitet haben. 3) Wiederum denken Sie nur an den Code, den das OP geschrieben hat, wie in diesem speziellen Beispiel, aber die Frage und diese Antwort gelten für alle Dateien auf dem Computer, einschließlich der ausführbaren Systemdateien.
Terdon
8

Ich rate nachdrücklich dazu, die wichtigen Skripte im Rahmen eines Git-Repos remote zu synchronisieren (eine ausgefallene selbst gehostete Plattform reicht aus ), wie in @ caseys Kommentar heißt.

Auf diese Weise sind Sie vor schlimmen menschlichen Fehlern wie dem Zurücksetzen der Datei in den vorherigen Arbeitszustand und dem erneuten Ausführen geschützt.

RcrdBrt
quelle
4

Ist die Datei wiederherstellbar?

Kurze Antwort: In der Regel nicht.

@ Mark Plotnick weist in den Kommentaren darauf hin, dass Sie .pyDateien .pycmit Uncompyle wiederherstellen können . Dies sollte perfekt für Ihre Situation sein.

Im Allgemeinen ist dies jedoch viel schwieriger. Theoretisch können Sie mit Forensik-Tools Dateien wiederherstellen. Wahrscheinlich ist die einfachste, die ich verwendet habe testdisk(auch bekannt als "PhotoRec"). Es funktioniert nur manchmal und es ist ein langsamer Prozess. Es ist normalerweise nicht wert, also ist es möglich , aber die wirkliche Antwort ist "nein".

Kann > geändert werden, um ausführbare Dateien nicht zu überschreiben?

Nein. Es gibt keine Standardmethode, mit der die Shell angewiesen wird, niemals nur Dateien umzuleiten, die als ausführbar gekennzeichnet sind. Es gibt "noclobber", das verhindert, dass in vorhandene Dateien umgeleitet wird, die ausführbar sind oder nicht, aber meine Kommentare dazu finden Sie weiter unten.

Was ist in Zukunft zu tun?

  1. Das mag albern klingen, aber um zukünftige Fehler zu vermeiden, müssen Sie wahrscheinlich nichts tun. Ich wette, Sie haben diese Lektion bereits gelernt.

    Ich benutze und unterrichte Unix schon sehr lange und obwohl die Leute diesen Fehler oft machen, wiederholen sie ihn selten. Warum nicht? Wahrscheinlich aus demselben Grund schneidet sich eine Person, die mit Messern zu tun hat, nicht selbst: Menschen können gut lernen. Irgendwann wird es zur zweiten Natur, das Richtige zu tun.

  2. Verwenden Sie einen Texteditor, der Backups für Sie erstellt. Wenn Sie beispielsweise verwenden emacs, wird die vorherige Version Ihres Programms in mac_ip.py ~ gespeichert. Andere Editoren können so konfiguriert werden, dass sie ähnlich funktionieren (z. B. "set backup" in .nanorc). Für Editoren, die keine automatischen Sicherungen unterstützen, können Sie in Ihrer .bashrc-Datei eine vereinfachende Funktion ausführen:

    myeditor() { cp -p "$1" "$1~";  editor "$1"; }
    
  3. Machen Sie es sich einfach, Kopien zu erstellen. Im Verzeichnis des Projekts, an dem Sie arbeiten, befindet sich beispielsweise möglicherweise ein Makefile mit einem Ziel wie dem folgenden:

    # 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}")
    

    (Hinweis: stackexchange gibt die obigen Tabulatoren als 4 Leerzeichen falsch wieder.)

  4. Ebenso können Sie ein Makefile-Ziel erstellen, das rsynceinen entfernten Unix-Host ansteuert, auf den Sie sshZugriff haben . (Verwenden ssh-copy-idSie diese Option, damit Sie nicht wiederholt nach Ihrem Passwort gefragt werden.)

  5. Verwenden Sie git. Es gibt viele hervorragende Tutorials zum Einstieg. Versuchen Sie man gittutorial, man gittutorial-2und man giteveryday. Ein eigenes Git-Repository einzurichten ist nicht schwer, aber Sie können auch kostenlos ein Remote-Repository auf github.com erstellen

  6. Wenn die oben genannten Lösungen zu schwer sind, können Sie kleine Skripte auf gist.github.com speichern . Es ist zwar möglich, Inhalte aus einem Webbrowser einzufügen oder hochzuladen, ich empfehle jedoch, eine Befehlszeilenschnittstelle zu verwenden , um die Dinge supereinfach zu machen.

Ich rate dringend davon ab, "noclobber" zu verwenden.

Ja, wenn Sie dies wünschen, erhalten Sie set -o noclobberFehlermeldungen, wenn Sie versuchen, eine vorhandene Datei zu überschreiben. Das ist meiner Meinung nach eine schlechte Idee. *

Dadurch funktioniert die Shell nicht standardgemäß, und es wird nicht angezeigt, ob sie aktiviert ist. Sie müssen eine andere Syntax verwenden, um normale Dinge zu tun. Am schlimmsten ist, dass Sie eines Tages eine andere Unix-Maschine ohne Noclobber verwenden, wenn Sie sich an Noclobber gewöhnen.

Wie Sie wahrscheinlich wissen, wurde die Unix-Shell als scharfes Werkzeug für Experten konzipiert. Es ist schnell zu bedienen und steht Ihnen nicht im Weg - und es schneidet Sie, wenn Sie vergessen, welches Ende spitz ist. Aber je öfter Sie es benutzen, desto mehr werden Sie es zu schätzen wissen, dass dies eine gute Sache sein kann.


* Fußnote: Nimm meine Meinung vielleicht mit einem Körnchen Salz. Ich bin auch die Art von Person, die Fahrrad-Stützräder für eine schlechte Idee hält.

hackerb9
quelle
Ich habe auch eine Weile Unix unterrichtet. Viele meiner Schüler haben noch nie gelernt, die direkte Einfachheit von Unix zu schätzen. Ich sage ihnen, dass sie nicht alleine sind und zumindest noch lernen können, während sie das Unix Hater's Handbook durchlesen, das ihnen einen Teil des Minenfeldes abbildet. simson.net/ref/ugh.pdf
Jason
Außerdem: Ich stimme zu - Stützräder auf einem Fahrrad sind hilfreich für alle, die lernen, wie man ein Dreirad fährt.
Jason
2

Möglicherweise konnten Sie die Daten nach dem ersten Auftreten wiederherstellen, wenn Sie das Skript kürzlich angesehen oder bearbeitet hatten und es sich noch im Speicherpuffer befand. Ansonsten hast du ziemlich viel Pech.

Wenn Sie weitergeleitet haben tee, um in eine Datei (sowie STDOUT) anstatt >(oder tee -aanstelle >>) zu schreiben , können Sie diese einfach durch teeeinen Alias, eine Funktion oder einen Symlink zu einem Skript ersetzen , der den Benutzer warnt, wenn die Datei geschrieben werden soll to ist ausführbar.

Das Folgende ist keineswegs ideal und könnte in vielem verbessert werden , aber es ist ein Ausgangspunkt, nur als Beispiel dafür, wie dies möglich ist:

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

... dann einfach echo 'alias tee="/path/to/wee.sh"' >> ~/.bashrcoder so ähnlich.

Zumindest werden Sie mehr Übung haben und die zweite Version Ihres Python-Skripts wird wahrscheinlich viel besser sein als die erste!

rubynorails
quelle
1

Sie haben nicht angegeben, ob Sie an einem PC oder einem Server arbeiten. Wenn Ihre Dateien zufällig auf einem dedizierten Dateiserver gespeichert sind, werden häufig automatische Sicherungen ("Snapshots") von der (Betriebssystem auf der) Dateiserverhardware gespeichert.

Unter Linux

Das virtuelle, versteckte Snapshot-Verzeichnis ist in jedem Verzeichnis Ihres Dateisystems vorhanden.

Versuchen:

cd .snapshot   
ls -l

Wenn dieses Verzeichnis existiert, haben Sie möglicherweise Glück. Sie sollten eine Reihe von Verzeichnissen sehen, in denen Backups gespeichert sind, die zu bestimmten Zeitpunkten automatisch gespeichert werden. Die Namen geben die relative Zeit in der Vergangenheit an, zu der der Schnappschuss gespeichert wurde. Beispielsweise:

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

Wechseln Sie in ein Zeitpunktverzeichnis, das alt genug ist (vor Ihrem Fehler beim Überschreiben von Dateien). Innerhalb des Timepoint-Verzeichnisses sollte der Status des ../..Verzeichnisses (und aller Unterverzeichnisse) zu diesem Zeitpunkt in der Vergangenheit angezeigt werden .

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

Anmerkungen:

  1. ls -azeigt das .snapshotVerzeichnis nicht an; Sie müssen es explizit benennen. Es wird virtuell vom Dateiserver eingefügt. Es existiert nicht als reales Verzeichnis in Ihrem Dateisystem.
  2. Diese automatischen Schnappschüsse sind eine fortlaufende Geschichte. Alte Änderungen fallen schließlich vom Ende und gehen verloren. Sie müssen diese Technik so schnell wie möglich anwenden, nachdem Sie festgestellt haben, dass Sie eine Datei zurück benötigen.

Unter Windows

Das versteckte Snapshot-Verzeichnis kann ~ snapshot heißen und ist nur auf der Stammebene eines bestimmten Laufwerks vorhanden.

Rat

Schnappschüsse sind ein Sicherheitsnetz, das die meiste Zeit funktioniert, aber nicht jedes Mal. Ich stimme den anderen Empfehlungen zu, ein Versionskontrollsystem (z. B. git) auch für einfache Dateien zu verwenden.

jskroch
quelle
1

Es wurde bereits gesagt, und ich werde es noch einmal sagen. Verwenden Sie ein Revisionskontrollsystem.

Backups dienen zur Wiederherstellung eines Hardwarefehlers. Die Revisionskontrolle ist für Situationen wie Ihre vorgesehen (und hat viele andere Verwendungszwecke). Mit den Tools zur Versionskontrolle können Sie den Verlauf einer Datei speichern und zu einem beliebigen Punkt in diesem Verlauf zurückkehren.

Beispiele für Tools zur Versionskontrolle sind Subversion (SVN) (etwas in die Jahre gekommen, aber immer noch gut), Quecksilber (hg) und Git (git) (schwer zu verwenden). svn ist gut für Office-Dokumente, und andere um-mergables, git und hg haben es für die meisten anderen Rollen übertroffen. Mit hg und git können Sie offline arbeiten und mit einem Remote-Server für die Verteilung und Sicherung synchronisieren.

Informieren Sie sich über die Versionskontrolle, dann über die verteilte Versionskontrolle, und probieren Sie sie dann aus.

Strg-Alt-Delor
quelle
Ich bin damit einverstanden, dass die Verwendung der Revisionskontrolle für Situationen wie meine am besten ist, aber die richtigen Berechtigungen für Dateien sind ebenso wichtig
Bharath Teja,