Hasherstellung für per sftp hochgeladene Dateien

Ausgangslage

Wie auch beim Kunden, bei dem das durch Lambda beim Upload passiert, soll mein sftp server auch für jedes .tar file das hochgeladen wird ein checksum für die Datei erstellt werden.
In der AWS wird das durch das auftauchen neuer .tar dateien "getriggert".

Abweichung von der AWS Lambda Lösung

Ich möchte an der Stelle keinen Dauerhaft laufenden Prozess zur überwachung des Verzeichnisses. Lieber einen minütlichen cronjob der schaut ob neue dateien vollständig eingetroffen sind.
Ich hab mehrer Probleme bei dieser Art der Umsetzung identifiziert.

  1. Sowohl Uploads als auch das erstellen eines SHA512 Hash kann je nach Grösse der Datei eine Weile dauern. Das Script soll aber nur ausgeführt werden wenn es noch nicht läuft
  2. anders als z.B. rsync taucht bei sftp die datei bereits unter dem endgültigen Namen auf, wärend der upload noch läuft. Das erstellen eines SHA512 Hash wärend des upload ist zu verhindern.
  3. es soll nur einmalig ein HASH erstellt werden. Also nur für Datein die noch keinen erhalten haben

Umsetzung

Die Lösung des 1. Problems hab ich bereits. Erstellen einer .lock datei die mit einem exit verhindert, dass das Script ausgeführt wird, wenn diese Lockdatei bereits vorhanden ist.

lockfile="$(cd $( dirname -- "$0");echo $PWD )/$(basename -- "$0"|sed "s/.sh$//").lock"
if [ -f $lockfile ]
then
        echo "lockfile exist"
        cat $lockfile
        echo $$
        exit 2
else
        echo $$ > $lockfile
fi
lockfile="$(cd $( dirname -- "$0");echo $PWD )/$(basename -- "$0"|sed "s/.sh$//").lock"
if [ -f $lockfile ]
then
        echo "lockfile exist"
        cat $lockfile
        echo $$
        exit 2
else
        echo $$ > $lockfile
fi

Die echos und das cat haben das Potential die cron mails zu zu spammen, sollten also später raus.
Nicht vergessen das lockfile nach jedem erfolgreichen run wieder zu löschen.


Für das 2. Problem habe ich mir gedacht, eine Lösung mit der Anzahl der Zeilen bei einem fstat auf die Datei zu verwenden. Da es in einer Schleife verwendet wird... (es kommen ja ggf n+ dateien pro Minute) müsst es aus dieser springen, wenn es bei Eintritt in die Schleife mehr als eine Zeile hat.
etwas wie

if [ $(fstat $i | wc -l) -gt 1 ]
then
    break
fi
if [ $(fstat $i | wc -l) -gt 1 ]
then
    break
fi

bei einem SFTP Job sind es z.B. 2 Zeilen

USER     CMD          PID   FD MOUNT        INUM  MODE         R/W    SZ|DV NAME
splunk_a sshd       30389    3 /home     3758401  -rw-r--r--     w 61046784 ./tarfrozentest.tar
USER     CMD          PID   FD MOUNT        INUM  MODE         R/W    SZ|DV NAME
splunk_a sshd       30389    3 /home     3758401  -rw-r--r--     w 61046784 ./tarfrozentest.tar

und bei einem Copy Job sind es 3 Zeilen

USER     CMD          PID   FD MOUNT        INUM  MODE         R/W    SZ|DV NAME

root     cp         34755    3 /home     3758401  -rw-r--r--    rp 551024640 /home/splunk_auditlog_user/tarfrozentest.tar
root     cp         34755    4 /home     3758405  -rw-r--r--    wp 292028416 /home/splunk_auditlog_user/tarfrozentest.tar3
USER     CMD          PID   FD MOUNT        INUM  MODE         R/W    SZ|DV NAME

root     cp         34755    3 /home     3758401  -rw-r--r--    rp 551024640 /home/splunk_auditlog_user/tarfrozentest.tar
root     cp         34755    4 /home     3758405  -rw-r--r--    wp 292028416 /home/splunk_auditlog_user/tarfrozentest.tar3

Das 3. Problem geht mit dem 2. Hand in Hand
Kommt es über die erst Hürde muss eine zweite Hürde her,
Wohl auch wieder mit einem Break

if [ -f ${i}.sha512]
then
    break
fi
if [ -f ${i}.sha512]
then
    break
fi

Dann nur noch das sha512sum auf die Datei formatiert in eine Datei schreiben.
Grad gut wenn das als root passiert, dann kann es nicht von aussen gelöscht werden anders als die tar dateien.


x Stunden der Fehlersuche. Und unter zuhilfe rufen von ChatGPT (KSH scheint bei manchen Sachen etwas mäkeliger als z.B. BASH) ist scheinbar ein ganz brauchbares Script rausgepurzelt.

#!/bin/ksh
lockfile="$(cd $( dirname -- "$0");echo $PWD )/$(basename -- "$0"|sed "s/.sh$//").lock"
if [ -f $lockfile ]
then
        echo "lockfile exist"
        cat $lockfile
        echo $$
        exit 2
else
        echo $$ > $lockfile
fi

cd /home/splunk_auditlog_user || exit

set -A files $(find . -name "*.tar" -type f)
if [ ${#files[@]} -eq 0 ]
then
    echo "Keine Files"
    rm $lockfile
    exit 3
fi

for file in "${files[@]}"
do
    cfsf=$(if [ $(fstat "$file" | wc -l | awk '{print $NF}') -gt 1 ]; then echo "unf";else echo "uf";fi)
    if [ "$cfsf" = "unf" ]
    then
            echo "${file} upload nicht beendet"
            continue
    fi

    if [ -f ${file}.sha512 ]
    then
            echo "${file}.sha512 exististiert"
            continue
    fi
    echo "Erstelle SHA512 fuer ${file}"
    sha512 $file | awk '{print $NF}' | tr -d "\n" > ${file}.sha512
done
rm $lockfile
#!/bin/ksh
lockfile="$(cd $( dirname -- "$0");echo $PWD )/$(basename -- "$0"|sed "s/.sh$//").lock"
if [ -f $lockfile ]
then
        echo "lockfile exist"
        cat $lockfile
        echo $$
        exit 2
else
        echo $$ > $lockfile
fi

cd /home/splunk_auditlog_user || exit

set -A files $(find . -name "*.tar" -type f)
if [ ${#files[@]} -eq 0 ]
then
    echo "Keine Files"
    rm $lockfile
    exit 3
fi

for file in "${files[@]}"
do
    cfsf=$(if [ $(fstat "$file" | wc -l | awk '{print $NF}') -gt 1 ]; then echo "unf";else echo "uf";fi)
    if [ "$cfsf" = "unf" ]
    then
            echo "${file} upload nicht beendet"
            continue
    fi

    if [ -f ${file}.sha512 ]
    then
            echo "${file}.sha512 exististiert"
            continue
    fi
    echo "Erstelle SHA512 fuer ${file}"
    sha512 $file | awk '{print $NF}' | tr -d "\n" > ${file}.sha512
done
rm $lockfile

Eine Iteration einfach über for file in $(find . -name "*.tar" -type f) war nicht möglich. Es muss erst ein Array daraus erstellt werden. Anders als erwartet, können die sha512 files doch über SFTP gelöscht werden
Obwohl diese als user root nur mit schreibrechten für den User ausgestattet sind.

-rw-r--r--  1 splunk_auditlog_user  splunk_auditlog_user  4294967296 Jun  4 01:41 db_1683913058_1683909363_41.tar
-rw-r--r--  1 root                  splunk_auditlog_user         128 Jun  4 01:42 db_1683913058_1683909363_41.tar.sha512
-rw-r--r--  1 splunk_auditlog_user  splunk_auditlog_user  4294967296 Jun  4 01:41 db_1683913058_1683909363_41.tar
-rw-r--r--  1 root                  splunk_auditlog_user         128 Jun  4 01:42 db_1683913058_1683909363_41.tar.sha512