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

linux permissions sudo io-redirection permission-denied

212510 观看

15回复

15785 作者的声誉

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

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

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

我刚收到回复:

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

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

作者: Jonathan 的来源 发布者: 2008 年 9 月 17 日

回应 (15)


5

0 作者的声誉

写脚本怎么样?

文件名:myscript

#!/bin/sh

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

# end script

然后使用sudo运行脚本:

sudo ./myscript
作者: Jd 发布者: 17.09.2008 11:48

16

2342 作者的声誉

让sudo运行一个shell,如下所示:

sudo sh -c "echo foo > ~root/out"
作者: Penfold 发布者: 17.09.2008 11:48

1124

15434 作者的声誉

决定

您的命令不起作用,因为重定向是由您的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的答案

  • 启动shell 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需要重定向才能阻止T恤输出到屏幕。要追加而不是覆盖输出文件(>>),请使用tee -atee --append(最后一个特定于GNU coreutils)。

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

作者: Cristian Ciupitu 发布者: 17.09.2008 11:48

3

6071 作者的声誉

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

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

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

作者: Adam J. Forster 发布者: 17.09.2008 11:49

1

381 作者的声誉

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

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

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

ctrl+ d

chmod a+x myscript.sh
sudo myscript.sh

希望它有所帮助。

作者: user15453 发布者: 17.09.2008 12:00

94

15785 作者的声誉

这里有人刚建议sudoing tee:

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

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

作者: Jonathan 发布者: 17.09.2008 12:26

40

8994 作者的声誉

问题是该命令在下运行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"
    
作者: dsm 发布者: 23.09.2008 10:10

76

2421 作者的声誉

我弄清楚自己的一招

sudo ls -hal /root/ | sudo dd of=/root/test.out
作者: rhlee 发布者: 21.11.2011 02:24

4

15180 作者的声誉

我会这样做:

sudo su -c 'ls -hal /root/ > /root/test.out'
作者: fardjad 发布者: 21.04.2013 12:33

20

56263 作者的声誉

关于主题的又一个变种:

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

或者当然:

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

它们具有(微小)优势,您不需要记住任何参数sudosh/bash

作者: Steve Bennett 发布者: 13.05.2013 03:53

18

318 作者的声誉

澄清为什么tee选项更可取

假设您具有执行创建输出的命令的适当权限,如果将命令的输出传递给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追加(如>>)附加到目标文件而不是覆盖它(如>)。

作者: jg3 发布者: 02.11.2013 01:51

2

447 作者的声誉

这是基于涉及的答案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

如代码中的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/设备的保护,这是本页评论中提到的一个问题。

作者: jamadagni 发布者: 27.11.2013 04:55

9

3900 作者的声誉

我对这个问题的看法是:

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

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

如果您需要附加到文件:

echo "some text" | sudo tee -a /path/to/file
作者: Nikola Petkanski 发布者: 24.06.2016 07:48

3

4560 作者的声誉

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

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

注意重定向是如何放在引号内的,以便它由一个shell sudo而不是运行它的shell来评估。

作者: haridsv 发布者: 28.07.2016 09:27

0

9 作者的声誉

sudo at now  
at> echo test > /tmp/test.out  
at> <EOT>  
job 1 at Thu Sep 21 10:49:00 2017  
作者: user8648126 发布者: 21.09.2017 10:55
32x32