如何执行存储为引号和星号字符串的bash命令

我尝试执行以下命令:

mysql AMORE -u username -ppassword -h localhost -e "SELECT  host  FROM amoreconfig"

我把它存储在一个字符串中:

cmd="mysql AMORE -u username -ppassword -h localhost -e\"SELECT  host  FROM amoreconfig\""

测试它:

echo $cmd
mysql AMORE -u username -ppassword -h localhost -e"SELECT host FROM amoreconfig"

尝试执行以下操作:

$cmd

我得到了mysql的帮助页面:

mysql  Ver 14.14 Distrib 5.1.31, for pc-linux-gnu (i686) using readline 5.1
Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
This software comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to modify and redistribute it under the GPL license
Usage: mysql [OPTIONS] [database]
(...)

我想我做了一些明显的错误与报价,但不能找出是什么问题。

367620 次浏览

你有没有试过:

eval $cmd

对于接下来的问题,如何转义*,因为它在裸字符串或双引号字符串中具有特殊含义:使用单引号。

MYSQL='mysql AMORE -u username -ppassword -h localhost -e'
QUERY="SELECT "'*'" FROM amoreconfig" ;# <-- "double"'single'"double"
eval $MYSQL "'$QUERY'"

额外的好处:它读起来也不错:eval mysql query;-)

试试这个

$ cmd='mysql AMORE -u root --password="password" -h localhost -e "select host from amoreconfig"'
$ eval $cmd

为了消除对cmd变量的需求,你可以这样做:

eval 'mysql AMORE -u root --password="password" -h localhost -e "select host from amoreconfig"'

你甚至不需要“eval”。只要在字符串前面加上一个美元符号:

cmd="ls"
$cmd

使用数组,而不是字符串,就像BashFAQ # 50中给出的指导一样。

使用字符串是极其糟糕的安全实践:考虑这样的情况:password(或查询中的where子句,或任何其他组件)是用户提供的;你不想eval一个包含$(rm -rf .)的密码!


只运行本地命令

cmd=( mysql AMORE -u username -ppassword -h localhost -e "SELECT  host  FROM amoreconfig" )
"${cmd[@]}"

清楚地打印你的命令

cmd=( mysql AMORE -u username -ppassword -h localhost -e "SELECT  host  FROM amoreconfig" )
printf 'Proposing to run: '
printf '%q ' "${cmd[@]}"
printf '\n'

通过SSH执行命令(方法一:使用Stdin)

cmd=( mysql AMORE -u username -ppassword -h localhost -e "SELECT  host  FROM amoreconfig" )
printf -v cmd_str '%q ' "${cmd[@]}"
ssh other_host 'bash -s' <<<"$cmd_str"

通过SSH执行命令(方式二:命令行)

cmd=( mysql AMORE -u username -ppassword -h localhost -e "SELECT  host  FROM amoreconfig" )
printf -v cmd_str '%q ' "${cmd[@]}"
ssh other_host "bash -c $cmd_str"