Запобігання введенню користувачем випадкового простору між rm та підстановкою


29

Намір:

rm -rf string*

Проблема:

rm -rf string *

Перший випадок - це законне і поширене використання rm, невеликий друкарський помилок може спричинити багато проблем у другому випадку. Чи існує простий спосіб інтелектуально захиститися від випадкового чи провідного підстановки?


8
З недавньою та добре налаштованою оболонкою ( zshабо bash) я скоріше скористаюся звичкою натискати клавішу вкладки (щоб запустити автоматичне завершення) перед натисканням клавіші повернення
Базиле Старинкевич

2
touch -- -iстворить файл, -iякий буде переданий rmяк параметр, -iколи ви включите підстановку у свої аргументи.
Відновіть Моніку - М. Шредер

@ MartinSchröder: Якщо ви потрапили в каталог, де існує файл.
Призупинено до подальшого повідомлення.

@ MartinSchröder Це спрацює лише при введенні rm *. Якщо ви введете текст rm name *, він розшириться до rm name -i other names. -iне буде оброблятися як варіант, тому що це не раніше, ніж імена файлів.
Бармар

1
Зазвичай користувач робить це лише один раз.
tedder42

Відповіді:


37

Можна DEBUGскасувати пастку, щоб скасувати команди, які виглядають підозріло. Наступне або подібний до нього код можна додати до вашого ~/.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

Налаштуйте логіку за смаком.

(Я насправді не очікую, що цей підхід буде корисним - занадто багато способів руйнувати команду деструктивно, щоб знайти їх тестування по одному, але він дає буквальну відповідь на питання).


47

Не існує ніякої можливості до цілковитої куленепробивної системи. І додаючи "Ви впевнені?" підказки до речей є контрпродуктивними і призводять до "Звичайно, я впевнений". реакції колінжерка.

Трюк, який я зібрав із книги за минулі роки, - спершу робити це ls -R blah*, робити, rm -fr blah* якщо і лише тоді, коли список, що з'явився, потрапив до того, що я хотів вдарити.

Досить просто спочатку виконати lsкоманду, потім видалити ls -Rта замінити на rm -fr.

Заключне питання: "Якщо інформація була для вас цінною, де ваша резервна копія?"


4
Замість стрілки вгору ви можете використовувати ^ls -R^rm -rf^і, можливо, встановити його як псевдонім
exussum

FWIW, це те ls -R, що я в основному роблю весь час, але воно настільки інстинктивно на цьому етапі, що воно зірвало мій свідомий розум, коли я сформувався у відповідь. Тож +1 для цього.
JakeGould

Це також має перевагу в тому, що це не принесе шкоди, якщо натиснути клавішу введення або зімкнути мишу та вставити щось із новими рядками. Іноді я ввожу речі в менш ефективному порядку лише для більшої безпеки, наприклад cat > .log, потім повертаюся назад, вставляю або виймаю ім'я файлу перед .log. Тож у жодному разі я не знаходжуся > valuablefileна cmdline.
Пітер Кордес

Я використовую rm-псевдонім rm -i, тому я часто просто складаю свою команду rm, а потім ставлю a \ на початку рядка. ( \rmуникає псевдоніму-розширення для rm, оскільки частина слова цитувалася). Якщо мені знадобилося -rабо -f, так, я іноді починаю lsзамість цього rm, або просто залишаю -rfчастину. (відредагуйте, як ви отримуєте зворотний косий формат коду? bquote bslash bslash bquote не вдалося.
Peter Cordes

8

Чи можете ви навчити себе використовувати, скажімо, rmrfзамість rm -rf?

Якщо так, ця функція bash надасть вам можливість побачити, що насправді відбудеться перед підтвердженням команди:

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

Щоб зробити цю функцію постійною, додайте цей рядок у ~/.bashrcфайл на кожному використовуваному комп'ютері.

Порівняння із загальним rmпсевдонімом

Загальним є визначення псевдоніма:

alias rm='rm -i'

Це має два обмеження:

  1. Якщо ви станете залежати від цього псевдоніма, тоді ви будете в шоці, коли ви знаходитесь на машині або в оточенні, у якого його немає. Навпаки, намагання працювати rmrfна машині без цієї функції повернеться нешкідливим command not found.

  2. Цей псевдонім не допомагає у вашому випадку, оскільки -fопція, яку ви надаєте в командному рядку, перекриває -iопцію в псевдонімі.


4
Не погана ідея. Але це залежить від того, що ця функція буде встановлена ​​та доступна в будь-яких системах, якими користувач користується. Отже, скажімо, вони увійдуть на віддалений сервер для певної роботи і виконують неправильну rm -rfкоманду, що трапляється? Створення таких функцій псевдо в кінцевому підсумку просто ускладнює просте рішення: Просто будьте уважнішими і зрозумійте, що таке дозволи.
JakeGould

4
@JakeGould І не використовуйте rm -f, якщо вам це не потрібно .
CVn

1
Навіщо турбуватися rmrf, на відміну від просто створення функції оболонки, rmяка перевіряє аргументи -rабо -rfі вводить у цьому випадку особливу логіку, інакше безпосередньо вимагає command rm "$@"викликати реальну rmкоманду?
Чарльз Даффі

3
Ви використовуєте інше ім’я, щоб не стріляти собі в ногу, коли вашої перемоги там немає. І я погоджуюся з @ MichaelKjörling, -fякщо вам цього не потрібно -i. Якщо вийти, -fви отримуєте додаткове попередження перед тим, як, наприклад, видалити файл, який читається лише для повторного використання.
Пітер Кордес

6

Якщо я перебуваю в ситуації , коли видалення бракованих файлів є дійсно великим справою, одна з речей , які я зробив , це зробити кошик для сміття папки, як mkdir trashcanі тоді у мене є сценарій , rmTrashcanякий має rm -rf trashcan/*або rm -rf *або подібні, написану дуже ретельно і перевіряли кілька разів.

Таким чином, якщо я помиляюся, помилка є на a mv команді, а не в rmкоманді. Після того, як я роблю lsі впевнений у тому , що саме я видаляю, rmTrashcanнасправді це виконує брудну роботу безпечно.

Це було надзвичайно зручно і для ситуації, коли мені довелося видалити резервні копії. Я міг mvцілий місяць резервного копіювання в кошик, mvкілька тих, кого я хотів утримати (1-го числа місяця, 15-го місяця) назад, у резервні копії, а потім rmTranshcanрешта. Виконувати подібну команду важкоrm самостійно, і робити це таким чином, дозвольте мені lsстворити резервні копії, щоб бути впевненим у тому, які файли я залишаю (а не просто перераховувати файли, які я маю намір видалити)


4

Замість того, щоб перейматися двома командами ( lsі rm), я думаю, що більш простий і простий спосіб - використовуватиfind :

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

Якщо ви випадково введете, "string *"він видалить файли з ім'ям string charsіstring letters (що все одно хотілося), але він не захопить кожен файл, як *у оболонці.

Крім того, ви можете залишити, -deleteщоб побачити, які файли буде видалено, а потім натисніть стрілку вгору та введіть -deleteпростіше, ніж набирати ^ls -R^rm -rfчи інші дурниці.


A findзробить вкладений пошук файлів, які відповідають замість явних параметрів, оголошених у командному рядку. Я думаю, що це не вистачає позначки. Я можу помилитися.
вбивця

3

Чи існує простий спосіб інтелектуально захиститися від випадкового чи провідного підстановки?

Не зовсім. Пропонується в іншій відповіді, ви можете створити спеціальну команду для додавання підказки перед виконанням завдання. Але проблема з цією спеціальною командою полягає в тому, що вона повинна бути свідомо встановлена ​​в системах, над якими ви працюєте. І навіть якщо він встановлений, проблема полягає в тому, що ваш рефлекс, щоб yвиконати завдання, може вступити в гру.

Це означає, що все це питання щодо інтерфейсу користувача, навіть якщо він знаходиться на рівні тексту / командного рядка. Скільки мереж безпеки ви очікуєте, щоб вони захистили вас від того, що ви не повинні робити? Це як пара ножиць: Якщо ви якось недбало і ковзаєте і ріжете руку, збираючись вирізати тканину чи папір, хто винен? Або навіть світлофори та знаки зупинки: насправді ніщо не заважає водієві керувати світлом або ігнорувати дорожні знаки, окрім гострого усвідомлення того, що може статися, якщо вони дійдуть до такої ризикової поведінки.

Це означає, що найкраще, реалістичне рішення полягає в системних дозволах як для користувачів, так і для груп. Це найкраща / єдина реальна сітка безпеки для захисту користувача від себе.

Якщо ви працюєте в системі, де ви єдиний, хто має до неї доступ, ви можете спокуситись на chmod 777все, але це не спосіб налаштування раціональної системи. Натомість дозволи повинні мати щось на зразок 755для всіх каталогів та 644для всіх невиконаних файлів. Виконаних файлів має бути 755як мінімум, але, можливо, навіть 744якщо ви хочете, щоб інші читали, але не запускали файли.


2

Спробуйте скласти початкову rmкоманду без -fпрапорця, але -iзамість цього такого, який rmпідкаже вам кожен файл, який він збирається видалити. Для невеликих рекурсивних видалень ви можете утримувати yклавішу, як тільки переконаєтесь, що команда була введена правильно. Для великих видалень ви можете перервати операцію та використовувати історію командних рядків, щоб обережно змінити -iна а -f.


Насправді потрібно натискати y[RETURN]кожен файл, нічого не можна затримувати за допомогою GNU rm. Відредагування -i- це шлях, коли ви правильно введете команду. Тоді ви отримуєте підказку лише у файлі, доступному лише для читання, і, можливо, інші речі.
Пітер Кордес

1
Просто використовуйте rm -Iтак, що це запросить лише один раз, і лише для потенційно небезпечних видалень (тобто багатьох файлів.)
Nick Matteo

1
На менш конструктивних форумах моя відповідь була б такою, що відповідає "Якщо ваша друк / коректура настільки погана, ви не маєте жодної справи, використовуючи 'rm -rf' з підстановкою". Я не знав про перемикач -I ... повинен був бути введений <20 років тому; "Щойно востаннє я робив" man rm ". :)
Невін Вільямс

2

rm має -iі -Iпрапори для підтвердження перед кожним видаленням. Раніше деякі дистрибутиви включали їх за замовчуванням. Це жахлива ідея. Дайте користувачеві занадто багато діалогів підтвердження для звичайних операцій, і він почне звично їх підтверджувати. Це просто зміщує вимогу "бути обережним" (завжди червоним прапором) на новий і більш дратівливий діалог. "Так. Так. Так. Так! Так! Боже, чорт забирай, дурний комп'ютер, просто видаляй файли YESYESYESYESYES - КРАП Я НЕ МАЮ! NOOOOOOO!" Це проблема діалогу "Так, але я мав на увазі, що немає". Ця відповідь дає наочне пояснення того, чому діалоги підтвердження приходять не в той час.

Помилка, яку ви описуєте, - це ковзання , "виконання дії, яка не була такою, що була задумана". Користувач зазвичай негайно розпізнає помилку і точно знає, як її виправити. На жаль, Unix не дає користувачеві можливості, rm видаляє файл негайно. Кожна інша операційна система вирішує цю проблему, дозволяючи видалити видалення, принаймні на деякий час, використання кошика.

Для Unix існують різні системи сміття, і ця відповідь повна пропозицій .

Питання в псевдонімі rm чи не в псевдонімі rm. Плюси до згладжування RM ...

  1. Ви не можете забути про використання альтернативи rm.

Мінуси для згладжування RM ...

  1. Ви можете покластися на нього в системах, у яких його немає.
  2. Може виникнути проблеми, коли диск майже повністю заповнений.
  3. Потрібна інфраструктура для періодичного спорожнення сміття.
  4. Потрібно бути впевненим, щоб не заважати очікуваній поведінці rm у програмах.
  5. Можливо, не повністю імітують rm.

Якщо ви дотримуєтесь першого аргументу надто далеко, ви закінчуєте використання vi (не vim, vi), csh (не tcsh, csh) та інших застарілих утиліт, оскільки вони доступні загальнодоступно. І все-таки існує небезпека перенастроювати своє оточення. Я вважаю за краще брати з собою комунальні послуги і робити це якомога простіше. YMMV.

Два та три - це технічні проблеми. Їх можна вирішити за допомогою розумної роботи з жаткою, яка перевіряє розмір сміття та періодично очищає речі, подібно до tmpreaper . Це може бути завданням cron, або більш розумна версія може використовувати різні інфраструктури подій файлової системи, доступні у багатьох настільних дистрибутивах Linux. Це не просто, а ще складніше зробити це ефективно. Краще знайти існуючу систему, ніж намагатися зробити власну.

Четверте може бути вирішено, зробивши ваш новий rm псевдонімом оболонки alias rm='trash', тоді це не вплине на програми.

П’яте - це проблема, яку я залишаю читачеві вирішити. rm не має багато комутаторів.


Мені довічно пристрастилося rm -i, але я часто використовую, \rmщоб отримати непристосовану поведінку. Я набираю rm -iбудь-який час, коли я ПЛАНУЮ, щоб сказати "ні" одному з аргументів. Я інколи запускаю команду з команди lsяк команду, а потім ставлю в \ rm лише тоді, коли закінчу. Тому я не можу випадково потрапити на повернення rm -rf /замість/.../file
Пітер Кордес

rm -Iабо rm --interactive=onceдалеко, набагато менш дратівливий, ніж rm -iі все-таки виловлює все небезпечне (він підказує лише тоді, коли є більше 3-х файлів, або якщо він є рекурсивним, і лише НАДЕЗ, а не для ВСІХ ФАЙЛІВ)
Нік Маттео

@Kundor Так, і це не змінює рівняння. Це, ймовірно, робить більш імовірним, що користувач проігнорує це. У користувача є мета: видалити речі. Підказка говорить: "Ви впевнені, що хочете видалити речі, які ви мені щойно сказали видалити?" Користувач все ще налаштований на вилучення матеріалів, не перевіряючи, що потрібно видалити, тому вони, не замислюючись, говорять "так". -iможе дати користувачеві час на зміну цілей. Ця відповідь на пов’язане питання містить усе це.
Шверн

@Schwern: але ніхто не може жити rm -iбільше 30 секунд, не вимикаючи його. Тоді якrm -I лише тоді, коли, ймовірно, що ви злякалися; підказка з'являється лише для великих видалень. Коли ви намагалися видалити пару речей, і підказка надається, ви розгублені і зрозумієте, що випадково набрали "foo *".
Нік Маттео

@Kundor Видалення більше трьох файлів та рекурсивне видалення (підтвердження відключено звичним -rfя щойно виявленим) є поганими проксі-серверами для виявлення ймовірного виходу з ладу . Хоча видалити підкаталог, швидше за все, не з’явиться помилка. Повідомлення не допомагає, оскільки воно просто підтверджує те, що сказав користувач, не додаючи корисної інформації в момент, коли користувач не хоче перевіряти. "rm: видалити 1 аргумент рекурсивно?" "Так, видаліть каталог. Я щойно сказав вам це зробити! ... зачекайте, який це був каталог? CRAP !!!"
Шверн

2

Я вчу всіх про !$= останній аргумент в останньому фокусі команди:

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

% rm !$

Це дозволяє перевіряти розширення підстановки, а потім використовувати такий самий зразок глобуса без можливості вставлення пробілу перед *.

Також я пропоную людям ніколи не вирізати та вставляти шаблони підстановочних символів на потенційно руйнівний командний рядок. Бо в моїх руках це була проблема :)

Технік у моїй лабораторії щойно зробив цю помилку минулого тижня (3 місяці роботи) - і так, у нас було резервне копіювання (1 день позаду).


0

Всі, здається, говорять: "Будьте обережніші", "Не робіть підказки / псевдоніма для підтвердження, оскільки ви звикте не звертати на нього належної уваги".

Класно, і все. Я маю на увазі, я не думаю, що ви повинні робити псевдонім для rm(а також rmrfтому, що ви можете легко викрутити це і ввести реальну команду).

Але чому ви не можете створити псевдонім / скрипт і назвати його, скажімо, removeі подати лише один аргумент (наприклад, $ 1)? Підстановочна карта повинна становити 2 долари через невмілий пробіл (amiright?), І таким чином ваш сценарій / обгортка / псевдонім не буде переданий другим. Так, ви можете одночасно робити лише один набір видалень (з підстановкою), але це ціна, яку ви заплатите.

Якби я писав щось приємне, я, можливо, змусив би сказати мені кількість файлів і каталогів, які планує видалити, і загальний розмір матеріалів, які я видаляв, а потім попросити підтвердження, але це може перешкодити вашому потоку. Можливо, увімкніть цей варіант прапора remove? (-і). Ви також можете зробити чек на 1 долар, щоб побачити, чи це просто одна підстановка, і попросити підтвердження та перерахувати, в якому каталозі ви фактично перебуваєте.


Крім того, існує ряд rmзамін там. Багато хто намагається бути сумісним із смітником для настільних інтерфейсів. Деякі з них, можливо, варто переглянути.


6
Псевдонім "видалити" ніколи не видалить більше одного файлу одночасно. Не можна використовувати підстановку, оскільки оболонка розгортає її, перш ніж команда побачить її.
гімі

Тож зробіть евал на ньому, а потім втягніть це в сценарій?
користувач3082

Отже, ви хочете ввести remove \*? Якщо ваш сценарій дозволяє оболонці глобально розширити свій вхід, я не бачу, що це дуже допомагає.
Пітер Кордес

0

Дуже простий трюк - це поставити -rfв кінці: rm whatever* -rf
Це зменшує драстично рівень помилок, тому що ви набираєте більше символів після знака *, тому у вас є більше часу, щоб побачити помилки.
Це не все вирішує. Просто простий щоденний трюк.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.