bash sequence: wait for output, then start next program
Question
In my case I have to run openvpn
before ssh'ing into a server, and the openvpn
command echos out "Initialization Sequence Completed".
So, I want my script to setup the openvpn
and then ssh in.
My question is: How do you execute a command in bash in the background and await it to echo "completed" before running another program?
My current way of doing this is having 2 terminal panes open, one running:
sudo openvpn --config FILE
and in the other I run:
ssh SERVER
once the the first terminal pane has shown me the "Initialization Sequence Completed" text.
Solution
It seems like you want to run openvpn as a process in the background while processing its stdout in the foreground.
exec 3< <(sudo openvpn --config FILE)
sed '/Initialization Sequence Completed$/q' <&3 ; cat <&3 &
# VPN initialization is now complete and running in the background
ssh SERVER
Explanation
Let's break it into pieces:
echo <(sudo openvpn --config FILE)
will print out something like/dev/fd63
- the
<(..)
runs openvpn in the background, and... - attaches its stdout to a file descriptor, which is printed out by
echo
- the
exec 3< /dev/fd63
- (where /dev/fd63 is the file descriptor printed from step 1)
- this tells the shell to open the file descriptor (/dev/fd63) for reading, and...
- make it available at the file descriptor
3
sed '/Initialization Sequence Completed$/q' <&3
- now we run sed in the foreground, but make it read from the file descriptor
3
we just opened - as soon as sed sees that the current line ends with "Initialization Sequence Completed", it quits (the /q part)
- now we run sed in the foreground, but make it read from the file descriptor
cat <&3 &
- openvpn will keep writing to file descriptor
3
and eventually block if nothing reads from it - to prevent that, we run cat in the background to read the rest of the output
- openvpn will keep writing to file descriptor
The basic idea is to run openvpn
in the background, but capture its output somewhere so that we can run a command in the foreground that will block until it reads the magic words, "Initialization Sequence Completed". The above code tries to do it without creating messy temporary files, but a simpler way might be just to use a temporary file.
OTHER TIPS
Use -m 1
together with --line-buffered
in grep to terminate a grep after first match in a continuous stream. This should work:
sudo openvpn --config FILE | grep -m "Initialization Sequence Completed" --line-buffered && ssh SERVER