I have a script which reads commands 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
I run it and test with command:
bash -c "echo 'abcdef' > host-pipe"
bash -c "echo 'abcdef' > host-pipe"
bash -c "echo 'abcdef' > host-pipe"
bash -c "echo 'abcdef' > host-pipe"
And get the strange output:
Running: abcdf
Running: abcdef
Running: abcde
Running: abcdf
Running: ace
Somehow the script can't read all the string it get from the pipe? How to read it?
You must have more than one reader of the named pipe host-pipe
running for this to happen.
Check to see if you have a second instance of the script running in the background or possibly in another terminal.
You will find that bash
will issue reads from the pipe 1 byte at a time. If you are on Linux, you can strace
your script. Here is an excerpt:
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
Once you have more than one process with this consumption pattern, any single process will see lost characters.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With