0

私は一日中私をブロックしている大きな問題を抱えています.

用途に基づいたさまざまな機能を備えた多数の機能ファイルがあります。SSH、ロギングなど

グローバルなエラー配列にエラーを追加するスクリプトを実行します。別の「exit_functions」ファイルでスクリプトを呼び出すエラー トラップがあります。

この exit_functions ファイルでは、さまざまなことを行いますが、問題があるのは、この配列を実行し、実際にはコマンドである配列要素を引き出すループです。これらのコマンドは、通常の. /path/to/functions_file 構文。

ロギングなどの他のすべての機能は exit_functions ファイルから機能しています。これらの特定の機能だけを呼び出すことはできません。エラーが発生します:

/functions/exit_functions: line 109: closeSSHTunnel /tmp/ssh_tunnel_iA0yj.lck: No such file or directory

現在、killSSHTunnel は、他の関数ファイルが含まれていたのと同じように、以前に含まれていた関数ファイルにある関数です。これらの関数呼び出しを配列から使用した場合にのみ、このエラーが発生します。

適切に説明したかどうかわかりません。他の情報を提供できる場合はお知らせください。


以下の完全な機能コードを編集します。

/functions/exit_functions ファイル: exitTrap (){ local LCL_SCRIPT_ERROR

    if [ $ERR_COUNT_EXIT_FUNCT -gt 0 ]; then
        for LCL_SCRIPT_ERROR in "${ERROR_ARRAY[@]}"; do
            case $LCL_SCRIPT_ERROR in
                SVN_IMPORT      )   # match the SVN_IMPORT error name and search for specific commands to run
                                    exitMsg "$LCL_SCRIPT_ERROR; 111"
                                    executeErrorActions $LCL_SCRIPT_ERROR

                                    exitScript 111
                                    ;;

                *               )   exitMsg "$LCL_SCRIPT_ERROR; 255"
                                    exitScript 255
                                    ;;
            esac
        done
    fi
}

したがって、私のテスト コードは、上記の関数 (exitTrap) を呼び出すエラー状態を導入します。ERROR_ARRAY という名前の配列が既に取り込まれています。

そのため、同じく /functions/exit_functions にある executeErrorActions 関数は、連想配列 ERROR_ACTION_ARRAY をループし、(このテストでは) SVN_IMPORTという名前のキーを探します。このキーが見つかると、':' で区切られた文字列を探します。区切られた各セクションは、このエラー状態が発生したときに実行する個別のコマンドになります。私のテストでは、次のような単一のエントリ (区切り記号なし) があります: *closeSSHTunnel /tmp/ssh_tunnel_iA0yj.lck*

さて、以下の関数では、IFS= と未設定の IFS の間にセクションを含めず、代わりに以下の二重コメント ハッシュを含む 1 行を使用すると正常に動作します。IFS セパレーターを導入して文字列を分割するとすぐに、エラーが発生します。

/functions/exit_functions: 109 行目: closeSSHTunnel /tmp/ssh_tunnel_iA0yj.lck: そのようなファイルまたはディレクトリはありません

executeErrorActions (){
    if [ ! $# -eq 1 ]; then
        return 1
    fi

    local ERROR_NAME=$1
    local ERROR_ACTION

    #ERROR_KEY="SVN_IMPORT"

    for ERROR_ACTION in ${!ERROR_ACTION_ARRAY[@]}; do
        #echo KEY: $i VALUE: ${ERROR_ACTION_ARRAY[$i]}
        if [ $ERROR_NAME == $ERROR_ACTION ]; then

            ##$(${ERROR_ACTION_ARRAY[$ERROR_ACTION]})

            IFS=":"
            for i in ${ERROR_ACTION_ARRAY[$ERROR_ACTION]}; do
                $i
            done
            unset IFS
            return 0
        fi
    done
}

これは、2 つの ':' で区切られたコマンド、上記の同じcloseSSHTunnel関数、および単純なls -la呼び出しを使用したテスト実行の set -x 出力です。以下のように addError 関数呼び出しを使用して、これらを ERROR_ACTION_ARRAY に追加します。

addError SVN_IMPORT closeSSHTunnel $SSH_TUNNEL_LCK_FILE:ls -la

これは set -x の出力です。

+ executeErrorActions SVN_IMPORT
+ '[' '!' 1 -eq 1 ']'
+ local ERROR_NAME=SVN_IMPORT
+ local ERROR_ACTION
+ for ERROR_ACTION in '${!ERROR_ACTION_ARRAY[@]}'
+ '[' SVN_IMPORT == SVN_IMPORT ']'
+ IFS=:
+ for i in '${ERROR_ACTION_ARRAY[$ERROR_ACTION]}'
+ 'closeSSHTunnel /tmp/ssh_tunnel_iA0yj.lck'
/functions/exit_functions: line 116: closeSSHTunnel /tmp/ssh_tunnel_iA0yj.lck: No such file or directory
+ for i in '${ERROR_ACTION_ARRAY[$ERROR_ACTION]}'
+ 'ls -la'
/functions/exit_functions: line 116: ls -la: command not found
+ unset IFS
+ return 0

それらの1つが「そのようなファイルまたはディレクトリはありません」と言い、もう1つが「コマンドが見つかりません」と言っていることに注意してください。これは、これを整理しようとしている2日目です!

私の結論は、IFS の変更と文字列の分割が問題を引き起こしているということです。

編集2

IFS 呼び出しを少し移動し、ループ内の「:」文字で IFS を終了し、実行呼び出しの後に再度確立すると、すべてが機能します!!!!!

for ERROR_ACTION in ${!ERROR_ACTION_ARRAY[@]}; do
        #echo KEY: $i VALUE: ${ERROR_ACTION_ARRAY[$i]}
        if [ $ERROR_NAME == $ERROR_ACTION ]; then
            #$(${ERROR_ACTION_ARRAY[$ERROR_ACTION]})
            IFS=$':'
            for i in ${ERROR_ACTION_ARRAY[$ERROR_ACTION]}; do
                unset IFS
                $i
                IFS=$':'
            done
            unset IFS
            return 0
        fi
done

誰でもこれを説明できますか?

4

2 に答える 2

1

これは、IFS を ":" に設定しているためです。bash は IFS を使用して、変数を個別のコマンドではなく、単語 (つまり、関数名とその引数) に分割します。したがって、引数 で指定closeSSHTunnel /tmp/ssh_tunnel_iA0yj.lckされたコマンドではなく、という名前のコマンドを実行しようとしています。closeSSHTunnel/tmp/ssh_tunnel_iA0yj.lck

$ ERROR_ACTION="echo something"
$ $ERROR_ACTION 
something
$ IFS=":"
$ $ERROR_ACTION 
-bash: echo something: command not found
$ ERROR_ACTION="echo:something"
$ $ERROR_ACTION 
something

複数のコマンドを含めることができるようにしたい場合は、それらを自分で分割する必要があります。

編集:より完全なスクリプトの抜粋を考えると、コマンドを分割するときにIFSを「:」に設定する必要がありますがfor、コマンドを実行すると通常に戻ります:

...
saveIFS="$IFS"
IFS=":"
for i in ${ERROR_ACTION_ARRAY[$ERROR_ACTION]}; do
    IFS="$saveIFS"
    $i
done
IFS="$saveIFS"

これは厳密に必要以上に IFS をリセットしますが、実際にいつリセットする必要があるかを判断するロジックを追加するよりも簡単です (ところで、ループが実行されない場合に備えて最後のリセットがあります)。

于 2013-03-20T14:21:41.297 に答える
0

これが正しい方法かどうかはわかりませんが、文字列を IFS=":" でループし、それを配列に入れてから IFS をリセットしました。次に、そのコマンドの配列をループして実行します。すべての作業。

executeErrorActions (){
    if [ ! $# -eq 1 ]; then
        return 1
    fi

    local ERROR_NAME=$1
    local ERROR_ACTION
    local ACTION_ARRAY
    local ACTION

    if [ ${#ERROR_ACTION_ARRAY[@]} -gt 0 ]; then
        for ERROR_ACTION in ${!ERROR_ACTION_ARRAY[@]}; do
            if [ $ERROR_NAME == $ERROR_ACTION ]; then
                if [ ${#ERROR_ACTION_ARRAY[$ERROR_ACTION]} -gt 0 ]; then
                    IFS=$':'
                    ACTION_ARRAY=( ${ERROR_ACTION_ARRAY[$ERROR_ACTION]} )
                    unset IFS
                    for ACTION in ${!ACTION_ARRAY[@]}; do
                        exitMsg "Running action for $ERROR_ACTION"
                        ${ACTION_ARRAY[$ACTION]}
                        if [ $? -eq 0 ]; then
                            exitMsg "Error action succeeded"
                        else
                            exitMsg "Error action failed"
                            return 1
                        fi
                    done
                    return 0
                else
                    return 1    #no contents in the array element; no actions to run; maybe there should have been; return error
                fi
            else
                return 0    #no matching actions for this error; still return success
            fi
        done
    else
        return 0    #action array is empty
    fi
}
于 2013-03-21T03:04:43.953 に答える