开发者

Pipeline metacharacter in variable in bash

In my bash script I need to check if logger binary exists. If so, I pipe the application output to it.

Edit--------

| It needs to be piping, the application should work permanently.

---------------

I tried to put the pipeline stuff to a variable and use it later. Something like:

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

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

but it doesn't work, the output is not piped to the logger. If I put the pipeline stuff directly into the application startline, it works. Unfortunately the real script becomes too complicated if I use command lines with and without logger stuff in if/else statements - the reason is that I already have if/else there and adding new ones will double the number of cases.

Simple test application

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

gives

$ ./test.sh

0

aas bdsd vasd

Seems that somehow command1 and command2 are开发者_高级运维 executed separately.

I managed to solve the problem (in both test and real scripts) using eval and putting the conditional stuff in double quotes.

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

$ ./test.sh

14

It feels like a workaround. What is the right way to do it?


The correct way to do this is to use 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

Edit:

In the case of a complex construct, you should use a function:

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

Then your log/no log if stays simple:

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


Just to throw another option into the mix, you could move the pipe outside the variable:

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

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

This avoids having duplicate commands for the two cases (or having to wrap everything in functions, per Dennis' suggestion). The disadvantage is that it's inefficient about how it handles the case where logger doesn't exist -- creating a cat process just to feed output to /dev/null is a complete waste. But a cat process isn't that big a resource drain, so if it makes your code cleaner it might be worth the waste.


Try

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

General rule: don't put commands inside variables and call it through the variable. Just run it directly off your script.


I tried a similar code and specified the last line like this and it worked

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


While ghostdog74's answer is correct, there is certainly a way to make this work

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

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

But I highly recommend that you think twice before using eval, and then don't use it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜