Kennt jemand Ressourcen, die über Best Practices oder Entwurfsmuster für Shell-Skripte (sh, bash usw.) sprechen?
design-patterns
bash
shell
user14437
quelle
quelle
Antworten:
Ich habe ziemlich komplexe Shell-Skripte geschrieben und mein erster Vorschlag ist "nicht". Der Grund ist, dass es ziemlich einfach ist, einen kleinen Fehler zu machen, der Ihr Skript behindert oder es sogar gefährlich macht.
Trotzdem habe ich keine anderen Ressourcen, um Sie weiterzugeben, als meine persönliche Erfahrung. Hier ist, was ich normalerweise mache, was übertrieben ist, aber dazu neigt, solide zu sein, obwohl es sehr ausführlich ist.
Aufruf
Lassen Sie Ihr Skript lange und kurze Optionen akzeptieren. Seien Sie vorsichtig, da es zwei Befehle zum Parsen von Optionen gibt: getopt und getopts. Verwenden Sie getopt, da Sie weniger Probleme haben.
Ein weiterer wichtiger Punkt ist, dass ein Programm immer Null zurückgeben sollte, wenn es erfolgreich abgeschlossen wurde, ungleich Null, wenn etwas schief gelaufen ist.
Funktionsaufrufe
Sie können Funktionen in bash aufrufen. Denken Sie daran, sie vor dem Aufruf zu definieren. Funktionen sind wie Skripte, sie können nur numerische Werte zurückgeben. Dies bedeutet, dass Sie eine andere Strategie erfinden müssen, um Zeichenfolgenwerte zurückzugeben. Meine Strategie besteht darin, eine Variable namens RESULT zu verwenden, um das Ergebnis zu speichern, und 0 zurückzugeben, wenn die Funktion sauber abgeschlossen wurde. Sie können auch Ausnahmen auslösen, wenn Sie einen anderen Wert als Null zurückgeben, und dann zwei "Ausnahmevariablen" festlegen (meine: EXCEPTION und EXCEPTION_MSG), wobei die erste den Ausnahmetyp und die zweite eine von Menschen lesbare Nachricht enthält.
Wenn Sie eine Funktion aufrufen, werden die Parameter der Funktion den speziellen Variablen $ 0, $ 1 usw. zugewiesen. Ich empfehle Ihnen, sie in aussagekräftigere Namen zu setzen. Deklarieren Sie die Variablen innerhalb der Funktion als lokal:
Fehleranfällige Situationen
In bash wird, sofern Sie nichts anderes deklarieren, eine nicht gesetzte Variable als leere Zeichenfolge verwendet. Dies ist im Falle eines Tippfehlers sehr gefährlich, da die schlecht typisierte Variable nicht gemeldet wird und als leer ausgewertet wird. verwenden
um dies zu verhindern. Seien Sie jedoch vorsichtig, denn wenn Sie dies tun, wird das Programm jedes Mal abgebrochen, wenn Sie eine undefinierte Variable auswerten. Aus diesem Grund können Sie nur dann überprüfen, ob eine Variable nicht definiert ist:
Sie können Variablen als schreibgeschützt deklarieren:
Modularisierung
Sie können eine "Python-ähnliche" Modularisierung erreichen, wenn Sie den folgenden Code verwenden:
Sie können dann Dateien mit der Erweiterung .shinc mit der folgenden Syntax importieren
"AModule / ModuleFile" importieren
Welches wird in SHELL_LIBRARY_PATH gesucht. Denken Sie beim Importieren in den globalen Namespace daran, allen Funktionen und Variablen ein korrektes Präfix voranzustellen, da sonst die Gefahr von Namenskonflikten besteht. Ich benutze doppelten Unterstrich als Python-Punkt.
Fügen Sie dies auch als erstes in Ihr Modul ein
Objekt orientierte Programmierung
In Bash können Sie keine objektorientierte Programmierung durchführen, es sei denn, Sie erstellen ein recht komplexes System zur Zuweisung von Objekten (ich habe darüber nachgedacht. Es ist machbar, aber verrückt). In der Praxis können Sie jedoch "Singleton-orientierte Programmierung" durchführen: Sie haben eine Instanz jedes Objekts und nur eine.
Was ich mache ist: Ich definiere ein Objekt in ein Modul (siehe den Modularisierungseintrag). Dann definiere ich leere Variablen (analog zu Mitgliedsvariablen), eine Init-Funktion (Konstruktor) und Mitgliedsfunktionen, wie in diesem Beispielcode
Signale einfangen und handhaben
Ich fand das nützlich, um Ausnahmen zu fangen und zu behandeln.
Hinweise und Tipps
Wenn etwas aus irgendeinem Grund nicht funktioniert, versuchen Sie, den Code neu zu ordnen. Ordnung ist wichtig und nicht immer intuitiv.
Denken Sie nicht einmal daran, mit tcsh zu arbeiten. Es unterstützt keine Funktionen und ist im Allgemeinen schrecklich.
Hoffe es hilft, obwohl bitte beachten. Wenn Sie die Art von Dingen verwenden müssen, die ich hier geschrieben habe, bedeutet dies, dass Ihr Problem zu komplex ist, um mit Shell gelöst zu werden. benutze eine andere Sprache. Ich musste es aufgrund menschlicher Faktoren und Vermächtnisse benutzen.
quelle
getopt
vsgetopts
?getopts
ist portabler und funktioniert in jeder POSIX-Shell. Insbesondere da es sich bei der Frage um Best Practices für Shell handelt, anstatt um Best Practices für Bashs, würde ich die POSIX-Konformität unterstützen, um nach Möglichkeit mehrere Shells zu unterstützen.Im Advanced Bash-Scripting Guide finden Sie viele Informationen zum Thema Shell-Scripting - nicht nur zu Bash.
Hören Sie nicht auf Leute, die Ihnen sagen, Sie sollen sich andere, wohl komplexere Sprachen ansehen. Wenn Shell-Skripte Ihren Anforderungen entsprechen, verwenden Sie diese. Sie wollen Funktionalität, keine Phantasie. Neue Sprachen bieten wertvolle neue Fähigkeiten für Ihren Lebenslauf, aber das hilft nicht, wenn Sie Arbeit haben, die erledigt werden muss, und Sie Shell bereits kennen.
Wie bereits erwähnt, gibt es nicht viele "Best Practices" oder "Entwurfsmuster" für Shell-Skripte. Unterschiedliche Verwendungen haben unterschiedliche Richtlinien und Vorurteile - wie jede andere Programmiersprache.
quelle
Shell-Skript ist eine Sprache zum Bearbeiten von Dateien und Prozessen. Das ist zwar großartig, aber keine Allzwecksprache. Versuchen Sie daher immer, Logik aus vorhandenen Dienstprogrammen zu kleben, anstatt neue Logik in Shell-Skripten neu zu erstellen.
Abgesehen von diesem allgemeinen Prinzip habe ich einige häufige Shell- Skriptfehler gesammelt .
quelle
Es gab dieses Jahr (2008) eine großartige Sitzung auf der OSCON zu diesem Thema: http://assets.en.oreilly.com/1/event/12/Shell%20Scripting%20Craftsmanship%20Presentation%201.pdf
quelle
Wissen, wann man es benutzt. Für schnelles und schmutziges Zusammenkleben ist es in Ordnung. Wenn Sie mehr als nur wenige nicht triviale Entscheidungen treffen müssen, wählen Sie Python, Perl und modularisieren Sie .
Das größte Problem mit Shell ist oft, dass das Endergebnis wie ein großer Schlammball aussieht, 4000 Zeilen Bash und Wachstum ... und Sie können es nicht loswerden, weil jetzt Ihr gesamtes Projekt davon abhängt. Natürlich begann es bei 40 Zeilen wunderschöner Bash.
quelle
Einfach: Verwenden Sie Python anstelle von Shell-Skripten. Sie erhalten eine nahezu 100-fache Verbesserung der Lesbarkeit, ohne dass Sie etwas komplizieren müssen, das Sie nicht benötigen, und behalten die Fähigkeit, Teile Ihres Skripts in Funktionen, Objekte, persistente Objekte (zodb) und verteilte Objekte (pyro) zu verwandeln, fast ohne zusätzlicher Code.
quelle
Verwenden Sie set -e, damit Sie nach Fehlern nicht vorwärts pflügen. Versuchen Sie, es sh-kompatibel zu machen, ohne sich auf bash zu verlassen, wenn Sie möchten, dass es unter Nicht-Linux ausgeführt wird.
quelle
Um einige "Best Practices" zu finden, schauen Sie, wie Linux-Distributionen (z. B. Debian) ihre Init-Skripte schreiben (normalerweise in /etc/init.d zu finden).
Die meisten von ihnen sind ohne "Bash-Ismen" und haben eine gute Trennung von Konfigurationseinstellungen, Bibliotheksdateien und Quellformatierung.
Mein persönlicher Stil ist es, ein Master-Shellscript zu schreiben, das einige Standardvariablen definiert, und dann zu versuchen, eine Konfigurationsdatei zu laden ("Quelle"), die möglicherweise neue Werte enthält.
Ich versuche, Funktionen zu vermeiden, da sie dazu neigen, das Skript komplizierter zu machen. (Perl wurde zu diesem Zweck erstellt.)
Um sicherzustellen, dass das Skript portabel ist, testen Sie nicht nur mit #! / Bin / sh, sondern verwenden Sie auch #! / Bin / ash, #! / Bin / dash usw. Sie werden den Bash-spezifischen Code früh genug erkennen.
quelle
Oder das ältere Zitat ähnlich dem, was Joao gesagt hat:
"Benutze Perl. Du wirst Bash wissen wollen, aber nicht benutzen."
Leider habe ich vergessen, wer das gesagt hat.
Und ja, heutzutage würde ich Python über Perl empfehlen.
quelle