我有一个需要执行许多命令的脚本,并且我希望能够将执行封装为函数。
示例函数如下
#!/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-cli
和info
作为两个单独的参数,第二个带有grep
和cluster_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"