Linux

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

Мне дали доступ 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

Как запустить сценарий оболочки при запуске системы

Установка Linux на ARM. Подробная пошаговая инструкция и советы
Linux

Установка Linux на ARM. Подробная пошаговая инструкция и советы

Как установить Gnome 3, что такое графическая оболочка Gnome Shell
Linux

Как установить Gnome 3, что такое графическая оболочка Gnome Shell

Linux

Как обнаружить скрытый процесс в Linux?

×