Виконайте рядок команд одним судо


21

Наприклад, якщо я хочу створити файл і ввести текст в одному рядку, я можу перенаправити вихід у файл за допомогою >оператора:

echo "something" > /path/foobar

але якщо я не маю доступу до папки /path/і мені потрібні привілеї sudo, як я можу досягти цієї самої команди як звичайний користувач із правами sudo?

я намагався

sudo echo "something" > /path/foobar

але це не спрацьовує, тому що судо розраховується лише editна правильну частину, але не
є>

Зрозуміло, я міг би стати root перед цим sudo suабо використовувати teeзамість нього:

echo "something" | sudo tee /path/foobar

Але я хотів би знайти рішення, де я можу працювати з останнім рядком як заміна через

sudo !!

Чи не існує способу "переробити" останній рядок і просто додати sudoспереду?



Це не дублікат. Я видобув справжнє споживання і змінив назву. Тепер це те, що я справді шукаю
rubo77

Це, звичайно, було дублікатом, але зараз дещо інакше. Мені здається, ви переписали це питання з урахуванням відповіді Бугі, що добре - це хороша відповідь. Я відмовився від свого закритого голосування, але це все-таки неминуче (люди часто голосують автоматично, як тільки питання стоїть у черзі, не звертаючи уваги на питання): зверніться до коментаря @goldilocks, коли він закриється, і я буду голосувати за повторне відкриття . Ви також можете попросити свою справу у чаті, як тільки це станеться.
золотинок

Відповіді:


13

Ви не можете просто вставити sudoперед командою оболонки, ви повинні викликати оболонку, щоб знову оцінити цю команду (виконуючи такі дії, як розширення змінних, відкриття файлів для операторів переадресації тощо). Так це

sudo bash -c !!

за винятком того, що це не зовсім працює, оскільки !!інтерполює текст попередньої команди, спеціальні символи та все. Вам потрібно отримати текст команди у вигляді рядка і передати це як аргумент sh. На щастя, fcвбудований баш дозволяє вам це зробити¹.

sudo bash -c "$(fc -ln -1)"

Або навіть, щоб бути впевненим, щоб викликати ту саму версію bash, яка зараз працює:

sudo "$BASH" -c "$(fc -ln -1)"

Зауважте, що оскільки команда виконується в окремому процесі оболонки, вона успадковує змінні середовища (лише ті, що sudoзберігає), але не внутрішні змінні оболонки. Параметри оболонки (наприклад kshglob) та інші налаштування також почнуться із замовчування.

Ця ж команда² працює в zsh і ksh, хоча ATT ksh93 вимагає передавати firstі lastчисло, і число до fc³ (що також працює в bash, zsh та pdksh / mksh):

sudo zsh -c "$(fc -ln -1)"
sudo ksh -c "$(fc -ln -1 -1)"
sudo "$0" -c "$(fc -ln -1 -1)"

Використання $0для позначення виконуваного файлу запущеної оболонки працює лише в тому випадку, якщо оболонку викликали через $ PATH і $ PATH не змінився або через абсолютний шлях.

Ось ще один метод в zsh, який трохи чіткіший, але довший:

sudo zsh -c $history[$[HISTCMD-1]]

Заключне слово попередження: sudoпризначено для потенційно небезпечних команд. Не робіть його занадто простим у використанні!

¹ На початку є кілька додаткових пробілів, а заміна команд знімає нові рядки в кінці, але синтаксис оболонки це не хвилює.
² Я не думаю, що zsh або ksh не мають нічого подібного до bash's $BASH; $0працює лише тоді, коли це абсолютний шлях або коли він не містить косою рисою і шлях пошуку команди не змінився.
³ псевдонім для ATT ksh, але це так само добре. fchist


9

Якщо ви хочете повторити ту саму команду з sudo !! після виконання такої команди:

echo "something">/path/file

Ви використовуєте синтаксис глобальної заміни для виклику команди:

!!:gs/>/|sudo tee -a /

Використовуйте пробіл після параметра -a .

Це еквівалент sudo !! але допоможе вам обійти обмеження судо для <і>. Тому що sudo не дозволяє використовувати [<,>].


Щоб обійти обмеження sudo взагалі для переадресацій, ви можете використовувати його так:

echo "something" | sudo tee myfile

Команда tee дозволить вам читати зі стандартного вводу та записувати на стандартний вихід та файли

Якщо ви хочете повторити команду та додати текст до файлу, команда tee має опцію -a для додавання. Тож ви могли згадати команду за допомогою

sudo !!

і текст буде доданий у файл

приклад:

echo "something" | sudo tee -a /path/file
sudo !!

приємне рішення, але трохи важко запам’ятовувати. Як я можу створити псевдонім для команди за допомогою !! щоб пригадати останню команду ?
rubo77

чи -aсправді потрібно? >перезапише файл, tee -aдодасть, що було б>>
rubo77

3

Здається, це так просто, як sudo sh -c "!!":

$ cd /
$ echo hello > foo
bash: foo: Permission denied
$ sudo sh -c "!!"
sudo sh -c "echo hello > foo"
$ ls -l foo
-rw-r--r-- 1 root root 6 Jun 20 16:21 foo

3
Якщо команда використовувала лапки, це не обов'язково еквівалентно. Поміркуйте, echo "foo bar"що б стало, sh -c "echo "foo bar""що просто надрукується fooзамість foo bar.
godlygeek

Я sudo sh -c '!!'натомість спробував, якщо ваша команда, але це теж не працює
rubo77

Тоді що робити, якщо ваша команда використовувала як одиничні, так і подвійні лапки? Або подвійні лапки та змінні розширення? Якби користувач зробив: a=bі тоді, echo "$a" >fileі тоді sudo sh -c '!!'він розшириться, до sudo sh -c 'echo $a >file'якого надрукував би порожній рядок замість bв file.
godlygeek

То, може, є ще краще рішення?
rubo77

1
Я не думаю, що існує рішення, яке б спрацювало 100% часу, без того, щоб вам коли-небудь потрібно було змінювати команду. Використовувати sudoдля отримання кореневої оболонки, а потім копіювати та вставляти команду в неї було б найближчим, але не вдалося, якщо команда повинна була використовувати змінні, встановлені у вашій некорінній оболонці. Використання sudo sh -c "!!"відмінно підходить для простих команд, але складне для складних. Я думаю, що найкраща порада - не сподіватися, що існує якась команда, яка буде працювати 100% часу - вивчити деякі можливі рішення та застосувати кожне, коли це найкраще підходить.
godlygeek
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.