6

I try to do the following in a Bash script: run a command (such as tail -f log_file), wait until a specific output arrives, then stop the command, and go on with the script.

I tried the following, but it didn't work:

tail -f log_file | grep some_text | head -n1

I got no output this way.

Now, I tried to diagnose the problem. When I simply run tail -n1, then type something into the terminal, it exits after the first line. However, if I run the following:

grep some_text | head -n1

In this case, I get no output until I press CTRL+D, and then it prints the first line of the input containing some_text.

My question is, why is this? If head outputs the first line immediately in the first case, why doesn't it do when it gets the input from a pipe? Shouldn't it output everything for the first n lines, then exit, sending a SIGPIPE signal to the other end of the pipe?

petersohn
  • 2,708

2 Answers2

3

grep buffers your input. Try grep --line-buffered.

There's an additional problem, head will only terminate after it receives a second line which can be a problem if your logfile is low-frequency. See How to read one line from tail -f through a pipeline, and then terminate?.

peth
  • 10,400
0

When you run tail -n1 with no input, it will exit after the first line of input from STDIN, that is how it should work. When you run grep some_text | head -n1 you are again not supplying any input to grep, so it would seem that the behavior that I think you are describing is normal. When you press CTRL D, you are closing the STDIN pipe, and head -n1 is outputting what `grep received from STDIN.

Kirk
  • 2,472