Shell-Skriptvorlagen
was wären Eure Vorschläge für einen guten bash/ksh-Skript-Vorlage als standard für alle neu erstellten Skripts?
Normalerweise beginne ich (nach der #! Zeile) mit kommentierter header mit einem mit dem Namen, synopsis, die Nutzung, die Werte zurückgeben, Autor(en), changelog und würde passen in die 80-char Linien.
alle Unterlagen Zeilen ich beginne mit Doppel-hash-Symbole : "##", so kann ich grep für Sie einfach und lokale var Namen vorangestellt mit "__".
andere best practices? Tipps? Namenskonventionen? was ist mit return codes?
Dank
edit : get Kommentare über version control : wir haben svn alles in Ordnung, aber ein anderer Abt in den Unternehmen hat ein separates repo-und dies ist das Skript - wie kann ich wissen, wer den Kontakt mit den Q ' s, wenn es keine @Autor info? javadocs-ähnliche Einträge haben, einige Verdienste, auch in den shell-Kontext, IMHO, aber ich könnte falsch sein. vielen Dank für die Antworten
InformationsquelleAutor der Frage |
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich würde verlängern Norman ' s Antwort zu 6 Zeilen, und die Letzte dieser leer ist:
Die Dritte Zeile ist ein version-control-Identifikation-string - es ist eigentlich ein hybrid mit einem SCC-marker '
@(#)
', die identifiziert werden können durch die (SCCS) Programmwhat
und ein RCS-version der Zeichenfolge, die erweitert wird, wenn die Datei unter RCS, die Standard-VCS, die ich für meine private Nutzung. Das RCS-Programmident
nimmt die erweiterte form$Id$
die Aussehen könnte wie$Id: mkscript.sh,v 2.3 2005/05/20 21:06:35 jleffler Exp $
. Die fünfte Zeile erinnert mich daran, dass das script sollte eine Beschreibung Ihres zwecks an der Spitze; ich Ersetze das Wort mit einer Beschreibung des Skripts (das ist, warum gibt es keinen Doppelpunkt, nachdem es, zum Beispiel).Danach gibt es praktisch nichts standard für ein shell-Skript. Es gibt standard-Fragmente, die angezeigt werden, aber keine standard-fragment, das erscheint in jedem Skript. (Meine Diskussion davon ausgegangen, dass ein Script geschrieben, in Bourne, Korn, oder POSIX (Bash -) shell-Notationen. Es gibt eine ganze separaten Diskussion auf, warum jemand setzen ein C-Shell-Derivat nach der
#!
Siegel ist in Sünde Leben.)Zum Beispiel, dieser code wird in einigen Form oder form, wenn ein Skript erstellt intermediate (temporäre) Dateien:
Erster Linie wählt ein temporäres Verzeichnis, standardmäßig /tmp, wenn der Benutzer nicht geben Sie eine alternative ($TMPDIR ist sehr weit anerkannte und standardisierte POSIX). Es erstellt dann eine Datei-Namen-Präfix einschließlich der Prozess-ID. Dies ist nicht eine Sicherheitsmaßnahme; es ist eine einfache Parallelität Messen, verhindern, dass mehrere Instanzen des Skripts von trampling auf den Daten des jeweils anderen. (Für Sicherheit, verwenden Sie nicht-vorhersagbaren Dateinamen in einem nicht-öffentlichen Verzeichnis.) Die zweite Zeile sorgt dafür, dass die '
rm
' und 'exit
" - Befehle, die ausgeführt werden, wenn die shell erhält jedes der Signale SIGHUP (1), SIGINT (2), SIGQUIT (3), SIGPIPE (13) oder SIGTERM (15). Die 'rm
' - Befehl, entfernt temporäre Dateien, entsprechend der Vorlage; dieexit
Befehl stellt sicher, dass der status nicht null, der angibt, irgendeine Art von Fehler. Die 'trap
' 0 " bedeutet, dass der code auch ausgeführt, wenn die shell aus irgendeinem Grund beendet - es umfasst Unachtsamkeit in der Sektion 'eigentliche Arbeit'. Der code am Ende dann entfernt alle überlebenden temporäre Dateien, vor heben die Falle, auf die Ausfahrt, und schließlich beendet mit einem null - (Erfolgs) status. Klar, wenn Sie verlassen wollen, mit einem anderen status, Sie können nur sicherstellen, dass Sie es in einer Variablen vor der Ausführung derrm
undtrap
Linien, und verwenden Sie dannexit $exitval
.Ich in der Regel verwenden Sie den folgenden entfernen Sie den Pfad und suffix von dem script, so kann ich mit
$arg0
wenn die Berichterstattung Fehler:Verwende ich oft eine shell-Funktion, um Fehler zu melden:
Ob es nur eine oder vielleicht zwei Fehler beendet, ich nicht die Mühe mit der Funktion; wenn es noch mehr werden, mache ich, denn es vereinfacht die Codierung. Außerdem erstelle ich mehr oder weniger aufwendige Funktionen aufgerufen
usage
zu geben, die Zusammenfassung, wie der Befehl zu benutzen ist - aber auch nur dann, wenn es mehr als einen Ort, wo es verwendet werden würde.Anderen ziemlich standard-fragment ist eine option parsing-loop, mit der
getopts
shell built-in:oder:
Die quotes um "$OPTARG" Griff Leerzeichen in den Argumenten. Die Dflag ist kumulativ, aber die notation, die hier verwendet verliert Leerzeichen in den Argumenten. Es gibt (nicht-standard) Möglichkeiten zur Umgehung dieses problem, auch.
Ersten shift-notation funktioniert mit jeder Schale (oder tun würde, wenn ich verwendet, back-ticks statt '
$(...)
'. Der zweite arbeitet in modernen shells; es könnte sogar eine alternative mit eckigen Klammern statt Runden Klammern, aber das funktioniert so ich habe mir nicht die Mühe gemacht herauszufinden, was das ist.Einen letzten trick für jetzt ist, dass ich oft sowohl GNU und nicht-GNU-version von Programmen um, und ich möchte in der Lage sein zu entscheiden, welche ich verwende. Viele meiner scripts, daher verwenden Sie Variablen wie:
Dann, wenn ich zum aufrufen von Perl-oder
sed
wird, verwendet das Skript$PERL
oder$SED
. Das hilft mir, wenn etwas sich anders Verhalten - ich kann mir aussuchen, die operative version - oder während der Entwicklung des Skripts (ich kann nur hinzufügen, zusätzliche debug-Optionen an den Befehl verändern, ohne das Skript).InformationsquelleAutor der Antwort
Ich den ersten Satz von ## Zeilen für die Benutzung der Dokumentation. Ich kann mich jetzt nicht daran erinnern, wo ich zum ersten mal sah diese.
InformationsquelleAutor der Antwort
Code, der wird in die wildnis entlassen werden sollten, haben Sie die folgenden kurzen header:
Halten ein change-log geht in code-Header ist ein Rückschritt aus, wenn die version-control-Systeme waren furchtbar unbequem. Ein Datum der letzten änderung zeigt jemand, wie alt das Skript ist.
Wenn Sie sich auf bashisms, verwenden Sie #!/bin/bash , nicht /bin/sh, da sh ist die POSIX-Aufruf einer shell. Selbst wenn /bin/sh Punkte bash, viele Funktionen ausgeschaltet werden, wenn man es über /bin/sh. Die meisten Linux-Distributionen wird nicht von Skripts, die sich auf bashisms, versuchen Sie tragbar sein.
Mir, Kommentare in shell-Skripten sind sowas von dumm, es sei denn, Sie Lesen so etwas wie:
Shell-scripting ist so einfach, dass (es sei denn, Ihr schreiben zu einer demonstration auf, um jemand beibringen, wie es zu tun) der code fast immer ausreicht, und sich selbst.
Einige Muscheln mag es nicht, gefüttert zu werden typisierte 'lokalen' Variablen. Ich glaube, an diesem Tag Busybox (eine gemeinsame rescue-shell) ist eine von Ihnen. Machen GLOBALS_OBVIOUS stattdessen seine viel einfacher zu Lesen, vor allem beim Debuggen über /bin/sh -x ./script.sh.
Meine persönliche Präferenz ist, lassen Sie die Logik für sich selbst sprechen und die Minimierung der Arbeit für den parser. Zum Beispiel, viele Menschen könnten Sie schreiben:
Wo wäre ich nur:
Genauso könnte jemand schreiben:
... wo würde ich:
Die einzige Zeit, die ich mit herkömmlichen if /then /else, wenn es eine else-if in die Waagschale werfen.
Einem schrecklich wahnsinnigen Beispiel von sehr guter portabler shell-code untersucht werden können, indem nur die Anzeige des 'configure' - Skript in den meisten freie-software-Pakete, die autoconf. Ich sage verrückt, weil seine 6300 Zeilen code, bietet jedes system auf den Menschen bekannt, dass eine UNIX-shell. Sie wollen nicht, dass die Art der aufblasen, aber es ist interessant zu untersuchen, einige der verschiedenen Portabilität hacks.. wie schön für diejenigen, die vielleicht Punkt /bin/sh, zsh 🙂
Den einzigen anderen Rat, den ich geben kann ist, sehen Sie Ihre expansion hier-docs, d.h.
... ist noch erweitern $name, wenn Sie wahrscheinlich wollen, lassen Sie die variable in den Ort. Lösen Sie diesen über:
die lassen $name als variable, anstatt auszubauen.
Ich auch sehr empfehlen, die lernen, wie man trap zum abfangen von Signalen .. und nutzen Sie diese Handler boilerplate-code. Erzählt ein Skript ausführen zu verlangsamen, mit einem einfachen SIGUSR1 ist ganz praktisch 🙂
Meisten neuen Programme, die ich Schreibe (was sind tool /command line-orientierte) als shell-Skripte, die eine gute Möglichkeit, um den Prototyp UNIX-tools.
Vielleicht möchten Sie auch den SHC shell-Skript-compiler, check it out hier.
InformationsquelleAutor der Antwort
Dies ist die Kopfzeile, die ich für mein shell-Skript (bash oder ksh).
Es ist ein
man
gleich Aussehen und es wird verwendet, um display-Verwendung (.).Und hier ist die Verwendung von Funktionen, um mit zu gehen:
Hier ist was Sie erhalten:
Können Sie die vollständigen Skript-Vorlage hier: http://www.uxora.com/unix/shell-script/18-shell-script-template
InformationsquelleAutor der Antwort
Aktivierung Fehlererkennung macht es viel einfacher, um Probleme zu erkennen, die in der script-Anfang:
Exit-Skript auf den ersten Fehler. So vermeiden Sie, fortfahren, etwas zu tun, die abhängig von etwas weiter oben in dem Skript, vielleicht am Ende mit einigen seltsamen system state.
Behandeln Verweise auf unset Variablen als Fehler. Sehr wichtig zu vermeiden, laufen die Dinge wie
rm -you_know_what "$var/"
mit einem unset$var
. Wenn Sie wissen, dass die variable kann gelöscht werden, und dies ist eine sichere situation, die Sie verwenden können${var-value}
einen anderen Wert zu verwenden, wenn es nicht gesetzt oder${var:-value}
einen anderen Wert zu verwenden, wenn es unset oder leer.Es ist leicht den Fehler machen, das einfügen eines
>
wo du meintest einfügen<
und überschreibt eine Datei, die du gemeint hast zu Lesen. Wenn Sie brauchen, um clobber eine Datei in Ihrem Skript haben, können Sie diese deaktivieren, bevor Sie die entsprechende Zeile und aktivieren Sie es anschließend wieder.Verwenden Sie das erste nicht-null exit-code (falls vorhanden) eine Reihe von Pipe-Kommando als exit-code den vollständigen Satz von Befehlen. Dies macht es leichter zu Debuggen, die weitergeleiteten Befehle.
Vermeiden, dass Ihre
/foo/*
glob interpretiert buchstäblichwenn es keine übereinstimmenden Dateien, Ausdruck.Kombinieren Sie alle diese in zwei Zeilen:
InformationsquelleAutor der Antwort
Meine bash-Vorlage ist als unten(Satz in meinem vim-Konfiguration):
InformationsquelleAutor der Antwort
Ich würde vorschlagen,
und das ist es. Schwergewichts-block-Kommentare für shell-Skripte? Bekomme ich eine ordentliche Gänsehaut bescherte.
Vorschläge:
Dokumentation sollten Daten oder code, nicht die Kommentare. Mindestens ein
usage()
Funktion. Haben Sie einen Blick auf, wie ksh und der andere AST-tools-Dokument selbst mit-man Optionen auf jeden Befehl. (Kann nicht verlinken, weil die Website down ist.)Lokale Variablen deklarieren, mit
typeset
. Das ist, was es ist. Keine Notwendigkeit für unangenehme unterstreicht.InformationsquelleAutor der Antwort Norman Ramsey
Was Sie tun können, ist, um ein Skript zum erstellen eines headers für einen Drehbuch - & und haben es automatisch öffnen Sie Sie in Ihrem Lieblings-editor. Ich sah einen Kerl zu tun, dass auf dieser Website:
http://code.activestate.com/recipes/577862-bash-script-to-create-a-header-for-bash-scripts/?in=lang-bash
InformationsquelleAutor der Antwort
In der Regel habe ich einige Konventionen, die ich gerne beibehalten, für jedes script, das ich schreiben.
Ich Schreibe alle Skripte mit der Annahme, dass andere Menschen Sie Lesen.
Beginne ich jedes Skript mit meinem header,
Verwende ich das Datum-format, für einfacher grep/Suche.
Ich benutze das '[' Klammern, um anzuzeigen, text, müssen die Leute geben sich.
wenn Sie auftreten, außerhalb einen Kommentar, ich versuche zu starten mit '#['.
So, wenn jemand fügt Sie so wie Sie ist, es wird nicht verwechselt werden, für Eingabe-oder einen test-Befehl. Überprüfen Sie den Abschnitt zur Verwendung auf einem Mann-Seite, um zu sehen, dieser Stil als Beispiel.
Wenn ich möchte, dass Sie zum auskommentieren einer Zeile code, verwende ich eine einfache '#'. Wenn ich arbeite gerade an einem Kommentar als Hinweis, ich benutze ein Doppel -'##'. Die
/etc/nanorc
verwendet diese Konvention auch. Ich finde es hilfreich, zu unterscheiden, ein Kommentar, der gewählt wurde, nicht zur Ausführung; Verse, die ein Kommentar erstellt wurde, als Hinweis.Alle meine shell-Variablen, die ich lieber tun in CAPS. Ich versuche immer, zwischen 4 - 8-Zeichen, sofern nicht anders erforderlich. Die Namen beziehen sich, soweit als möglich, mit Ihrer Verwendung.
Ich auch immer " beenden mit 0, wenn erfolgreich, oder eine 1 für Fehler. Wenn das Skript hat viele verschiedene Arten von Fehlern (und würde eigentlich auch jemand helfen, oder könnte verwendet werden, in einigen code in irgendeiner Weise), die ich wählen würde, eine dokumentierte Sequenz über 1.
Im Allgemeinen, exit-codes sind nicht so streng durchgesetzt, in der *nix-Welt. Leider habe ich nie herausgefunden, eine gute Allgemeine Reihe-Schema.
Ich gerne verarbeiten-Argumente in der standard-Weise. Ich bevorzuge immer getopts, um getopt. Ich mache nie etwas hack mit 'read ()' Befehle und if-Anweisungen. Benutze ich auch gerne die case-Anweisung zur Vermeidung geschachtelter ifs. Ich verwende eine übersetzung von Skripts für lange Optionen, also-Hilfe -h getopts. Ich Schreibe alle Skripte entweder in bash (wenn zulässig) oder generische sh.
Ich NIE verwenden die bash interpretiert Symbole (oder jeder interpretiert-Zeichen) in Dateinamen, oder einen beliebigen Namen für diese Angelegenheit.
speziell... "' ` $ & * # () {} [] -, ich benutze _ für Leerzeichen.
Denken Sie daran, dies sind nur Konventionen. Best-practice -, grob -, aber manchmal sind Sie gezwungen, außerhalb der Linien. Das wichtigste ist, konsequent zu sein, über und in Ihre Projekte.
InformationsquelleAutor der Antwort