Ich schreibe ein Bash-Skript für mich, um das Schreiben von Skripten zu lernen. Irgendwann muss ich Trap hinzufügen, um unerwünschte Verzeichnisse und Dateien zu bereinigen, wenn das Skript beendet wird. Aus irgendeinem Grund, den ich nicht verstehe, ruft Trap die Reinigungsfunktion auf clean_a()
- wenn das Skript beendet wird, zeigt aber $LINENO
auf eine Zeile in der Reinigungsfunktion selbst, nicht in der Funktion archieve_it()
- wenn das Skript beendet wird.
Erwartetes Verhalten:
- Skript ausführen
- Drücken Sie Ctrl+C
- Trap Caches Ctrl+ Cund ruft
clean_a()
Funktion auf clean_a()
Die Funktion gibt die Zeilennummer wieder, die Ctrl+ Cgedrückt wird. Lassen Sie es Zeile 10 in seinarchieve_it()
.
Was passiert eigentlich:
- Skript ausführen
- Drücken Sie Ctrl+C
- Trap Caches Ctrl+ Cund ruft
clean_a()
Funktion auf clean_a()
gibt eine irrelevante Zeilennummer wieder. Sagen wir, Zeile 25 inclean_a()
Funktion.
Hier ist ein Beispiel als Teil meines Skripts:
archieve_it () {
trap 'clean_a $LINENO $BASH_COMMAND'\
SIGHUP SIGINT SIGTERM SIGQUIT
for src in ${sources}; do
mkdir -p "${dest}${today}${src}"
if [[ "$?" -ne 0 ]] ; then
error "Something!"
fi
rsync "${options}" \
--stats -i \
--log-file="${dest}${rsync_log}" \
"${excludes}" "${src}" "${dest}${today}${src}"
done
}
clean_a () {
error "something!
line: $LINENO
command: $BASH_COMMAND
removing ${dest}${today}..."
cd "${dest}"
rm -rdf "${today}"
exit "$1"
}
PS: Original - Skript zu sehen ist hier . Definitionen und Variablennamen sind auf Türkisch. Wenn es benötigt wird, kann ich alles ins Englische übersetzen.
BEARBEITEN: Ich ändere das Skript so gut ich kann gemäß der Erklärung von @ mikeserv wie folgt:
#!/bin/bash
PS4='DEBUG: $((LASTNO=$LINENO)) : '; set -x
archieve_it () {
trap 'clean_a $LASTNO $LINENO $BASH_COMMAND'\
SIGHUP SIGINT SIGTERM SIGQUIT
..
}
clean_a () {
error " ...
line: $LINENO $LASTNO
..."
}
Wenn ich nun ein Skript mit ausführe set -x
und es mit Ctrl+ Cbeende, wird die richtige Zeilennummer ausgegeben, wie unten zu sehen ist:
DDEBUG: 1 : clean_a 1 336 rsync '"${options}"' ...
In der clean_a()
Funktion wird der Wert von $LASTNO
jedoch als 1 gedruckt.
line: 462 1
Hat es etwas mit dem Fehler zu tun, der von @Arkadiusz Drabczyk angezeigt wird?
EDIT2 : Ich habe das Skript genau so geändert, wie es mir @mikesrv empfohlen hat. Aber $ LASTNO hat 1 als Wert der Zeile zurückgegeben, als das Skript beendet wurde (es hätte 337 sein sollen).
#!/bin/bash
PS4='^MDEBUG: $((LASTNO=$LINENO)) : '; set -x
archieve_it () {
trap 'clean_a $LASTNO $LINENO "$BASH_COMMAND"' \
SIGHUP SIGINT SIGTERM SIGQUIT
...
} 2>/dev/null
clean_a () {
error " ...
line: $LASTNO $LINENO
..."
} 2>&1
Wenn ich ein Skript ausführe und es mit Ctrl+ Cbeende, während rsync ausgeführt wurde, erhalte ich folgende Ausgabe:
^^MDEBUG: 1 : clean_a '337 1 rsync "${options}" --delete-during ...
...
line: 1 465
Wie Sie sehen können, ist der Wert von $ LASTNO 1.
Während ich versuchte herauszufinden, wo das Problem liegt, schrieb ich eine andere Funktion - testing
- unter Verwendung des Parametersubstitutionsformats ${parameter:-default}
. Das Skript stellte sich also wie folgt heraus:
#!/bin/bash
PS4='^MDEBUG: $((LASTNO=$LINENO)) : '; set -x
archieve_it () {
trap 'testing "$LASTNO $LINENO $BASH_COMMAND"'\
SIGHUP SIGINT SIGTERM SIGQUIT
...
} 2>/dev/null
testing() {
echo -e "${1:-Unknown error!}"
exit 1
} 2>&1
Wenn ich nun ein Skript ausführe und Ctrl+ drücke C, erhalte ich folgende Ausgabe:
^^MDEBUG: 1 : testing '337 1 rsync "${options}" --delete-during ...
337 1 rsync "${options}" --delete-during ...
337 zeigt auf die Linie, als ich Ctrl+ drückte C, während rsync lief.
Für einen weiteren Test habe ich versucht, eine clear_a
Funktion wie diese zu schreiben :
clear_a () {
echo -e " $LASTNO $LINENO"
}
und $ LASTNO gab immer noch 1 zurück.
Das bedeutet also, dass wir beim Beenden des Skripts die korrekte Zeilennummer erhalten können, wenn wir die Parametersubstitution verwenden?
EDIT3 Es scheint, dass ich die Erklärung von @ mikeserv in EDIT2 falsch angewendet habe. Ich habe meinen Fehler korrigiert. Der Positionsparameter "$1
sollte in der Funktion durch $ LASTNO clear_a
ersetzt werden.
Hier ist das Skript, das so funktioniert, wie ich es haben möchte:
#!/bin/bash
PS4='^MDEBUG: $((LASTNO=$LINENO)) : '; set -x
archieve_it () {
trap 'clean_a $LASTNO $LINENO "$BASH_COMMAND"' \
SIGHUP SIGINT SIGTERM SIGQUIT
...
} 2>/dev/null
clean_a () {
error " ...
line: $1
..."
} 2>&1
Wenn das Skript beendet wird, werden trap
das $LASTNO
erste Argument, das $LINENO
zweite Argument und das dritte Argument ausgewertet und $BASH_COMMAND
die Werte an die clear_a
Funktion übergeben. Schließlich drucken wir $ LASTNO mit $1
der Zeilennummer, mit der das Skript beendet wird.
BASH_LINENO
Array, das wahrscheinlich genau das ist, was Sie wollen, anstatt nur LINENO
.