Как использовать sudo для перенаправления вывода в местоположение, в которое у меня нет разрешения на запись? - PullRequest
792 голосов
/ 17 сентября 2008

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

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

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

Я только что получил ответ:

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

Как мне заставить это работать?

Ответы [ 15 ]

1108 голосов
/ 17 сентября 2008

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

Благодарю Jd , Адама Дж. Форстера и Джонатана за второе, третье и четвертое решения.

93 голосов
/ 17 сентября 2008

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

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

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

74 голосов
/ 21 ноября 2011

Я понял, что уловка была

sudo ls -hal /root/ | sudo dd of=/root/test.out
41 голосов
/ 23 сентября 2008

Проблема в том, что команда запускается под 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"
    
20 голосов
/ 13 мая 2013

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

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

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

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

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

18 голосов
/ 02 ноября 2013

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

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

16 голосов
/ 17 сентября 2008

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

sudo sh -c "echo foo > ~root/out"
9 голосов
/ 24 июня 2016

Я бы решил об этой проблеме:

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

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

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

echo "some text" | sudo tee -a /path/to/file
5 голосов
/ 17 сентября 2008

Как насчет написания сценария?

Имя файла: myscript

#!/bin/sh

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

# end script

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

sudo ./myscript
4 голосов
/ 21 апреля 2013

Я бы сделал это так:

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