bash中变量的管道元字符

时间:2010-10-13 09:45:47

标签: bash shell pipe pipeline

在我的bash脚本中,我需要检查logger二进制文件是否存在。如果是这样,我将应用程序输出传递给它。

修改--------
| 它需要管道,应用程序应该永久工作 的 ---------------

我尝试将管道内容放到变量中,稍后再使用它。类似的东西:

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 个答案:

答案 0 :(得分:2)

执行此操作的正确方法是使用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 :(得分:2)

只需向混合中添加另一个选项,您可以将管道移动到变量之外:

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

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

根据Dennis的建议,这可以避免两种情况下的重复命令(或者必须将所有内容包装在函数中)。缺点是它如何处理不存在记录器的情况效率低下 - 创建一个cat进程只是为了将输出提供给/ dev / null是一个完全的浪费。但是cat进程并非 消耗大量资源,因此如果它使代码更清晰,则可能值得浪费。

答案 2 :(得分:1)

尝试

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

一般规则:不要将命令放在变量中并通过变量调用它。只需直接从脚本中运行它。

答案 3 :(得分:0)

我尝试了类似的代码并指定了最后一行,并且它有效

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

答案 4 :(得分:0)

虽然ghostdog74的答案是正确的,但肯定有办法让这项工作

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

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

但我强烈建议您在使用eval之前再三考虑,然后不要使用它。