Как выполнить команду, которая включает перенаправление или использование конвейера с sudo?

Вопрос или проблема

Я пытаюсь следовать тому, что, как я предполагаю, является лучшими практиками использования sudo вместо учетной записи root.

Я выполняю простую операцию конкатенации файла, такую как:

sudo echo 'clock_hctosys="YES"' >> /etc/conf.d/hwclock

Это не удается, поскольку справа от “>>” выполняется команда от имени обычного пользователя. Добавление дополнительных sudo также не удается (ожидаемое поведение, так как команда направляется в sudo, а не в файл).

Этот пример проверен и протестирован под учетной записью root.

Вы можете вызвать новую оболочку как root:

sudo sh -c 'echo clock_hctosys=\"YES\" >> /etc/conf.d/hwclock'

Вы также можете просто повысить права процесса, чтобы записывать в файл:

sudo tee -a /etc/conf.d/hwclock > /dev/null << EOF
clock_hctosys="YES"
EOF

Другой вариант, не менее безопасный, – использовать переключатель -i команды sudo, чтобы войти как root:

$ sudo -i
# echo clock_hctosys=\"YES\" >> /etc/conf.d/hwclock'

Это все равно соответствует правилам лучших практик, поскольку учетная запись root фактически не активируется, а позволяет безопасно выполнять действия от имени root. Из man sudo:

Опция -i (симуляция первоначального входа) запускает оболочку,
    указанную записью базы данных паролей целевого пользователя,
    как логин-оболочку. Это означает, что файлы ресурсов,
    специфичные для логина, такие как .profile или .login, будут
    прочитаны оболочкой. Если команда указана, она передается
    оболочке для выполнения через опцию -c оболочки. Если команда
    не указана, запускается интерактивная оболочка.

sudo dd of=

Чтобы добавить, как с помощью >>:

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

или чтобы воссоздать файл с нуля, как с помощью >:

echo inbytes | sudo dd of=path/to/outfile

Кроме того, можно сделать dd более тихим с помощью status=none, как в:

echo inbytes | sudo dd of=path/to/outfile status=none

иначе он выводит некоторую информацию о состоянии типа:

0+1 записей прочитано
0+1 записей записано
8 байт скопировано, 2.7432e-05 с, 292 кБ/с

Альтернативно, можно также сделать более подробным и наблюдать скорость передачи с status=progress, как я упомянул в этом другом ответе.

Преимущества:

  • удобнее, чем tee, так как нет перенаправления /dev/null
  • удобнее, чем sh, так как нет подсистемы
  • dd имеет много мощных опций, например, status=progress для отображения хода передачи

Работает, потому что sudo перенаправляет стандартный ввод на команду.

Если выразить команду без одинарных кавычек, ее можно поместить внутрь одинарных кавычек и выполнить через промежуточную оболочку.

Чтобы выполнить это как root:

echo 'clock_hctosys="YES"' >> /etc/conf.d/hwclock

Запишите команду по-другому, чтобы не использовать ':

echo clock_hctosys=\"YES\" >> /etc/conf.d/hwclock

Затем вызовите sudo sh -c …:

sudo sh -c 'echo clock_hctosys=\"YES\" >> /etc/conf.d/hwclock'

Альтернативно, чтобы записать вывод в файл, в который может записывать только root, вызовите sudo tee. Передайте опцию -a для tee, чтобы добавить в файл назначения, в противном случае файл будет усечен.

echo 'clock_hctosys="YES"' | sudo tee -a /etc/conf.d/hwclock >/dev/null

Для более сложных модификаций файла можно вызвать sudo sed, sudo ed, sudo perl и т.д.

Или используйте приличный редактор и заставьте его вызвать sudo. В Emacs откройте /sudo:/etc/conf.d/hwclock. В Vim вызовите :w !sudo tee %, чтобы записать в открытый файл как root, или используйте плагин sudo.vim. Или войдите в систему через sudo и вызовите sudoedit /etc/conf.d/hwclock.

Или можно уступить на темной стороне и запустить оболочку как root.

$ sudo -i
# echo 'clock_hctosys="YES"' >> /etc/conf.d/hwclock

Команда не выполняется из-за разрешений на файл, в который происходит перенаправление. Перенаправление происходит еще до того, как вызывается команда sudo.

Вы должны убедиться, что именно root открывает файл для записи.

Самый простой способ сделать это:

echo 'clock_hctosys="YES"' | sudo tee -a /etc/conf.d/hwclock >/dev/null

Команда echo может быть выполнена обычным пользователем, так как она просто генерирует текстовую строку. Тем не менее, утилита tee должна выполняться от имени root, причем tee -a добавит данные. Мы перенаправляем вывод в /dev/null, поскольку tee по умолчанию дублирует свой ввод на стандартный вывод помимо записи в указанные файлы.

С помощью bash или любой оболочки, которая понимает “строки”:

sudo tee -a /etc/conf.d/hwclock >/dev/null <<<'clock_hctosys="YES"'

Это идентично вышеуказанному. Единственное изменение – способ генерации строки.


Другой, слегка обходной способ сделать это:

sudo sh -c 'echo clock_hctosys=\"YES\" >>/etc/conf.d/hwclock'

Здесь перенаправление происходит в sh -c дочерней оболочке, выполняющейся как root.

Или дать строку для добавления как аргумент оболочке sh -c, выполняемой как root:

sudo sh -c 'printf "%s\n" "$1" >>/etc/conf.d/hwclock' sh 'clock_hctosys="YES"'

… что может быть обобщено для добавления всех аргументов как строк в файл:

set -- 'строка 1' 'строка 2' 'строка 3'
sudo sh -c 'printf "%s\n" "$@" >>/etc/conf.d/hwclock' sh "$@"

Удивительно, как редко этот инструмент упоминается, учитывая, насколько он полезен:

sponge из пакета moreutils. Он доступен практически в каждом дистрибутиве под тем же именем и может справляться с множеством ситуаций, с которыми оболочка плохо справляется.

Изначально его предназначение – позволить сначала прочитать, а затем записать обратно в тот же файл (что оболочка не может, потому что перенаправление обрабатывается первым). Тем не менее, он также отлично подходит для этой цели:

echo "hello world" | sudo sponge /path/to/privileged/file

Все просто. А если нужно добавить вместо перезаписывания (>>), есть флаг -a.

Посмотрите руководство.

.

Ответ или решение

В ситуациях, когда вы работаете в операционных системах на базе Unix или Linux, нередко возникает необходимость выполнять команды с привилегированным доступом, особенно при работе с файлами и каталогами, доступ к которым ограничен. Одним из лучших решений для этого является использование команды sudo, которая позволяет временно получать права суперпользователя для выполнения определенных команд. Однако, есть определенные сложности, когда речь идет о перенаправлении вывода или использовании конвейеров (пайпов) с sudo, так как стандартное перенаправление и пайпинг выполняются оболочкой, а не командой.

Теория

Основная проблема возникает из-за того, что когда используется перенаправление с помощью > или >>, это перенаправление обрабатывается самой оболочкой, а не командой sudo. То есть, команда sudo предоставляет привилегии только для выполнения указанной команды, но не для перенаправления вывода, которое по-прежнему выполняется с правами текущего пользователя. Это приводит к ошибкам доступа при попытке записать данные в файлы, принадлежащие root-пользователю.

Пример

Рассмотрим пример использования команды sudo с перенаправлением:

sudo echo 'clock_hctosys="YES"' >> /etc/conf.d/hwclock

Эта команда не выполнится успешно, так как echo отрабатывает с правами root, но перенаправление >> все еще выполняется от имени обычного пользователя. В результате мы получаем ошибку доступа.

Применение

Есть несколько методов, позволяющих корректно выполнять такие операции, используя sudo без прямого входа в систему под root.

  1. Использование оболочки sh -c:

    Один из самых простых способов заключается в запуске новой командной оболочки от имени root, и выполнение всей команды в этой оболочке:

    sudo sh -c 'echo clock_hctosys="YES" >> /etc/conf.d/hwclock'

    Здесь вся строка, включая перенаправление, выполняется в привилегированной оболочке, что решает проблему доступа.

  2. Команда tee:

    tee — это утилита, которая может считывать ввод из стандартного потока и записывать его в несколько файлов, не разрывая поток, и она может быть использована для записи в файлы с правами суперпользователя:

    echo 'clock_hctosys="YES"' | sudo tee -a /etc/conf.d/hwclock > /dev/null

    Здесь -a указывает на добавление в файл, а не перезапись, а выход tee перенаправляется в /dev/null, чтобы не отображать результаты.

  3. Пакет moreutils и утилита sponge:

    Утилита sponge, доступная в пакете moreutils, предлагает другой подход, позволяющий сначала полностью считывать ввод перед записью:

    echo 'clock_hctosys="YES"' | sudo sponge /etc/conf.d/hwclock

    Использование -a с sponge позволяет дописывать в файл, как и при использовании >>.

Это лишь несколько способов правильно использовать sudo для операций с перенаправлением. Важно помнить, что каждое решение должно быть выбрано в зависимости от контекста задачи и специфики работы.

Вне зависимости от выбранного метода, важно убедиться в безопасности и корректности выполняемых команд, следя за правами доступа и подтверждая необходимость выполнения тех или иных операций с повышенными привилегиями.

Оцените материал
Добавить комментарий

Капча загружается...