如何防止Bash在将变量作为命令运行时删除引号?

3

我有一个存储在变量中的命令,然后我运行它:

[root@cxpxwly01wel001 init.d]# cat test
#!/bin/bash
command="su - root -c 'java -Xms16m -the_rest_of_my_java_command'"
echo $command
$command
[root@cxpxwly01wel001 init.d]# ./test
su - root -c 'java -Xms16m -the_rest_of_my_java_command'
su: invalid option -- 'X'
Try `su --help' for more information.

如果没有单引号,就会出现su错误:

[root@cxpxwly01wel001 init.d]# su - root -c java -Xms16m -the_rest_of_my_java_command
su: invalid option -- 'X'
Try `su --help' for more information.

使用单引号,该命令可以按预期工作:

[root@cxpxwly01wel001 init.d]# su - root -c 'java -Xms16m -the_rest_of_my_java_command'
-bash: java: command not found

这可能意味着在将变量作为命令运行时,单引号并没有被保留。如何保留它们?

注意:我正在编辑一个现有的脚本(在java命令周围插入su -),因此我希望尽可能少地更改以使其接近原始代码。


让我添加使用set -x运行时的输出:

+ command='su - root -c '\''java -Xms16m -the_rest_of_my_java_command'\'''
+ echo su - root -c ''\''java' -Xms16m '-the_rest_of_my_java_command'\'''
su - root -c 'java -Xms16m -the_rest_of_my_java_command'
+ su - root -c ''\''java' -Xms16m '-the_rest_of_my_java_command'\'''
su: invalid option -- 'X'
Usage: su [options] [LOGIN]

Options:
  -c, --command COMMAND         pass COMMAND to the invoked shell
  -h, --help                    display this help message and exit
  -, -l, --login                make the shell a login shell
  -m, -p,
  --preserve-environment        do not reset environment variables, and
                                keep the same shell
  -s, --shell SHELL             use SHELL instead of the default in passwd
1个回答

1

我用的方法来避免“引号内引号”的问题是在数组中构建命令。例如,不是:

command="su - root -c 'java -Xms16m -the_rest_of_my_java_command'"

我会使用:

declare -a command=(su - root -c 'java -Xms16m -the_rest_of_my_java_command')

您仍然可以使用数组展开来回显命令:
echo "${command[@]}"

或者运行它:

"${command[@]}"

双引号是数组扩展中很重要的:它们告诉Shell在不进行任何单词拆分的情况下扩展项目,因此包含空格的项目将保持其作为单个字符串的身份。
通过这种方式,最后一个参数(在引号内)将保持为单个字符串,并且su命令将不会将-Xms16m视为(无效的)选项。
顺便说一下,“${command[@]}”中的“[@]”表示“数组中的所有元素”。而在类似“${command[1]}”的表达式中,“[1]”表示“仅索引为1的元素”。

++ 用于演示如何完成,这里也有很好的解释 [BashFAQ-050] (http://mywiki.wooledge.org/BashFAQ/050)。 - Inian
所以必须在脚本运行的地方进行更改?我正在编辑一个非常长的脚本的一部分,我只想更改命令,但不更改调用它的脚本部分。目前,我倾向于创建第二个脚本,该脚本仅以所需用户的身份调用原始脚本。 - mazz0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接