bash 或 Ksh 引号和命令 exec

bash 或 Ksh 引号和命令 exec

在创建脚本时,我目前面临一个“奇怪”的问题,到目前为止我无法解决。

typeset -r SERVICE=\"ldap://localhost:10389\ ldaps://solsrv02.internal.vbox:10689\ ldaps://solsrv02.prod.internal.vbox:10689\"
SLAPD="/usr/lib/slapd -u ${LDAPUSR} -g ${LDAPGRP} -h ${SERVICE} -F ${CONF_DIR}"

目前,变量分配如上所示,当我回显 SLAPD 时,它就像一个魅力。但是当我执行命令时:回显输出

 /usr/lib/slapd -u openldap -g openldap -h "ldap://localhost:10389 ldaps://solsrv02.internal.vbox:10689 ldaps://solsrv02.prod.internal.vbox:10689" -F /etc/openldap/standalone

调试输出

+ [[ ! -d /var/openldap/run ]]
+ /bin/rm -f /var/openldap/run/slapd.pid
+ /usr/lib/slapd -u openldap -g openldap -h '"ldap://localhost:10389' ldaps://solsrv02.internal.vbox:10689 'ldaps://solsrv02.prod.internal.vbox:10689"' -F /etc/openldap/standalone

所以,我现在的问题是,openldap 命令行强制我拥有 -h“URL”,然后将其添加到变量中,它将变量作为 3 个参数,而不是我希望的单个参数。

我尝试将引号退格,但它扩展为 3 个单引号。如果我只是复制 echo 的输出并将其粘贴到脚本上,它就可以工作。但这有一个缺点,就是我无法使用变量进行自定义。

所有变量均已设置typeset -r

更新1

根据 cas 给出的答案,我更新了代码,但仍然面临同样的问题:

   #!/usr/bin/bash
echo $SHELL
typeset -r SLAPD=/usr/lib/slapd
typeset -r LDAPUSR=openldap
typeset -r LDAPGRP=openldap
typeset -r VARRUNDIR=/var/openldap/run
typeset -r PIDFILE=${VARRUNDIR}/slapd.pid
typeset -r CONF_DIR=/etc/openldap/standalone
typeset -r SERVICE=(ldap://localhost:10389 ldaps://solsrv02.internal.vbox:10689 ldaps://solsrv02.prod.internal.vbox:10689)
SLAPARGS=" -u ${LDAPUSR}"
SLAPARGS+=" -g ${LDAPGRP}"
SLAPARGS+=" -F ${CONF_DIR}"
SLAPARGS+=" -h "
SIZE=${#SERVICE[@]}

#for i in {1..${#SERVICE[@]}$}; do
SLAPARGS+="'"
for ((i=0;i<$SIZE;i=$i+1)); do
        SLAPARGS+="${SERVICE[$i]} "
done
SLAPARGS+="'"
[[ ! -d ${CONF_DIR} ]] && exit $SMF_EXIT_ERR_CONFIG

echo "$SLAPD $SLAPARGS"
set -x
$SLAPD $SLAPARGS 2>&1

输出是这样的:

/usr/bin/bash
/usr/lib/slapd  -u openldap -g openldap -F /etc/openldap/standalone -h 'ldap://localhost:10389 ldaps://solsrv02.internal.vbox:10689 ldaps://solsrv02.prod.internal.vbox:10689 '
+ [[ ! -d /var/openldap/run ]]
+ /bin/rm -f /var/openldap/run/slapd.pid
+ /usr/lib/slapd -u openldap -g openldap -F /etc/openldap/standalone -h ''\''ldap://localhost:10389' ldaps://solsrv02.internal.vbox:10689 ldaps://solsrv02.prod.internal.vbox:10689 ''\'''

Bash 版本是 4.1.17

答案1

尝试这样的事情:

SLAPD='/usr/bin/slapd'

SERVICE='ldap://localhost:10389 ldaps://solsrv02.internal.vbox:10689  ldaps://solsrv02.prod.internal.vbox:10689'

SLAPDARGS="-u '${LDAPUSR}'"
SLAPDARGS+=" -g '${LDAPGRP}'"
SLAPDARGS+=" -h '${SERVICE}'"
SLAPDARGS+=" -F '${CONFDIR}'"

$SLAPD $SLAPDARGS

这样您就可以看到它的作用(当在$LDAPUSR$LDAPGRP、 和$CONFDIR已正确定义之后运行时):

$ echo $SLAPD $SLAPDARGS 
/usr/bin/slapd -u 'ldap' -g 'ldap' -h 'ldap://localhost:10389 ldaps://solsrv02.internal.vbox:10689 ldaps://solsrv02.prod.internal.vbox:10689' -F '/etc/ldap'

如果您的 shell 不支持+=,请改用如下内容:

SLAPDARGS="-u '${LDAPUSR}'"
SLAPDARGS="${SLAPDARGS} -g '${LDAPGRP}'"
SLAPDARGS="${SLAPDARGS} -h '${SERVICE}'"
SLAPDARGS="${SLAPDARGS} -F '${CONFDIR}'"

关键是当您不需要插值和全局扩展等时使用单引号,而当您确实需要时可以不使用引号或使用双引号。例如,$SLAPDARGS当您在运行的命令行上使用它时,您不希望有任何引号$SLAPD,否则它们将作为单个参数传递给slapd

另一种替代方法是对 SLAPDARGS 使用数组而不是简单的字符串。

顺便说一句,如果您希望将脚本行长度保持在 80 列以下,$SERVICE可以按照与以前相同的方式逐步构建$SLAPDARGS- 并且也可以定义为数组而不是简单的字符串。

相关内容