3

I need to ssh into a server and check for a service to see if it is up and running. What i do is to use ssh and run a command which calls that service and check the output of that command. I want to have a progress bar to show the user that the script is trying to check the status of the service; but I am not able to run the progress bar function while ssh command is not returned from the server! (ssh must wait for the service to fully start before it can check the status) and I miss that part of the progress.

Is there a standard way to deal with such a scenario?

My ssh command is something like this:

State=$(ssh host "app-status")

And it should return something like:

Status OK
Vombat
  • 12,884

3 Answers3

5

You can run ssh in the background and have it write its output to a FIFO

#! /bin/bash
mkfifo fifo-ssh
(ssh host "app-status"; echo error;) >fifo-ssh &
exec 3<>fifo-ssh
until read -t 1 -u 3 status; do
  echo -n .
done
# if [ "$status" = error ]; then...
Hauke Laging
  • 90,279
5

Alternative to Hauke's that doesn't involve creating a named pipe (and the hassle associated with exclusive access, cleanup... of it), that preserves the exit status, and supports multi-line output:

result=$(
  {
    {
      ssh host app-status >&3 3>&-; echo "$?"
    } | {
      until read -t1 ret; do
        printf . >&2
      done
      exit "$ret"
    }
  } 3>&1
)

should work in zsh, ksh93 and bash ($status is special (an alias for $?) in zsh like in (t)csh).

Above, we've got a subshell ({ ssh ...; echo "$?"; }) whose output goes to the until loop. Nothing is output by that subshell except the $? when ssh returns. ssh output itself goes to $result by way of file descriptor 3 which we've made to point to the pipe that feeds the command substitution.

So, while ssh is running, the read -t1 will timeout, and as soon as ssh returns, read will read the exit status and finish the loop.

More detailed explanation at this question that's a follow up on this one.

0

I found out that it is much simpler to run the progress bar in the background instead of the ssh command. Something like this:

function progress {
while :
do
    sleep 1
    echo -e ".\c"
done
}

progress &

PROGRESS_PID=$!

ssh_command_runs_here

status_check_command_here

kill -9 $PROGRESS_PID
Vombat
  • 12,884