Bash脚本将stdin重定向到程序并将其输出重定向到另一个程序

时间:2016-05-22 16:42:39

标签: bash redirect io pipe fifo

我正在学习bash脚本。这是我第一次将输出重定向到另一个程序而我不知道该怎么做。

我必须编写一个连接GUI程序和零,一个或两个程序的脚本 - 我需要两个玩家,都可以是计算机或人。 GUI从两个程序(或人类,我的意思是从stdin)获得输出。

假设有一个人和一个comp_player。 Human使用stdin发出命令,必须将此命令重定向到正在运行的GUI程序并运行comp_player,两者都需要输入。然后,必须将comp_player的输出重定向到GUI(如果有第二台计算机播放器,则还需要将此输出重定向到第二台计算机播放器的输入)。转弯结束。

我知道如何创建一个文件来读写,并重定向它的输入或输出。例如:

echo "anything" >&3
exec 3<>sometextfile
read line <&3
echo $line

但我不知道的是如何重定向,例如,我只是读到正在运行的程序的行,他希望输入并捕获其输出,我可以将其重定向到GUI和另一个程序。

我知道它不像上面的代码那么简单,而且我必须使用一个叫做命名管道的东西,但是我试着阅读一些教程,但我没有编写工作脚本。

你能给我一个脚本片段的例子,比如说:

(gui程序和计算机播放器程序正在运行)

- 从stdin

读取行

- &#34;发送&#34; gui程序和comp_player的输入行

- &#34;读&#34;从comp_player输出并将其写入stdout并且&#34;发送&#34;它是gui输入

1 个答案:

答案 0 :(得分:1)

命名管道是一种特殊的文件,用于连接两个完全独立的程序的输入和输出。可以把它想象成一个临时缓冲区,或者是两个彼此不了解的程序之间共享的数组。这使得它们成为在两个程序之间共享消息并使它们非常有效地进行通信的绝佳工具。

作为查看命名管道如何工作的简单测试,在同一目录中打开两个终端,并在第一个中键入 mkfifo mypipe 以创建文件。现在,使用它只是写一些东西,例如:

echo "A very important message" > mypipe

现在消息存储在管道文件中,您将看到终端被阻止,好像 echo 没有完成。转到第二个终端并使用以下内容获取管道内容:

cat mypipe

您将打印出非常重要的消息&#34;你存储在第一个终端的管道中。注意管道现在是空的,你根本无法再从中获取消息。


现在您已经了解了命名管道的工作方式,这里有三个玩家如何沟通的一个非常简单的例子。请注意,我们不能为所有这些文件使用单个文件,而是创建单独的管道来传达player1和player2,player1和gui,以及player2和gui。我猜猜gui程序是用另一种语言编写的,但我会把它留给你。

第1人(人)

player2pipe="pipe1"
guipipe="pipe2"

#First make sure we have our files
if [ ! -p $player2pipe ]; then
    mkfifo $player2pipe
fi

if [ ! -p $guipipe ]; then
    mkfifo $guipipe
fi


while true; do #Or until the game ends
    echo -n "Do something: "
    read move
    # Send our move to the other two players
    echo $move > $player2pipe
    echo $move > $guipipe

    playermove=$(cat $player2pipe) # Read other player's move from the pipe file. The execution will pause until there's something to read

    # Do something about that move here

done

PLAYER2(计算机)

player1pipe="pipe1"
guipipe="pipe3"


if [ ! -p $player1pipe ]; then
    mkfifo $player1pipe
fi

if [ ! -p $guipipe ]; then
    mkfifo $guipipe
fi


while true; do

    playermove=$(cat $player1pipe)

    # Do something about that move here

    move="A very good move made by a computer" #Obviously you will have to generate a new move
    echo $move > $player1pipe
    echo $move > $guipipe

done

GUI

player1pipe="pipe2"
player2pipe="pipe3"

if [ ! -p $player1pipe ]; then
    mkfifo $player1pipe
fi

if [ ! -p $player1pipe ]; then
    mkfifo $player1pipe
fi


while true; do #Or until the game ends

    # Read other players' move from the pipe files. Notice the order here, if player2 moved before player1 the execution would be locked until the pipe is emptied
    player1move=$(cat $player1pipe)
    player2move=$(cat $player2pipe)

    #Print out their move or whatever you need to do with it.
    echo $player1move
    echo $player2move

    # Do whatever else you need to do about those moves
done


将这三个文件保存在同一目录中,并从三个不同的终端执行它们以查看它们的工作方式。 希望我帮忙。

相关问题