sh 正在评估父 shell 中的 bash 代码,并进行分解

sh 正在评估父 shell 中的 bash 代码,并进行分解

我有这个代码巴什脚本:

r2g(){

   echo "executable is: $0"  # "/bin/bash"

  (
      set -e;
      r2g_internal "$@" \
       2> >( while read line; do echo "r2g error: $line"; done ) \
       1> >( while read line; do echo "r2g: $line"; done )
  )

    exit_code="$?"
    if [[ "$exit_code" != "0" ]]; then
        echo "something experienced an error, to see log, run: r2g_view_log";
        return 1;
    fi
}

发生的情况是,r2g_internal运行后,sh 由某个进程启动,它显然试图为 bash 环境提供资源,我从 sh 中得到了他奇怪的语法错误:

r2g error: sh: r2g: line 2: syntax error near unexpected token `>'
r2g error: sh: r2g: line 2: ` r2g_internal "$@" 2> >( while read line; do echo "r2g error: $line"; done ) > >( while read line; do echo "r2g: $line"; done ) );'
r2g error: sh: error importing function definition for `r2g'

我制作了一个视频来演示这个问题: https://www.uselooom.com/share/82f23ebfe6754412a20be057957e45f4

以及后续视频: https://www.uselooom.com/share/0465c2857cc244879b52b7bdb516243e

运行时npm install,某些sh进程必须由 .. 启动npm。有时,当我运行 git 命令时git,似乎也会启动一个sh进程,并且在这种情况下,终端中会显示相同类型的语法错误。

我不明白为什么通过 bash 启动的 sh 进程会尝试从父 shell/env 获取一些 bash 代码?

该视频使问题更加清晰(我希望)。

如果我打电话unset -f r2g,问题就会立即消失。所以我猜/bin/sh正在调用我的 r2g 函数,但我不知道如何或为什么。

这是 r2g 和 r2g_internal 的源代码: https://gist.github.com/ORESoftware/0fa7e3d6b75a65b17b6b126a7bec3397

答案1

这可能无法解决您的问题,只需花点时间做一些笔记,评论太长了:

  • 如果您不需要这样做,请不要这样做结构您的代码作为一行,我引用:

    r2g_internal "$@"  2> >( while read line; do echo "r2g error: $line"; done ) 1> >( while read line; do echo "r2g: $line"; done )
    

    对于其他人来说,甚至对你来说,我怀疑它都是难以阅读的。

  • 我将从头开始:

    我没有看到舍邦喜欢:

    #!/bin/bash
    

    或者

    #!/bin/sh
    

    等等。

  • 如果您不需要 Bash,但此 shell 脚本似乎需要它,请使用POSIX sh出于便携性目的。

  • 由于exit_code仅使用一次,因此您可以避免它。

  • 您无需始终引用数字。在这种情况下"$?"

  • 避免 Bash 特定的[[ .. ]],并使用经典的测试命令。在这种情况下:

    if [ $? -ne 0 ]
    
  • 您不需要在行尾添加分号,您可以使用如下结构:

    if [ $? -ne 0 ]
    then
        echo "something experienced an error, to see log, run: r2g_view_log"
        return 1
    fi
    
  • 使用-r开关与read.阅读有关此主题的更多信息这里

  • 我还做了一些调整,请检查一下。

  • 我不确定这是否是故意的,但我想不是故意的;return 1从我看来,你用过的地方应该是exit 1

  • 舍邦可以包含set -e如下内容:

    #!/bin/bash -e
    

根据上面重写:

#!/bin/bash -e

r2g()
{

    echo "executable name is: $0"

    r2g_internal "$@" 2> >( while read -r line; do echo "r2g error: $line"; done ) >( while read -r line; do echo "r2g: $line"; done )

    if [ $? -ne 0 ]
    then
        echo "something experienced an error, to see log, run: r2g_view_log"
        exit 1
    fi

}

答案2

无意冒犯,但您是否尝试过阅读并理解错误消息:

意外标记 ` 附近出现语法错误>'

它明确告诉您的代码包含明显的错误:2> >(。 '>' 是将标准输出直接写入文件。您正在尝试将 r2g_internal 的输出定向到从标准输入读取的脚本。您必须使用 '|'而不是'>'。

还有一个错误 - 您可以将 stdout 和 stderr 定向到单独的文件,但不能轻松地将它们定向到单独的脚本。您必须先将它们写入文件,然后单独处理它们。

r2g_internal "$@" 1> stdout.txt 2> stderr.txt
cat stderr.txt | ( while read line; do echo "r2g error: $line"; done )
cat stdout.txt | ( while read line; do echo "r2g: $line"; done )

相关内容