在脚本命令行 SFTP 会话中检测上传成功/失败?

在脚本命令行 SFTP 会话中检测上传成功/失败?

我正在编写一个 BASH shell 脚本,用于将目录中的所有文件上传到远程服务器,然后删除它们。它将通过 CRON 作业每隔几个小时运行一次。

下面是我的完整脚本。基本问题是,应该确定文件上传是否成功的部分不起作用。无论上传是否成功,SFTP 命令的退出状态始终为“0”。

我如何才能确定文件是否正确上传,以便知道是否要删除它或保留它?

#!/bin/bash

# First, save the folder path containing the files.
FILES=/home/bob/theses/*

# Initialize a blank variable to hold messages.
MESSAGES=""
ERRORS=""


# These are for notifications of file totals.
COUNT=0
ERRORCOUNT=0

# Loop through the files.
for f in $FILES
do
    # Get the base filename
    BASE=`basename $f`

    # Build the SFTP command. Note space in folder name.
    CMD='cd "Destination Folder"\n'
    CMD="${CMD}put ${f}\nquit\n"


    # Execute it.
    echo -e $CMD | sftp -oIdentityFile /home/bob/.ssh/id_rsa [email protected]

    # On success, make a note, then delete the local copy of the file.
    if [ $? == "0" ]; then
        MESSAGES="${MESSAGES}\tNew file: ${BASE}\n"
        (( COUNT=$COUNT+1 ))

        # Next line commented out for ease of testing
        #rm $f
    fi

    # On failure, add an error message.
    if [ $? != "0" ]; then
        ERRORS="${ERRORS}\tFailed to upload file ${BASE}\n"
        (( ERRORCOUNT=$ERRORCOUNT+1 ))
    fi

done

SUBJECT="New Theses"

BODY="There were ${COUNT} files and ${ERRORCOUNT} errors in the latest batch.\n\n"

if [ "$MESSAGES" != "" ]; then
    BODY="${BODY}New files:\n\n${MESSAGES}\n\n"
fi

if [ "$ERRORS" != "" ]; then
    BODY="${BODY}Problem files:\n\n${ERRORS}"
fi

# Send a notification. 
echo -e $BODY | mail -s $SUBJECT [email protected]

由于一些让我头疼的操作考虑,我无法使用 SCP。远程服务器在 Windows 上使用 WinSSHD,并且没有 EXEC 权限,因此任何 SCP 命令都会失败,并显示消息“通道 0 上的 Exec 请求失败”。因此必须通过交互式 SFTP 命令进行上传。

答案1

如果您批量处理 SFTP 会话,退出状态$?将告诉您传输是否失败。

echo "put testfile1.txt" > batchfile.txt
sftp -b batchfile.txt user@host
if [[ $? != 0 ]]; then
  echo "Transfer failed!"
  exit 1
else
  echo "Transfer complete."
fi

编辑后添加:这是我们在工作中的生产脚本中使用的内容,因此我确信它是有效的。我们不能使用 scp,因为我们的一些客户使用的是 SCO Unix。

答案2

serverfault 的传统是不过度质疑先决条件,但我不得不问:您是否不能 1) 通过 SMB 挂载远程文件系统,或者 2) 改用 fuse/sshfs?(我在这里假设发送机器是 Linux 机器,因为您使用的是 bash 和 ssh。)

实际上,要回答你的问题,我认为你的问题很简单。考虑一下:

quest@wonky:~$ false
quest@wonky:~$ if [ $? != "0" ] ; then echo asdf ; fi
asdf
quest@wonky:~$ if [ $? != "0" ] ; then echo asdf ; fi

尝试这样做:

quest@wonky:~$ false
quest@wonky:~$ res=$?
quest@wonky:~$ if [ $res != "0" ] ; then echo asdf ; fi
asdf
quest@wonky:~$ if [ $res != "0" ] ; then echo asdf ; fi
asdf

解释一下:你的第二个 if 语句“if [ $? != "0" ]; then”测试最新语句的退出状态,它不再是 sftp,而是前一个 if 语句。

然后我想知道,如果 sftp 在上传文件时出现问题,它真的会以非零值退出吗?粗略的测试表明我的不会。

答案3

使用rsync(.exe)并深入研究--remove-source-files,甚至不关心上传失败,他会的!;-)

是的,你可以用 ssh 来绑定它,看看--rsh

答案4

** 编辑为实际使用批处理文件以扩展基于批处理的解决方案。
在我运行的 sftp 副本上,批处理文件在出现错误时退出,即使错误点之外存在多个命令

根据最初发布的逻辑,通过检查 $?,您正在测试整个批处理的结果。如果您同意删除一些已成功传输的文件,则在每次 put 后​​使用 !rm 构建批处理文件。如果 put 失败,!rm 将不会运行

(for F in *.pgp
do
echo put $F
echo !rm $F
done;echo quit) > Batchfile ; sftp -b Batchfile user@targetServer

相关内容