![bash 或 Ksh 引号和命令 exec](https://linux22.com/image/86922/bash%20%E6%88%96%20Ksh%20%E5%BC%95%E5%8F%B7%E5%92%8C%E5%91%BD%E4%BB%A4%20exec%20.png)
在创建脚本时,我目前面临一个“奇怪”的问题,到目前为止我无法解决。
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
- 并且也可以定义为数组而不是简单的字符串。