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

我已经在我们的RedHat linux的一个开发箱上获得了sudo访问权限,而且我似乎常常需要将输出重定向到我通常没有写权限的位置。

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

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

我刚收到回复:

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

我怎样才能使这个工作?

您的命令不起作用,因为重定向是由您的shell执行的,而该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然后运行你的命令:

     [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 -atee --append (最后一个特定于GNU coreutils )。

感谢Jd , Adam J. Forster和Johnathan提供了第二,第三和第四个解决方案。

这里有人建议sudoing tee:

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

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

我弄明白了自己的一招

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

问题是命令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 

另一个主题变化是:

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

或者当然:

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

他们有(小)优势,你不需要记住sudosh / bash任何参数

让sudo运行一个shell,像这样:

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

澄清一下为什么T恤选项是可取的

假设你有适当的权限来执行创建输出的命令,如果你将你的命令的输出用管道输出,你只需要用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选项来将追加追加(如>> )到目标文件而不是覆盖它(如> )。

如何编写脚本?

文件名:myscript

 #!/bin/sh /bin/ls -lah /root > /root/test.out # end script 

然后使用sudo来运行脚本:

 sudo ./myscript 

我会去解决这个问题的方法是:

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

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

如果你需要附加到文件:

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

每当我必须做这样的事情,我只是成为根:

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

这可能不是最好的方式,但它的工作原理。

我会这样做:

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

这是涉及三通的答案的延伸。 为了使事情变得更简单,你可能需要创建一个小脚本(我称之为suwrite,或者你可以称它为sutee),并把它放在/ usr / local / bin /中,并且带有+ x权限:

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

现在你所要做的就是将输出传送给这个脚本,然后是所需的超级用户可访问的文件名,如果需要的话它会自动提示你输入你的密码(因为它包括sudo)。

 echo test | suwrite /root/test.txt 

请注意,由于这是一个简单的三通包装,它也将接受三通的-a(或任何其他)选项,以追加到您刚刚传递的所需文件-a:

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

也许你被授予sudo访问只有一些程序/路径? 那么没有办法做你想做的事情。 (除非你会以某种方式破解)

如果不是这样的话,也许你可以写bash脚本:

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

ctrl + d

 chmod a+x myscript.sh sudo myscript.sh 

希望它有帮助。

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

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

请注意,重定向是如何放置在引号内的,以便通过由sudo启动的shell来执行,而不是运行该sudo的shell。

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