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

Bar*_*rth 237 bash quotes scripting escaping

我尝试执行以下命令:

mysql AMORE -u username -ppassword -h localhost -e "SELECT  host  FROM amoreconfig"
Run Code Online (Sandbox Code Playgroud)

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

cmd="mysql AMORE -u username -ppassword -h localhost -e\"SELECT  host  FROM amoreconfig\""
Run Code Online (Sandbox Code Playgroud)

测试一下:

echo $cmd
mysql AMORE -u username -ppassword -h localhost -e"SELECT host FROM amoreconfig"
Run Code Online (Sandbox Code Playgroud)

尝试执行:

$cmd
Run Code Online (Sandbox Code Playgroud)

我得到了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]
(...)
Run Code Online (Sandbox Code Playgroud)

我想我正在做一些关于引号的错误但却无法找出问题所在.

sle*_*man 354

你有没有尝试过:

eval $cmd
Run Code Online (Sandbox Code Playgroud)

关于如何逃避的后续问题,*因为它在裸体或双引号字符串中具有特殊含义时:使用单引号.

MYSQL='mysql AMORE -u username -ppassword -h localhost -e'
QUERY="SELECT "'*'" FROM amoreconfig" ;# <-- "double"'single'"double"
eval $MYSQL "'$QUERY'"
Run Code Online (Sandbox Code Playgroud)

奖励:它也读得很好:eval mysql查询;-)

  • 有关此用途的安全陷阱的讨论,请参阅 BashFAQ #48:http://mywiki.wooledge.org/BashFAQ/048 (3认同)
  • @joshmcode,...如果我们希望已部署的系统运行基于 ServerFault 的建议构建的脚本具有注入漏洞。获取正确的细节*很重要*。我遇到过的最严重的数据丢失事件是,当有人在处理“永远不可能”包含除十六进制数字以外的任何文件名时没有使用足够的引用。直到有一天 *did*(由于构建文件的程序中的一个错误,将随机内存内容转储到用作名称的缓冲区中),并且该脚本(负责修剪古代备份)删除了数月的计费数据。 (2认同)

Cha*_*ffy 49

使用数组,而不是字符串,如BashFAQ#50中的指导.

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


只运行一个本地命令

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

毫不含糊地打印命令

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

通过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"
Run Code Online (Sandbox Code Playgroud)

通过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"
Run Code Online (Sandbox Code Playgroud)

  • 如果您有安全漏洞,那就更令人兴奋了. (9认同)
  • 我...真的不知道我能回答的是什么.除了"请不要申请与我合作".或者,也许,"请不要申请任何地方制作我使用的产品". (6认同)
  • @DavidBeckwith,为什么具有安全漏洞的方法比没有安全漏洞的方法更有用?它增加了什么好处?您仍然可以动态构建数组; 你只是得到的好处是不要冒险以不同于预期的方式解析他们的内容. (5认同)
  • 考虑查询中没有密码的情况.想想它会有多大用处. (3认同)
  • ...也就是说:可以运行`cmd + =( - e"$ query")`将这些参数附加到现有数组中,并确保将`query`作为单个参数添加到`-e `那传递给`mysql`; 无需查看其内容以确定它是否生成子shell或转义其引号并启动rootkit或其他任何内容. (3认同)

gho*_*g74 23

试试这个

$ cmd='mysql AMORE -u root --password="password" -h localhost -e "select host from amoreconfig"'
$ eval $cmd
Run Code Online (Sandbox Code Playgroud)

  • 在它工作的范围内,这非常有效*.需要"eval"$ cmd"`而不是`eval $ cmd`来处理任何分词组件可以全局扩展到当前目录中的文件的情况 - 或者IFS中的字符不能的情况无害地替代他人. (4认同)
  • 如果eval'ed字符串的任何输入是用户提供的,则此解决方案存在命令注入安全漏洞的风险.@CharlesDuffy提供的解决方案要好得多. (4认同)

Dav*_*ith 6

你甚至不需要“评估”。只需在字符串前面放一个美元符号:

cmd="ls"
$cmd
Run Code Online (Sandbox Code Playgroud)

  • 仅适用于极其简单的命令;不适用于 OP 在他们的示例中给出的那个。 (11认同)
  • 阅读 http://mywiki.wooledge.org/BashFAQ/050 以了解原因。 (2认同)