Bash 使用eval通过ssh运行sqlite时出现语法错误
当我想在bash脚本中运行这个sqllite3命令时,我收到了错误消息。 非常感谢您的帮助Bash 使用eval通过ssh运行sqlite时出现语法错误,bash,Bash,当我想在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 loo
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:
命令的这一部分:
/out.csv\”
看起来它的结尾有一个额外的引号
“
,如果是这样,解释器会认为它是一个新的(但未终止的)字符串的开始 你的情况已经相当复杂了。不要试图将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"
这就是说,将代码保存在字符串中并评估它们是而不是最佳实践。取而代之的是,考虑使用函数作为局部评估的一部分:
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
}
现在,为什么所有的printf%q
?首先,这意味着您不需要自己做所有的引用(正如您可能已经注意到的,正确引用多个嵌套的评估级别是很困难的!)。第二:安全原因
想一想如果你的程序运行时带有一个参数'$(rm-rf/)'
——你永远都不希望你的脚本能够运行cd~/test/emane/gvine/node-$(rm-rf/)
;使用printf%q
构建eval-safe字符串可确保内容始终安全转义
下一个问题:为什么将一些东西(如>out.csv
,放在printf%q
的外部)作为常量是安全的?因为:
- 这些片段包含shell语法,
printf%q
将通过安全转义转换为数据,使它们不再作为shell的指令
- 数据组件是常量。如果
out.csv
改为$2.csv
,那么我们希望使用printf%q
来转义“$2”
部分
另外,BashFAQ#50:通过ssh传递命令已经将它们暴露于一层eval
处理中。在上面加上第二个是把已经很容易出错的东西混合起来。这是真的,但它甚至还没有接近问题的全部。
run_remote_sql 10