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

バッシュバージョンは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'

シェルがそれをサポートしていない場合は、+=代わりに以下を使用してください。

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

重要なのは、補間やグローバル拡張などが不要な場合は単一引用符を使用し、必要に応じて引用符を使用しないか、二重引用符を使用することです。たとえば、$SLAPDARGS実行しているコマンドラインでこれを使用するときに引用符を使用したくありません。$SLAPDそれ以外の場合、引用符は単一の引数として渡されますslapd

もう1つの選択肢は、SLAPDARGSに単純な文字列の代わりに配列を使用することです。

ちなみに、スクリプト行の長さを80列未満に保つには、前と$SERVICE同じ方法で段階的に作成し、$SLAPDARGS単純な文字列の代わりに配列として定義することもできます。

関連情報