如何使用 sudo 将输出重定向到我没有写权限的位置?

sudo ls -hal /root/ > /root/test.out
-bash: /root/test.out: Permission denied

答案

您的命令不起作用,因为重定向是由您的外壳执行的,该外壳无权写入/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输出到屏幕。要附加而不是覆盖输出文件( >> ),请使用tee -atee --append (最后一个特定于GNU coreutils )。

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

这里有人建议 steeing 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下运行,但是重定向在您的用户下运行。这是由 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任何参数。

澄清为什么最好使用 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无关紧要,但是当 source 命令是您不完全信任的脚本时,它至关重要。

请注意,您可以使用 - a 选项 tee 来将追加(如>> )追加到目标文件,而不是覆盖它(如> )。

使 sudo 运行 shell,如下所示:

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'