【问题标题】:sudo echo "something" >> /etc/privilegedFile doesn't work [duplicate]sudo echo "something" >> /etc/privilegedFile 不起作用[重复]
【发布时间】:2010-09-10 05:41:46
【问题描述】:

这是一个非常简单的问题,至少看起来应该是,关于 Linux 中的 sudo 权限。

很多时候,我只想将某些内容附加到 /etc/hosts 或类似文件,但最终无法做到,因为不允许使用 > 和 >>,即使使用 root 也是如此。

有没有办法让这项工作无需su 或sudo su 进入根目录?

【问题讨论】:

    标签: bash shell scripting permissions sudo


    【解决方案1】:

    使用tee --append 或tee -a。

    echo 'deb blah ... blah' | sudo tee -a /etc/apt/sources.list
    

    确保避免引号内的引号。

    为避免将数据打印回控制台,请将输出重定向到 /dev/null。

    echo 'deb blah ... blah' | sudo tee -a /etc/apt/sources.list > /dev/null
    

    记住 (-a/--append) 标志! 只需 tee 就可以像 > 一样工作,并且会覆盖您的文件。 tee -a 与 >> 类似,将写入文件末尾。

    【讨论】:

    • 我绝对喜欢这个。这只是最简单的(它让我对 tee 感到很困惑,它在其他情况下也很方便)。
    • 我同意。似乎也比开始一个新的 sh 更整洁,尤其是可能与环境等有关的事情。
    • 需要注意的重要一点:永远不要忘记 -a!想象一下echo 'tmpfs /tmp tmpfs defaults 0 0' | sudo tee /etc/fstab 会做什么
    • 在 OS X 下,这应该是 tee -a 而不是 tee --append。
    • 对于那些不明白@mic_e 说了什么的人:没有-a (--append) 标志该命令将覆盖整个文件 使用给定的字符串,而不是将其附加到末尾。
    【解决方案2】:

    问题是 shell 会输出重定向,而不是 sudo 或 echo,所以这是作为您的普通用户完成的。

    试试下面的代码sn-p:

    sudo sh -c "echo 'something' >> /etc/privilegedfile"
    

    【讨论】:

    • 什么是“sudo 权限边界”?出于显而易见的原因,它只是解析重定向运算符的 shell 比命令具有更高的优先级
    • 根据您的sh,echo 可以解释转义序列,如单引号内的\t。你可以改用printf %s 'something'。
    • 使用 tee 更受欢迎,并且更兼容较新的发行版。
    • 这是唯一一个可以在远程节点上执行的 SSH 命令。
    • 我同意这里的其他帖子。这使用了一个 shell,并且只使用了一个 shell,所以这里不需要像 tee 这样的另一个程序。是的,我知道 tee 已经安装了,但可能并不取决于您使用的微型发行版,就像裸骨高山一样。我喜欢你也有一个 shell 选项:例如sudo /bin/bash -c "echo 'fs.inotify.max_user_watches = 524288' > /etc/sysctl.d/60-golang-inotify.conf"。
    【解决方案3】:

    问题在于处理重定向的是你的shell;它正在尝试使用 your 权限而不是您在 sudo 下运行的进程的权限打开文件。

    使用类似的东西,也许:

    sudo sh -c "echo 'something' >> /etc/privilegedFile"
    

    【讨论】:

    • @GordonSun 这是因为sudo(出于安全原因)不会将环境传播到子进程。您可以使用sudo -E 绕过此限制。
    • @GordonSun 是的,它会的,我不明白你为什么一直重复这个声明!如果您使用双引号执行sudo sh -c "echo 'something' >> $FILENAME",则此将起作用-变量替换由外壳完成,而不是由sudoed shell完成。
    【解决方案4】:
    sudo sh -c "echo 127.0.0.1 localhost >> /etc/hosts"
    

    【讨论】:

      【解决方案5】:

      在做

      sudo sh -c "echo >> somefile"
      

      应该可以。问题是 > 和 >> 由您的 shell 处理,而不是由“sudoed”命令处理,因此权限是您的,而不是您“sudo”进入的用户的权限。

      【讨论】:

        【解决方案6】:

        我会注意到,出于好奇,您也可以引用 heredoc(对于大块):

        sudo bash -c "cat <<EOIPFW >> /etc/ipfw.conf
        <?xml version=\"1.0\" encoding=\"UTF-8\"?>
        
        <plist version=\"1.0\">
          <dict>
            <key>Label</key>
            <string>com.company.ipfw</string>
            <key>Program</key>
            <string>/sbin/ipfw</string>
            <key>ProgramArguments</key>
            <array>
              <string>/sbin/ipfw</string>
              <string>-q</string>
              <string>/etc/ipfw.conf</string>
            </array>
            <key>RunAtLoad</key>
            <true></true>
          </dict>
        </plist>
        EOIPFW"
        

        【讨论】:

        • 这很好用,除了嵌入的引号可能需要用 \ 转义
        • 非常正确@NJones!我将编辑我的答案。 (但是请注意,不这样做会剥离内部",但不会导致命令失败。)
        【解决方案7】:

        在 bash 中,您可以结合使用 tee 和 &gt; /dev/null 来保持标准输出干净。

         echo "# comment" |  sudo tee -a /etc/hosts > /dev/null
        

        【讨论】:

          【解决方案8】:

          使用Yoo's answer,将其放入您的~/.bashrc:

          sudoe() {
              [[ "$#" -ne 2 ]] && echo "Usage: sudoe <text> <file>" && return 1
              echo "$1" | sudo tee --append "$2" > /dev/null
          }
          

          现在你可以运行sudoe 'deb blah # blah' /etc/apt/sources.list


          编辑:

          一个更完整的版本,它允许您通过管道输入或从文件重定向,并包括一个 -a 开关来关闭附加(默认情况下是打开的):

          sudoe() {
            if ([[ "$1" == "-a" ]] || [[ "$1" == "--no-append" ]]); then
              shift &>/dev/null || local failed=1
            else
              local append="--append"
            fi
          
            while [[ $failed -ne 1 ]]; do
              if [[ -t 0 ]]; then
                text="$1"; shift &>/dev/null || break
              else
                text="$(cat <&0)"
              fi
          
              [[ -z "$1" ]] && break
              echo "$text" | sudo tee $append "$1" >/dev/null; return $?
            done
          
            echo "Usage: $0 [-a|--no-append] [text] <file>"; return 1
          }
          

          【讨论】:

            【解决方案9】:

            一些用户在使用多行时不知道解决方案。

            sudo tee -a  /path/file/to/create_with_text > /dev/null <<EOT 
            line 1
            line 2
            line 3
            EOT
            

            【讨论】:

              【解决方案10】:

              通过使用 sed -i 和 $ a ,您可以在最后一行之后附加包含变量和特殊字符的文本。

              例如,将带有 $NEW_IP 的 $NEW_HOST 添加到 /etc/hosts:

              sudo sed -i "\$ a $NEW_IP\t\t$NEW_HOST.domain.local\t$NEW_HOST" /etc/hosts
              

              sed 选项说明:

              • -i 就地
              • $ 最后一行
              • a 用于追加

              【讨论】:

              • 我认为您被否决了,因为只有 GNU sed 允许您在命令后立即放置文本。在 OSX 上,我必须实际使用换行符和 -e 选项:sudo sed -ie '$a\ &gt; export GOOGLE_APPLICATION_CREDENTIALS="adapter-gcp-compute-test-WWWXXXYYYZZZ.json" &gt; ' /Users/gcpclient/.bashrc
              【解决方案11】:

              您也可以使用moreutils 包中的sponge,而无需重定向输出(即,无需隐藏tee 噪音):

              echo 'Add this line' | sudo sponge -a privfile
              

              【讨论】:

                【解决方案12】:

                echo 'Hello World' | (sudo tee -a /etc/apt/sources.list)

                【讨论】:

                  【解决方案13】:

                  怎么样:
                  回显文本 | sudo dd status=none of=privilegedfile
                  我想更改 /proc/sys/net/ipv4/tcp_rmem。
                  我做到了:
                  sudo dd status=none of=/proc/sys/net/ipv4/tcp_rmem 用单行文档消除回声

                  【讨论】:

                  【解决方案14】:

                  这对我有用: 原始命令

                  echo "export CATALINA_HOME="/opt/tomcat9"" >> /etc/environment
                  

                  工作指令

                  echo "export CATALINA_HOME="/opt/tomcat9"" |sudo tee /etc/environment
                  

                  【讨论】:

                  • 应该是tee -a。只需tee 将覆盖该文件!
                  【解决方案15】:

                  您可以更改文件的所有权,然后在使用cat &gt;&gt; 追加后将其更改回来吗?

                  sudo chown youruser /etc/hosts  
                  sudo cat /downloaded/hostsadditions >> /etc/hosts  
                  sudo chown root /etc/hosts  
                  

                  这样的东西适合你吗?

                  【讨论】:

                  • Chown 是一个破坏性的命令。如果配置管理器使用它来更新 /etc/hosts,突然 /etc/hosts 属于配置用户而不是 root。这可能会导致其他进程无法访问 /etc/hosts。 sudo 的全部意义在于避免将某些内容登录到 root,并且通过 sudoers 还可以增加更多限制。
                  猜你喜欢
                  • 2017-10-02
                  • 2018-08-14
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-01-12
                  • 1970-01-01
                  • 2017-01-10
                  • 1970-01-01
                  相关资源
                  最近更新 更多