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

问题是,这个人为的例子不起作用:

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

我刚刚收到回复:

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

我怎样才能让它工作呢?


当前回答

澄清一点为什么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

在这些示例中,您都获取了一个非特权命令的输出,并将其写入到一个通常只能由根用户写入的文件中,这就是问题的根源。

这样做是个好主意,因为生成输出的命令没有使用提升权限执行。对于echo,这似乎无关紧要,但当源命令是一个您不完全信任的脚本时,这是至关重要的。

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

其他回答

我对这个问题的看法是:

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

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

如果你需要追加到文件:

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

这个主题还有另一个变体:

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

或者当然:

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

它们有一个(微小的)优势,即您不需要记住sudo或sh/bash的任何参数

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

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

并不是要白费口功,但是这里有太多的答案使用tee,这意味着您必须将stdout重定向到/dev/null,除非您想在屏幕上看到一个副本。

一个更简单的解决方案是像这样使用cat:

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

请注意重定向是如何放在引号内的,以便由sudo启动的shell而不是运行它的shell来计算它。

澄清一点为什么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

在这些示例中,您都获取了一个非特权命令的输出,并将其写入到一个通常只能由根用户写入的文件中,这就是问题的根源。

这样做是个好主意,因为生成输出的命令没有使用提升权限执行。对于echo,这似乎无关紧要,但当源命令是一个您不完全信任的脚本时,这是至关重要的。

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