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

StackOverflow https://stackoverflow.com/questions/82256

Вопрос

Мне был предоставлен доступ к sudo в одном из наших модулей разработки RedHat linux, и, похоже, мне довольно часто приходится перенаправлять выходные данные в папку, к которой у меня обычно нет доступа на запись.

Проблема в том, что этот надуманный пример не работает:

sudo ls -hal /root/ > /root/test.out

Я просто получаю ответ:

-bash: /root/test.out: Permission denied

Как я могу заставить это сработать?

Это было полезно?

Решение

Ваша команда не работает, потому что перенаправление выполняется вашей командной оболочкой, у которой нет разрешения на запись в /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 (если вам приходится часто убегать при использовании -c вариант):

    sudo ls -hal /root/ | sudo tee /root/test.out > /dev/null
    

    Перенаправление на /dev/null это необходимо, чтобы остановить тройник от вывода на экран.Для добавить вместо перезаписи выходного файла (>>), использовать tee -a или tee --append (последнее относится конкретно к GNU coreutils ( основные файлы GNU )).

Спасибо, что обратились к Джей Ди, Адам Дж .Форстер и Джонатан для второго, третьего и четвертого решений.

Другие советы

Кто-то здесь только что предложил использовать sudoing tee:

sudo ls -hal /root/ | sudo tee /root/test.out > /dev/null

Это также может быть использовано для перенаправления любой команды в каталог, к которому у вас нет доступа.Это работает, потому что программа tee фактически является программой "echo to a file", а перенаправление на /dev/null предназначено для того, чтобы остановить ее вывод на экран, чтобы сохранить ее такой же, как в оригинальном надуманном примере выше.

Трюк, который я сам придумал, заключался в следующем

sudo ls -hal /root/ | sudo dd of=/root/test.out

Проблема в том, что команда попадает под 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"
    

Еще одна вариация на эту тему:

sudo bash <<EOF
ls -hal /root/ > /root/test.out
EOF

Или, конечно:

echo 'ls -hal /root/ > /root/test.out' | sudo bash

У них есть (крошечное) преимущество в том, что вам не нужно запоминать никаких аргументов, чтобы sudo или sh/bash

Немного разъясняю, почему вариант с тройником предпочтительнее

Предполагая, что у вас есть соответствующее разрешение на выполнение команды, которая создает выходные данные, если вы передаете выходные данные своей команды tee, вам нужно только повысить привилегии tee с помощью sudo и направить 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 но когда исходная команда представляет собой скрипт, которому вы не полностью доверяете, это имеет решающее значение.

Примечание. вы можете использовать опцию -a для добавления tee для добавления append (например >>) в целевой файл, а не перезаписывать его (например >).

Заставьте sudo запустить оболочку, например, так:

sudo sh -c "echo foo > ~root/out"

Способ, которым я бы подошел к этому вопросу, таков:

Если вам нужно записать / заменить файл:

echo "some text" | sudo tee /path/to/file

Если вам нужно добавить в файл:

echo "some text" | sudo tee -a /path/to/file

Как насчет того, чтобы написать сценарий?

Имя файла:myscript

#!/bin/sh

/bin/ls -lah /root > /root/test.out

# end script

Затем используйте sudo для запуска скрипта:

sudo ./myscript

Я бы сделал это таким образом:

sudo su -c 'ls -hal /root/ > /root/test.out'

Всякий раз, когда мне приходится делать что-то подобное, я просто становлюсь root:

# sudo -s
# ls -hal /root/ > /root/test.out
# exit

Возможно, это не самый лучший способ, но он работает.

Я не хочу бить дохлую лошадь, но здесь слишком много ответов, которые используют tee, что означает, что вы должны перенаправить stdout Для /dev/null если только вы не хотите увидеть копию на экране.Более простым решением является просто использование cat вот так:

sudo ls -hal /root/ | sudo bash -c "cat > /root/test.out"

Обратите внимание, как перенаправление помещается в кавычки, чтобы оно оценивалось оболочкой, запускаемой sudo вместо того, кто им управляет.

Это основано на ответе, включающем 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 "Found dangerous argument ‘$arg’. Will exit."
        exit 2
    fi
done
sudo tee "$@" > /dev/null

Как показано на рисунке ИСПОЛЬЗОВАНИЕ в коде все, что вам нужно сделать, это передать выходные данные в этот скрипт, за которым следует желаемое имя файла, доступное суперпользователю, и он автоматически запросит у вас пароль, если это необходимо (поскольку он включает sudo).

echo test | suwrite /root/test.txt

Обратите внимание, что, поскольку это простая оболочка для tee, он также будет принимать тройники -a возможность добавления, а также поддерживает запись в несколько файлов одновременно.

echo test2 | suwrite -a /root/test.txt
echo test-multi | suwrite /root/test-a.txt /root/test-b.txt

Он также имеет некоторую упрощенную защиту от записи в /dev/ устройства, которые вызывали озабоченность, упомянутые в одном из комментариев на этой странице.

Может быть, вам был предоставлен доступ sudo только к некоторым программам / путям?Тогда нет никакого способа делать то, что вы хотите.(если только вы не взломаете это каким-то образом)

Если это не так, то, возможно, вы сможете написать скрипт bash:

cat > myscript.sh
#!/bin/sh
ls -hal /root/ > /root/test.out 

Пресса ctrl + d :

chmod a+x myscript.sh
sudo myscript.sh

Надеюсь, это поможет.

sudo at now  
at> echo test > /tmp/test.out  
at> <EOT>  
job 1 at Thu Sep 21 10:49:00 2017  
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top