Erkennen eines erfolgreichen / fehlgeschlagenen Uploads in einer Skript-Befehlszeilen-SFTP-Sitzung?


7

Ich schreibe ein BASH-Shell-Skript, um alle Dateien in einem Verzeichnis auf einen Remote-Server hochzuladen und sie dann zu löschen. Es wird alle paar Stunden über einen CRON-Job ausgeführt.

Mein komplettes Skript ist unten. Das Grundproblem ist, dass der Teil, der herausfinden soll, ob die Datei erfolgreich hochgeladen wurde oder nicht, nicht funktioniert. Der Exit-Status des SFTP-Befehls ist immer "0", unabhängig davon, ob der Upload tatsächlich erfolgreich war oder nicht.

Wie kann ich herausfinden, ob eine Datei korrekt hochgeladen wurde oder nicht, damit ich weiß, ob ich sie löschen oder zulassen soll?

#!/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 bob@ftp.example.edu

    # 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 bob@example.edu

Aufgrund einiger betrieblicher Überlegungen, die meinen Kopf verletzen, kann ich SCP nicht verwenden. Der Remote-Server verwendet WinSSHD unter Windows und verfügt nicht über EXEC-Berechtigungen. Daher schlagen SCP-Befehle mit der Meldung "Exec-Anforderung auf Kanal 0 fehlgeschlagen" fehl. Das Hochladen muss daher über den interaktiven SFTP-Befehl erfolgen.

Antworten:


8

Wenn Sie Ihre SFTP-Sitzung stapeln, zeigt der Exit-Status $?an, ob die Übertragung fehlgeschlagen ist oder nicht.

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

Bearbeitet, um hinzuzufügen: Dies ist etwas, das wir in einem Produktionsskript bei der Arbeit verwenden, daher bin ich sicher, dass es gültig ist. Wir können scp nicht verwenden, da einige unserer Kunden mit SCO Unix arbeiten.


Ich habe keine umfangreichen Tests durchgeführt, aber ich denke, der Batch-Modus ändert, wie sftpExits und welcher Exit-Status angezeigt werden. Ich bin froh, dass das den Trick gemacht hat.
UtahJarhead

sftp erweist sich als ziemlich kniffliges kleines Tier. Es unterstützt weder die einfache Operation, eine Datei in einen Einzeiler zu legen (ohne Shell-Gymnastik), noch macht es Ihnen die Mühe, Sie wissen zu lassen, ob ein Fehler aufgetreten ist, es sei denn, Sie fragen ausdrücklich danach. Es ist, als ob diese Einschränkungen absichtlich hinzugefügt wurden, obwohl sie keinen Sinn ergeben. Wie auch immer, es stellt sich heraus, dass Sie Batch und einen Bindestrich verwenden können, um immer noch von stdin zu lesen. Vielen Dank, es hat funktioniert. Verwenden von: echo 'put [somefile]' | sftp -b - [remotehost]
Teekin

Sind Sie sicher, dass Sie für Ihr Szenario nicht wollen scp?
UtahJarhead

1

Es ist die Tradition von Serverfault, die Voraussetzungen nicht übermäßig in Frage zu stellen, aber ich muss fragen: Ist es Ihnen nicht möglich, entweder 1) das Remote-Dateisystem über SMB zu mounten oder 2) stattdessen fuse / sshfs zu verwenden? (Ich gehe hier davon aus, dass der sendende Computer eine Linux-Box ist, da Sie bash und ssh verwenden.)

Um Ihre Frage tatsächlich zu beantworten, denke ich, dass Ihr Problem einfach ist. Erwägen:

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

Versuchen Sie es stattdessen so:

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

Zur Erklärung: Ihre zweite if-Anweisung "if [$ ?! =" 0 "]; dann" testet auf den Exit-Status der letzten Anweisung, die nicht mehr sftp ist, sondern die vorherige if-Anweisung.

Dann frage ich mich, ob sftp wirklich mit einem Wert ungleich Null beendet wird, wenn es Probleme beim Hochladen von Dateien hat. Flüchtige Tests zeigen, dass meine dies nicht tun.


Dies ist ein guter Tipp - ich habe nicht verstanden, dass jede IF-Anweisung die Exit-Statusvariable geändert hat. Also, +1, und ich habe mein Skript angepasst, um dies widerzuspiegeln. Aber SFTP beendet das Skript tatsächlich wie oben beschrieben ungleich Null - ich denke, weil der Befehl "quit" erfolgreich ist. Wenn Sie eine Batch-Datei verwenden (wie in einer anderen Antwort), wird der richtige Exit-Code generiert. Zwischen den beiden Antworten funktioniert es also meiner Meinung nach.
Will Martin

0

Benutze rsync(.exe)und grabe in --remove-source-files& co., Kümmere dich nicht einmal um fehlgeschlagene Uploads, das wird er! ;-);

Ja, Sie können dies mit ssh verknüpfen --rsh


0

Jarhead

Wie wäre es mit einem SFTP-Batch-Skript unter Windows, um Erfolg / Misserfolg zu erkennen?

Ich verwende% errorlevel%, um Erfolg / Misserfolg zu erkennen. Manchmal wird% errorlevel% um 0 zurückgegeben, aber diese Sitzung ist fehlgeschlagen und die Datei wird nicht auf den Server hochgeladen. Mein Skript ist unten

Wie kann ich das hochgeladene SFTP erkennen? vielen Dank

@echo off
(echo cd %4
  echo put %2
  echo exit)>sftpScript.txt
sftp -b sftpScript.txt %3
set result=%errorlevel%
if result EQU 0 (
  del sftpScript.txt
  del %2
) else (
  del sftpScript.txt
)
exit %result%

0

** bearbeitet, um tatsächlich eine Batch-Datei zu verwenden Zum Erweitern der Batch-basierten Lösung.
Auf der von mir ausgeführten SFTP-Kopie wird eine Batch-Datei bei einem Fehler beendet, auch wenn mehrere Befehle jenseits des Fehlerpunkts vorhanden sind

Nach der ursprünglich veröffentlichten Logik testen Sie durch Überprüfen von $? Das Ergebnis des gesamten Stapels. Wenn Sie einige der Dateien entfernen möchten, die erfolgreich übertragen wurden, erstellen Sie die Batch-Datei mit! Rm nach jedem Put. Wenn der Put fehlschlägt, wird der! Rm nicht ausgeführt

(for F in *.pgp
do
echo put $F
echo !rm $F
done;echo quit) > Batchfile ; sftp -b Batchfile user@targetServer
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.