【发布时间】:2012-03-10 07:01:17
【问题描述】:
我正在向 bash 脚本添加一些自定义日志记录功能,但无法弄清楚为什么它不会从一个命名管道获取输出并将其反馈回另一个命名管道。
这是脚本的基本版本 (http://pastebin.com/RMt1FYPc):
#!/bin/bash
PROGNAME=$(basename $(readlink -f $0))
LOG="$PROGNAME.log"
PIPE_LOG="$PROGNAME-$$-log"
PIPE_ECHO="$PROGNAME-$$-echo"
# program output to log file and optionally echo to screen (if $1 is "-e")
log () {
if [ "$1" = '-e' ]; then
shift
$@ > $PIPE_ECHO 2>&1
else
$@ > $PIPE_LOG 2>&1
fi
}
# create named pipes if not exist
if [[ ! -p $PIPE_LOG ]]; then
mkfifo -m 600 $PIPE_LOG
fi
if [[ ! -p $PIPE_ECHO ]]; then
mkfifo -m 600 $PIPE_ECHO
fi
# cat pipe data to log file
while read data; do
echo -e "$PROGNAME: $data" >> $LOG
done < $PIPE_LOG &
# cat pipe data to log file & echo output to screen
while read data; do
echo -e "$PROGNAME: $data"
log echo $data # this doesn't work
echo -e $data > $PIPE_LOG 2>&1 # and neither does this
echo -e "$PROGNAME: $data" >> $LOG # so I have to do this
done < $PIPE_ECHO &
# clean up temp files & pipes
clean_up () {
# remove named pipes
rm -f $PIPE_LOG
rm -f $PIPE_ECHO
}
#execute "clean_up" on exit
trap "clean_up" EXIT
log echo "Log File Only"
log -e echo "Echo & Log File"
我认为第 34 行和第 35 行的命令会从$PIPE_ECHO 获取$data 并将其输出到$PIPE_LOG。但是,它不起作用。相反,我必须将该输出直接发送到日志文件,而不通过 $PIPE_LOG。
为什么这不符合我的预期?
编辑:我将 shebang 更改为“bash”。不过问题是一样的。
解决方案:A.H.'s answer 帮助我了解我没有正确使用命名管道。从那以后,我什至不使用命名管道来解决我的问题。该解决方案在这里:http://pastebin.com/VFLjZpC3
【问题讨论】:
-
您说这是一个 bash 脚本,但您在脚本的第一行指定了
/bin/sh。您确定需要在 bash 中执行此操作吗?请记住,并非每个操作系统都默认安装 bash。 -
我想说潜在的问题是,如果你使用它的路径而不是 bash [path] 运行这个脚本,你将调用 bash 的“sh”版本(即使它是相同的可执行文件),它的工作原理并不完全相同(限制)。
-
我尝试用“bash”替换“sh”,它的工作方式相同(即它没有)。
-
有些东西我不明白:如果我用“#!/bin/sh”运行它,我会遇到错误(21: [[: not found)并且它不起作用.如果我使用“#!/bin/bash”运行,它就像一个魅力(它回显“Echo & Log File”,在日志文件中,我有“Log File Only”和“Echo & Log File”)。是你所期望的吗?
-
我希望第 34、35 和 36 行都将“Echo & Log File”输出到日志文件,因此日志文件中应该有 3 个“Echo & Log File”行。实际上,第 34 行和第 35 行没有,但第 36 行有。我想在 34 或 35 中使用该方法,因此我不必复制输出逻辑。在生产版本中,我将其他内容添加到输出中,例如日期时间戳,我最好能够将“pipe_echo”输出传递给“pipe_log”输出而不是复制逻辑“pipe-echo”函数中的“pipe_log”例程。
标签: bash pipe named-pipes sh mkfifo