私は多くのコマンドを実行する必要があるスクリプトを持っており、それを実行できるようにしたいです。実行を関数にカプセル化する。
サンプル関数は次のとおりです。
#!/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-cli
and コマンドを実行するためのシェル構文です/path/to/grep
。最初は2 つredis-cli
のinfo
個別パラメータ、2 番目はgrep
2cluster_enabled
つの個別パラメータで、パイプを使用して 1 番目の Enter の標準出力と 2 番目の Enter の標準を連結します。
$cmd
、inを使用して変数$(cmd 2>&1)
を拡張するときに変数をIFSに分割するかどうか$cmd
(スペースとタブに加えてコマンドラインを解析するときにシェルが実行する操作とは無関係で、デフォルトもトークンシェル構文$IFS
区切り文字です)ファイル名の生成(いわゆる分割+glob)と最初の結果の単語から派生したコマンドを実行し、すべての単語を引数として使用します。したがって、 のコードを評価せず、$cmd
に保存された名前を必要とするコマンドを実行しません。$cmd
"$cmd"
したがって、コマンドを実行する代わりに、関数に渡された引数をシェル構文のコードとして評価したいと思います。
さらに、exec
これはすでにシェルの特別な組み込み関数であり、複数のシェル(bashを含む)の場合は、sh
POSIXモードで、またはより一般的に呼び出されたときに関数としてオーバーライドすることはできません。
だから
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"