Przypadkowo użyłem przekierowania wyjściowego> zamiast potoku |

21

Miesiąc temu napisałem skrypt Pythona do mapowania adresów MAC i IP ze standardowego wejścia. Dwa dni temu zapamiętałem to i użyłem do filtrowania wyników, tcpdumpale poszło nie tak z powodu literówki. Wpisałem

tcpdump -ne > ./mac_ip.py

a wynik jest niczym. Ale dane wyjściowe powinny być „Nieznane”, jeśli nie można przeanalizować danych wejściowych, więc znalazłem cat ./mac_ip.pyi znalazłem wszystkie tcpdumpdane zamiast programu. Potem zdałem sobie sprawę, że powinienem użyć

tcpdump -ne | ./mac_ip.py

Czy jest jakiś sposób na odzyskanie mojego programu? W każdym razie mogę napisać mój program ponownie, ale jeśli to się powtórzy w przypadku ważniejszego programu, powinienem być w stanie coś zrobić. LUB czy jest jakiś sposób, aby powiedzieć przekierowaniu wyjścia, aby sprawdzić plik i ostrzec, czy jest to plik wykonywalny?

Bharath Teja
źródło
18
Możesz odzyskać swój program z ostatniej kopii zapasowej przed nadpisaniem, w przeciwnym razie nie. BTW w powłoce, którą możesz określić, set -o noglobbera bash nie będzie już przekierowywać do istniejących plików. Zobacz szczegóły: cyberciti.biz/tips/howto-keep-file-safe-from-overwriting.html
eckes
12
Nie powinieneś mieć pozwolenia na pisanie ważnych plików wykonywalnych ...
Hagen von Eitzen
20
@eckesset -o noclobber
GnP
38
@HagenvonEitzen Nienawidzę takich porad, tak jakbyś ustawił odpowiednią własność i uprawnienia do każdej jednorazowej powłoki i skryptu Pythona, który kiedykolwiek napisałeś przed uruchomieniem (i, oczywiście, na krótko, jeśli chcesz edytować) ). Ma tylko nieznacznie większe znaczenie niż „Nie należy pisać, >gdy masz na myśli |”. Nie zapomnij o rzeczywistości.
Jason C
30
Repozytorium Git jest tanie. Zatwierdź cały swój kod, bez względu na to, jak mały i bez znaczenia, a wtedy taki błąd jest szybkim i łatwym rozwiązaniem.
Casey

Odpowiedzi:

22

Niestety podejrzewam, że musisz go przepisać. (Jeśli masz kopie zapasowe, nadszedł czas, aby je usunąć. Jeśli nie, zdecydowanie zalecam skonfigurowanie systemu tworzenia kopii zapasowych na przyszłość. Wiele dostępnych opcji, ale nie na temat tej odpowiedzi.)

Uważam, że umieszczenie plików wykonywalnych w osobnym katalogu i dodanie tego katalogu do pliku PATHjest pomocne. W ten sposób nie muszę odwoływać się do plików wykonywalnych jawną ścieżką. Moim preferowanym katalogiem programów dla osobistych (prywatnych) skryptów jest "$HOME"/bini można go dodać do ścieżki wyszukiwania programów za pomocą PATH="$HOME/bin:$PATH". Zazwyczaj byłoby to dodane do skryptów startowych powłoki .bash_profilei / lub .bashrc.

Wreszcie, nic nie powstrzymuje Cię przed usunięciem uprawnień do zapisu we wszystkich programach wykonywalnych:

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
źródło
2
/usr/local/binjest standardową lokalizacją plików wykonywalnych i skryptów tworzonych przez użytkowników
gardenhead
4
@gardenhead Zależy to od konfiguracji systemu. /usr/localjest przeznaczony do specyficznych dla hosta rzeczy (w przeciwieństwie do katalogu współdzielonego przez hosty za pośrednictwem podłączenia sieciowego) i może, ale nie musi, być zapisywalny przez użytkowników innych niż root.
chepner
4
@gardenhead to z pewnością jedna standardowa lokalizacja. Używam /use/local/binlokalnie zainstalowanych skryptów i programów, które mogą być używane przez wiele kont użytkowników, oraz $HOME/bindo rzeczy osobistych dla jednego użytkownika. W obu jest wartość.
roaima
1
Zauważ, że Fedora próbuje pchać używając$HOME/.local/bin
Zan Lynx,
1
@Zan eeeww! Poważnie, dziękuję. Wygląda na to, że RH próbuje wszystko wepchnąć, ~/.localponieważ jest to kolejny przedmiot przeniesiony z „tradycyjnego” miejsca.
roaima
38

Aby zapobiec zastępowaniu istniejących plików przez przekierowanie, >użyj noclobberopcji w bashlub powłoki podobnej do POSIX (również w (t)cshmiejscu, w którym funkcja faktycznie się pojawiła, chociaż robisz to set noclobberzamiast set -o noclobber/ set -Ctam). Następnie, jeśli musisz wymusić zamianę pliku, użyj >|operatora przekierowania ( >!in (t)csh).

Przykład:

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

BTW, możesz sprawdzić bieżące ustawienia za pomocą set -o:

$ set -o
...
monitor         on
noclobber       on
noexec          off
...
jimmij
źródło
Chociaż doskonale odpowiada to pytanie, nie poleciłbym tego. 1. Pisanie >|zamiast |nie jest mniej prawdopodobne niż pisanie >. 2. Tworzenie kopii zapasowych jest łatwe i wysoce wskazane (edytor, którego nazwa jest warta, może zapisać ostatnią wersję; istnieje cronitd.). 3. Każdy kawałek kodu powinien podlegać kontroli wersji, nawet małe skrypty. YMMV.
maaartinus
2
@maaartinus daj spokój, 1) wpisanie dwóch osobnych znaków zamiast jednego jest wyraźnie mniej prawdopodobne. 2) Oczywiście kopie zapasowe są niezbędne, nikt nie radził OP, aby nie tworzył kopii zapasowych, ta odpowiedź w żaden sposób nie sugeruje, że nie ma kopii zapasowych, a kopie zapasowe edytora zakładają, że edytowałeś plik w edytorze. 3) Ponownie, myślisz tylko o kodzie, który OP napisał, jak w tym konkretnym przykładzie, ale pytanie i ta odpowiedź dotyczy dowolnego pliku na komputerze, w tym plików wykonywalnych systemu.
terdon
8

Zdecydowanie radzę mieć ważne skrypty w ramach repozytorium git , synchronizowane zdalnie ( zrobi to fantazyjna platforma hostowana ), jak mówi komentarz @ casey.

W ten sposób jesteś chroniony przed złymi ludzkimi błędami, takimi jak przywrócenie pliku do poprzedniego stanu roboczego i ponowne uruchomienie.

RcrdBrt
źródło
4

Czy plik można odzyskać?

Krótka odpowiedź: zwykle nie.

@Mark Plotnick wskazuje w komentarzach, że możesz odzyskać .pypliki .pycprzy użyciu Uncompyle . To powinno być idealne dla twojej sytuacji.

Ogólnie jednak jest to o wiele trudniejsze. Teoretycznie możesz użyć narzędzi kryminalistycznych do usunięcia plików. Prawdopodobnie najłatwiejszy, z jakiego korzystałem testdisk(aka „PhotoRec”). Działa tylko czasami i jest to powolny proces. Zwykle nie jest tego warte, więc tak, jest to możliwe , ale prawdziwą odpowiedzią jest „nie”.

Czy można zmienić >, aby nie zastępować plików wykonywalnych?

Nie. Nie ma standardowego sposobu, aby powiedzieć powłoce, aby nigdy nie przekierowywała tylko dla plików oznaczonych jako wykonywalne. Istnieje „noclobber”, który zapobiegnie przekierowywaniu do istniejących plików, wykonywalnych lub nie, ale zobacz moje komentarze na ten temat poniżej.

Co robić w przyszłości?

  1. Może to zabrzmieć głupio, ale aby zapobiec przyszłym błędom, prawdopodobnie nie musisz nic robić. Założę się, że już nauczyłeś się tej lekcji.

    Używam i uczę Uniksa od bardzo dawna i chociaż ludzie często popełniają ten błąd raz, rzadko go powtarzają. Dlaczego nie? Prawdopodobnie z tego samego powodu, że osoba doświadczona z nożami się nie tnie: ludzie są dobrzy w nauce. W końcu robienie właściwych rzeczy staje się drugą naturą.

  2. Użyj edytora tekstu, który tworzy dla Ciebie kopie zapasowe. Na przykład, jeśli używasz emacs, poprzednia wersja twojego programu jest zapisywana w mac_ip.py ~. Inne edytory można skonfigurować tak, aby działały podobnie (np. „Ustaw kopię zapasową” w .nanorc). W przypadku edytorów, które nie obsługują automatycznych kopii zapasowych, możesz uprościć funkcję .bashrc:

    myeditor() { cp -p "$1" "$1~";  editor "$1"; }
    
  3. Ułatw sobie wykonywanie kopii. Na przykład w katalogu projektu, nad którym pracujesz, możesz mieć Makefile z celem takim jak ten:

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

    (Uwaga: stackexchange źle podaje tabele powyżej jako 4 spacje).

  4. Podobnie możesz utworzyć cel Makefile, który robi rsynczdalny host Unix, do którego masz sshdostęp. (Użyj ssh-copy-id, abyś nie był wielokrotnie proszony o podanie hasła).

  5. Zastosowanie git. Na początek jest wiele doskonałych samouczków. Spróbuj man gittutorial, man gittutorial-2a man giteveryday. Utworzenie własnego repozytorium git nie jest trudne, ale możesz również utworzyć zdalne repozytorium bez żadnych kosztów na github.com

  6. Jeśli powyższe rozwiązania są zbyt ciężkie, możesz zapisać małe skrypty na gist.github.com . Chociaż możliwe jest wklejenie lub przesłanie z przeglądarki internetowej, zalecam użycie interfejsu gist z wiersza poleceń, aby wszystko było super łatwe.

Zdecydowanie odradzam używanie „noclobber”.

Tak, jeśli wybierzesz, możesz to zrobić, set -o noclobberaby otrzymywać komunikaty o błędach za każdym razem, gdy próbujesz zastąpić istniejący plik. To jest, moim zdaniem, zły pomysł. *

Powoduje, że powłoka działa w niestandardowy sposób bez widocznego wskazania, czy jest włączona. Musisz używać innej składni do robienia normalnych rzeczy. Co najgorsze, jeśli przyzwyczaisz się do noclobbera, pewnego dnia użyjesz innej maszyny uniksowej bez noclobbera i taki wypadek może się powtórzyć.

Jak zapewne wiesz, powłoka uniksowa została zaprojektowana jako ostre narzędzie dla ekspertów. Jest szybki w użyciu i nie przeszkadza - i cię cię, jeśli zapomnisz, który koniec jest spiczasty. Ale im częściej go używasz, tym bardziej myślę, że docenisz, że może to być dobra rzecz.


* Przypis: być może wezmę moje opinie z odrobiną soli. Jestem także osobą, która uważa koła treningowe za rower za zły pomysł.

hackerb9
źródło
Przez jakiś czas uczyłem także Uniksa. Wielu moich studentów nigdy nie nauczyło się doceniać bezpośredniej prostoty Uniksa; Mówię im, że nie są sami, a przynajmniej mogą się uczyć, jednocześnie wspominając Podręcznik Unix Hater's Handbook, który przedstawia dla nich część pola minowego. simson.net/ref/ugh.pdf
Jason
Ponadto: Zgadzam się - koła treningowe na rowerze są pomocne dla każdego, kto uczy się jeździć na rowerze trzykołowym.
Jason
2

Być może udało się odzyskać dane po ich pierwszym wystąpieniu, jeśli skrypt był ostatnio przeglądany lub edytowany i nadal znajdował się w buforze pamięci. W przeciwnym razie nie będziesz miał szczęścia.

Jeśli chcesz teezapisać w pliku (jak również STDOUT) zamiast >(lub tee -azamiast >>), możesz łatwo zastąpić teego aliasem, funkcją lub dowiązaniem symbolicznym do skryptu, który ostrzega użytkownika, jeśli plik, który zamierza zapisać jest wykonywalny.

Poniższa bynajmniej nie jest idealna, można poprawić na wiele , ale jest to punkt wyjścia, tylko jako przykład, jak to możliwe:

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

... wtedy po prostu echo 'alias tee="/path/to/wee.sh"' >> ~/.bashrclub coś podobnego.

Z drugiej strony, przynajmniej dostaniesz więcej praktyki, a druga wersja skryptu w Pythonie będzie prawdopodobnie znacznie lepsza niż pierwsza!

rubinorails
źródło
1

Nie określono, czy pracujesz na komputerze, czy na serwerze. Jeśli twoje pliki są przechowywane na dedykowanym serwerze plików, często są tworzone automatyczne kopie zapasowe („migawki”) przez sprzęt serwera (system operacyjny).

Pod Linuksem

Wirtualny, ukryty katalog migawek istnieje w każdym katalogu w systemie plików.

Próbować:

cd .snapshot   
ls -l

Jeśli ten katalog istnieje, możesz mieć szczęście. Powinieneś zobaczyć serię katalogów, w których kopie zapasowe są przechowywane automatycznie w określonych momentach. Nazwy wskazują względny czas w przeszłości, w którym migawka była przechowywana. Na przykład:

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

Przejdź do dowolnego katalogu punktu czasowego, który jest wystarczająco stary (przed błędem zastąpienia pliku). W katalogu timepoint powinieneś zobaczyć stan tego ../..katalogu (i wszystkich podkatalogów) od tego momentu w przeszłości.

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

Uwagi:

  1. ls -anie pokaże .snapshotkatalogu; musisz to nazwać jednoznacznie. Jest wstawiany wirtualnie przez serwer plików. Nie istnieje jako prawdziwy katalog w twoim systemie plików.
  2. Te automatyczne migawki są ciągłą historią. Stare zmiany w końcu wypadają z końca i giną. Musisz użyć tej techniki jak najszybciej, gdy zorientujesz się, że potrzebujesz pliku z powrotem.

Pod Windows

Ukryty katalog migawek może mieć nazwę ~ migawka i istnieć tylko na poziomie głównym danego dysku.

Rada

Migawki są siatką bezpieczeństwa, która działa przez większość czasu, ale nie za każdym razem. Zgadzam się z innymi zaleceniami, aby używać systemu kontroli wersji (np. git) Nawet w przypadku trywialnych plików.

jskroch
źródło
1

To zostało powiedziane wcześniej i powtórzę to jeszcze raz. Użyj systemu kontroli wersji.

Kopie zapasowe służą do odzyskiwania awarii sprzętu. Kontrola wersji dotyczy sytuacji takich jak Twoja (i ma wiele innych zastosowań). Narzędzia kontroli wersji pozwalają zachować historię pliku i wrócić do dowolnego punktu tej historii.

Przykłady narzędzi kontroli wersji obejmują subversion (SVN) (teraz trochę stary, ale nadal dobry), mercurial (hg) i git (git) (trudny w użyciu). SVN jest dobry dla dokumentów biurowych, a inne um-scalenia, git i hg przekroczyły go w przypadku większości innych ról. hg i git umożliwiają pracę w trybie off-line i synchronizację ze zdalnym serwerem w celu dystrybucji i tworzenia kopii zapasowych.

Przeczytaj informacje o kontroli wersji, a następnie rozproszoną kontrolę wersji, a następnie wypróbuj je.

ctrl-alt-delor
źródło
Zgadzam się, że korzystanie z kontroli wersji jest najlepsze w sytuacjach takich jak moja, ale udzielenie odpowiednich uprawnień do plików jest równie ważne
Bharath Teja