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

如何执行存储为带引号和星号的字符串的bash命令,bash,scripting,escaping,quotes,Bash,Scripting,Escaping,Quotes,我尝试执行以下命令: 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

我尝试执行以下命令:

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]
(...)
我猜我在引用中犯了一些明显的错误,但我无法找出问题所在

您是否尝试过:

eval $cmd
接下来的问题是如何转义*,因为它在裸字符串或双引号字符串中有特殊意义:使用单引号

MYSQL='mysql AMORE -u username -ppassword -h localhost -e'
QUERY="SELECT "'*'" FROM amoreconfig" ;# <-- "double"'single'"double"
eval $MYSQL "'$QUERY'"
另外,它还读得很好:evalmysql查询-

试试这个

$ 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"'

你甚至不需要评估。只要在绳子前面放一个美元符号:

cmd="ls"
$cmd

使用数组,而不是字符串,如中所示

使用字符串是非常糟糕的安全实践:考虑查询中的密码或WHERE子句或任何其他组件是用户提供的情况;您不想评估包含$rm-rf的密码

只是运行一个本地命令 明确打印命令 通过SSH方法1运行命令:使用Stdin

谢谢,它起作用了。我把另一个答案标为被接受的答案,因为它之前就已经出现了。从某种程度上说,它起作用了,但效果很差。需要是eval$cmd,而不是eval$cmd,以处理任何分词组件都可以全局扩展到当前目录中的文件的情况,或者IFS中的字符不能无害地替换其他字符的情况。如果eval’ed字符串的任何输入是用户提供的,则此解决方案存在命令注入安全漏洞的风险。@CharlesDuffy提供的解决方案要好得多。谢谢,它很有效。如何选择所有列?如何转义“*”?有关此用法的安全隐患的讨论,请参见BashFAQ 48:…eval语句中的文字引号,当它们通过使用eval变成语法时,可以通过数据中的任何文字引号撤消其效果;因此,它们不能提供有效的安全性。@joshmcode,…如果我们想让运行脚本的部署系统具有注入漏洞,这些脚本是根据ServerFault的建议构建的。获取正确的细节很重要。我遇到过的最糟糕的数据丢失事件是,有人在处理只能包含十六进制数字的文件名时没有使用足够的引号。直到有一天,由于一个构建文件的程序中出现了一个错误,该程序将随机内存内容转储到用作名称的缓冲区中,而该脚本负责删除已删除数月的账单数据。@joshmcode,是的,这在这里很重要-eval$cmd与eval$cmd不同,它将您的输入拆分为单词,将每个单词作为一个glob进行计算,然后用空格将它们粘贴在一起,这样一个包含空格和星号的命令可能会导致计算当前工作目录文件名中的shell扩展;我特别喜欢这样:如果你的脑袋太高,以至于你仍然认为你需要在运行之前写出你要运行的每个命令——我想知道,这篇文章的作者会如何解决一个脚本,在这个脚本中,你动态地构造一个命令,并显式地想要回显它——以便提示用户你想运行这个命令吗?运行之前?..@sdaau,取决于使用常见问题解答中给出的方法。对于函数,可以使用declare-f打印其文本;对于数组,典型的动态构造方法是:printf'%q'${array[@]};顺便说一句,最佳实践方法不是将命令存储为字符串。如果要动态构造它,请使用数组。使用eval,正如前面的答案所做的那样,会带来巨大的安全风险,如果任何内容被参数化,就会导致shell注入攻击。@DennisWilliamson-我喜欢在[big]shell中使用if for a-dryrun功能,该功能有多个阶段,用户可能会跳过。有意义??仅适用于极其简单的命令;对于OP在他们的示例中给出的一个不起作用。请阅读grok why。这对我来说适用于nodejs工具,而不是“$cmd”@PauloOliveira,这是因为您之前尝试的是捕获命令的输出,将输出分解为文字,并将这些单词作为另一个命令本身运行。在GitBash中不起作用。如果您只是想要一个硬编码的文本,为什么还要使用eval,而不是只运行mysql[…]?使用常量文本的eval毫无意义!考虑查询中没有密码的情况。想想它有多有用。@DavidBeckwith,为什么有安全漏洞的方法比没有安全漏洞的方法更有用?它增加了什么好处?您仍然可以动态构造数组;您只需获得一个好处,即不会以与预期不同的方式解析其内容……也就是说:可以运行cmd+=-e$query将这些参数附加到现有数组中,并确保
ry将作为单个参数添加到-e中,并传递给mysql;无需查看其内容来确定它是否生成子shell或转义其引用并启动rootkit或其他任何内容。如果您有安全漏洞,则更令人兴奋。我。。。我真的不知道我能对此说些什么。除了请不要申请和我一起工作。或者,也许,请不要申请在任何地方生产我使用的产品。
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'
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"
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"