在Linux Shell(Bash)中使用命名管的示例

问题描述 投票:0回答:6
有人可以在Linux上发布一个简单的示例吗?

linux bash shell pipe named-pipes
6个回答
107
投票

Http://en.wikipedia.org/wiki/netcat

其他有用的行为是将

netcat
用作代理。端口和主机都可以重定向。查看此示例:

nc -l 12345 | nc www.google.com 80

PORT12345代表请求。
在端口12345上启动了
nc

服务器,所有连接都将重定向到

google.com:80

。如果Web浏览器向

nc
提出请求,则该请求将发送到Google,但不会将响应发送到Web浏览器。那是因为管道是单向的。可以使用命名管来处理这可以重新定向输入和输出。
mkfifo backpipe
nc -l 12345  0<backpipe | nc www.google.com 80 1>backpipe
    

命令是:
mkfifo named_pipe echo "Hi" > named_pipe & cat named_pipe

48
投票
第一个命令创建管道。

第二个命令写入管道(阻塞)。

&
将其放入后台,因此您可以继续在同一外壳中键入命令。下一个命令将FIFO倒空时,它将退出。
最后一个命令从管道上读取。

打开两个不同的贝壳,然后将它们并排放置。在这两个中,转到

/tmp/
目录:

cd /tmp/


36
投票

mkfifo myPipe echo "IPC_example_between_two_shells">myPipe

在第二个,类型:

while read line; do echo "What has been passed through the pipe is ${line}"; done<myPipe

第一个外壳不会给您任何提示,直到您在第二个Shell中执行代码的第二部分。这是因为fifo读写和写作正在阻止。

您还可以通过进行
ls -al myPipe
来查看FIFO类型,并查看此特定类型的文件的详细信息。 next步骤是在脚本中登录代码!

创建命名管

$ mkfifo pipe_name

在Unix类型Pipe(FIFO)中是一种特殊的文件,没有内容。 
mkfifo

命令在文件系统上创建管道(向其分配一个名称),但没有打开。您需要像其他任何文件一样单独打开和关闭它。

使用命名管

当您需要从/到多个进程或无法用匿名管道连接两个进程时,name姓名是有用的。它们可以通过多种方式使用:

25
投票
与另一个过程并行:

$ echo 'Hello pipe!' > pipe_name & # runs writer in a background $ cat pipe_name Hello pipe!
hereWriter沿着读者运行,允许过程之间实时通信。

用文件描述符序列:

$ # open the pipe on auxiliary FD #5 in both ways (otherwise it will block), $ # then open descriptors for writing and reading and close the auxiliary FD $ exec 5<>pipe_name 3>pipe_name 4<pipe_name 5>&- $ $ echo 'Hello pipe!' >&3 # write into the pipe through FD #3 ... $ exec 3>&- # close the FD when you're done $ # (otherwise reading will block) $ cat <&4 Hello pipe! ... $ exec 4<&-

    实际上,通过管道的通信可能是顺序的,但限制为64 kb(缓冲尺寸)
  • .

    。 最好使用描述符传输多个数据块以减少开销。

    带信号的条件

  • $ handler() { > cat <&3 > > exec 3<&- > trap - USR1 # unregister signal handler (see below) > unset -f handler writer # undefine the functions > } $ $ exec 4<>pipe_name 3<pipe_name 4>&- $ trap handler USR1 # register handler for signal USR1 $ $ writer() { > if <condition>; then > kill -USR1 $PPID # send the signal USR1 to a specified process > echo 'Hello pipe!' > pipe_name > fi > } $ export -f writer # pass the function to child shells $ $ bash -c writer & # can actually be run sequentially as well $ Hello pipe!
  • FD允许数据传输在壳准备接收之前开始。顺序使用时需要。 如果管道缓冲区填充,则应在数据之前发送信号,以防止死锁。

    destroying命名的管道
    当所有描述符都关闭时,管道本身(及其内容)将被破坏。剩下的只是一个名字。
    为了使管道匿名且在给定名称下不可用(可以在管道仍打开时可以完成),您可以使用

    rm控制台命令(与mkfifo
    命令相反):

  • $ rm pipe_name
  • terminal 1:

    $ mknod new_named_pipe p $ echo 123 > new_named_pipe
    
    

    末端1创建了一个指定的管道。
    使用Echo在其中编写了数据。

  • 它被阻止,因为没有接收端(因为命名和未命名的管道需要接收和写作结束)

末端2:


$ cat new_named_pipe $ 123 $


从终端2,添加了数据的接收端。
使用CAT阅读其中的数据。

从接收和写作结束的情况下,它可以显示信息并阻止停止

2
投票
new_named_pipe

命令中看到的大多数字符和块文件是char和block管道(所有这些都位于 /dev)。 这些管道可以阻止和非阻滞,主要优势是这些管道为IPC提供了最简单的方法。

我想说您可以为管道操作而不是主CMD创建背景过程。自定义日志处理将为您提供很多帮助。
LET我们有以下多行命令。
    ls -l
  • 我们需要从即时抓取
  • make target1 \ --opt 1 \ --opt 2
  • 的东西。很难用
  • make
  • (手动或使用SED等工具)替换多元命令,因此您可以替换为
${cmd} >log &

>log ${cmd}
    谢谢你
  • 想象一个过程缓慢产生输出的过程:
  • mkfifo log grep "something" log & >log make target1 \ --opt 1 \ --opt 2
    ,但是您不想等待它与快速过程并行处理输出:
slow_writer() { for i in $(seq 1 10); do echo $i sleep 1 done }

使用文件不起作用,因为
fast_reader() { while IFS="" read i; do echo $i done < /dev/stdin }

不等待

0
投票
完成:

slow_writer

但使用指定的管道可根据需要进行工作:
: > file
slow_writer > file &
fast_reader < file

当然,正常管道可以做到,但是人们可以很容易地想到更复杂的示例,在这些示例中,命名管实际上是有益的。
    

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.