Как использовать sudo для перенаправления вывода в местоположение, на которое у меня нет разрешения на запись?
Мне предоставлен sudo-доступ в одном из наших оконных блоков RedHat для разработки, и мне кажется, что мне довольно часто приходится перенаправлять вывод на место, в котором я обычно не имею доступа на запись.
Проблема в том, что этот надуманный пример не работает:
sudo ls -hal /root/ > /root/test.out
Я просто получаю ответ:
-bash: /root/test.out: Permission denied
Как я могу заставить это работать?
Ответы
Ответ 1
Ваша команда не работает, потому что перенаправление выполняется вашей оболочкой, которая не имеет права на запись в /root/test.out
. Перенаправление вывода не выполняется sudo.
Существует несколько решений:
-
Запустите оболочку с sudo и дайте ей команду с помощью опции -c
:
sudo sh -c 'ls -hal /root/ > /root/test.out'
-
Создайте script с вашими командами и запустите script с помощью sudo:
#!/bin/sh
ls -hal /root/ > /root/test.out
Запустите sudo ls.sh
. См. Steve Bennett answer, если вы не хотите создавать временный файл.
-
Запустите оболочку с sudo -s
, затем запустите свои команды:
[[email protected]]$ sudo -s
[[email protected]]# ls -hal /root/ > /root/test.out
[[email protected]]# ^D
[[email protected]]$
-
Используйте sudo tee
(если вам нужно много избегать при использовании опции -c
):
sudo ls -hal /root/ | sudo tee /root/test.out > /dev/null
Переадресация на /dev/null
необходима для остановки tee от вывода на экран. Добавление вместо перезаписи выходного файла
(>>
) используйте tee -a
или tee --append
(последний относится к GNU coreutils).
Спасибо, Jd, Адам Дж. Форстер и Johnathan для второго, третьего и четвертого решений.
Ответ 2
Кто-то здесь только что предложил sudoing tee:
sudo ls -hal /root/ | sudo tee /root/test.out > /dev/null
Это также можно использовать для перенаправления любой команды в каталог, к которому у вас нет доступа. Это работает, потому что программа tee эффективно представляет собой программу "echo to file", а перенаправление на /dev/null - это также остановка ее вывода на экран, чтобы она оставалась такой же, как и исходный надуманный пример выше.
Ответ 3
Трюк, который я понял, был
sudo ls -hal /root/ | sudo dd of=/root/test.out
Ответ 4
Проблема в том, что команда запускается под sudo
, но перенаправление запускается под вашим пользователем. Это делается оболочкой, и вы можете сделать это очень мало.
sudo command > /some/file.log
'-----v-----''-------v-------'
command redirection
Обычными способами обхода этого являются:
-
Оберните команды в скрипт, который вы вызываете в sudo.
Если команды и/или файл журнала изменяются, вы можете заставить сценарий воспринимать их как аргументы. Например:
sudo log_script command /log/file.txt
-
Вызвать оболочку и передать командную строку в качестве параметра с помощью -c
Это особенно полезно для одной команды соединения. Например:
sudo bash -c "{ command1 arg; command2 arg; } > /log/file.txt"
Ответ 5
Еще одна вариация темы:
sudo bash <<EOF
ls -hal /root/ > /root/test.out
EOF
Или, конечно же:
echo 'ls -hal /root/ > /root/test.out' | sudo bash
У них есть (крошечное) преимущество, что вам не нужно запоминать какие-либо аргументы для sudo
или sh
/bash
Ответ 6
Уточнение вопроса о том, почему предпочтительнее вариант тройника
Предполагая, что у вас есть соответствующее разрешение для выполнения команды, которая создает вывод, если вы передаете вывод вашей команды в tee, вам нужно только поднять тэли с помощью sudo и direct tee для записи (или добавления) в файл в вопрос.
в примере, указанном в вопросе, который будет означать:
ls -hal /root/ | sudo tee /root/test.out
для еще нескольких практических примеров:
# kill off one source of annoying advertisements
echo 127.0.0.1 ad.doubleclick.net | sudo tee -a /etc/hosts
# configure eth4 to come up on boot, set IP and netmask (centos 6.4)
echo -e "ONBOOT=\"YES\"\nIPADDR=10.42.84.168\nPREFIX=24" | sudo tee -a /etc/sysconfig/network-scripts/ifcfg-eth4
В каждом из этих примеров вы принимаете вывод не-привилегированной команды и записываете в файл, который обычно записывается только root, что является источником вашего вопроса.
Это хорошая идея сделать это так, потому что команда, которая генерирует вывод, не выполняется с повышенными привилегиями. Здесь не имеет значения echo
, но когда исходная команда является script, которую вы не полностью доверяете, это имеет решающее значение.
Обратите внимание, что вы можете использовать параметр -a для tee, чтобы добавить append (например, >>
) в целевой файл, а не перезаписывать его (например, >
).
Ответ 7
Сделать sudo запустить оболочку, например:
sudo sh -c "echo foo > ~root/out"
Ответ 8
Как я могу решить эту проблему:
Если вам нужно написать/заменить файл:
echo "some text" | sudo tee /path/to/file
Если вам нужно добавить файл:
echo "some text" | sudo tee -a /path/to/file
Ответ 9
Как насчет написания script?
Имя файла: myscript
#!/bin/sh
/bin/ls -lah /root > /root/test.out
# end script
Затем используйте sudo для запуска script:
sudo ./myscript
Ответ 10
Я бы сделал это следующим образом:
sudo su -c 'ls -hal /root/ > /root/test.out'
Ответ 11
Всякий раз, когда мне приходится делать что-то подобное, я просто становлюсь root:
# sudo -s
# ls -hal /root/ > /root/test.out
# exit
Это, вероятно, не самый лучший способ, но он работает.
Ответ 12
Не нужно бить мертвой лошади, но здесь слишком много ответов, которые используют tee
, что означает, что вам нужно перенаправить stdout
в /dev/null
, если вы не хотите видеть копию на экране. Более простым решением является просто использовать cat
следующим образом:
sudo ls -hal /root/ | sudo bash -c "cat > /root/test.out"
Обратите внимание, как перенаправление помещается внутри кавычек, чтобы оно оценивалось оболочкой, запущенной sudo
, а не той, которая ее запускала.
Ответ 13
Это основано на ответе с участием tee
. Чтобы упростить задачу, я написал небольшой скрипт (я называю его suwrite
) и поместил его в /usr/local/bin/
с разрешением +x
:
#! /bin/sh
if [ $# = 0 ] ; then
echo "USAGE: <command writing to stdout> | suwrite [-a] <output file 1> ..." >&2
exit 1
fi
for arg in "[email protected]" ; do
if [ ${arg#/dev/} != ${arg} ] ; then
echo "Found dangerous argument ‘$arg. Will exit."
exit 2
fi
done
sudo tee "[email protected]" > /dev/null
Как показано в коде " ИСПОЛЬЗОВАНИЕ" в коде, все, что вам нужно сделать, - это передать выходные данные в этот сценарий, за которым следует желаемое имя доступного суперпользователя -a, и при необходимости он автоматически запросит ваш пароль (поскольку он включает sudo
).
echo test | suwrite /root/test.txt
Обратите внимание, что, поскольку это простая оболочка для tee
, она также принимает опцию tee -a
для добавления, а также поддерживает запись в несколько файлов одновременно.
echo test2 | suwrite -a /root/test.txt
echo test-multi | suwrite /root/test-a.txt /root/test-b.txt
Он также имеет некоторую упрощенную защиту от записи в /dev/
devices, о чем упоминалось в одном из комментариев на этой странице.
Ответ 14
Возможно, вам предоставили доступ к sudo только для некоторых программ/путей? Тогда нет способа сделать то, что вы хотите. (если вы его не взломаете)
Если это не так, возможно, вы можете написать bash script:
cat > myscript.sh
#!/bin/sh
ls -hal /root/ > /root/test.out
Нажмите ctrl + d:
chmod a+x myscript.sh
sudo myscript.sh
Надеюсь, что это поможет.
Ответ 15
sudo at now
at> echo test > /tmp/test.out
at> <EOT>
job 1 at Thu Sep 21 10:49:00 2017