1

This question already has an answer here:

while creating a script I am facing currently a "strange" issue that so far I am unable to fix.

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}"

Currently the variable assignment is like above and when I echo the SLAPD it works like a charm. but when I execute the command : Echo output

 /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

Debug output

+ [[ ! -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

So, my issue now, is that openldap command line forces me to have -h "URLs" and adding then to the variable it takes the variable as 3 parameters instead of a single as I wish.

I have tried to backspace the quotes but it expands to 3 single quotes. If I just copy the output of echo and paste it on the script it works. but this has the downside that I cannot customize using variables.

all the variables have been set with typeset -r

UPDATE 1

Based on the given answer by cas, I updated my code but still facing the same issue:

   #!/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

the output is this:

/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 version is 4.1.17

marked as duplicate by Gilles bash Apr 4 '16 at 21:37

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 1. why do you need SERVICE to be read-only? 2. don't use \" when defining SERVICE, use single-quotes instead. 3. use double-quotes around $SERVICE when you use it on the slapd command line. – cas Apr 4 '16 at 9:22
  • @cas thank you for the input and answer, but still it does not solve my problem. when using echo the output is just fine. executing the command is when I get added quotes / double quotes. – BitsOfNix Apr 4 '16 at 12:03
  • not sure why you're creating SERVICE as an array and then have a loop appending elements from it to $SLAPARGS...you seem to be defeating the purpose. simpler to just add it to $SLAPARGS with SLAPARGS+="$SLAPARGS -h '$SERVICE[@]}'" - remember slapd's -h option requires a single string as an arg. BTW, set -x will try to print quoted strings in a format that can be copy-pasted, which may not be exactly the same as what was executed....and the correct way to embed a single-quote inside single quotes is '\'' – cas Apr 4 '16 at 13:11
  • i still don't get why you're defining all those variables as read-only? is there any particular reason for that? – cas Apr 4 '16 at 13:13
  • BTW, the method of building up SLAPARGS that i outlined in my answer is exactly the same as i use to build up and use ARGS variables for my rsync backup scripts and my debmirror wrapper script, and in many other scripts. the method works exactly as i want/expect it to in all those scripts. – cas Apr 4 '16 at 13:16
2

Try something like this:

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

Just so you can see what that does (when run after $LDAPUSR, $LDAPGRP, and $CONFDIR have been appropriately defined):

$ 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'

If your shell doesn't support +=, use something like this instead:

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

The key is to use single-quotes when you DON'T want interpolation and glob expansion etc, and either no quotes or double-quotes when you do want them. For example, you DON'T wany any quotes around $SLAPDARGS when you're using it on the command-line that runs $SLAPD, otherwise they will be passed as a single argument to slapd.

Another alternative is to use an array for SLAPDARGS instead of a simple string.

BTW, if you like to keep script line lengths below 80 columns, $SERVICE can be built up incrementally the same way $SLAPDARGS was - and could also be defined as an array rather than a simple string.

Not the answer you're looking for? Browse other questions tagged or ask your own question.