Возможная проблема с пробелами в скрипте bash.Команда не будет выполняться в скрипте, но будет скопирована из вывода - PullRequest
0 голосов
/ 05 октября 2011

Я ходил по цитатам на http://tldp.org для bash и гуглил, пока у меня не посинело лицо. Я также попробовал все очевидные схемы цитирования для этой проблемы, но пока ничего не работает.

Проблема, похоже, заключается в том, что пробел внутри аргумента в кавычках в команде, выполняемой в конце скрипта, интерпретируется как разделитель, а не как пробел в кавычках.

Вот мой сценарий (я прекрасно знаю, что я новичок, поэтому я буду учиться комментировать мой стиль и / или необязательный синтаксис):

#!/bin/bash

date=`date`
args="$@"
MSEND_HOME=/home/patrol/Impact           #Path to the Impact Directory
integrationName=Introscope               #Name of the integration
persistEnabled=1                         #1 for Yes, 0 for No
persist=""
bufDir=$MSEND_HOME/tmp/$integrationName  #DO NOT CHANGE
cellName=linuxtest                       #Cell name to forward events to

loggingEnabled=1                         #1 for Yes, 0 for No
logFile=$MSEND_HOME/log/$integrationName.$cellName.log


die () {
  if [ $loggingEnabled -eq 1 ]
  then
    echo >>$logFile "$@"
  fi
  exit 1
}

[ "$#" -ge 1 ] || die "$date - At least 1 argument required, $# provided" "$@"

# This is where you would parse out your arguments and form the following
# slots as a minimum for sending an event.

class=$2
msg=\"$3\"

# Parse the first argument and assign the correct syntax
if [[ $1 == "INFORMATIONAL" ]]
then
  severity=INFO
elif [[ $1 == "WARN" ]]
then
  severity=WARNING
elif [[ $1 == "CRIT" ]]
then
  severity=CRITICAL
else
  severity=INFO
fi

#Additional slots can be set, parse them all in this variable;
#e.g., additionalSlots="slot1=value1;slot2=value2;slot3=\"value 3\""
additionalSlots=""


cmd="$MSEND_HOME/bin/msend"
cmd="$cmd -q"
cmd="$cmd -l $MSEND_HOME"

if [ $persistEnabled -eq 1 ]
then
  cmd="$cmd -j $bufDir"
fi

cmd="$cmd -n $cellName"
cmd="$cmd -a $class"
cmd="$cmd -m $msg"
cmd="$cmd -r $severity"

if [ $additionalSlots ]
then
  cmd="$cmd -b $additionalSlots"
fi

$cmd || die "$date - msend exited with error $? | Original arguments: $args | Command: $cmd"
#echo "msend exited with error $? | Original arguments: $args | Command: $cmd"

Сценарий выполняется так:

./sendEvent.sh "CRIT" "EVENT" "Test Event"

Ошибка, которую я получаю от исполняемого файла msend, состоит в том, что аргументы неверны, но я записываю командную строку целиком в файл, и когда я в интерактивном режиме запускаю эту зарегистрированную команду в оболочке, она работает.

Вот вывод журнала:

Tue Oct 4 20:31:29 CDT 2011 - msend exited with error 27 | Original arguments: CRIT EVENT Test Event | Command: /home/patrol/Impact/bin/msend -q -l /home/patrol/Impact -j /home/patrol/Impact/tmp/Introscope -n linuxtest -a EVENT -m "Test Event" -r CRITICAL

Так что, если я вставлю /home/patrol/Impact/bin/msend -q -l /home/patrol/Impact -j /home/patrol/Impact/tmp/Introscope -n linuxtest -a EVENT -m "Test Event" -r CRITICAL и запусту его, он будет работать.

Если я запускаю скрипт как ./sendEvent.sh "CRIT" "EVENT" "TestEvent", он работает. Но мне нужен этот аргумент, чтобы разрешить пробелы.

Я на пути к тому, что это проблема $ IFS или что-то в этом роде ... возможно, разница между интерактивной оболочкой и средой сценариев.

Буду признателен за понимание более умных людей, чем я!

tl; dr - Моя команда не работает при запуске из скрипта, но работает, когда синтаксис зарегистрированной команды используется в интерактивной оболочке.

Ответы [ 3 ]

1 голос
/ 05 октября 2011

Краткий ответ: см. BashFAQ # 50 .

Длинный ответ: когда bash анализирует строку, он анализирует кавычки перед выполнением подстановки переменной; в результате, когда вы помещаете кавычки в переменную, они не делают то, что вы ожидаете. Вы фактически передаете список аргументов, включающий '-m' '' Test '' Event '' '-r' - эти двойные кавычки не заключаются в аргументы, они в аргументах .

В этом случае лучшее решение - это построить команду в массив, а не в строку. Кроме того, попробуйте использовать двойные кавычки вокруг переменных (например, имена файлов) при их использовании, чтобы избежать путаницы, если они содержат пробелы. С этими изменениями (и несколькими другими изменениями) вот моя версия вашего скрипта:

#!/bin/bash

date="$(date)"  # Backquotes are confusing, use $() instead
args=("$@")   # Save the args in an array rather than mushing them together in a string
MSEND_HOME=/home/patrol/Impact           #Path to the Impact Directory
MSEND_HOME="$HOME/tmp"           #Path to the Impact Directory
integrationName=Introscope               #Name of the integration
persistEnabled=1                         #1 for Yes, 0 for No
persist=""
bufDir="$MSEND_HOME/tmp/$integrationName"  #DO NOT CHANGE
cellName=linuxtest                       #Cell name to forward events to

loggingEnabled=1                         #1 for Yes, 0 for No
logFile="$MSEND_HOME/log/$integrationName.$cellName.log"


die () {
  if [ $loggingEnabled -eq 1 ]
  then
    echo >>"$logFile" "$@"
  fi
  exit 1
}

[ "$#" -ge 1 ] || die "$date - At least 1 argument required, $# provided" "$@"

# This is where you would parse out your arguments and form the following
# slots as a minimum for sending an event.

class="$2"   # Quotes not strictly needed here, but a good habbit
msg="$3"

# Parse the first argument and assign the correct syntax
if [[ "$1" == "INFORMATIONAL" ]]
then
  severity=INFO
elif [[ "$1" == "WARN" ]]
then
  severity=WARNING
elif [[ "$1" == "CRIT" ]]
then
  severity=CRITICAL
else
  severity=INFO
fi

#Additional slots can be set, parse them all in this array;
#e.g., additionalSlots="slot1=value1;slot2=value2;slot3=value 3"  # Don't embed quotes
additionalSlots=""


cmd=("$MSEND_HOME/bin/msend")   # Build the command as an array, not a string
cmd+=(-q)   # Could equivalently use cmd=("${cmd[@]}" -q), but this is simpler
cmd+=(-l "$MSEND_HOME")

if [ $persistEnabled -eq 1 ]
then
  cmd+=(-j "$bufDir")
fi

cmd+=(-n "$cellName")
cmd+=(-a "$class")  # Possible bug: $2 and @3 aren't required, but they're getting added unconditionally
cmd+=(-m "$msg")    # These should probably be conditional, like additionalSlots
cmd+=(-r "$severity")

if [ -n "$additionalSlots" ]
then
  cmd+=(-b "$additionalSlots")
fi

"${cmd[@]}" || die "$date - msend exited with error $? | Original arguments:$(printf " %q" "${args[@]}") | Command:$(printf " %q" "${cmd[@]}")"
#echo "msend exited with error $? | Original arguments:$(printf " %q" "${args[@]}") | Command:$(printf " %q" "${cmd[@]}")"
0 голосов
/ 05 октября 2011

Хорошо, я не вижу точной проблемы сразу, но я могу сказать вам, что это;этот совет должен помочь.

Помните, что механизм цитирования оболочки интерпретирует только строку один раз .В результате, если вы не будете осторожны, то, что вы подумали «foo», a «b» на самом деле - «foo ab», то есть все один токен, а не три.

Выполнитьскрипт с bash -x, который будет показывать вам на каждом шаге, что на самом деле видит оболочка.

0 голосов
/ 05 октября 2011

Я думаю, что arg не так с этим заданием: cmd="$cmd -m $msg".

Измените его на cmd="$cmd -m \"$msg\"".

...