Как решить "отказано в разрешении" при использовании sudo с перенаправлением в Bash?
Когда я использую 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
Есть идеи?
7 ответов
Перенаправление вывода (через >
оператор) выполняется оболочкой, а не эхом. Вы должны войти в систему как root
sudo -i
Тогда вы можете использовать перенаправление
echo N> /sys/module/drm_kms_helper/parameters/poll
В противном случае вы можете запустить строку bash с помощью sudo
sudo bash -c "echo N> /sys/module/drm_kms_helper/parameters/poll"
Перенаправление вывода выполняется оболочкой, из которой была вызвана команда. Итак, разбивая все на кусочки, вот что происходит *:
оболочка вызывает
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"
эхо, работает с
root
привилегии, печатает строку в стандартный вывод.echo
команда завершается, суперпользовательская оболочка завершается,sudo
завершаясьоболочка, из которой была вызвана команда, собирает выходные данные и пытается перенаправить их
/etc/modprobe.d/local.conf
, который доступен для записи только root. Получает ошибку "Отказано в доступе".
Чтобы узнать, как это исправить, смотрите ответ @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
содержащий слово "корень". Однако, когда перенаправление вывода завершается неудачно в вызывающей оболочке, файл who.txt также отсутствует, так как команда не была вызвана.
Добавление к ответу Шантану:
... Или вы могли бы использовать tee
команда как это:
sudo tee /sys/module/drm_kms_helper/parameters/poll <<<10
или если вывод команды:
echo 10 | sudo tee /sys/module/drm_kms_helper/parameters/poll
Подход, о котором я не упомянул, это просто выполнить всю командную строку в своей собственной оболочке. sudo
Сама manpage приводит пример такого подхода:
Составить список использования каталогов в разделе / home. Обратите внимание, что это запускает команды в под-оболочке, чтобы заставить работать перенаправление компакт-дисков и файлов.
$ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE"
Другой вариант - использовать временный файл. Это полезно в скрипте bash.
temp=$(mktemp)
echo "Hello, world!" > $temp
sudo cp $temp /etc/wherever
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 в команду.
Создайте однострочный скрипт из своей команды, затем выполните скрипт как . Например:
Используйте редактор для создания файла; Например:
nano my_script.sh
В редакторе вставьте свой шебанг и команду:
#!/bin/bash echo "options drm_kms_helper poll=N" > /etc/modprobe.d/local.conf
Сохраните файл и выйдите из редактора; например
~/my_script.sh
Сделайте исполняемый файл:
chmod 755 ~/my_script.sh
Запустите скрипт под
sudo
:sudo ./my_script.sh