Check if remote destination is available before running scp command

I have a script on a Linux box which scp the files to windows server without any issues. but there are time frames where the windows server will not be available due to maintenance. hence I need to check if the remote location is available before running the scp command.

scp /path/to/file/filename user@host:/destination/path/

I tried with ssh command to check if remote directory exists but does not work and get the error message below

ssh user@host test -d /destination/path/ && echo exists
exec request failed on channel 0

You could try a simple ping host before running the scp , but there is always the chance that your Windows server will go down between the time that you run the ping and the time that you run the scp .

It is frequently easier to just check whether or not the scp command succeeds...

if scp "$sourcepath" "$destpath"
then	echo "scp of $sourcepath to $destpath succeeded"
else	# Add "scp $sourcepath $destpath" to a list of copy commands that
	# need to be rerun later.
	echo "scp \"$sourcepath\" \"$destpath\"" >> /path/to/todo_list
	# Note that the diagnostic from scp will serve as your visual
	# indication that the scp failed this time, but you can also add
	# your own diagnostic here if you want to.
fi

or even just:

scp "$sourcepath" "$destpath" &&
    echo "scp \"$sourcepath\" \"$destpath\" succeeded" ||
    echo "scp \"$sourcepath\" \"$destpath\"" >> /path/to/todo_list

Use ssh-option connecttimeout to not have to wait so long for the error to occur:

scp -o ConnectTimeout=5 file user@host:/dir/

In my ruby scripts for ssh i use the following steps(layed out in bash here) to set up an ssh connection, which wastes as little time as possible:

#!/bin/bash

LC_ALL=C
SSH_PORT=22
SSH_OPTS="-o ConnectTimeout=5 -o PasswordAuthentication=No"

export LC_ALL SSH_PORT SSH_OPTS

ping_test()      { ping -w 3 -i 0.2 -c3 "$1" &>/dev/null ; }
port_test()      { nmap -p $SSH_PORT -P0 "$1" | grep -qE "$SSH_PORT/tcp.*open" ; }
sshd_test()      { ssh -o Port=$SSH_PORT $SSH_OPTS -v "$1" date 2>&1 | grep -qE "Remote protocol version [0-9]+" ; }
ssh_login_test() { ssh -o Port=$SSH_PORT $SSH_OPTS "$1" echo ssh connect success 2>&1 | grep -qE "ssh connect success" ; }

check_ssh() {
  
   local target="$1"
   ping_test       "$target"    || return 1
   port_test       "$target"    || return 2
   sshd_test       "$target"    || return 3
   ssh_login_test  "$target"    || return 4   # this can be done as the same step with the step before
   return 0

}

# -- start of main program  

if check_ssh my_hostname; then
  if scp ... 
     ...
  fi
fi
1 Like

Just a word of caution about nmap in that it can be badly used too easily and excessive or injudicious use may be seen as a hacking attempt by either the target host(s) or networks and automatic defences may be causing you to get blocked or may trigger blocking future connections if you are too aggressive in your probing.

Is it the very long timeout that you are worried about? I agree that you should try the option -o ConnectTimeout=5 where 5 is a configurable number of seconds to wait for the connection to open. Don't make it too short or you may always fail to connect.

I hope that this helps,
Robin