【问题标题】:Wrong read from a named pipe从命名管道读取错误
【发布时间】:2020-07-18 03:08:15
【问题描述】:

我有一个从命名管道读取命令的脚本:

#! /usr/bin/env bash
host_pipe="host-pipe"

#pipe for executing commands
[ -p "$host_pipe" ] || mkfifo -m 0600 "$host_pipe" || exit 1 
chmod o+w "$host_pipe"

set -o pipefail

while :; do
    if read -r cmd <$host_pipe; then
        if [ "$cmd" ]; then
            printf 'Running: %s \n' "$cmd"
        fi
    fi
done

我运行它并使用命令进行测试:

bash -c "echo 'abcdef' > host-pipe"
bash -c "echo 'abcdef' > host-pipe"
bash -c "echo 'abcdef' > host-pipe"
bash -c "echo 'abcdef' > host-pipe"

然后得到奇怪的输出:

Running: abcdf 
Running: abcdef 
Running: abcde 
Running: abcdf 
Running: ace

不知何故,脚本无法读取它从管道中获取的所有字符串?怎么读?

【问题讨论】:

  • 你在哪个bash 版本上运行这个?无法在 GNU bash v4.4 上重现此内容
  • 几个 nitpicks - 1. 您不必使用子 shell 来写入 fifo,只需 echo 'abcdef' &gt; host-pipe 就足够了 2. 也不要使用 [ "$cmd" ] 进行检查字符串是否为空,您很幸运,该字符串已被引用,但[..] 下的未引用字符串可能会产生不良结果。使用[ ! -z "$cmd" ][[ $cmd ]]

标签: bash pipe named-pipes


【解决方案1】:

您必须运行多个命名管道host-pipe 的读取器才能发生这种情况。

检查您是否有脚本的第二个实例在后台运行或可能在另一个终端中运行。

说明

您会发现bash 将一次从管道发出 1 个字节的读取。如果你在 Linux 上,你可以strace你的脚本。摘录如下:

open("host-pipe", O_RDONLY|O_LARGEFILE) = 3
fcntl64(0, F_GETFD)                     = 0
fcntl64(0, F_DUPFD, 10)                 = 10
fcntl64(0, F_GETFD)                     = 0
fcntl64(10, F_SETFD, FD_CLOEXEC)        = 0
dup2(3, 0)                              = 0
close(3)                                = 0
ioctl(0, TCGETS, 0xbf99bfec)            = -1 ENOTTY (Inappropriate ioctl for device)
_llseek(0, 0, 0xbf99c068, SEEK_CUR)     = -1 ESPIPE (Illegal seek)
read(0, "a", 1)                         = 1
read(0, "b", 1)                         = 1
read(0, "c", 1)                         = 1
read(0, "d", 1)                         = 1
read(0, "e", 1)                         = 1
read(0, "f", 1)                         = 1
read(0, "\n", 1)                        = 1
dup2(10, 0)                             = 0
fcntl64(10, F_GETFD)                    = 0x1 (flags FD_CLOEXEC)
close(10)                               = 0

一旦您有多个具有这种消费模式的进程,任何单个进程都会看到丢失的字符。

【讨论】:

  • 哦,你是对的!我在后台有另一个脚本实例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-03
  • 1970-01-01
  • 1970-01-01
  • 2023-03-09
  • 2017-12-12
相关资源
最近更新 更多