Як вирішити "дозвіл відмовлено" при використанні sudo з перенаправленням в Bash?


137

Використовуючи sudo для дозволу редагування файлів, мені регулярно відмовлено у дозволі.

Наприклад, моя миша хитра і млява, тому я хочу відключити опитування:

sudo echo "options drm_kms_helper poll=N">/etc/modprobe.d/local.conf

Мені запропоновано ввести пароль, а потім отримати:

bash: /etc/modprobe.d/local.conf: Permission denied

Тому я спробував зробити тимчасову зміну, щоб відключити опитування, використовуючи:

sudo echo N> /sys/module/drm_kms_helper/parameters/poll

І знову система відповіла:

bash: /sys/module/drm_kms_helper/parameters/poll: Permission denied

Якісь ідеї?

Відповіді:


156

Перенаправлення виводу (через >оператора) здійснюється оболонкою, а не відлунням . Ви повинні увійти як root

sudo -i

Тоді можна використовувати перенаправлення

echo N> /sys/module/drm_kms_helper/parameters/poll

Інакше ви можете запустити bash string з sudo

sudo bash -c "echo N> /sys/module/drm_kms_helper/parameters/poll"

1
Ви не можете запустити ехо з судо? що з результатом я отримав:saji@laptop:~$ sudo echo "Hi" [sudo] password for saji: Hi
saji89

Ви можете написати у файл, повторюючи "щось"> деякий. Це за допомогою труби. У цьому проблема.
шантану

4
Гаразд, якщо це так, то, будь ласка, оновіть свою відповідь, щоб відобразити, що запущене відлуння є проблемою лише в цьому випадку.
saji89

Ви не можете просто запустити вбудовану оболонку echoяк судо, якщо ви не зробите щось подібне sudo bash -c 'echo …'; однак системи POSIX зазвичай постачають зовнішню echoкоманду, таку як /bin/echoна OS X, яку sudo може виконувати без ригамароли. Таким чином, echoкоманда, яку ви зазвичай виконуєте, і echoкоманда, яку ви виконуєте з sudo, ймовірно, дві різні, але схожі команди.
kojiro

Якщо це так, чому відповіді на це питання запропонували відлуння? askubuntu.com/questions/840431/…
Харша,

75

Перенаправлення виводу здійснюється оболонкою, з якої викликана команда . Отже, розбиваючи все на біти, ось що відбувається *:

  • викликає оболонку sudo echo "options drm_kms_helper poll=N", яка виконує sudoкоманду з echo "options drm_kms_helper poll=N"командного рядка

  • sudo запитує пароль, відкриває оболонку суперрусера і викликає echo "options drm_kms_helper poll=N", який запускає echoкоманду, передаючи його"options drm_kms_helper poll=N"

  • echo, працює з rootпривілеями, друкує рядок до його стандартного виводу.

  • echoкоманда припиняється, оболонка суперрусера виходить, sudoзакінчується

  • оболонка, з якої викликана команда, збирає результат і намагається перенаправити його, до /etc/modprobe.d/local.confякого можна записати лише корінь. Він отримує помилку "відмовлено у дозволі".

Про способи виправити це див. У відповіді @shantanu.


(*) - хоча вищевказана послідовність допомагає зрозуміти, чому команда не вдається, насправді все відбувається дещо поза порядком: оригінальна оболонка помічає перенаправлення та намагається відкрити файл для запису перед тим, як викликати sudo ...команду. Під час відкриття файлу не вдається, оболонка навіть не викликає команду, яка повинна була написати в файл (спасибі @PanosRontogiannis за вказівку на це).

Ось швидкий тест:

$ touch ./onlyroot.txt
$ sudo chown root:root ./onlyroot.txt
$ sudo bash -c "whoami | tee who.txt" > onlyroot.txt
bash: onlyroot.txt: Permission denied

У тесті вище whoami | tee who.txtзбирався створити файл з назвою, who.txtщо містить слово "root". Однак, коли перенаправлення виводу виходить з ладу в оболонці виклику, файл "who.txt" також відсутній, оскільки команду не викликали.


Швидше за все, оболонка "розщеплюється" і намагається відкрити /etc/modprobe.d/local.conf перед тим, як спробувати "виконати" sudo, що означає, що перші 4 кроки вашого опису насправді не трапляються, тому що файл неможливо відкрити.
Panos Rontogiannis

1
@PanosRontogiannis: спасибі, я оновив відповідь
Сергій

60

Додавання до відповіді Шантану:

... Або ви можете використовувати таку teeкоманду:

sudo tee /sys/module/drm_kms_helper/parameters/poll <<<10

або якщо результат його команди:

echo 10 | sudo tee /sys/module/drm_kms_helper/parameters/poll

3
+1 вхід як root - це погана ідея для ручної роботи та дуже погана ідея для сценаріїв.
l0b0

2
Крім того, sudo tee /sys/module/drm_kms_helper/parameters/poll > /dev/nullякщо ви не хочете, щоб це також було друком stdout.
Fabian Tamp

16

Я не бачив тут підходу, щоб просто виконати весь командний рядок у власній оболонці. sudoСама сторінка керівництва дає приклад такого підходу:

Створення списку використання каталогів у розділі / home. Зауважте, що це виконує команди в підколонці, щоб змусити працювати перенаправлення CD та файлів.

$ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE"

вау спасибі просте рішення
Resilience

4

Інший варіант - використовувати тимчасовий файл. Це корисно в сценарії bash.

temp=$(mktemp)
echo "Hello, world!" > $temp
sudo cp $temp /etc/wherever

3

sudo dd of=

Щоб додати як потрібно:

echo inbytes | sudo dd of=outfile oflag=append conv=notrunc

або відтворити файл з нуля:

echo inbytes | sudo dd of=outfile

Переваги:

  • приємніше, ніж teeз моменту /dev/nullперенаправлення
  • приємніше, ніж тоді, shколи явної підзаголовки немає (але неявна для перенаправлення)
  • ddмає багато потужних варіантів, наприклад, status=progressщоб побачити хід передачі

Працює тому, що sudo пересилає stdin до команди.


1
Це добре. Ми думаємо про ddте, як ми перезаписуємо наші колись чудові файлові системи, і не усвідомлюємо, що це теж для повсякденних завдань - і що інші команди як root також завдають великої шкоди, якщо вони використовуються на неправильних файлах / пристроях. Якsudo tee і , sudo ddзвичайно , також працювати з тут рядків , наприклад, sudo dd of=outfile <<<'hello world'. [Дякуємо за редагування Зауважте sh -c 'cmd', що shце підпроцес, який є оболонкою, але насправді не підпунктом, за винятком сенсу, що всі зовнішні команди починаються як одна.]
Eliah Kagan
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.