当我想在bash脚本中运行此sqllite3命令时,我收到错误消息。 我将不胜感激。
DB_CMD="ssh -X node-11 \"cd ~/test/emane/gvine/node-10/ && sqlite3 -header -csv emane_data.db \"select * from rxfile;\" >>./out.csv\\"""
eval $DB_CMD
eval: line 56: unexpected EOF while looking for matching `"' eval: line 57: syntax error: unexpected end of file
sqlite3: Error: too many options:
答案 0 :(得分:2)
你已经有了相当复杂的情况。不要试图将eval
扔进混合物中,或者至少让shell本身完成构建引用的工作。
# put a shell-quoted version of your sqlite command into sqlite_cmd_str
printf -v sqlite_cmd_str '%q ' sqlite3 -header -csv emane_data.db "select * from rxfile;"
# substitute that into remote_cmd_str
remote_command_str="cd ~/test/emane/gvine/node-10/ && ${sqlite_cmd_str} >>out.csv"
# ...now, run that remote command...
ssh -X node-11 "$remote_command_str"
# ...or, if you **really** want to use eval:
printf -v local_cmd_str '%q ' ssh -X node-11 "$remote_command_str"
eval "$local_cmd_str"
这就是说 - 在字符串中保存代码并eval
对其进行保存不是最佳做法。相反,请考虑使用函数进行本地评估:
run_remote_sql() {
local sqlite_cmd_str remote_cd_cmd_str remote_cmd_str
local node_num=$1
printf -v sqlite_cmd_str '%q ' \
sqlite3 -header -csv emane_data.db "select * from rxfile;"
printf -v remote_cd_cmd_str '%q ' \
cd "test/emane/gvine/node-$1"
remote_cmd_str="$remote_cd_cmd_str && $sqlite_cmd_str >>out.csv"
ssh -X "node-$1" "$remote_cmd_str"
}
...定义一个可以调用的函数:
run_remote_sql 10
或者,在远程端进行参数管理:
run_remote_sql() {
printf -v extra_args '%q ' "$@"
ssh -X node-"$1" "bash -s $extra_args" <<'EOF'
cd ~/test/emane/gvine/node-"$1"/ || exit
sqlite3 -header -csv emane_data.db "select * from rxfile;" >>./out.csv
EOF
}
...再次......
run_remote_sql 10
现在,为什么所有printf %q
?首先,这意味着您不需要自己进行所有引用(您可能已经注意到,正确引用多个嵌套评估级别很难!)。第二:安全原因。
考虑如果您的程序使用'$(rm -rf /)'
参数运行会发生什么 - 您不希望脚本能够运行cd ~/test/emane/gvine/node-$(rm -rf /)
;使用printf %q
构建eval-safe字符串可确保始终安全地转义内容。
下一个问题:为什么将>>out.csv
,printf %q
之外的等作为常量放一些东西是安全的?这是因为:
printf %q
将通过安全转义 - 变成数据,使它们不再被shell视为指令。out.csv
改为$2.csv
,那么我们希望使用printf %q
来逃避"$2"
部分。答案 1 :(得分:0)
命令的这一部分:./out.csv\"""
在最后看起来它是一个额外的引用"
,如果是这样,解释器认为它是一个新的(但未终止的)字符串的开头。