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

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

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

我刚刚收到回复:

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

我怎样才能让它工作呢?


当前回答

我自己发现的一个把戏

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

其他回答

我会这样做:

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

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

有多种解决方案:

Run a shell with sudo and give the command to it by using the -c option: sudo sh -c 'ls -hal /root/ > /root/test.out' Create a script with your commands and run that script with sudo: #!/bin/sh ls -hal /root/ > /root/test.out Run sudo ls.sh. See Steve Bennett's answer if you don't want to create a temporary file. Launch a shell with sudo -s then run your commands: [nobody@so]$ sudo -s [root@so]# ls -hal /root/ > /root/test.out [root@so]# ^D [nobody@so]$ Use sudo tee (if you have to escape a lot when using the -c option): sudo ls -hal /root/ | sudo tee /root/test.out > /dev/null The redirect to /dev/null is needed to stop tee from outputting to the screen. To append instead of overwriting the output file (>>), use tee -a or tee --append (the last one is specific to GNU coreutils).

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

每当我要做这样的事情时,我就变成root:

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

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

问题是命令在sudo下运行,而重定向在您的用户下运行。这是由shell完成的,对此您几乎无能为力。

sudo command > /some/file.log
`-----v-----'`-------v-------'
   command       redirection

通常绕过这个的方法是:

Wrap the commands in a script which you call under sudo. If the commands and/or log file changes, you can make the script take these as arguments. For example: sudo log_script command /log/file.txt Call a shell and pass the command line as a parameter with -c This is especially useful for one off compound commands. For example: sudo bash -c "{ command1 arg; command2 arg; } > /log/file.txt" Arrange a pipe/subshell with required rights (i.e. sudo) # Read and append to a file cat ./'file1.txt' | sudo tee -a '/log/file.txt' > '/dev/null'; # Store both stdout and stderr streams in a file { command1 arg; command2 arg; } |& sudo tee -a '/log/file.txt' > '/dev/null';

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

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

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

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