ubuntuusers.de

Error Codes in bash

Status: Gelöst | Ubuntu-Version: Ubuntu GNOME 22.04 (Jammy Jellyfish)
Antworten |

pacmexx

Anmeldungsdatum:
11. Februar 2019

Beiträge: 56

Hallo, ich möchte in einem Bash-Script einen Fehler bzw. Errorcode auswerten, komme bei der Umsetzung jedoch nicht weiter. Die Suche im Netz ergab den: BASH Exit Status (0,1,2) der mit $? abgefragt werden kann. Weiterhin gibt es die: BASH Error Codes (Anz. 8?) die wohl auch mittels $? verarbeitet werden. Letztlich die für mich interessanten: Linux OS Error Numbers die aber wohl eher mit der C-Programmierung zusammen hängen.

Im speziellen geht es um das Aushängen einer Partition per sshfs:

1
2
3
4
#!/bin/bash
fusermount -u /home/pac/RemoteDir-dell
...
...

Dieser Vorgang schlägt fehl da halt eine Datei von dieser Partition noch in Bearbeitung ist und wird mit folgender Meldung quittiert:

1
fusermount: failed to unmount /home/pac/RemoteDir-dell: Device or resource busy.

Diese Meldung enspricht nun der "Linux OS ErrorNo 16 (EBUSY)" und ich weiss aktuell nicht wie man diese ErrorNo auswertet da die Variable für den Beendigungsstatus für ein Shellscript ($?) hier wohl nicht genutzt wird.

Quelle: https://www.adminschoice.com/exit-error-codes-in-bash-and-linux-os

Gruss pac

Dakuan

Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6479

Wohnort: Hamburg

... da die Variable für den Beendigungsstatus für ein Shellscript ($?) hier wohl nicht genutzt wird.

Wie hast du das festgestellt?

Du musst den Errorcode direkt nach dem aufgerufenen Befehl auswerten. Die Frage ist aber, ob der dir wirklich noch den originalen Code gibt. Viele Programme geben einfach nur einen von Null verschiedenen Wert zurück (oft -1), um einen Fehler anzuzeigen. Außerdem kann der ursprüngliche Code schon innerhalb des aufgerufenen Programms durch Folgefehler überschrieben worden sein.

Übrigens, wenn man den Code hat, kann man sich den zugehörigen Text in der Konsole anzeigen lassen:

1
2
$ errno 16
EBUSY 16 Das Gerät oder die Ressource ist belegt

ChickenLipsRfun2eat Team-Icon

Anmeldungsdatum:
6. Dezember 2009

Beiträge: 12067

Hallo!

Was konkret willst du denn im Falle eines Scheiterns machen? Ich sehe da zwei Möglichkeiten:

1
2
3
fusermount -zu MOUNTPOINT  # "lazy" unmount, klappt immer

fusermount -u MOUNTPOINT || echo Fehler $?  # mittels OR eine Alternativbehandlung starten

Letzteres gibt übrigens Fehler 1 aus wie Dakuan schon angesprochen hat. Brauchst du denn den konkreten Fehlergrund in deinem Script?

frostschutz

Avatar von frostschutz

Anmeldungsdatum:
18. November 2010

Beiträge: 7782

Wenn das Programm (fusermount) die Errorcodes nicht durchreicht (nur 0 oder 1), kommst du da so einfach nicht ran.

Da kannst du genausogut stderr fangen und anschauen. Oder einen anderen Befehl probieren...

Lazy umount ist keine Lösung, das kehrt die Probleme nur unter den Teppich. Das Dateisystem ist weiter gemountet und laufende Prozesse können weiter darauf schreiben. Der tatsächliche umount erfolgt erst, wenn es ohne lazy auch geklappt hätte.

ChickenLipsRfun2eat Team-Icon

Anmeldungsdatum:
6. Dezember 2009

Beiträge: 12067

frostschutz schrieb:

Lazy umount ist keine Lösung…

Kommt auf den Anwendungsfall an. Ich nutze das gerne, wenn noch ein Kopiervorgang o.ä. läuft. Dann wird nach Abschluss des letzten Zugriffes (man darf auch nicht im Verzeichnis sein!) automatisch ausgehängt.

Und ja, fusermount gibt nur 1 zurück und schreibt die errno auf die stderr.

pacmexx

(Themenstarter)

Anmeldungsdatum:
11. Februar 2019

Beiträge: 56

ChickenLipsRfun2eat schrieb:

Was konkret willst du denn im Falle eines Scheiterns machen?

Es sollte eigentlich nur eine Fingerübung werden, man hätte sich vorstellen können eine Test-Abfrage zu basteln mit Meldungstext damit man weiß woran man ist und evtl. eine Auswahl für weitere Aktionen (whiptail). Es würde mich abschliessend interessieren in welchem Zusammenhang die "Linux OS Error Numbers" genutzt, wenn diese nicht ausgegeben werden?

Wie frostschutz schon anmerkte wird nur 1 bzw. stderr ausgegeben und ist für einen Exit Status dann doch ein bischen dünn.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13166

pacmexx schrieb:

Es sollte eigentlich nur eine Fingerübung werden, man hätte sich vorstellen können eine Test-Abfrage zu basteln mit Meldungstext damit man weiß woran man ist und evtl. eine Auswahl für weitere Aktionen (whiptail). Es würde mich abschliessend interessieren in welchem Zusammenhang die "Linux OS Error Numbers" genutzt, wenn diese nicht ausgegeben werden?

Wie frostschutz schon anmerkte wird nur 1 bzw. stderr ausgegeben und ist für einen Exit Status dann doch ein bischen dünn.

Du musst die Fehlermeldungen (errno) unterscheiden von Prozess-Exit-Stati. Die ersten sind normiert und stehen im Header errno.h (siehe hier). Letztere können beliebig vergeben werden. Da gilt nur die Konvention, dass eine 0 "OK" bedeutet und alles andere einen Fehler anzeigt. Es gibt keine Verbindung zwischen den beiden.

In Shell-Skripten reicht normalerweise die Unterscheidung "OK" / "Nicht OK", weil ja Programme üblicherweise ihre eigenen Fehler ausgeben. Ich schreibe meine Skripte oft mit set -e am Anfang, so dass das Skript beim ersten Fehler abbricht, der nicht behandelt wird (also mittels Bedingung bei if oder until).

Wenn Du eine differenzierte Fehlerbehandlung machen willst, dann musst Du in der Doku (z.B. Manpage) des Programms nachschauen, welcher Exit-Status welchen Fehler anzeigt. Dann kannst Du sie unterschiedlich behandeln. Aber, wie gesagt, das ist für ein Skript meistens zu viel des Guten.

Dakuan

Avatar von Dakuan

Anmeldungsdatum:
2. November 2004

Beiträge: 6479

Wohnort: Hamburg

pacmexx schrieb:

Es würde mich abschliessend interessieren in welchem Zusammenhang die "Linux OS Error Numbers" genutzt, wenn diese nicht ausgegeben werden?

Ich glaube, hier liegt eine falsche Erwartungshaltung vor. errno ist eine globale (Kernel?) Variable, die von Systemfunktionen gesetzt wird. Sie enthält immer den zuletzt gesetzten Fehlercode. Eine Funktion, die ihre Aufgabe ohne Fehler erfüllen konnte, sieht möglicherweise keine Notwendigkeit, errno anzufassen.

Es kann also vorkommen, dass errno einen bösen Fehlercode enthält, die Funktion aber trotzdem fehlerfrei durchgelaufen ist. In der Literatur wird daher empfohlen errno erst dann abzufragen, wenn die aufgerufene Funktion einen Fehler gemeldet hat.

Noch unübersichtlicher wird es, wenn z.B. Threads ins Spiel kommen. Da würden sich dann mehrere Treads um diese Variable streiten. Daher ist heute der Direkte Zugriff auf errno verboten. Gelöst wird das Problem durch einbeziehen der Datei errno.h bei C. Da wird das dann über Makros oder sonst wie geregelt, damit der Programmierknecht keine grauen Haare bekommt (ist bei mir aber schon zu spät).

Wenn du in der Bash ein anderes Programm aufrufst, wird wahrscheinlich ein neuer Prozess oder ein neuer Thread gestartet. Wenn der beendet ist, ist wohl auch dessen Kopie von errno weg. Fang also lieber den Text auf.

ChickenLipsRfun2eat Team-Icon

Anmeldungsdatum:
6. Dezember 2009

Beiträge: 12067

pacmexx schrieb:

… wenn diese nicht ausgegeben werden?

Werden sie doch. Allerdings in Textform und nicht als Nummer. In den meisten Fällen wäre es auch doof, wenn das journalctl ein Gewirr aus Zahlen wäre, die man dann einzeln nachschlagen muss.
Es gibt auch die Möglichkeit in einem Programm den besagten letzten Fehlercode auszugeben. Bringt aber wenig und kann u.U. auch falsch sein.
Stell dir vor, du schreibst ein Script. Das hat während seines Ablaufs zwei Fehler, läuft aber weiter und beendet die Hauptaufgabe zufriedenstellend. Du kannst jetzt die Fehlernummer des ersten Fehlers, des zweiten oder auch 0 zurückgeben, da beide Fehler aufgetreten sind, für den Fehlersuchenden relevant sein können — oder 0 zurück geben, was dann so viel bedeutet wie „Gab Fehler, kann aber weitergehen“.

Egal wie du es machst, es wird immer jemanden geben, der was anderes braucht. Im Fall von fusermount kommt noch hinzu, das sämtliche Fehlercodes aus mount auch gelten. Ich nehme mal an es wird daher nur ermittelt, ob die Hauptaufgabe erfolgreich war (0) oder nicht (1) und alle Fehler „auf dem Weg“ nur auf stderr ausgegeben, so das die Information nicht verloren ist.

Du könntest ja mittels Umleitung auch die Fehlerausgabe separat behandeln, wenn du weitere Fingerübungen brauchst.

Antworten |