Script for testing SFTP login status?
Solution 1
Most "SSH File Transfer Protocol (SFTP) clients" are primarily/initially built for interactive use.
This doesn't mean that they lack batch mode options and such, but if you're looking for a script based file transfer over the SSH protocol, have a look at scp or lftp instead.
lftp (homepage) is what I use in all my automated file transfers, and it has excellent error handling with reliable exit status. It was designed with reliability in mind.
There are tons of options to lftp, and you can supply any ssh options you like, such as -oStrictHostKeyChecking=yes if you specify a specific connection program to use.
Example:
MYSSHOPTIONS="-oStrichtHostKeyChecking=yes"
CONNPROG="ssh -a -x ${MYSSHOPTIONS}"
cat > ${cmdfile} <<- EOF
set sftp:max-packets-in-flight 16
set sftp:connect-program ${CONNPROG}
open -u ${remoteuser},${password-unless-pubkey-setup} sftp://${remotehost}
put localfile -o remotepathname
EOF
lftp -f ${cmdfile} > ${sendlog} 2>&1
RC=$?
if test $RC -ne 0
then
failed
else
reliably OK
fi
The example is a bit long. It creates a command file that sets some options and uploads one file localfile with optionally another remotepathname on the other side.
sftp variant if you don't want to use lftp:
If you are interested in checking sftp login access you can use this template as a starting point for further experimenting:
#!/bin/sh -
mykey=/home/localuser/.ssh/id_rsa
remusr=bupuser
remhost=server.destination.domain.com
tmpfile=/tmp/sftptest.$$
cleanup() {
rm -f ${tmpfile}
}
trap cleanup 0
sftp -i $mykey -oPubkeyAuthentication=yes -oPasswordAuthentication=no -oKbdInteractiveAuthentication=no -oStrichtHostKeyChecking=yes ${remusr}@${remhost} ${tmpfile} 2>&1
dir
exit
EOF
ST=$?
if test $ST -ne 0
then
echo SFTP LOGIN FAILURE. RC=${ST} 1>&2
exit $ST
fi
cat ${tmpfile} # or do some clever grepping on it
exit $ST
Solution 2
I've written expect and bash scripts to work this.... (though it can get fancier as mentioned above).
Bash script:
executed with three arguments: user, pass, and host. For example ./bwrap.sh ninja_user ninja_star1234 ninja.com
The script creates a log file which later used for checking successful log in/out.
#!/bin/bash
# log file
log="connection_test.log"
if [ -f $log ];
then
echo "Older file $log exists, removing and creating new..."
rm -rf $log
touch $log
else
echo "Creating log file"
touch $log
fi
# running expect script.
# arg 1 is user, arg 2 is pass, arg 3 is host
./one.exp $1 $2 $3 >> $log
# checking log for connections
if grep --quiet logout $log; then
echo "connection successful, proceeding to backup" >> $log
else
echo "connection failed, please check server" >> $log
exit 1
fi
Now to the expect script, it has a timeout of 10 seconds, and I actually prefer to work w/o strict host key. If you do want to work with strict host key edit the relevant line and add an expect "yes/no" ....
#!/usr/bin/expect -f
set user [lindex $argv 0];
set password [lindex $argv 1];
set host [lindex $argv 2];
set timeout 10
# now ssh
spawn ssh [email protected]$host -o StrictHostKeyChecking=no
match_max 100000 # Look for passwod prompt
expect "*?assword:*"
# Send password aka $password
send -- "$password\r"
expect "*$ "
send -- "whoami\r"
expect "<user name>" # change user
send -- "exit\r"
expect eof
Hope this helps.
For sftp connection please:
add line to bash script where $4 is port
./one.exp $1 $2 $3 $4 >> $log
add line to expect script:
set port [lindex $argv 3];
replace in expect script
spawn ssh [email protected]$host -o StrictHostKeyChecking=no
with
spawn sftp [email protected]$user -o Port=$port StrictHostKeyChecking=no
and
expect "*$ "
with
expect "sftp>"
Since I do not have an SFTP server to test it on, the changes are made based on [this question]: sftp a file using shell script
Also, [expect homepage]: http://expect.sourceforge.net/ might be handy.
Lastly, reading your comment regarding a straight forward approach, it's possible to simply use nc and see if the host:port is up. For this you can use:
#!/bin/bash
# log file
log="connection_test.log"
if [ -f $log ];
then
echo "Older file $log exists, removing and creating new..."
rm -rf $log
touch $log
else
echo "Creating log file"
touch $log
fi
# nc
nc_command=`nc -z -w 5 $1 $2 | tee -a $log`
if [[ $nc_command == *succeeded* ]];
then
echo "Server is listening, ready for backup" | tee -a $log
else
echo " Server seems to be offline, please check" | tee -a $log
exit 1
fi
To run the last script use: ./test.sh host port
Related videos on Youtube
Question Overflow
I don't have any formal education on programming. I guess it is the passion that gets me started and keeps me going. Thanks everybody for sharing your knowledge. Don't worry, I am no critic. I see no wrong answer, only good and not so good answers. All are welcome to learn and to share.
Updated on September 18, 2022Comments
-
Question Overflow 3 monthsI need to perform an automated backup task that connects to an SFTP server. The first stage involves testing the server connection by connecting to it. To be absolutely sure that it is connecting to the correct server, I am setting the
StrictHostKeyCheckingin ssh_config to yes.So, when the connection to the SFTP server is made, how do I script the response from the server. The pseudo code is as follows:
If connection success disconnect initiate backup procedure Else log error exit scriptAdditional Info:
I am using
ForceCommand internal-sftpin the backup server's sshd_config, so runningsshcommand is out of the question.-
MattBianco over 8 yearsI've provided a shell script in my answer that you can use the exit code from in the "connection success test". It includes the "disconnect" part. The only way I can think of to do the checking and other dependant logic branching inside the same sftp session is to script it withexpect/tclwhich never becomes elegant, as it is very hard to parse text and foresee any possible error conditions before you have found them the first time. Using for examplelftp, the client itself checks the sftp-protocol's built-in status response codes. This makes catching errors easy.
-
-
MattBianco over 8 yearsassuming that the SFTP server allows SSH login -
Belmin Fernandez over 8 yearsCorrect. I've used annmapcommand line for servers that do not allow SSH login. I'll add that to the answer just in case it's useful. Thanks! -
MattBianco over 8 yearsNo, I mean the ssh shell subsystem. You can configuresshdto only allow (or force)sftponly. The user account can have a shell that only allows sftp, and so on. -
Question Overflow over 8 yearsThank you. Can this be modified to connect withsftpcommand instead ofssh? Have updated my question to clarify that point. -
Question Overflow over 8 yearsThank you. I think this may be useful though I was expecting something more straight forward. Seems like all answers here seems to suggest that it is not possible to obtain status from sftp directly. -
Simply_Me over 8 years@QuestionOverflow Yes, please review edits at the bottom. Note that I do not havesftpto connect to, so this is based from examples. -
Simply_Me over 8 years@QuestionOverflow added lines needed to change tosftpand another solution using more straight forward approach. -
MattBianco over 8 yearsWell.. If you're mainly interested in validating that login is possible and that you are connecting to the correct server, scripting it with the normalsftpclient from the openssh package is certainly possible if you have set up public key authentication and don't mind parsing stdout output for extra safety. If you want it robust and easy to expand I recommendlftpthough. It is very easy and has many features you might want later on. It's just my example that is not so pretty. -
Question Overflow over 8 yearsThank you. I think I will adopt your method and pipestdouttodev/nullso that cron will not send me email every time.