Мне дали доступ sudo на одном из наших рабочих компьютеров RedHat linux, и я часто сталкиваюсь с необходимостью перенаправить вывод в место, к которому у меня обычно нет доступа на запись. Проблема в том, что этот надуманный пример не работает:
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'
Создайте сценарий со своими командами и запустите этот сценарий с помощью sudo:
#!/bin/sh
ls -hal /root/ > /root/test.out
Запустите sudo ls.sh, если вы не хотите создавать временный файл.
Запустите оболочку sudo –s, а затем выполните эти команды:
[nobody@so]$ sudo -s
[root@so]# ls -hal /root/ > /root/test.out
[root@so]# ^D
[nobody@so]$
Используйте sudo tee (если вам нужно часто использовать escape вместе с опцией -c):
sudo ls -hal /root/ | sudo tee /root/test.out > /dev/null
Перенаправление на /dev/null необходимо, чтобы остановить вывод tee на экран. Чтобы добавить вместо перезаписи выходной файл ( >>), используйте tee –a или tee --append (последний специфичен для GNU coreutils).
Ответ 2
При использовании sudoing tee:
sudo ls -hal /root/ | sudo tee /root/test.out > /dev/null
Это также можно использовать для перенаправления любой команды в каталог, к которому у вас нет доступа. Это работает, потому что программа tee фактически является программой «эхо в файл», а перенаправление на /dev/null должно остановить ее вывод на экран, чтобы она оставалась такой же, как в исходном надуманном примере выше.
Ответ 3
Проблема в том, что команда выполняется под 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"
Ответ 4
Если у вас есть соответствующие права на выполнение команды, создающей вывод, то при передаче вывода команды в tee вам нужно только повысить права tee с помощью sudo и направить tee на запись (или добавление) в соответствующий файл.
В примере, приведенном в вопросе, это означает:
ls -hal /root/ | sudo tee /root/test.out
Еще несколько практических примеров:
# уничтожить один источник
echo 127.0.0.1 ad.doubleclick.net | sudo tee -a /etc/hosts
# настройте eth4 на загрузку, установите IP и маску сети (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 это не имеет значения, но, когда исходной командой является скрипт, которому вы не вполне доверяете, это очень важно. Обратите внимание, что вы можете использовать опцию -a для tee, чтобы добавлять (как >>) к целевому файлу, а не перезаписывать его (как >).
Ответ 5
Это основано на ответе с участием 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 "$@" ; do
if [ ${arg#/dev/} != ${arg} ] ; then
echo "Найден опасный аргумент ‘$arg’. Will exit."
exit 2
fi
done
sudo tee "$@" > /dev/null
Как показано в USAGE в коде, все, что вам нужно сделать, — это передать вывод в этот скрипт, а затем указать желаемое имя файла с доступом суперпользователя, и он автоматически запросит ваш пароль, если это необходимо (поскольку он включает 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/.
Ответ 6
Может быть, вам дали доступ sudo только к некоторым программам/путям? Тогда нет возможности сделать то, что вы хотите (если только вы не взломаете его каким-то образом).
Если это не так, то, возможно, вы можете написать bash-скрипт:
cat > myscript.sh
#!/bin/sh
ls -hal /root/ > /root/test.out
chmod a+x myscript.sh
sudo myscript.sh
Linux