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

Jon*_*han 843 linux permissions sudo permission-denied io-redirection

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

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

sudo ls -hal /root/ > /root/test.out
Run Code Online (Sandbox Code Playgroud)

我刚收到回复:

-bash: /root/test.out: Permission denied
Run Code Online (Sandbox Code Playgroud)

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

Cri*_*itu 1169

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

有多种解决方案:

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

  • 有一个很好的答案告诉您如何在此处分别重定向 STDERR 和 STDOUT:http://stackoverflow.com/questions/692000/how-do-i-write-stderr-to-a-file-while-using-tee- with-a-pipe ... 基本上是`perl -e 'print "STDIN\n"; 打印 STDERR "STDERR\n"; ' > >( tee stdout.log ) 2> >( tee stderr.log >&2 )` (2认同)
  • 你需要做'sudo -E ...'以便在shelled out命令中使用变量(例如在脚本中使用它时). (2认同)
  • 在许多将输出回显到屏幕无害的情况下,可能不需要将tee输出重定向到/ dev / null。例如,仅处理常规命令的输出或小型文本文件的内容时。 (2认同)

Jon*_*han 98

这里有人刚建议sudoing tee:

sudo ls -hal /root/ | sudo tee /root/test.out > /dev/null
Run Code Online (Sandbox Code Playgroud)

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

  • 在许多情况下,即如果普通用户有执行命令的执行并且"only"无法写入所需的输出文件,则可能会省略第一个"sudo"(即,对于命令本身) (5认同)

rhl*_*lee 79

我弄清楚自己的一招

sudo ls -hal /root/ | sudo dd of=/root/test.out
Run Code Online (Sandbox Code Playgroud)

  • 每当你在彼此旁边输入单词`sudo dd`时,你想非常*非常确定后面的参数是正确的(特别是考虑到它的非标准语法).他们没有把它称为"磁盘驱逐舰"...... (22认同)
  • `sudo dd`比上面的`sudo tee/root/file>/dev/null`更好! (14认同)
  • @steve在你了解它是什么之前,一切都是"模糊的".`of`表示*输出文件*和`dd`是Linux和OSX中使用的非常流行的工具(主要用于将图像写入磁盘).这肯定是一个巧妙的技巧. (13认同)
  • dd不是一个奇怪的模糊命令.无论何时需要通过两个块设备之间的缓冲来复制大量数据,都会使用它.语法实际上非常简单,`dd`是命令名,`= = root/test.out`是告诉`dd`输出文件是什么的参数. (12认同)
  • `dd`在这里可能与`tee`同样有用.在这两种情况下,您使用的是一个常见的,众所周知的命令,其目的虽然与其最初的预期目的略有不同,但仍然是众所周知且有充分记录的.虽然`dd`擅长复制大量数据,但它不会少量吸收.它的好处是不会将输出回显到标准输出. (11认同)
  • @ali_m`sudo dd`很危险(我喜欢*"数据驱逐舰"*名称)但是`sudo tee`和`sudo cat`同样能够覆盖驱动器.它应该是'sudo`,它是红旗,但它经常被使用......我真的注意`/ dev/sd ...`或`/ dev /`中的任何东西,它们不是'null`或'0 ` (8认同)
  • 不,不得不学习另一个奇怪的,模糊的命令与奇怪的,模糊的语法(= ...,真的!)不是'更好'. (6认同)
  • 整洁的!不幸的是,附加版本有点冗长:`... | sudo dd of=out oflag=append conv=notrunc` (2认同)
  • 嗯,实际上这根本不一样。dd 默认使用 512 字节的块,它可能会很慢。但是`tee` 试图尽可能快地发送数据。 (2认同)

dsm*_*dsm 41

问题是该命令在下运行sudo,但重定向在您的用户下运行.这是由shell完成的,你可以做的很少.

sudo command > /some/file.log
`-----v-----'`-------v-------'
   command       redirection
Run Code Online (Sandbox Code Playgroud)

绕过这个的常用方法是:

  • 将命令包装在您在sudo下调用的脚本中.

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

    sudo log_script command /log/file.txt
    
    Run Code Online (Sandbox Code Playgroud)
  • 调用shell并将命令行作为参数传递给 -c

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

    sudo bash -c "{ command1 arg; command2 arg; } > /log/file.txt"
    
    Run Code Online (Sandbox Code Playgroud)


Ste*_*ett 21

主题的又一个变种:

sudo bash <<EOF
ls -hal /root/ > /root/test.out
EOF
Run Code Online (Sandbox Code Playgroud)

或者当然:

echo 'ls -hal /root/ > /root/test.out' | sudo bash
Run Code Online (Sandbox Code Playgroud)

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


jg3*_*jg3 18

澄清为什么tee选项更可取

假设您具有执行创建输出的命令的适当权限,如果将命令的输出传递给tee,则只需要使用sudo提升tee的权限并直接将tee写入(​​或追加)到相关文件中.

在问题中给出的示例中,这意味着:

ls -hal /root/ | sudo tee /root/test.out
Run Code Online (Sandbox Code Playgroud)

对于一些更实际的例子:

# 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
Run Code Online (Sandbox Code Playgroud)

在每个示例中,您将获取非特权命令的输出并写入通常只能由root写入的文件,这是您的问题的起源.

这样做是个好主意,因为生成输出的命令不会使用提升的权限执行.这似乎并不重要,echo但是当源命令是一个你不完全信任的脚本时,它是至关重要的.

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

  • 你是对的,乔纳森,我会更新我的答案,以扩展为什么这是一个更好的选择的原因.感谢您提供的有用反馈. (2认同)

Pen*_*old 17

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

sudo sh -c "echo foo > ~root/out"
Run Code Online (Sandbox Code Playgroud)


har*_*dsv 14

并不是说要打败一匹马,但这里有太多答案使用tee,这意味着您必须重定向stdout/dev/null,除非您想在屏幕上看到副本。

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

sudo ls -hal /root/ | sudo bash -c "cat > /root/test.out"
Run Code Online (Sandbox Code Playgroud)

sudo请注意如何将重定向放在引号内,以便由启动的 shell (而不是运行它的 shell)对其进行评估。

  • 我认为它没有得到太多的喜爱,因为它并不比 `sudo bash -c "ls -hal /root &gt; /root/test.out"` 好多少。使用 tee 可以避免需要 shell,而 cat 则不需要。 (7认同)

Nik*_*ski 9

我对这个问题的看法是:

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

echo "some text" | sudo tee /path/to/file
Run Code Online (Sandbox Code Playgroud)

如果您需要附加到文件:

echo "some text" | sudo tee -a /path/to/file
Run Code Online (Sandbox Code Playgroud)

  • 这与上面的答案有何本质不同? (2认同)
  • 它不是“本质上不同”,但它澄清了替换和附加到文件之间的独特用法。 (2认同)
  • 这是我复制到我的备忘单中的答案。 (2认同)

小智 5

写脚本怎么样?

文件名:myscript

#!/bin/sh

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

# end script
Run Code Online (Sandbox Code Playgroud)

然后使用sudo运行脚本:

sudo ./myscript
Run Code Online (Sandbox Code Playgroud)


Ada*_*ter 5

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

# sudo -s
# ls -hal /root/ > /root/test.out
# exit
Run Code Online (Sandbox Code Playgroud)

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


far*_*jad 5

我会这样做:

sudo su -c 'ls -hal /root/ > /root/test.out'
Run Code Online (Sandbox Code Playgroud)

  • 这实际上看起来更简洁,因为您不需要明确指定外壳。 (3认同)