sh は親シェルで bash コードを評価し、それを分離します。

sh は親シェルで 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_internalshを実行した後、明らかに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プロセスが親シェル/環境からbashコードを取得しようとする理由を理解できません。

この動画で問題がより明確になることを願っています。

に電話すると、unset -f r2g問題はすぐに解決されます。だから私のr2g関数が呼び出されているようですが、/bin/sh方法と理由がわかりません。

以下は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は必要ありませんが、このシェルスクリプトがBashを要求しているような場合は、次のようにします。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の出力を標準入力から読み取るスクリプトに送信しようとしています。 'を使用する必要があります。|'>'の代わりに'.

もう1つのバグ - 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 )

関連情報