it-swarm.cn

如何使用Sudo将输出重定向到我无权写入的位置?

我已经在我们的一个开发RedHat linux盒子上获得了Sudo访问权限,我似乎发现自己经常需要将输出重定向到我通常没有写入权限的位置。

麻烦的是,这个人为的例子不起作用:

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

我刚收到回复:

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

我怎样才能让它发挥作用?

786
Jonathan

您的命令不起作用,因为您的Shell执行重定向,但没有写入/root/test.out的权限。输出 的重定向不是 由Sudo执行。

有多种解决方案:

  • 使用Sudo运行Shell并使用-c选项向其发出命令:

    Sudo sh -c 'ls -hal /root/ > /root/test.out'
    
  • 使用您的命令创建脚本并使用Sudo运行该脚本:

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

    运行Sudo ls.sh。如果您不想创建临时文件,请参阅Steve Bennett的 回答

  • 使用Sudo -s启动Shell然后运行命令:

    [[email protected]]$ Sudo -s
    [[email protected]]# ls -hal /root/ > /root/test.out
    [[email protected]]# ^D
    [[email protected]]$
    
  • 使用Sudo tee(如果在使用-c选项时必须进行大量转义):

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

    重定向到/dev/null需要停止 tee 从输出到屏幕。要append而不是覆盖输出文件(>>),请使用tee -atee --append(最后一个特定于 GNU coreutils )。

感谢 JdAdam J. ForsterJohnathan 第二,第三和第四个解决方案。

1096
Cristian Ciupitu

这里有人刚建议sudoing tee:

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

这也可用于将任何命令重定向到您无权访问的目录。它的工作原理是因为tee程序实际上是一个“回显到文件”程序,重定向到/ dev/null是为了阻止它也输出到屏幕以保持它与上面原始设计的例子相同。

91
Jonathan

我弄清楚自己的一招

Sudo ls -hal /root/ | Sudo dd of=/root/test.out
71
rhlee

问题是 命令 Sudo下运行,但 重定向 在你的用户下运行。这是由Shell完成的,你几乎无能为力。

Sudo command > /some/file.log
`-----v-----'`-------v-------'
   command       redirection

绕过这个的常用方法是:

  • 将命令包装在您在Sudo下调用的脚本中。

    如果命令和/或日志文件发生更改,则可以使脚本将这些作为参数。例如:

    Sudo log_script command /log/file.txt
    
  • 调用Shell并使用-c将命令行作为参数传递

    这对于一个复合命令特别有用。例如:

    Sudo bash -c "{ command1 arg; command2 arg; } > /log/file.txt"
    
41
dsm

关于主题的又一个变种:

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

或者当然:

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

它们具有(微小)优势,您无需记住Sudosh/bash的任何参数

20
Steve Bennett

澄清为什么T恤选项更合适

假设您具有执行创建输出的命令的适当权限,如果您将命令的输出传递给tee,则只需要使用Sudo提升tee的权限并直接将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追加(如>>)附加到目标文件而不是覆盖它(如>)。

18
jg3

让Sudo运行一个Shell,如下所示:

Sudo sh -c "echo foo > ~root/out"
16
Penfold

我对这个问题的看法是:

如果您需要编写/替换文件:

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

如果您需要附加到文件:

echo "some text" | Sudo tee -a /path/to/file
9
Nikola Petkanski

写脚本怎么样?

文件名:myscript

#!/bin/sh

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

# end script

然后使用Sudo运行脚本:

Sudo ./myscript
5
Jd

我会这样做:

Sudo su -c 'ls -hal /root/ > /root/test.out'
4
fardjad

每当我必须做这样的事情时,我才会成为根:

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

这可能不是最好的方式,但它确实有效。

3
Adam J. Forster

不要打败死马,但这里有太多的答案使用tee,这意味着你必须将stdout重定向到/dev/null,除非你想在屏幕上看到一个副本。一个更简单的解决方案就是像这样使用cat

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

注意重定向如何放在引号内,以便由Sudo启动的Shell而不是运行它的Shell进行评估。

3
haridsv

这基于涉及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 "[email protected]" ; do
    if [ ${arg#/dev/} != ${arg} ] ; then
        echo "Found dangerous argument ‘$arg’. Will exit."
        exit 2
    fi
done
Sudo tee "[email protected]" > /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/设备,这是本页评论中提到的一个问题。

2
jamadagni

也许你只能获得一些程序/路径的Sudo访问权限?然后没有办法做你想要的。 (除非你以某种方式破解它)

如果不是这样,那么也许你可以编写bash脚本:

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

按 ctrl + d :

chmod a+x myscript.sh
Sudo myscript.sh

希望它有所帮助。

1
user15453
Sudo at now  
at> echo test > /tmp/test.out  
at> <EOT>  
job 1 at Thu Sep 21 10:49:00 2017  
0
user8648126