代码之家  ›  专栏  ›  技术社区  ›  Jonathan

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

  •  760
  • Jonathan  · 技术社区  · 16 年前

    我已经在我们的一个开发Redhat Linux设备上获得了sudo访问权,我似乎经常需要将输出重定向到我通常没有写访问权的位置。

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

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

    我刚收到回复:

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

    我怎样才能让这个工作?

    15 回复  |  直到 16 年前
        1
  •  1061
  •   Community Dunja Lalic    7 年前

    您的命令不起作用,因为重定向是由没有写入权限的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 . 看史蒂夫·班纳特的 answer 如果不想创建临时文件。

    • 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 从输出到屏幕。到 追加 而不是重写输出文件 ( >> )、使用 tee -a tee --append (最后一个特定于 GNU coreutils )

    谢谢 Jd , Adam J. Forster Johnathan 对于第二、第三和第四个解决方案。

        2
  •  86
  •   Jonathan    7 年前

    这里有人刚刚推荐了sudoing tee:

    sudo ls -hal /root/ | sudo tee /root/test.out > /dev/null
    

    这也可以用于将任何命令重定向到您无权访问的目录。它之所以有效,是因为tee程序实际上是一个“回显到文件”程序,而重定向到/dev/null是为了停止它同时输出到屏幕,使其与上面的原始人为示例保持一致。

        3
  •  70
  •   rhlee    13 年前

    我自己发现的一个诀窍是

    sudo ls -hal /root/ | sudo dd of=/root/test.out
    
        4
  •  41
  •   wisbucky Ishan    6 年前

    问题是 命令 运行下 sudo 但是 重定向 在您的用户下运行。这是由壳牌公司完成的,你几乎无能为力。

    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"
      
        5
  •  19
  •   Steve Bennett    11 年前

    这一主题的另一个变化是:

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

    当然,

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

    他们的优势很小,你不需要记住 sudo sh / bash

        6
  •  17
  •   jg3    11 年前

    解释一下为什么选择发球

    假设您有适当的权限执行创建输出的命令,那么如果您将命令的输出通过管道传输到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 但是当源命令是一个您不完全信任的脚本时,它是至关重要的。

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

        7
  •  15
  •   Jonathon Reinhart    16 年前

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

    sudo sh -c "echo foo > ~root/out"
    
        8
  •  7
  •   Nikola Petkanski    8 年前

    我处理这个问题的方式是:

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

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

    如果需要附加到文件:

    echo "some text" | sudo tee -a /path/to/file
    
        9
  •  5
  •   JD    16 年前

    写剧本怎么样?

    文件名:myscript

    #!/bin/sh
    
    /bin/ls -lah /root > /root/test.out
    
    # end script
    

    然后使用sudo运行脚本:

    sudo ./myscript
    
        10
  •  4
  •   fardjad    11 年前

    我会这样做:

    sudo su -c 'ls -hal /root/ > /root/test.out'
    
        11
  •  3
  •   Adam J. Forster    16 年前

    每当我要做这样的事情时,我都会变得根深蒂固:

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

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

        12
  •  3
  •   haridsv    8 年前

    不是要打死马,但这里有太多的答案 tee ,这意味着你必须重新定向 stdout /dev/null 除非你想在屏幕上看到副本。一个简单的解决方案是只使用 cat 这样地:

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

    请注意,重定向是如何放在引号内的,以便它由一个由 sudo 而不是运行它的那个。

        13
  •  2
  •   jamadagni    5 年前

    这是基于涉及 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
    

    注意,因为这是 球座 ,它还接受T形三通 -a 附加选项,还支持同时写入多个文件。

    echo test2 | suwrite -a /root/test.txt
    echo test-multi | suwrite /root/test-a.txt /root/test-b.txt
    

    它也有一些简单的保护措施来防止 /dev/ 本页评论中提到的设备。

        14
  •  1
  •   franzlorenzon    11 年前

    也许你只允许sudo访问一些程序/路径?那就没有办法做你想做的事。(除非你以某种方式破解)

    如果不是这样,那么您可以编写bash脚本:

    cat > myscript.sh
    #!/bin/sh
    ls -hal /root/ > /root/test.out 
    

    出版社 CTRL + D :

    chmod a+x myscript.sh
    sudo myscript.sh
    

    希望能有所帮助。

        15
  •  0
  •   templatetypedef    7 年前
    sudo at now  
    at> echo test > /tmp/test.out  
    at> <EOT>  
    job 1 at Thu Sep 21 10:49:00 2017