kip*_*oan 3 bash pipe sh named-pipes mkfifo
我正在为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"
Run Code Online (Sandbox Code Playgroud)
我认为第34和35行的命令会从中$data取出$PIPE_ECHO并将其输出到$PIPE_LOG.但是,它不起作用.相反,我必须将该输出直接发送到日志文件,而不通过$PIPE_LOG.
为什么这不符合我的预期?
编辑:我把shebang改为"bash".但问题是一样的.
解决方案: AH的回答帮助我理解我没有正确使用命名管道.我已经解决了我的问题,甚至没有使用命名管道.解决方案在这里:http: //pastebin.com/VFLjZpC3
在我看来,你不明白命名管道到底是什么.命名管道不是普通管道的一个流.它是一系列普通管道,因为命名管道可以关闭,生产者端的关闭可能在消费者端显示为关闭.
在可能的部分是:直到有没有更多的数据,消费者将读取的数据.没有更多数据意味着,在read调用时没有生产者打开命名管道.这意味着只有在没有至少一个生产者的时间点没有时间点的情况下,多个生产者才能喂养一个消费者.想一想自动关闭的门:如果有一个稳定的人流,通过将门把手递给下一个门或者同时挤压多个人来保持门始终打开,门就打开了.但是一旦门关闭,它就会保持关闭状态.
一点点演示应该让差异更加清晰:
打开三个炮弹.第一壳:
1> mkfifo xxx
1> cat xxx
Run Code Online (Sandbox Code Playgroud)
没有显示输出,因为cat已打开命名管道并正在等待数据.
第二壳:
2> cat > xxx
Run Code Online (Sandbox Code Playgroud)
没有输出,因为这cat是一个生产者,它保持命名管道打开,直到我们告诉他明确地关闭它.
第三壳:
3> echo Hello > xxx
3>
Run Code Online (Sandbox Code Playgroud)
该生产者立即返回.
第一壳:
Hello
Run Code Online (Sandbox Code Playgroud)
消费者收到数据,写下来 - 由于还有一个消费者保持开门,继续等待.
第三壳
3> echo World > xxx
3>
Run Code Online (Sandbox Code Playgroud)
第一壳:
World
Run Code Online (Sandbox Code Playgroud)
消费者收到数据,写下来 - 由于还有一个消费者保持开门,继续等待.
第二个Shell:写入cat > xxx窗口:
And good bye!
(control-d key)
2>
Run Code Online (Sandbox Code Playgroud)
第一个壳
And good bye!
1>
Run Code Online (Sandbox Code Playgroud)
在^D关键的关闭最后生产的cat > xxx,因此消费者也退出.
在你的情况下,这意味着:
log功能将尝试多次打开和关闭管道.不是个好主意.while循环都比你想象的更早退出.(检查一下(while ... done < $PIPE_X; echo FINISHED; ) &sleep 1在log功能结束时添加一个.)sleeps),因为你的生产者可能找不到任何消费者.所以我可以解释你的代码中的问题,但我不能告诉你一个解决方案,因为不清楚你的需求的边缘是什么.
| 归档时间: |
|
| 查看次数: |
3354 次 |
| 最近记录: |