如何使用 sudo 将输出重定向到我无权写入的位置?
-
09-06-2019 - |
题
我在我们的一台开发 RedHat Linux 机器上获得了 sudo 访问权限,而且我似乎发现自己经常需要将输出重定向到我通常没有写入权限的位置。
问题是,这个人为的例子不起作用:
sudo ls -hal /root/ > /root/test.out
我刚刚收到回复:
-bash: /root/test.out: Permission denied
我怎样才能让它发挥作用?
解决方案
您的命令不起作用,因为重定向是由您的 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
. 。参见史蒂夫·贝内特的 回答 如果您不想创建临时文件。启动一个 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
需要停止 球座 从输出到屏幕。到 附加 而不是覆盖输出文件(>>
), 使用tee -a
或者tee --append
(最后一项具体针对 GNU 核心工具).
其他提示
这里有人刚刚建议 sudoing 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
它们有一个(微小的)优势,那就是你不需要记住任何论点 sudo
或者 sh
/bash
澄清一下为什么 T 恤选项更可取
假设您有适当的权限来执行创建输出的命令,如果您将命令的输出通过管道传输到 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 选项来执行附加操作(例如 >>
)到目标文件而不是覆盖它(例如 >
).
让 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
写个剧本怎么样?
文件名:脚本
#!/bin/sh
/bin/ls -lah /root > /root/test.out
# end script
然后使用 sudo 运行脚本:
sudo ./myscript
我会这样做:
sudo su -c 'ls -hal /root/ > /root/test.out'
每当我必须做这样的事情时,我就会成为root:
# sudo -s
# ls -hal /root/ > /root/test.out
# exit
这可能不是最好的方法,但它确实有效。
并不是要打败一匹马,但这里有太多答案使用 tee
, ,这意味着你必须重定向 stdout
到 /dev/null
除非您想在屏幕上看到副本。一个更简单的解决方案是使用 cat
像这样:
sudo ls -hal /root/ | sudo bash -c "cat > /root/test.out"
请注意如何将重定向放在引号内,以便由以下命令启动的 shell 对其进行评估 sudo
而不是运行它的人。
这是基于涉及的答案 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
如图所示 用法 在代码中,您所要做的就是将输出通过管道传输到此脚本,后跟所需的超级用户可访问的文件名,如果需要,它会自动提示您输入密码(因为它包括 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/
设备,这是本页评论之一中提到的一个问题。
也许您只获得了对某些程序/路径的 sudo 访问权限?那么就没有办法做你想做的事了。(除非你会以某种方式破解它)
如果不是这种情况,那么也许你可以编写 bash 脚本:
cat > myscript.sh
#!/bin/sh
ls -hal /root/ > /root/test.out
按 控制键 + d :
chmod a+x myscript.sh
sudo myscript.sh
希望有帮助。
sudo at now
at> echo test > /tmp/test.out
at> <EOT>
job 1 at Thu Sep 21 10:49:00 2017