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


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

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

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

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

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

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

15 718

15 ответов:

ваша команда не работает, потому что перенаправление выполняется вашей оболочкой, которая не имеет разрешения на запись в /root/test.out. Перенаправление вывода не в исполнении sudo.

есть несколько решений:

  • запустите оболочку с sudo и дайте ему команду с помощью :

    sudo sh -c 'ls -hal /root/ > /root/test.out'
    
  • создайте скрипт с вашими командами и запустите этот скрипт с помощью судо:

    #!/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 (если вы должны бежать много при использовании ):

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

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

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

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

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

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

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

сделать 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

Это, наверное, не лучший способ, но он работает.

вот расширение ответа с участием тройника. Чтобы упростить работу, вы можете сделать небольшой скрипт (я называю его suwrite или вы можете назвать его sutee) и поместить его в /usr / local/bin/ с разрешением +x:

#! /bin/sh
sudo tee $@ > /dev/null

Теперь все, что вам нужно сделать, это передать вывод в этот скрипт с последующим желаемым именем файла, доступным для суперпользователя, и он автоматически предложит вам ввести пароль, если это необходимо (поскольку он включает sudo).

echo test | suwrite /root/test.txt

обратите внимание, что, так как это простая обертка для tee, он также будет принимать tee's-a (или любой другой) вариант, чтобы добавить к нужному файлу вы просто передаете -a:

echo test | suwrite -a /root/test.txt

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

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

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

может быть, вам был предоставлен доступ 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