【问题标题】:Write and read from a fifo from two different script从两个不同的脚本写入和读取 fifo
【发布时间】:2014-11-12 02:21:00
【问题描述】:

我有两个 bash 脚本。 一个脚本写入fifo。第二个从 fifo 读取,但在第一个结束后写入。

但是有些东西不起作用。我不明白问题出在哪里。代码在这里。

第一个脚本是(作者):

#!/bin/bash

fifo_name="myfifo";

# Se non esiste, crea la fifo;
[ -p $fifo_name ] || mkfifo $fifo_name;

exec 3<> $fifo_name;

echo "foo" > $fifo_name;
echo "bar" > $fifo_name;

第二个脚本是(读者):

#!/bin/bash

fifo_name="myfifo";

while true
do
    if read line <$fifo_name; then
       # if [[ "$line" == 'ar' ]]; then
        #    break
        #fi
        echo $line
    fi
done

谁能帮帮我? 谢谢

【问题讨论】:

  • 您所说的“有些东西不起作用”是什么意思?
  • 没有脚本给我任何错误。但是当我运行第二个脚本时,屏幕上没有打印任何内容。所以我不明白当我在fifo中写入或从fifo读取时我是否错了

标签: bash fifo writer


【解决方案1】:

将第二个脚本替换为:

#!/bin/bash    
fifo_name="myfifo"
while true
do
    if read line; then
        echo $line
    fi
done <"$fifo_name"

这只会打开一次先进先出并从中读取每一行。

【讨论】:

  • 对我不起作用:(当我运行第二个脚本时没有任何反应,脚本也没​​有终止:(我必须按 CTRL + C
  • @Ciccio 是的,脚本不会终止,因为它正在等待从 fifo 读取某些内容。在等待时,运行另一个写入 fifo 的脚本。
  • @Ciccio 此外,第一个脚本不会终止,直到某个进程从 fifo 读取。当第二个脚本完成读取第一个脚本所写的内容时,第一个脚本将终止。由于while true 循环,第二个脚本继续等待更多输入。
  • 谢谢约翰,但也许这不是我真正需要的。我试图更好地解释。我需要一个脚本来创建一个先进先出,写入两个数字并关闭先进先出。然后我需要一个打开fifo的secon脚本,读取已写入的内容,将已读取的内容打印出屏幕并最终终止。
  • @Ciccio 来自man fifo:“FIFO 必须在两端(读取和写入)都打开才能传递数据。通常,打开 FIFO 块直到另一端也打开。”您的应用程序听起来更适合使用普通文件进行消息传递。
【解决方案2】:

您的设置问题在于,如果您希望在阅读器实际运行时控制对时间的 fifo 访问,那么您在错误的脚本中创建了 fifo。为了纠正问题,您需要执行以下操作:

读者:fifo_read.sh

#!/bin/bash

fifo_name="/tmp/myfifo"                         # fifo name

trap "rm -f $fifo_name" EXIT                    # set trap to rm fifo_name at exit

[ -p "$fifo_name" ] || mkfifo "$fifo_name"      # if fifo not found, create

exec 3< $fifo_name                              # redirect fifo_name to fd 3
                                                # (not required, but makes read clearer)
while :; do
    if read -r -u 3 line; then                  # read line from fifo_name
        if [ "$line" = 'quit' ]; then           # if line is quit, quit
            printf "%s: 'quit' command received\n" "$fifo_name"
            break
        fi
        printf "%s: %s\n" "$fifo_name" "$line"  # print line read
    fi
done

exec 3<&-                                       # reset fd 3 redirection

exit 0

作者:fifo_write.sh

#!/bin/bash

fifo_name="/tmp/myfifo"

# Se non esiste, exit :);
[ -p "$fifo_name" ] || {
    printf "\n Error fifo '%s' not found.\n\n" "$fifo_name"
    exit 1
}

[ -n "$1" ] && 
    printf "%s\n" "$1" > "$fifo_name" || 
    printf "pid: '%s' writing to fifo\n" "$$" > "$fifo_name"

exit 0

操作:(在第一个终端启动阅读器)

$ ./fifo_read.sh                         # you can background with & at end

(在第二个终端启动编写器)

$ ./fifo_write.sh "message from writer"  # second terminal
$ ./fifo_write.sh
$ ./fifo_write.sh quit

在第一个终端输出:

$ ./fifo_read.sh
/tmp/myfifo: message from writer
/tmp/myfifo: pid: '28698' writing to fifo
/tmp/myfifo: 'quit' command received

【讨论】:

  • +1 您解决了手头的问题,但请注意:read -r line&lt;$fifo_name 会不会更好?因为现在 reader 脚本将在第一条消息后进入 CPU 密集型循环。 given by John1024 的方法也是如此。
  • 谢谢。正如评论中所指出的,持续重定向到 fd3 是不必要的,其目的只是为了保持脚本逻辑清晰,从而使 fifo 明显被重定向并用于提供读取。 (它还提供了显示从自定义文件描述符读取的机会——如果在单个循环中从多个 fd 读取(例如 fd3 和标准输入),这是必要的。我看不出有任何理由你的方法不能同样有效随手一试。
【解决方案3】:

以下脚本应该可以完成这项工作:

#!/bin/bash

FIFO="/tmp/fifo"

if [ ! -e "$FIFO" ]; then
        mkfifo "$FIFO"
fi

for script in "$@"; do
        echo $script > $FIFO &
done

while read script; do
        /bin/bash -c $script
done < $FIFO

给定两个脚本 a.sh 和 b.sh,其中两个脚本分别将“a”和“b”传递给标准输出,将得到以下结果(假设上面的脚本称为 test.sh):

./test.sh /tmp/a.sh /tmp/b.sh
a
b

最好, 朱利安

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-04
    • 1970-01-01
    • 2017-04-24
    • 2021-04-29
    • 1970-01-01
    相关资源
    最近更新 更多