シェル実行を関数としてカプセル化する方法

シェル実行を関数としてカプセル化する方法

私は多くのコマンドを実行する必要があるスクリプトを持っており、それを実行できるようにしたいです。実行を関数にカプセル化する

サンプル関数は次のとおりです。

#!/bin/bash

cmd="redis-cli info | grep cluster_enabled"
cmd1="cmd1"
cmd2="cmd2"

exec(){
    local cmd=$1
    EXEC_RET=$($cmd 2>&1)
    EXEC_STATUS=$?
    echo "$EXEC_RET"
    echo "$EXEC_STATUS"
}

main(){
    exec "$cmd"
}

main "$@"

ただし、実行後、次のエラーが報告されます。

$ bash test.sh
ERR syntax error
0

ただし、実行コマンドを抽出しないと、エラーは報告されません。

exec(){
    EXEC_RET=$(redis-cli info | grep cluster_enabled 2>&1)
    EXEC_STATUS=$?
    echo "$EXEC_RET"
    echo "$EXEC_STATUS"
}
main(){
    exec 
}

main "$@"

# stdout
$ bash temp.sh 
cluster_enabled:1
0

このエラーの原因と解決策は何ですか?これにご協力いただきありがとうございます。

ベストアンサー1

redis-cli info | grep cluster_enabled/path/to/redis-cliand コマンドを実行するためのシェル構文です/path/to/grep。最初は2 つredis-cliinfo個別パラメータ、2 番目はgrep2cluster_enabledつの個別パラメータで、パイプを使用して 1 番目の Enter の標準出力と 2 番目の Enter の標準を連結します。

$cmd、inを使用して変数$(cmd 2>&1)を拡張するときに変数をIFSに分割するかどうか$cmd(スペースとタブに加えてコマンドラインを解析するときにシェルが実行する操作とは無関係で、デフォルトもトークンシェル構文$IFS区切り文字です)ファイル名の生成(いわゆる分割+glob)と最初の結果の単語から派生したコマンドを実行し、すべての単語を引数として使用します。したがって、 のコードを評価せず、$cmdに保存された名前を必要とするコマンドを実行しません。$cmd"$cmd"

したがって、コマンドを実行する代わりに、関数に渡された引数をシェル構文のコードとして評価したいと思います。

さらに、execこれはすでにシェルの特別な組み込み関数であり、複数のシェル(bashを含む)の場合は、shPOSIXモードで、またはより一般的に呼び出されたときに関数としてオーバーライドすることはできません。

だから

run(){
    local shell_code="$1"
    RUN_STDOUT_AND_ERR=$(eval " $shell_code" 2>&1)
    RUN_STATUS="$?"
    printf '%s\n' "$RUN_STDOUT_AND_ERR" "$RUN_STATUS"
    return "$RUN_STATUS"
}

run "$cmd"

おすすめ記事