Zapobiegaj wpisywaniu przez użytkownika przypadkowej spacji między poleceniem rm a symbolem wieloznacznym

29

Zamiar:

rm -rf string*

Problem:

rm -rf string *

Pierwszy przypadek to legalne i powszechne użycie rm, mała literówka może powodować wiele problemów w drugim przypadku. Czy istnieje prosty sposób, aby skutecznie zabezpieczyć się przed przypadkowym pociągnięciem lub wiodącym znakiem wieloznacznym?

Bobdole
źródło
8
Z najnowszą i dobrze skonfigurowaną powłoką ( zshlub bash) wolałbym raczej przyzwyczaić się naciskać klawisz tab (aby uruchomić automatyczne uzupełnianie) przed naciśnięciem klawisza powrotu
Basile Starynkevitch
2
touch -- -iutworzy plik, -iktóry zostanie przekazany rmjako parametr, -igdy w argumentach dodasz symbol wieloznaczny.
Przywróć Monikę - M. Schröder
@ MartinSchröder: Jeśli znajdziesz się w katalogu, w którym plik istnieje.
Wstrzymano do odwołania.
@ MartinSchröder To zadziała tylko po wpisaniu rm *. Jeśli wpiszesz rm name *, rozwinie się do rm name -i other names. -inie będzie przetwarzany jako opcja, ponieważ nie jest wcześniejszy niż nazwy plików.
Barmar
1
Zazwyczaj użytkownik robi to tylko raz.
tedder42

Odpowiedzi:

37

DEBUGPułapka może być napisane, aby anulować poleceń, które wyglądają podejrzanie. Następujące lub podobny do niego kod można dodać do ~/.bashrc:

shopt -s extdebug
checkcommand() {
  if [[ $BASH_COMMAND = 'rm -r'*' *' ]]; then
    echo "Suppressing rm -r command ending in a wildcard" >&2
    return 1
  fi
  # check for other commands here, if you like
  return 0
}
trap checkcommand DEBUG

Dostosuj logikę do smaku.

(Tak naprawdę nie spodziewam się, że to podejście będzie przydatne - zbyt wiele sposobów, by zniszczyć komendę destrukcyjnie, aby znaleźć je testujące jeden po drugim - ale zapewnia dosłowną odpowiedź na pytanie).

Charles Duffy
źródło
47

Nie ma sposobu na całkowicie kuloodporny system. I dodając „Jesteś pewien?” podpowiedzi do rzeczy przynoszą efekt przeciwny do zamierzonego i prowadzą do „Oczywiście, że jestem pewien”. reakcje kneejerk.

Sztuczka, którą wybrałem z książki w poprzednich latach, polega na tym ls -R blah*, by zrobić to rm -fr blah* wtedy i tylko wtedy, gdy pojawiła się lista, która pojawiła się, co chciałem.

Wystarczy lsnajpierw wykonać polecenie, a następnie usunąć ls -Ri zastąpić rm -fr.

Ostatnie pytanie brzmi: „Jeśli informacje były dla Ciebie cenne, gdzie jest twoja kopia zapasowa?”

killermist
źródło
4
Zamiast strzałki w górę możesz użyć ^ls -R^rm -rf^i być może ustawić jako alias
exussum
FWIW, to jest ls -Rto, co właściwie robię cały czas, ale jest to tak instynktowne w tym momencie, że wymknęło mi się z umysłu, kiedy formowałem się przez odpowiedź. Więc +1 za to.
JakeGould,
Ma to również tę zaletę, że nie zaszkodzi, jeśli uderzysz klawisz Enter lub uderzysz myszką i wkleisz coś z nowymi liniami. Czasami wprowadzam rzeczy w mniej wydajnej kolejności, tylko dla większego bezpieczeństwa, np. cat > .logPotem wracam i wklejam lub szarpię nazwę pliku przed .log. Więc w żadnym momencie nie mam > valuablefilena cmdline.
Peter Cordes,
Używam rm z aliasem do rm -i, więc często po prostu komponuję moje polecenie rm, a następnie umieszczam \ na początku linii. ( \rmunika się rozwijania aliasu dla rm, ponieważ cytowano część słowa). Jeśli potrzebowałem -rlub -f, tak, czasami zaczynam lsod rmlub po prostu rezygnuję z tej -rfczęści. (edytuj, jak uzyskać formatowanie odwrotnego ukośnika? bquote bslash bslash bquote nie udaje się
Peter Cordes
8

Czy możesz nauczyć się używać, powiedzmy, rmrfzamiast rm -rf?

Jeśli tak, ta funkcja bash da ci szansę zobaczyć, co się właściwie stanie przed potwierdzeniem polecenia:

rmrf() { echo rm -rf "$@"; read -p "Proceed (y/N)? "; [ "${REPLY,,}" = y ] && rm -rf "$@"; }

Aby ta funkcja była stała, dodaj tę linię do ~/.bashrcpliku na każdym używanym komputerze.

Porównanie z popularnym rmaliasem

Często określa się alias:

alias rm='rm -i'

Ma to dwa ograniczenia:

  1. Jeśli zaczniesz polegać na tym aliasie, będziesz w szoku, gdy jesteś na maszynie lub w środowisku, które go nie ma. Natomiast próba uruchomienia rmrfna komputerze bez tej funkcji zwróci nieszkodliwość command not found.

  2. Ten alias nie jest pomocny w twoim przypadku, ponieważ -fopcja podana w wierszu poleceń zastępuje -iopcję aliasu.

John1024
źródło
4
Niezły pomysł. Zależy to jednak od zainstalowania tej funkcji i udostępnienia jej na dowolnych systemach, z których korzysta ten użytkownik. Powiedzmy, że logują się na serwerze zdalnym w celu wykonania pracy i wykonania niewłaściwego rm -rfpolecenia, co się stanie? Tworzenie takich pseudo funkcji ostatecznie komplikuje proste rozwiązanie: Bądź bardziej ostrożny i zrozum, jakie są uprawnienia.
JakeGould
4
@JakeGould I nie używaj rm -f, chyba że naprawdę potrzebujesz .
CVn
1
Po co zawracać sobie głowę rmrf, a nie tylko tworzeniem funkcji powłoki, rmktóra sprawdza argumenty -rlub -rfwprowadza w tym przypadku specjalną logikę, w przeciwnym razie bezpośrednio wywołując command rm "$@"prawdziwe rmpolecenie?
Charles Duffy
3
Używasz innej nazwy, więc nie strzelaj sobie w stopę, gdy nie ma nadpisania. I zgadzam się z @ MichaelKjörling, nie potrzebujesz, -fjeśli nie masz -i. Opuszczenie -fdaje dodatkowe ostrzeżenie, na przykład przed usunięciem pliku tylko do odczytu.
Peter Cordes,
6

Jeśli jestem w sytuacji, w której usunięcie niewłaściwych plików jest naprawdę wielka sprawa, jedna z rzeczy robiłem jest dokonać kosza folder podobny mkdir trashcan, a następnie Mam skrypt rmTrashcan, który ma rm -rf trashcan/*lub rm -rf *lub podobna, napisany bardzo starannie i sprawdzone kilka razy.

W ten sposób, jeśli popełniam błąd, błąd dotyczy mvpolecenia, a nie rmpolecenia. Kiedy zrobię lsi jestem pewien , co dokładnie usuwam, rmTrashcanbrudna praca jest bezpieczna.

Było to również niezwykle wygodne w sytuacji, gdy musiałem usuwać kopie zapasowe. Mógłbym mvcały miesiąc tworzenia kopii zapasowych w koszu, mvtych kilku, które chciałem zachować (1. miesiąca, 15. miesiąca) z powrotem w kopiach zapasowych, a potem rmTranshcanresztę. Wykonywanie podobnego polecenia jest trudne do rmsamodzielnego wykonania, a wykonanie tego w ten sposób pozwala mi lsmieć pewność, że mam pewność, jakie pliki zostawiam (zamiast wyliczania plików, które zamierzam usunąć)

Cort Ammon - Przywróć Monikę
źródło
4

Zamiast kłopotać się dwoma poleceniami ( lsi rm), myślę, że prostszym i łatwiejszym sposobem jest użycie find:

find . -maxdepth 1 -name "string*" -delete

Jeśli przypadkowo wpiszesz "string *", usunie pliki o nazwach string charsi string letters( i tak właśnie chciałeś), ale nie pobierze każdego pliku jak *w powłoce.

Możesz także pominąć, -deleteaby zobaczyć, które pliki mają zostać usunięte, a następnie nacisnąć strzałkę w górę i pisać -deletełatwiej niż pisanie ^ls -R^rm -rflub inne bzdury.

niania
źródło
A findwykona zagnieżdżone wyszukiwanie plików, które pasują zamiast tylko jawnych parametrów zadeklarowanych w wierszu poleceń. Myślę, że to mija się z celem. Mogę się jednak mylić.
killermist
3

Czy istnieje prosty sposób, aby skutecznie zabezpieczyć się przed przypadkowym pociągnięciem lub wiodącym znakiem wieloznacznym?

Nie całkiem. W innej odpowiedzi zaproponowano utworzenie niestandardowego polecenia w celu dodania monitu przed wykonaniem zadania. Problem z tym niestandardowym poleceniem polega na tym, że musi być świadomie zainstalowany w systemach, nad którymi pracujesz. I nawet jeśli jest zainstalowany, problemem jest twój refleks, aby trafić, yaby wykonać zadanie, może wejść w grę.

Oznacza to, że jest to wszystko problem z interfejsem użytkownika, nawet jeśli jest na poziomie tekstu / wiersza poleceń. Jak wiele oczekujesz sieci ochronnych, które ochronią cię przed zrobieniem czegoś, czego nie powinieneś? To jest jak nożyce: jeśli jesteś w jakiś sposób niedbały i poślizgniesz się i podciąłeś rękę, gdy zamierzasz przeciąć tkaninę lub papier, kto jest winny? A nawet sygnalizacja świetlna i znaki stop: Naprawdę nic nie stoi na przeszkodzie, aby kierowca uruchomił światło lub zignorował znaki drogowe, poza wyraźną świadomością tego, co może się zdarzyć, jeśli zaangażują się w tak ryzykowne zachowanie.

To powiedziawszy, że najlepsze, realistyczne rozwiązanie polega na uprawnieniach systemowych dla użytkowników i grup. To najlepsza / jedyna prawdziwa siatka bezpieczeństwa do ochrony użytkownika przed sobą.

Jeśli pracujesz w systemie, w którym jako jedyny masz do niego dostęp, możesz mieć ochotę na chmod 777wszystko, ale nie w ten sposób konfiguruje się system racjonalny. Zamiast tego uprawnienia powinny być podobne 755do wszystkich katalogów i 644wszystkich plików niewykonywalnych. Pliki wykonywalne powinny być 755co najmniej, ale może nawet 744jeśli chcesz, aby inni czytali, ale nie uruchamiali plików.

JakeGould
źródło
2

Spróbuj skomponować początkowe rmpolecenie bez -fflagi, ale -izamiast tego, takie, które rmbędą monitować o każdy plik, który zamierza usunąć. W przypadku małych rekurencyjnych operacji usuwania możesz przytrzymać yklawisz, gdy masz pewność, że polecenie zostało wpisane poprawnie. W przypadku dużych usunięć możesz przerwać operację i użyć historii wiersza poleceń, aby ostrożnie zmienić na -ia -f.

Nevin Williams
źródło
W rzeczywistości musisz nacisnąć y[RETURN]każdy plik, nic nie możesz powstrzymać dzięki GNU rm. Edycja tego -ijest właściwą drogą, gdy już poprawnie wypiszesz polecenie. Następnie pojawia się monit tylko w pliku tylko do odczytu i może inne rzeczy.
Peter Cordes
1
Po prostu użyj, rm -Iaby wyświetlał monit tylko raz i tylko w przypadku potencjalnie niebezpiecznych usunięć (tj. Wielu plików).
Nick Matteo
1
Na mniej konstruktywnych forach moja odpowiedź brzmiałaby podobnie: „Jeśli twoje pisanie / korekta jest tak zła, to nie musisz używać„ rm -rf ”z symbolami wieloznacznymi”. Nie wiedziałem o zmianie -I ... musiałem zostać <20 lat temu; o ostatnim razem, gdy zrobiłem „man rm”. :)
Nevin Williams
2

rm ma -ii -Iflagi do potwierdzenia przed każdym usunięciem. W przeszłości niektóre dystrybucje domyślnie je włączały. To okropny pomysł. Daj użytkownikowi zbyt wiele okien dialogowych z potwierdzeniami do normalnych operacji, a oni zaczną je normalnie potwierdzać. To po prostu przenosi wymóg „ostrożności” (zawsze czerwonej flagi) na nowy i bardziej irytujący dialog. „Tak. Tak. Tak. Tak! Tak! Cholera, głupi komputer, po prostu usuń pliki TAK TAK TAK TAK TAK - ODPAD ZNACZENIE NIE! NIEEEEEE!” To jest problem z dialogiem „Tak, ale miałem na myśli brak”. Ta odpowiedź zawiera wizualne wyjaśnienie, dlaczego okna dialogowe potwierdzenia pojawiają się w niewłaściwym czasie.

Rodzaj błędu, który opisujesz, to poślizgnięcie się „wykonania akcji, która nie była zamierzona”. Użytkownik zazwyczaj natychmiast rozpoznaje błąd i dokładnie wie, jak go naprawić. Niestety, Unix nie daje użytkownikowi możliwości, rm natychmiast usuwa plik. Każdy inny system operacyjny rozwiązuje ten problem, umożliwiając cofnięcie usuwania, przynajmniej przez krótką chwilę, przy użyciu Kosza.

Istnieją różne systemy śmieci dla Uniksa i ta odpowiedź jest pełna sugestii .

Pytanie dotyczy aliasu rm lub nie aliasu rm. Plusy do aliasingu rm ...

  1. Nie można zapomnieć o użyciu alternatywy RM.

Wady aliasingu rm ...

  1. Możesz polegać na systemach, które go nie mają.
  2. Może powodować problemy, gdy dysk jest prawie pełny.
  3. Potrzebujesz infrastruktury, aby okresowo opróżniać kosz.
  4. Muszą mieć pewność, że nie będą zakłócać oczekiwanego zachowania rm w programach.
  5. Może nie do końca emulować rm.

Jeśli podążysz za pierwszym argumentem za daleko, zakończysz używanie vi (nie vim, vi), csh (nie tcsh, csh) i innych przestarzałych narzędzi, ponieważ są one powszechnie dostępne. Mimo to istnieje ryzyko nadmiernego dostosowania środowiska. Wolę zabrać ze sobą narzędzia i uczynić to tak łatwym, jak to możliwe. YMMV.

Dwa i trzy to problemy techniczne. Można je rozwiązać za pomocą sprytnej pracy żniwiarza, która sprawdza wielkość kosza i okresowo czyści rzeczy, podobnie jak tmpreaper . Może to być zadanie cron lub bardziej sprytna wersja może korzystać z różnych infrastruktur zdarzeń systemu plików dostępnych w wielu dystrybucjach stacjonarnych Linuksa. To nie jest proste, a jeszcze trudniejsze do zrobienia wydajnie. Lepiej jest znaleźć istniejący system niż próbować stworzyć własny.

Czwarty może być rozwiązany przez uczynienie z nowego rm aliasu powłoki alias rm='trash', wtedy nie wpłynie to na programy.

Piąty to problem, który pozostawiam czytelnikowi do rozwiązania. rm nie ma wielu przełączników.

Schwern
źródło
Mam alias do rm -i, ale często używam, \rmaby uzyskać niezrównane zachowanie. Piszę w rm -idowolnym momencie PLANOWANIA, aby powiedzieć „nie” jednemu z argumentów. Czasami uruchamiam komendę lsjako komendę, a następnie wstawiam \ rm dopiero po zakończeniu. Więc nie ma szans, żebym przypadkowo wrócił do powrotu rm -rf /zamiast/.../file
Peter Cordes
rm -Ilub rm --interactive=oncejest o wiele, znacznie mniej irytujący niż rm -ii wciąż łapie coś niebezpiecznego (monituje tylko, gdy są więcej niż 3 pliki lub jeśli jest rekurencyjny, i tylko RAZ zamiast KAŻDEGO PLIKU.)
Nick Matteo
@Kundor Tak, i to nie zmienia równania. Prawdopodobnie zwiększa prawdopodobieństwo, że użytkownik go zignoruje. Użytkownik ma cel: usunąć rzeczy. Pytanie brzmi: „Czy na pewno chcesz usunąć rzeczy, które kazałeś mi usunąć?” Użytkownik nadal jest nastawiony na usuwanie rzeczy, nie weryfikując, co ma zostać usunięte, więc mówi bez zastanowienia „tak”. -imoże dać użytkownikowi czas na zmianę celów. Ta odpowiedź na powiązane pytanie określa to wszystko.
Schwern
@ Schwern: ale nikt nie może żyć rm -idłużej niż 30 sekund bez jego wyłączenia. Mając na uwadze, rm -Iże wyświetla monity tylko wtedy, gdy jest prawdopodobne, że spieprzyłeś; monit pojawia się tylko w przypadku dużych usunięć. Gdy próbujesz usunąć kilka rzeczy i pojawia się monit, jesteś zaskoczony i zdajesz sobie sprawę, że przypadkowo wpisałeś „foo *”.
Nick Matteo,
@Kundor Usuwanie więcej niż trzech plików i usuwanie rekurencyjne (potwierdzenie jest wyłączone przez zwyczajowe, -rfktóre właśnie odkryłem) są słabymi serwerami proxy do wykrywania prawdopodobnego zepsucia. Chęć usunięcia podkatalogu prawdopodobnie nie jest zepsuta. Wiadomość nie pomaga, ponieważ tylko potwierdza to, co zrobił użytkownik, bez dodawania użytecznych informacji w momencie, gdy użytkownik nie chce tego zweryfikować. „rm: usunąć 1 argument rekurencyjnie?” „Tak, usuń katalog, właśnie kazałem ci to zrobić! ... czekaj, który to katalog? CRAP !!!”
Schwern
2

Uczę wszystkich o !$= ostatnim argumencie w ostatniej sztuczce polecenia:

% ls job[XYZ].*
jobX.out1
jobX.out2
[rest of the matches]

% rm !$

Umożliwia to sprawdzenie rozszerzenia symbolu wieloznacznego, a następnie użycie dokładnie tego samego wzorca globu bez możliwości wstawienia spacji przed znakiem *.

Sugeruję również, aby ludzie nigdy nie wycinali i nie wklejali globblującego wzoru wieloznacznego w potencjalnie destrukcyjnej linii poleceń. Bo w moich rękach to był problem :)

Technik w moim laboratorium właśnie popełnił ten błąd w zeszłym tygodniu (3 miesiące pracy) - i tak, mieliśmy kopię zapasową (1 dzień opóźnienia).

kael
źródło
0

Wydaje się, że wszyscy mówią: „Bądź bardziej ostrożny”, „Nie rób aliasu / potwierdzenia, ponieważ przyzwyczaisz się nie zwracać na to należytej uwagi”.

Fajnie i wszystko. To znaczy, nie sądzę, że powinieneś tworzyć alias rm(ani rmrf, ponieważ możesz łatwo to zepsuć i wpisać prawdziwe polecenie).

Ale dlaczego nie możesz utworzyć aliasu / skryptu i nazwać go, powiedzmy, removei podać tylko jeden argument (np. 1 $)? Symbol wieloznaczny powinien wynosić 2 USD, z powodu przypadkowej spacji (amiright?), A zatem twój skrypt / opakowanie / alias nie będzie zasilany drugim. Tak, możesz wykonać tylko jeden zestaw skasowań (z symbolem wieloznacznym) na raz, ale to cena, którą zapłacisz.

Gdybym pisał coś fajnego, mógłbym poprosić o podanie liczby plików i katalogów, które planuje usunąć, oraz całkowitego rozmiaru rzeczy, które usuwałem, a następnie poprosić o potwierdzenie, ale może to utrudnić przepływ. Może spraw, aby ta opcja była włączona remove? (-ja). Możesz również sprawdzić 1 $, aby sprawdzić, czy jest to tylko jeden symbol wieloznaczny i poprosić o potwierdzenie, a także podać katalog, w którym aktualnie się znajdujesz.


Poza tym istnieje wiele rmzamienników. Wiele osób stara się zachować zgodność z koszem pulpitu interfejsu użytkownika. Warto zajrzeć do niektórych z nich.

użytkownik3082
źródło
6
Twój alias „usuń” nigdy nie usunie więcej niż jednego pliku na raz. Nie można użyć znaku wieloznacznego, ponieważ powłoka rozwija go, zanim polecenie go zobaczy.
hymie
Więc zrób ewaluację, a następnie wciągnij to do skryptu?
user3082 15.01.2015
Więc chcesz pisać remove \*? Jeśli twój skrypt pozwala globalnej powłoce rozszerzyć swoje dane wejściowe, nie widzę, aby pomogła.
Peter Cordes
0

Bardzo prostą sztuczką jest postawienie -rfna końcu: rm whatever* -rf
To drastycznie zmniejsza wskaźnik błędów, ponieważ wpisujesz więcej znaków po *, więc masz więcej czasu na literówki.
To nie rozwiązuje wszystkiego. Prosta codzienna sztuczka.

Gregory MOUSSAT
źródło