2013-01-12 15 views
0

我从here下载tracd init.d启动脚本,我试图将它采用到我自己的服务器。但是当我运行脚本时,我得到以下错误信息:Bash不能不能运行由多个变量创建的命令

Usage: tracd [options] [projenv] ... 

tracd: error: the --single-env option cannot be used with more than one enviroment 

所以我试图修改脚本以使其工作。这是我的实际版本:

#!/bin/sh 
### BEGIN INIT INFO 
# Provides:   tracd 
# Required-Start: networking 
# Required-Stop:  networking 
# Default-Start:  2 3 4 5 
# Default-Stop:  0 1 6 
# Short-Description: Start the tracd standalone Trac web server. 
### END INIT INFO 
# (C) 2008 Guy Rutenberg <http://www.guyrutenberg.com> 

## Options you should probably change ## 
HOSTNAME=193.17.184.23 # to which hostname should we listen 
# If you only want to serve one project keep this variable 
# empty and set the PROJECT_ENV variable 
ENV_PARENT_DIR= 
PROJECT_ENV=/opt/trac/bds5/ 
PORT=8000 
# add any additional options (such as authentication) here. If you only have one 
# project you should probably add -s here 
ADDITIONAL_OPTS='-s --basic-auth="bds5,/opt/trac/bds5/.htpasswd,Baza Doskonalenia Systemu"' 

## Options you should probably not change ## 
DAEMON=/usr/local/bin/tracd 
NAME=tracd-bds5 
DESC="web server" 
PIDFILE=/var/run/$NAME.pid 
SCRIPTNAME=/etc/init.d/$NAME 
SSD="/sbin/start-stop-daemon" 

test -x $DAEMON || exit 1 

set -e 

. /lib/lsb/init-functions 

DAEMON_OPTS="--daemonize --pidfile=$PIDFILE --port=$PORT --hostname=$HOSTNAME $ADDITIONAL_OPTS" 
if [ -n "$ENV_PARENT_DIR" ]; then 
    DAEMON_OPTS="$DAEMON_OPTS --env-parent-dir=$ENV_PARENT_DIR" 
else 
    DAEMON_OPTS="$DAEMON_OPTS $PROJECT_ENV" 
fi 

case "$1" in 
    start) 
    log_daemon_msg "Starting $DESC" $NAME 
    echo "$SSD --start --quiet --pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS" 
    $SSD --start --quiet --pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS 
    if [[ -n $! ]]; then 
      log_end_msg 0 
    else 
      log_end_msg 1 
    fi 
    ;; 
    stop) 
    log_daemon_msg "Stopping $DESC" $NAME 
    if $SSD --stop --retry 30\ 
    --pidfile $PIDFILE ; then 
     rm -f $PIDFILE 
     log_end_msg 0 
    else 
     log_end_msg 1 
    fi 
    ;; 
    restart|force-reload) 
    $0 stop 
    [ -r $PIDFILE ] && while pidof -x $NAME |\ 
     grep -q `cat $PIDFILE 2>/dev/null` 2>/dev/null ; do sleep 1; done 
    $0 start 
    ;; 
    *) 
    echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2 
    exit 1 
    ;; 
esac 

exit 0 

,这是它的输出:

Starting web server: tracd-bds5 
/sbin/start-stop-daemon --start --quiet --pidfile /var/run/tracd-bds5.pid --exec /usr/local/bin/tracd -- --daemonize --pidfile=/var/run/tracd-bds5.pid --port=8000 --hostname=127.0.0.1 -s --basic-auth="bds5,/opt/trac/bds5/.htpasswd,Baza Doskonalenia Systemu" /opt/trac/bds5/ 
Usage: tracd [options] [projenv] ... 

tracd: error: the --single-env option cannot be used with more than one enviroment 

什么是有趣的 - 当我从终端复制命令,并运行它,寄托都工作正常。所以我认为从scrit运行这个命令是有问题的。我究竟做错了什么?

回答

4

简短的回答:看BashFAQ #050: I'm trying to put a command in a variable, but the complex cases always fail!

龙答:当bash解析命令行,它会寻找(&作用)的报价和逃逸它可以替代变量。所以当一个变量包含类似-s --basic-auth="bds5,/opt/trac/bds5/.htpasswd,Baza Doskonalenia Systemu"的东西时,在该值包含在命令行中的时候,引用中的引号做任何有用的事情都为时已晚。

如果您需要在一个变量中存储复杂的命令选项,最好的选择是使用一个数组。每个shell字都作为数组中的单独元素存储,并且如果将数组正确地展开(如"$arrayname[@]}"),该数组会被保留并传递到命令完好:

ADDITIONAL_OPTS=(-s --basic-auth="bds5,/opt/trac/bds5/.htpasswd,Baza Doskonalenia Systemu") 
... 
DAEMON_OPTS=(--daemonize --pidfile=$PIDFILE --port=$PORT --hostname=$HOSTNAME "${ADDITIONAL_OPTS[@]}") 
if [ -n "$ENV_PARENT_DIR" ]; then 
    DAEMON_OPTS+=(--env-parent-dir=$ENV_PARENT_DIR) 
else 
    DAEMON_OPTS+=($PROJECT_ENV) 
fi 
... 
$SSD --start --quiet --pidfile $PIDFILE --exec $DAEMON -- "${DAEMON_OPTS[@]}"