Метасимвол конвейера в переменной в bash - PullRequest
1 голос
/ 13 октября 2010

В моем скрипте bash мне нужно проверить, существует ли двоичный файл журнала. Если это так, я передаю выходные данные приложения.

Редактировать --------
| Это должно быть трубопроводом, приложение должно работать постоянно.
---------------

Я пытался поместить материал конвейера в переменную и использовать его позже. Что-то вроде:

if [ -e /usr/bin/logger ]; then
  OUT=| /usr/bin/logger 
fi

application  param1  2>&1   $OUT   >  /dev/null &

но это не работает, выходные данные не передаются в логгер. Если я помещаю материал конвейера прямо в стартовую строку приложения, это работает. К сожалению, настоящий сценарий становится слишком сложным, если я использую командные строки с и без логгера в операторах if / else - причина в том, что у меня уже есть if / else и добавление новых удвоит число наблюдений .

Простое тестовое приложение

TMP=| wc -m
echo aas bdsd vasd $TMP

дает

$ ./test.sh
0
AAS BDSD VASD

Кажется, что каким-то образом command1 и command2 выполняются отдельно.

Мне удалось решить проблему (как в тестовом, так и в реальном сценариях), используя eval и поместив условные выражения в двойные кавычки.

TMP="| wc -m"
eval echo aas bdsd vasd $TMP

$ ./test.sh
14

Это похоже на обходной путь. Как правильно это сделать?

Ответы [ 5 ]

2 голосов
/ 13 октября 2010

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

if [ -e /usr/bin/logger ]; then
    logcmd=/usr/bin/logger
else
    logcmd=/bin/cat
fi

application param1 2>&1 | $logcmd >/dev/null &

Это позволяет избежать дублирования команд для двух случаев (или обернуть все в функции, согласно Деннису).' предложение).Недостатком является то, что он неэффективен в том, как он обрабатывает случай, когда регистратор не существует - создание процесса cat просто для передачи вывода в / dev / null является полной тратой.Но cat процесс - это не , что большой расход ресурсов, поэтому, если он сделает ваш код чище, он может стоить растраты.

2 голосов
/ 13 октября 2010

Правильный способ сделать это - использовать if/else:

if [ -e /usr/bin/logger ]
then
    application  param1  2>&1 | /usr/bin/logger >  /dev/null &
else
    application  param1 > /dev/null 2>&1 &
fi

Редактировать:

В случае сложной конструкции вы должны использоватьфункция:

foo () {
    if [ ... ]
    then
        do_something
    else
        something_else
    fi
    while [ ... ]
    do
        loop_stuff
    done
    etc.
}

Тогда ваш журнал / без журнала if остается простым:

if [ -e /usr/bin/logger ]
then
    foo  2>&1 | /usr/bin/logger >  /dev/null &
else
    foo > /dev/null 2>&1 &
fi
1 голос
/ 13 октября 2010

Попробуйте

if [ -e /usr/bin/logger ]; then
  logger $(application  param1 2>&1)
fi

Общее правило: не помещайте команды внутри переменных и вызывайте их через переменную. Просто запустите его прямо из вашего скрипта.

0 голосов
/ 13 октября 2010

Хотя ответ ghostdog74 правильный, безусловно, есть способ заставить эту работу

if [ -e /usr/bin/logger ]; then
  OUT='| /usr/bin/logger'
fi

eval application param1 2>&1 $OUT > /dev/null

Но я настоятельно рекомендую дважды подумать перед использованием eval, а затем не использовать его.

0 голосов
/ 13 октября 2010

Я попробовал подобный код и указал последнюю строку, как это, и это сработало

application  param1  &2>1   ${OUT}   >  /dev/null
...