【问题标题】:echo -e acts differently when run in a script by root on ubuntuecho -e 在 ubuntu 上由 root 在脚本中运行时的行为不同
【发布时间】:2011-02-25 06:55:30
【问题描述】:

在 ubuntu 9.10 上运行 bash 脚本时,我会从 bash echo 的“-e”选项中获得不同的行为,具体取决于我是否以 root 身份运行。

考虑这个脚本:

$ cat echo-test
if [ "`whoami`" = "root" ]; then
  echo "Running as root" 
fi
echo Testing /bin/echo -e
/bin/echo -e "foo\nbar"
echo Testing bash echo -e
echo -e "foo\nbar"

当以非 root 用户身份运行时,我会看到以下输出:

$ ./echo-test 
Testing /bin/echo -e
foo
bar
Testing bash echo -e
foo
bar

当以 root 身份运行时,我会看到以下输出:

$ sudo ./echo-test 
Running as root
Testing /bin/echo -e
foo
bar
Testing bash echo -e
-e foo
bar

请注意,在最后一种情况下会回显“-e”(倒数第二行是“-e foo”而不是“foo”)。当以 root 身份运行脚本时,echo 命令会像给定“-e”一样运行,如果给定 -e,则回显选项本身。

我可以理解 /bin/echo 和 bash echo 之间在行为上的一些细微差别,但我希望 bash echo 无论哪个用户调用它都表现相同。

有人知道为什么会这样吗?这是 bash echo 中的错误吗?

仅供参考——我正在运行 GNU bash,版本 4.0.33(1)-release (x86_64-pc-linux-gnu)

【问题讨论】:

    标签: bash ubuntu scripting echo


    【解决方案1】:

    Ubuntu 9.10 及更高版本使用 dash 作为默认 shell,而不是 bash。

    Dash 可以被认为是 bash 的轻量级替代品,但它有一些轻微的不兼容性。您应该通过“Shebang”符号明确指定 bash

    【讨论】:

      【解决方案2】:

      查看 POSIXLY_CORRECT 环境变量的值并确定在这两种情况下是否启用 xpg_echo shell 选项可能会很有趣。

      if test -n "${POSIXLY_CORRECT+yes}"; then
          pc="set '$POSIXLY_CORRECT'"
      else
          pc=unset
      fi
      echo POSIXLY_CORRECT: "$pc"
      shopt -q xpg_echo && xe=set || xe=unset
      echo xpg_echo: $xe
      

      这是我用来检查各种组合的测试代码:

      { n=1
      for p in '' p; do
          for x in '' x; do
              for e in '' e; do
                  printf "\nmode: ${p:-_}${x:-_}${e:-_}\n"
                  test -n "$x" && xx=-s || xx=-u
                  bash ${p:+--posix} -c "              shopt $xx xpg_echo
                    test -n \"\${POSIXLY_CORRECT+yes}\" && pc=\"set '\$POSIXLY_CORRECT'\" || pc=unset
                    shopt -q xpg_echo && xe=set || xe=unset
                    echo POSIXLY_CORRECT: \"\$pc\"
                    echo xpg_echo: \$xe
                    echo${e:+ -e} \"$n\n$((n+1))\"
                  "
                  n=$((n+2))
              done
          done
      done
      }
      

      在我的系统上,您的“作为 root”效果在最后一种情况下重现(POSIXLY_CORRECT 和 xpg_echo 均已设置)。

      mode: ___
      POSIXLY_CORRECT: unset
      xpg_echo: unset
      1\n2
      
      mode: __e
      POSIXLY_CORRECT: unset
      xpg_echo: unset
      3
      4
      
      mode: _x_
      POSIXLY_CORRECT: unset
      xpg_echo: set
      5
      6
      
      mode: _xe
      POSIXLY_CORRECT: unset
      xpg_echo: set
      7
      8
      
      mode: p__
      POSIXLY_CORRECT: set 'y'
      xpg_echo: unset
      9\n10
      
      mode: p_e
      POSIXLY_CORRECT: set 'y'
      xpg_echo: unset
      11
      12
      
      mode: px_
      POSIXLY_CORRECT: set 'y'
      xpg_echo: set
      13
      14
      
      mode: pxe
      POSIXLY_CORRECT: set 'y'
      xpg_echo: set
      -e 15
      16
      

      这些行为变化是提倡使用 printf 而非 echo 的主要原因。

      根据系统和shell的不同,有时printf是shell内置命令,有时是外部命令,但其行为一般比echo。

      您可以确定以下每个命令都会产生一个嵌入的换行符,并且没有尾随的换行符:

      printf 'foo\nbar'
      printf '%s\n%s' foo bar
      

      顺便说一句,这显示了我对格式字符串使用单引号的首选风格,以表明其中没有任何奇怪的内容(例如,插入未反映在参数列表中的额外格式说明符的参数扩展)。

      【讨论】:

        【解决方案3】:

        你确定你的用户和 root 都使用 bash 作为他们的 shell 吗? 尝试在脚本中添加“shebang”行(#!/bin/bash)作为第一行,然后再次运行

        【讨论】:

        • #!/bin/bash 在顶部修复它。因此,root 必须使用具有不同回声的不同 shell。这就说得通了。谢谢!
        猜你喜欢
        • 2011-10-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多