如何将shell执行封装到函数中

如何将shell执行封装到函数中

我有一个需要执行许多命令的脚本,并且我希望能够将执行封装为函数

示例函数如下

#!/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/path/to/grep命令的 shell 语法,第一个带有redis-cliinfo作为两个单独的参数,第二个带有grepcluster_enabled作为两个单独的参数,同时使用管道连接第一个的标准输出和第二个的标准输入。

$cmd,当您使用 in$(cmd 2>&1)扩展$cmd变量时,是否对其进行 IFS 分割(请注意,它与 shell 在解析命令行时所做的操作无关,除了空格和制表符之外,默认值$IFS也恰好是 token shell 语法中的分隔符),然后是文件名生成(所谓的 split+glob),并执行从第一个结果单词派生的命令,并将所有单词作为参数。因此,它既不评估 中的代码,也不运行您需要$cmd的名称存储在 中的命令。$cmd"$cmd"

因此,您似乎想要将传递给函数的参数作为 shell 语法中的代码进行计算,而不是执行命令。

此外,exec它已经是 shell 的一个特殊内置函数,并且对于多个 shell(包括 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"

相关内容