无FIFO的进程间通信(Inter-process communication without FIFOs)

里面一个bash脚本,我们可以在背景,互通使用命名管道,在文件系统中注册的FIFO运行多个进程。 这方面的一个例子是:

#!/bin/bash
mkfifo FIFO

# BG process 1
while :; do echo x; done & >FIFO

# BG process 2
while :; do read; done & <FIFO

exit

我不知道是否有可能做一个脚本的后台进程之间的相同互通,而不使用在文件系统中的FIFO,可能与某种文件描述符重定向。

Answer 1:

下面是运行作为同一外壳脚本的功能实现的两个子过程的示例...一张子过程生成数字1 ... 5(睡在打印之间),第二个从固定文件描述符(5读取,向其中STDOUT第一FD是由2和打印再次重定向到),乘法运算。 主处理重定向该第二过程的STDOUT到另一个固定文件描述符(6),并从该一个循环中稍后读取。

它的工作原理基本相同,你会在C代码由管(2)系统调用创建的FD对做。 为了了解情况,下使用strace -f运行脚本!

击版是4.2.24(1)在Ubuntu / x86上运行。

[ubuntu /home/chris]
$ bash --version
GNU bash, version 4.2.24(1)-release (i686-pc-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

脚本的输出:

[ubuntu /home/chris]
$ ./read_from_fd.sh
Got number 2.
Got number 4.
Got number 6.
Got number 8.
Got number 10.

源代码:

#!/bin/bash

# Generate data, output to STDOUT.
generate_five_numbers() {
        for n in `seq 5` ; do
                echo $n
                sleep 2
        done
}

# Read data from FD#5, multiply by two, output to STDOUT.
multiply_number_from_fd5_by_two() {
        while read n <&5 ; do
                echo "$(( $n * 2 ))"
        done
}

# choose your FD number wisely ;-)

# run generator with its output dup'ed to FD #5
exec 5< <( generate_five_numbers )

# run multiplyier (reading from fd 5) with output dup'ed to FD #6
exec 6< <( multiply_number_from_fd5_by_two )

# read numbers from fd 6
while read n <&6 ; do
        echo "Got number $n."
done

运行时进程树:

──read_from_fd.sh(8118)─┬─read_from_fd.sh(8119)───sleep(8123)
                        └─read_from_fd.sh(8120)


Answer 2:

击4有协进程

您也可以使用匿名命名管道,又名进程替换在击2,3或4。



Answer 3:

你可以使用nc (又名netcat ),它可以连接一个脚本的标准流网络套接字。 当然,它也可以在本地主机上,这样你就可以在脚本之间使用它的IPC。 奖金是发生在不同的主机上,这是不可能的FIFO运行脚本的可能性(好吧,也许在NFS它,但是这将是相当麻烦的设置,除非你已经拥有了NFS到位)。



Answer 4:

我只是想指出的是,丑陋的黑客不希望被与生俱来的。

其接收数据的一部分:

node -e "require('net').createServer(function(s){s.pipe(process.stdout)}).listen(1337)"

将数据发送部分:

echo "write clean code they said" > /dev/tcp/localhost/1337
echo "it will pay off they said" > /dev/tcp/localhost/1337

作品即使在MSysGit的击适用于Windows,出乎我的意料。



Answer 5:

你有没有考虑信号的使用? 如果你需要的唯一一件事就是触发事件(不传递参数),使用kill和陷阱完美的作品(注意语义不过,使用SIGUSR1例如)。

您可能需要返工,虽然逻辑,如下面的例子:

subprocess_finished()
{
    np=$( jobs -p | wc -l )
}

start_processing()
{
    myfile="$1"
    # DO SOMETHING HERE!!
    kill -SIGUSR1 $2
}

CPUS=$( lscpu | grep "^CPU(s):" | rev | cut -f 1 -d ' ' | rev )
POLLPERIOD=5  # 5s between each poll
np=0
trap subprocess_finished SIGUSR1

for myfile in *
do 
        start_processing "$myfile" $$ &
        np=$( jobs -p | wc -l )
        echo "$( date +'%Y-%m-%d %H:%M:%S' ) [$!] Starting #$np on $CPUS: $myfile"

        if [ $np -eq $CPUS ] 
        then
            # Wait for one CPU to be free
            trap subprocess_finished SIGUSR1
            while [ $np -eq $CPUS ]
            do
                sleep $POLLPERIOD
            done
        fi
    done
done

# wait for the last subprocesses
while [ ! -z "$( jobs -rp )" ]
do
    sleep $POLLPERIOD
done