从命名管道读取错误
Wrong read from a named pipe
我有一个从命名管道读取命令的脚本:
#! /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
不知何故脚本无法读取它从管道获得的所有字符串?怎么读?
您必须有一个以上的 reader 命名管道 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
一旦您拥有多个具有这种消费模式的进程,任何一个进程都会看到丢失的字符。
我有一个从命名管道读取命令的脚本:
#! /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
不知何故脚本无法读取它从管道获得的所有字符串?怎么读?
您必须有一个以上的 reader 命名管道 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
一旦您拥有多个具有这种消费模式的进程,任何一个进程都会看到丢失的字符。