Как решить "отказано в разрешении" при использовании 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