提问人:Barth 提问时间:1/5/2010 最后编辑:Stephane RollandBarth 更新时间:4/7/2018 访问量:390996
如何执行存储为带有引号和星号的字符串 [duplicate] 的 bash 命令
How to execute a bash command stored as a string with quotes and asterisk [duplicate]
问:
我尝试执行以下命令:
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]
(...)
我想我对引号做了一些明显错误的事情,但无法找出问题所在。
答:
521赞
slebetman
1/5/2010
#1
你试过吗:
eval $cmd
对于如何逃脱的后续问题,因为它在裸露或双引号字符串时具有特殊含义:使用单引号。*
MYSQL='mysql AMORE -u username -ppassword -h localhost -e'
QUERY="SELECT "'*'" FROM amoreconfig" ;# <-- "double"'single'"double"
eval $MYSQL "'$QUERY'"
奖励:它读起来也不错:eval mysql查询;-)
评论
0赞
Barth
1/5/2010
谢谢,它有效。如何选择所有列?如何转义“*”?
8赞
Charles Duffy
9/19/2015
请参阅 BashFAQ #48 来讨论围绕此用途的安全陷阱:mywiki.wooledge.org/BashFAQ/048
1赞
Charles Duffy
9/19/2015
...语句中的文字引号,当它们通过使用 成为句法时,可以被数据中的任何文字引号所抵消;因此,它们不能提供有效的安全性。eval
eval
6赞
Charles Duffy
10/20/2017
@joshmcode,......如果我们希望部署的系统运行根据 ServerFault 的建议构建的脚本,则存在注入漏洞。正确处理细节很重要。我遇到过的最严重的数据丢失事件是,有人在处理“永远不能”包含十六进制数字以外的任何内容的文件名时没有使用足够的引号。直到有一天,有人这样做了(由于构建文件的程序中的错误,将随机内存内容转储到用作名称的缓冲区中),并且该脚本(负责修剪旧备份)删除了数月的计费数据。
1赞
Charles Duffy
10/20/2017
@joshmcode,(是的,这很重要,-- ,不同,将您的输入拆分为单词,将每个单词评估为一个 glob,然后用空格将它们粘贴回一起,因此带有空格包围的星号的命令可能会导致评估当前工作目录文件名中的 shell 扩展)。eval $cmd
eval "$cmd"
30赞
ghostdog74
1/5/2010
#2
试试这个
$ cmd='mysql AMORE -u root --password="password" -h localhost -e "select host from amoreconfig"'
$ eval $cmd
评论
1赞
Barth
1/5/2010
谢谢,它有效。我将另一个答案标记为已接受的答案,因为它之前出现过。
4赞
Charles Duffy
2/4/2016
就其工作而言,这很糟糕。需要 ,而不是 ,以处理任何单词拆分组件可以 glob 扩展为当前目录中的文件的情况,或者 IFS 中的字符无法无害地替换其他字符的情况。eval "$cmd"
eval $cmd
4赞
jsears
2/26/2016
如果对计算的字符串的任何输入是用户提供的,则此解决方案存在命令注入安全漏洞的风险。@CharlesDuffy提供的解决方案要好得多。
-5赞
Paul Havens
1/28/2015
#3
要消除对 cmd 变量的需求,可以执行以下操作:
eval 'mysql AMORE -u root --password="password" -h localhost -e "select host from amoreconfig"'
评论
6赞
Charles Duffy
8/29/2015
如果你只是要有一个硬编码的文字,为什么要使用,而不是只是运行?eval
mysql [...]
3赞
Sedat Kilinc
1/2/2017
具有常量文字的 eval 毫无意义!
5赞
David Beckwith
8/29/2015
#4
您甚至不需要“eval”。只需在字符串前面放一个美元符号:
cmd="ls"
$cmd
评论
13赞
Charles Duffy
8/29/2015
仅适用于极其简单的命令;不适用于 OP 在他们的示例中给出的那个。
4赞
Charles Duffy
8/29/2015
阅读 mywiki.wooledge.org/BashFAQ/050 以了解原因。
0赞
Paulo Oliveira
3/31/2017
这对我有用,用于 nodejs 工具而不是`$cmd`
0赞
Charles Duffy
4/30/2017
@PauloOliveira,这是因为您之前尝试的是尝试捕获命令的输出,将该输出分解为单词,然后将这些单词作为另一个命令本身运行。
1赞
kyb
3/23/2018
在 GitBash 中不起作用。
84赞
Charles Duffy
8/29/2015
#5
使用 BashFAQ #50 中给出的数组,而不是字符串。
使用字符串是极其糟糕的安全实践:考虑用户提供的情况(或查询中的 where 子句或任何其他组件);您不希望密码包含 !password
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 运行命令(方法 1:使用 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 运行命令(方法 2:命令行)
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"
评论
3赞
David Beckwith
8/30/2015
请考虑查询中没有密码的情况。想想它会有多大用处。
8赞
Charles Duffy
8/30/2015
@DavidBeckwith,为什么有安全漏洞的方法比没有安全漏洞的方法更有用?它增加了什么好处?您仍然可以动态构造数组;您只是获得了不会冒着以与预期不同的方式解析其内容的风险。
4赞
Charles Duffy
8/30/2015
...也就是说:可以运行将这些参数附加到现有数组中,并确保将作为单个参数添加到传递给的数组中;无需查看其内容即可确定它是否生成了子 shell 或转义了其引号并启动了 rootkit 或其他任何东西。cmd+=( -e "$query" )
query
-e
mysql
15赞
David Beckwith
8/31/2015
如果您有安全漏洞,那就更令人兴奋了。
8赞
Charles Duffy
3/29/2017
我。。。真的不知道我能说些什么来回应。除了“请不要申请与我合作”。或者,也许,“请不要申请在任何地方生产我使用的产品”。
评论
declare -f
printf '%q ' "${array[@]}"; echo
eval