You can use tail -f
to keep reading from the file as it grows. Be careful with what you feed tail -f
into. You can pipe tail -f
into a filter that waits until the desired log line and quits. What won't work is if you pipe tail -f
into a filter that pipes into another filter, because the intermediate filter will buffer its output. This works:
: >file.log # create an empty log file
start-selenium-session --log-file=file.log &
{ tail -n +1 -f file.log & } | sed -n '/Started SocketListener/q'
speak-to-socket
Note that I put tail
in the background. This is because when sed
finds the desired line, it exits, but the pipeline keeps running as long as tail
is waiting for the next line, which may not come immediately if at all¹. tail
will exit when the next line comes and it receives a SIGPIPE
. This may leave a stray tail
process if the log is removed without any line being written to it (obtaining the PID of the tail
process to kill it when sed
exits would be possible but tricky).
¹ Thanks to Peter.O for pointing out the bug in an earlier version.
As others have said, there isn't any way to wait on "not" a process ID. However this pattern of code doesn't seem that bad to me, so I offer it as a suggested way of achieving what you're after.
It makes use of Bash arrays which you can then give as a list to the wait
command.
Example
A modified version of your example code, cmd.bash
.
!/bin/bash
array[0]=1
array[0]=2
sleep 30 &
pid=$!
pidArr=()
for i in ${array[@]}; do
for n in $(seq 3); do
if [ $n -eq 1 ]; then
sleep 31 > file &
pidArr+=($!)
else
sleep 32 >> file &
pidArr+=($!)
fi
done
done
echo ${pidArr[@]}
I've substituted sleep
commands in this example just to simulate some long running jobs that we can background. They have nothing to do with this other than to act as stand-ins.
Also the final echo
command is there purely so we can see what happens when the for loops complete. Ultimately we'll replace it with an actual wait
command, but let's not get ahead of ourselves.
Example run #1
So let's run our program and see what happens.
$ ./cmd.bash
24666 24667 24668
Now if we check ps
:
$ ps -eaf|grep sleep
saml 24664 1 0 22:28 pts/9 00:00:00 sleep 30
saml 24666 1 0 22:28 pts/9 00:00:00 sleep 31
saml 24667 1 0 22:28 pts/9 00:00:00 sleep 32
saml 24668 1 0 22:28 pts/9 00:00:00 sleep 32
If we wait a bit, these will ultimately finish. But this shows that if we add the process IDs to an array we can echo
them out afterwards.
Example #2
So let's change that echo
line out and swap in a wait
line now, something like this:
wait ${pidArr[@]}
Now when we run our modified version we see that it's waiting on ALL the process IDs:
$ ./cmd.bash
...after ~30 seconds passes
$
We get back our prompt. So we successfully waited for all the processes. A quick check of ps
:
$ ps -eaf|grep sleep
$
So it worked.
Best Answer
this will start an infinite while loop that echos a spinner every second, executed in the background.
Instead of the
sleep10
command run any command you want.When that command finishes executing this will kill the last job running in the background (which is the infinite while loop)
source: https://stackoverflow.com/a/16348366/1069083
You can use various while loops instead, e.g. a spinner like this: