0

In a shell script, I want to write to the stdin of an external process X using a named pipe, and I want to send the stdout/stderr from another named pipe to the current terminal.

The external process X is receiving stdin via PIPEIN and it's sending it's stdout/stderr to PIPEOUT.

tail -f $(tail -F PIPEOUT) &  # (1) this is completely wrong, need help here

for i; do
    echo "${i}" > PIPEIN  # send stdin to X
done

echo "[stdin end]" > PIPEIN  # signal that we are done writing (there might be a better way lol)

So in the above script, we have already started process X, it's been running for some time. But now, when we run the above script we want to send X some stdin and we want to read in the stdout from process X, using PIPEOUT.

What I am trying to do above is set-up a read on PIPEOUT before sending stdin to X, to make sure I capture all of the stdout/stderr of X. The problem is that I don't know how to run some background process (tail or cat to read from PIPEOUT) and send that stdio to the current terminal.

Does anyone know what I am talking about. If I am not mistaken, I just need to fix line labeled (1) and somehow setup a read in the background that can read from PIPEOUT and send that stdio to the current terminal/tty somehow.

2

I'm not clear on what you meant tail -f $(tail -F PIPEOUT) & to do. It's tail -fing the file that is the result of tail -F, which conventionally never terminates. My assumption is that you want to output everything that comes through the pipe, however long that takes.

The issue with just tail -f is that it has to find the end of the file before it outputs anything, which for the pipe never happens. You can give tail an explicit start point instead with -n +x, picking the line to start at (from the start, 1-indexed). tail -n 1 -f foo will display everything it can get from foo.

tr 'a-z' 'A-Z' < PIPEIN > PIPEOUT & # for example
tail -n +1 -f PIPEOUT &
for i in a b c d ; do
    echo $i > PIPEIN
done
echo "[stdin end]" > PIPEIN

Do note, however, that echo > foo will close foo after writing the line — the command on the other end will need to be happy to deal with that. If this example is artificial and the real input comes from somewhere else, you can disregard this.


Note also that the tail process will never terminate — it keeps expecting that something more might come through the pipe. You'll have to kill it explicitly yourself, perhaps with your shell's job control. If there's some pattern to the output that would indicate it was done, you might find retail ("tail with regular expressions") useful — retail -n +1 -f -u REGEX PIPEOUT will terminate when a line matching REGEX appears. (As a disclaimer, I wrote retail several years ago for this exact purpose)

  • Thanks, it's ok that tail -f won't end, the user can terminate it in this case manually...although it would better if there were a command that could capture all the stdio from X and then close, as X has a definite end. Maybe cat is better than tail, then. – Alexander Mills Jul 7 '17 at 9:24
  • If my original question wasnt clear, I am just looking for a command that can read the stdout/stderr from a named pipe, in some sort of streaming fashion. After I figure out that, I need to run it in the background, but still send the stdio from the background process to the terminal if that makes sense. – Alexander Mills Jul 7 '17 at 9:27
  • tail's output has always been going to the terminal. – Michael Homer Jul 7 '17 at 9:28
  • I am trying my best but I don't follow...is there a way to pipe data from a subshell to the parent? Does you answer already cover that? – Alexander Mills Jul 7 '17 at 9:30
  • Why don't you try it and see? I can't tell you what you wanted, only what was in the question. – Michael Homer Jul 7 '17 at 9:32
0

By only opening PIPEIN for writing once, the program terminates - even if there is a 2 second delay:

mkfifo PIPEIN PIPEOUT
tr 'a-z' 'A-Z' < PIPEIN > PIPEOUT & # for example
tail -n +1 -f PIPEOUT &
(
for i in a b c d ; do
    echo $i
done
sleep 2
echo "[stdin end]"
) > PIPEIN

If you open the fifo several times, then it may be seen as closed by the reader of the fifo, and thus the writer will be hung until another reader comes along to read from the fifo.

So the save bet is to only open PIPEIN once. Otherwise you may see that the program locks up.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.