Schreiben eines Shell-Skripts von Grund auf

Das Schreiben von Shell-Skripten kann ziemlich entmutigend sein, vor allem, weil die Shell nicht die benutzerfreundlichsten Sprachen ist. Ich hoffe jedoch, Ihnen in diesem Tutorial zeigen zu können, dass Shell-Scripting nicht so schwierig oder unheimlich ist, wie Sie es vielleicht erwarten.

Für dieses Tutorial schreiben wir ein Skript, das die Verwendung des Jasmine-Test-Frameworks ein wenig einfacher macht. Eigentlich würde ich dieses Skript heute nicht verwenden. Ich würde Grunt.js oder ähnliches verwenden. Allerdings habe ich dieses Skript geschrieben, bevor Grunt in der Nähe war, und ich stellte fest, dass das Schreiben ein hervorragender Weg war, um sich mit dem Shell-Scripting vertraut zu machen. Deshalb verwenden wir es.

Ein Hinweis: Dieses Tutorial ist lose mit meinem kommenden Tuts + Premium-Kurs "Advanced Command Line Techniques" verbunden. Um mehr über so ziemlich alles in diesem Tutorial zu erfahren, bleiben Sie für die Veröffentlichung dieses Kurses auf dem Laufenden. In diesem Tutorial wird es im Folgenden als "Kurs" bezeichnet.

Also unser Skript, das ich anrufe Jazz, wird vier Hauptmerkmale haben:

  • Es wird Jasmine aus dem Internet herunterladen, entpacken und den Beispielcode löschen.
  • Es erstellt JavaScript-Dateien und die zugehörigen Spezifikationsdateien und füllt sie mit etwas Template-Code aus.
  • Die Tests werden im Browser geöffnet.
  • Daraufhin wird der Hilfetext angezeigt, der die obigen Angaben enthält.

Beginnen wir mit der Skriptdatei.


Schritt 1 - Erstellen der Datei

Das Schreiben eines Shellskripts ist nur nützlich, wenn Sie es vom Terminal aus verwenden können. Damit Sie Ihre benutzerdefinierten Skripts auf dem Terminal verwenden können, müssen Sie sie in einem Ordner ablegen, der sich in Ihrem Terminal befindet PFAD Variable (Sie können Ihre sehen PFAD Variable durch Laufen echo $ PATH). Ich habe eine erstellt ~ / bin Ordner (wo ~ ist das Ausgangsverzeichnis auf meinem Computer, und dort möchte ich benutzerdefinierte Skripts aufbewahren (wenn Sie dasselbe tun, müssen Sie es Ihrem Pfad hinzufügen). Erstellen Sie also einfach eine Datei namens Jazz, und legen Sie es in Ihrem Ordner.

Natürlich müssen wir diese Datei auch ausführbar machen. Andernfalls können wir es nicht ausführen. Wir können dies tun, indem Sie den folgenden Befehl ausführen:

 chmod + x jazz

Nun, da wir das Skript tatsächlich ausführen können, fügen wir einen sehr wichtigen Teil hinzu. Alle Shell-Skripte sollten mit einem Shebang beginnen. Wie Wikipedia sagt, sollte dies die erste Zeile des Skripts sein. Es gibt an, mit welchem ​​Interpreter oder Shell dieses Skript ausgeführt werden soll. Wir werden nur eine einfache Standard-Shell verwenden:

 #! / bin / sh

In Ordnung, mit all diesen Einstellungen können wir mit dem Schreiben des eigentlichen Codes beginnen.


Schritt 2 - Überblick über den Skriptfluss

Zuvor habe ich darauf hingewiesen, was die verschiedenen Funktionen unseres Shell-Skripts sein sollten. Aber woher weiß das Skript, welche Funktion ausgeführt werden soll? Wir verwenden eine Kombination aus einem Shell-Parameter und einer Case-Anweisung. Wenn Sie das Skript über die Befehlszeile ausführen, verwenden wir einen Unterbefehl wie diesen:

 jazz init jazz erstellen SomeFile Jazz Run Jazz-Hilfe

Das sollte Ihnen bekannt vorkommen, besonders wenn Sie Git verwendet haben:

 git init git status git begehen

Basierend auf diesem ersten Parameter (drin, erstellen, Lauf, Hilfe), unsere Case-Anweisung entscheidet, was ausgeführt werden soll. Wir benötigen jedoch einen Standardfall: Was passiert, wenn kein erster Parameter angegeben wird oder wir einen nicht erkannten ersten Parameter erhalten? In diesen Fällen zeigen wir den Hilfetext. Also lasst uns anfangen!


Schritt 3 - Hilfetext schreiben

Wir beginnen mit dem ob Eine Anweisung, die nach unserem ersten Parameter sucht:

 Wenn [$ 1], dann # tun Sie andere Dinge # zeigen Sie die Hilfe fi

Sie könnten zuerst etwas verwirrt sein, weil eine Muschel ob Aussage unterscheidet sich ziemlich von einer "normalen" Programmiersprache ob Aussage. Um dies besser zu verstehen, schauen Sie sich den Screencast mit bedingten Anweisungen im Kurs an. Dieser Code prüft das Vorhandensein eines ersten Parameters (1 US-Dollar); Wenn es da ist, führen wir das aus dann Code; sonst, Wir zeigen den Hilfetext.

Es ist eine gute Idee, den Druck des Hilfetextes in eine Funktion zu packen, da wir ihn mehrmals aufrufen müssen. Wir müssen die Funktion definieren, bevor sie aufgerufen wird, also setzen wir sie an die Spitze. Ich mag das, denn jetzt, wenn ich die Datei öffne, sehe ich die Dokumentation für das Skript. Dies kann eine hilfreiche Erinnerung sein, wenn Sie zu Code zurückkehren, den Sie seit einiger Zeit nicht mehr gesehen haben. Ohne weiteres, hier ist die Hilfe Funktion:

 function help () echo "jazz - Ein einfaches Skript, das die Verwendung des Jasmine-Testframeworks in einem eigenständigen Projekt etwas einfacher macht." echo "echo" jazz init - Include jasmine in das Projekt "; echo" jazz create FunctionName - erstellt ./src/FunctionName.js ./spec/FunctionNameSpec.js "; echo" jazz führt Tests im Browser aus ";

Jetzt ersetzen Sie das einfach # Zeig Hilfe Funktion mit einem Anruf an die Hilfe Funktion.

 sonst hilfe fi

Schritt 4 - Verfassen der Fallerklärung

Wenn es einen ersten Parameter gibt, müssen wir herausfinden, um welchen Parameter es sich handelt. Dafür verwenden wir eine Fall Aussage:

 Fall "$ 1" in init) ;; erstellen) ;; Lauf) ;; *) Hilfe ;; esac

Wir übergeben den ersten Parameter an den Fall Aussage; dann sollte es mit einem von vier Dingen übereinstimmen: "init", "create", "run" oder unsere Wildcard, Standardfall. Beachten Sie, dass wir keinen expliziten "Hilfe" -Fall haben: Dies ist nur unser Standardfall. Das funktioniert, weil alles andere als "init", "create" und "run" keine Befehle sind, die wir erkennen, also den Hilfetext erhalten soll.

Jetzt können wir den Funktionscode schreiben und beginnen mit Jazz-Init.


Schritt 5 - Vorbereiten von Jasmin mit Jazz-Init

Der gesamte Code, den wir hier schreiben, wird in unseren Code aufgenommen drin) Fall aus der obigen Fallaussage. Der erste Schritt ist das eigentliche Herunterladen der Standalone-Version von Jasmine, die in einer ZIP-Datei enthalten ist:

 echo "Jasmin wird heruntergeladen ..." curl -sO $ JASMINE_LINK

Zuerst wiederholen wir eine kleine Nachricht, und dann benutzen wir locken den zip herunterladen. Das s Flag macht es stumm (keine Ausgabe) und die O Flag speichert den Inhalt der ZIP-Datei in einer Datei (andernfalls wird der Standardwert ausgegeben). Aber was ist damit? $ JASMINE_LINK Variable? Nun, Sie könnten den eigentlichen Link in die zip-Datei einfügen, aber ich ziehe es aus zwei Gründen vor, ihn in eine Variable zu setzen: Erstens verhindert es, dass wir einen Teil des Pfads wiederholen, wie Sie gleich sehen werden. Zweitens erleichtert diese Variable am oberen Rand der Datei das Ändern der verwendeten Jasmine-Version: Ändern Sie einfach diese eine Variable. Hier ist diese Variablendeklaration (ich habe sie außerhalb der ob Aussage, ganz oben):

 JASMIME_LINK = "http://cloud.github.com/downloads/pivotal/jasmine/jasmine-standalone-1.3.1.zip"

Denken Sie daran, dass in dieser Zeile keine Leerzeichen um das Gleichheitszeichen stehen.

Nun, da wir unsere ZIP-Datei haben, können wir sie entpacken und den Inhalt vorbereiten:

 entpacken Sie -q Basisname $ JASMINE_LINK rm -rf Basisname $ JASMINE_LINK src / *. js spec / *. js

In zwei dieser Zeilen verwenden wir Basisname $ JASMINE_LINK; das Basisname Befehl reduziert nur einen Pfad auf den Basisnamen: so Pfad / zu / Datei.zip wird gerecht file.zip. Dies erlaubt uns, das zu nutzen $ JASMINE_LINK Variable, um auf unsere lokale ZIP-Datei zu verweisen.

Nach dem Entpacken löschen wir diese ZIP-Datei sowie alle JavaScript-Dateien in der src und spez Verzeichnisse. Dies sind die Beispieldateien, mit denen Jasmine geliefert wird, und wir brauchen sie nicht.

Als Nächstes haben wir ein Problem, das nur für Mac gilt. Wenn Sie etwas aus dem Internet auf einen Mac herunterladen und versuchen, es zum ersten Mal auszuführen, werden Sie standardmäßig aufgefordert, zu bestätigen, dass Sie es ausführen möchten. Dies liegt an dem erweiterten Attribut com.apple.quarantine dass Apple die Datei anlegt. Wir müssen dieses Attribut entfernen.

 wenn welches xattr> / dev / null && ["xattr SpecRunner.html"=" com.apple.quarantine "] dann xattr -d com.apple.quarantine SpecRunner.html fi

Wir beginnen mit der Überprüfung der Anwesenheit von xattr Befehl, da er auf einigen Unix-Systemen nicht vorhanden ist (ich bin nicht sicher, aber es kann nur ein Mac-Programm sein). Wenn Sie sich den Screencast des Kurses unter Bedingungen angesehen haben, wissen Sie, dass wir jeden Befehl an dieses übergeben können ob; wenn es einen Exit-Status hat, aber nicht 0, es ist falsch. Ob welche findet das xattr Befehl wird mit beendet 0; Andernfalls wird mit beendet 1. In beiden Fällen, welche zeigt etwas Ausgabe an; Wir können verhindern, dass dies angezeigt wird, indem Sie es auf umleiten / dev / null (Dies ist eine spezielle Datei, in der alle darin enthaltenen Daten verworfen werden.).

Dieses doppelte Et-Zeichen ist ein boolesches UND; Es ist für die zweite Bedingung da, die wir überprüfen wollen. Das heißt, tut das SpecRunner.html habe dieses Attribut? Wir können das einfach laufen lassen xattr Befehl für die Datei, und vergleichen Sie die Ausgabe mit der Zeichenfolge, die Sie erwarten. (Wir können nicht einfach erwarten, dass die Datei das Attribut hat, da Sie diese Funktion in Mac OS X tatsächlich deaktivieren können. Wenn Sie versuchen, die Datei zu entfernen, wird eine Fehlermeldung angezeigt.).

Also wenn xattr gefunden wird und die Datei das Attribut hat, entfernen wir sie mit der d (zum Löschen) kennzeichnen. Ziemlich unkompliziert, richtig?

Der letzte Schritt ist zu bearbeiten SpecRunner.html. Derzeit enthält es Skript-Tags für die von uns gelöschten Beispiel-JavaScript-Dateien. Wir sollten auch diese Scripts-Tags löschen. Ich weiß zufällig, dass diese Skript-Tags die Zeilen 12 bis 18 in den Dateien umfassen. Wir können also den Stream-Editor verwenden sed um diese Zeilen zu löschen:

 sed -i "" '12, 18d 'SpecRunner.html echo "Jasmin initialisiert!"

Das ich flag sagt sed um die Datei an Ort und Stelle zu bearbeiten oder die Ausgabe des Befehls in derselben Datei zu speichern, in der wir sie übergeben haben; Die leere Zeichenfolge hinter der Markierung bedeutet, dass wir dies nicht möchten sed um die Datei für uns zu sichern; Wenn Sie das möchten, können Sie einfach eine Dateierweiterung in diese Zeichenfolge einfügen (wie .bak, bekommen SpecRunner.html.bak).

Schließlich informieren wir den Benutzer darüber, dass Jasmine initialisiert wurde. Und das ist es für uns Jazz-Init Befehl.


Schritt 6 - Erstellen von Dateien mit Jazz schaffen

Als Nächstes können wir unseren Benutzern die Erstellung von JavaScript-Dateien und der zugehörigen Spezifikationsdateien ermöglichen. Dieser Teil des Codes wird in den Abschnitt "Erstellen" von Fall Aussage, die wir früher geschrieben haben.

 Wenn [$ 2] dann # Dateien erstellen, sonst Echo "Bitte geben Sie einen Namen für die Datei" fi

Beim Benutzen Jazz schaffen, Wir müssen einen Namen für die Datei als zweiten Parameter angeben: Jazz erstellen View, zum Beispiel. Wir werden dies zum Erstellen verwenden src / View.js und spec / ViewSpec.js. Wenn also kein zweiter Parameter vorhanden ist, werden wir den Benutzer daran erinnern, einen hinzuzufügen.

Wenn es einen Dateinamen gibt, erstellen wir zuerst diese beiden Dateien (in der dann Teil oben):

 echo "function $ 2 () \ n \ n"> src / $ 2.js echo "beschreiben ('$ 2', function () \ n \ n);" > spec / $ 2Spec.js

Natürlich können Sie alles, was Sie möchten, in Ihr einfügen src Datei. Ich mache hier etwas Grundlegendes. so Jazz erstellen View wird erzeugen src / View.js mit diesem:

 Funktion View () 

Sie könnten das zuerst ersetzen Echo Zeile mit diesem:

 echo "var $ 2 = (Funktion () \ n \ tvar $ 2Prototype = \ n \ n \ t; \ n \ n \ treturn \ n \ t \ t \ create: function (attrs) \ n \ t \ t \ tvar o = Object.create ($ 2Prototype); \ n \ t \ t \ t \ textend (o, attrs); \ n \ t \ t \ t \ t \ treturn o; \ n \ t \ t \ n \ t; \ n ()); " > src / $ 2.js

Und dann Jazz erstellen View führt dazu:

 var View = (function () var ViewPrototype = ; return create: function (attrs)) var o = Object.create (ViewPrototype); extend (o, attrs); return o;; ()) ;

Ihre Phantasie ist also die Grenze. Natürlich möchten Sie, dass die Spec-Datei der Standard-Jasmine-Spec-Code ist, den ich oben habe. Sie können das aber beliebig ändern.

Im nächsten Schritt fügen Sie die Skript-Tags für diese Dateien hinzu SpecRunner.html. Auf den ersten Blick mag dies schwierig erscheinen: Wie können wir programmgesteuert Zeilen in die Mitte einer Datei einfügen? Wieder ist es sed das macht den Job.

 sed -i "" "11a \\ \\  "SpecRunner.html

Wir beginnen wie zuvor: In-Place-Bearbeitung ohne Backup. Dann unser Befehl: In Zeile 11 wollen wir die beiden folgenden Zeilen anhängen. Es ist wichtig, die zwei neuen Zeilen zu entfernen, damit sie im Text erscheinen. Wie Sie sehen, werden hier nur diese beiden Scripts-Tags eingefügt. Genau das, was wir für diesen Schritt benötigen.

Wir können mit etwas Ausgabe enden:

 echo "Erstellt:" echo "\ t- src / $ 2.js" echo "\ t- spec / $ 2Spec.js" echo "Bearbeitet:" echo "\ t- SpecRunner.html"

Und das ist Jazz schaffen!


Schritt 7 - Ausführen der Spezifikationen mit Jazzlauf

Der letzte Schritt besteht darin, die Tests tatsächlich auszuführen. Dies bedeutet das Öffnen der SpecRunner.html Datei in einem Browser. Hier gibt es eine Einschränkung. Unter Mac OS X können Sie das verwenden öffnen Befehl zum Öffnen einer Datei in ihrem Standardprogramm; Das funktioniert auf keinem anderen Betriebssystem, aber so mache ich es hier. Leider gibt es keine echte plattformübergreifende Methode, die ich kenne. Wenn Sie dieses Skript unter Cygwin unter Windows verwenden, können Sie verwenden Cygstart anstelle von öffnen; Andernfalls versuchen Sie, "[Ihr Betriebssystem] Shell Script Browser öffnen" und sehen Sie, was Sie dazu bringen. Leider haben einige Linux-Versionen (zumindest Ubuntu, meiner Erfahrung nach) eine öffnen Befehl, der für etwas völlig anderes ist. All dies, um zu sagen, dass Ihre Laufleistung mit den folgenden Angaben variieren kann.

Wenn ["'which open'" = '/ usr / bin / open'], dann öffnen Sie SpecRunner.html else echo "Bitte öffnen Sie SpecRunner.html in Ihrem Browser" fi

Inzwischen wissen Sie genau, was das bedeutet: Wenn wir haben öffnen, wir öffnen uns SpecRunner.html, Andernfalls drucken wir einfach eine Meldung, in der der Benutzer aufgefordert wird, die Datei im Browser zu öffnen.

Ursprünglich das ob Zustand sah so aus:

wenn was offen ist / dev / null

Wie wir mit gemacht haben xattr, es hat nur nach Existenz von gesucht öffnen; da ich jedoch herausgefunden habe, dass es einen anderen gibt öffnen Befehl unter Linux (sogar auf meinem Ubuntu-Server, der nicht einmal einen Browser öffnen kann!), dachte ich, es wäre besser, den Pfad des zu vergleichen öffnen Programm, da das Linux an ist / bin / offen (wieder mindestens auf Ubuntu-Server).

All diese zusätzlichen Wordiness über öffnen klingt vielleicht nach einer Entschuldigung für meinen Mangel an einer guten Lösung, es zeigt tatsächlich etwas Wichtiges auf der Kommandozeile. Verwechseln Sie das Terminal nicht mit der Konfiguration eines Computers. Dieses Tutorial und der zugehörige Kurs haben Ihnen ein wenig mehr über die Bash-Shell (und die Z-Shell) beigebracht. Dies bedeutet jedoch nicht, dass jeder Computer, den Sie verwenden, gleich konfiguriert ist. Es gibt viele Möglichkeiten, neue Befehle (oder verschiedene Versionen von Befehlen) zu installieren und Befehle zu entfernen. Vorsorgeentwickler.

Nun, das ist das gesamte Skript! Hier ist es wieder alles zusammen:

 #! / bin / sh function help () echo "jazz - Ein einfaches Skript, das die Verwendung des Jasmine-Testframeworks in einem eigenständigen Projekt etwas einfacher macht." echo "" echo "jazz init - Include Jasmin in das Projekt"; echo "jazz create Funktionsname - erstellt ./src/FunctionName.js ./spec/FunctionNameSpec.js"; echo "jazz run - testet im Browser";  JASMIME_LINK = "http://cloud.github.com/downloads/pivotal/jasmine/jasmine-standalone-1.3.1.zip" wenn [$ 1] dann Fall "$ 1" in init) echo "Download Jasmine ..." curl - sO $ JASMIME_LINK entpacken -q 'basname $ JASMIME_LINK' rm 'basname $ JASMIME_LINK' src / *. js spec / *. js Wenn? .quarantine "] dann xattr -d com.apple.quarantine SpecRunner.html fi -i" "" 12,18d "SpecRunner.html echo" Jasmine initialisiert! " ;; create) wenn [$ 2] dann echo "function $ 2 () \ n \ n"> ./src/$2.js echo "beschreiben ('$ 2', function () \ nit ('läuft'); \ n ); " > ./spec/$2Spec.js sed -i "" "11a \\ \\  "SpecRunner.html echo" Erstellt: "echo" \ t- src / $ 2.js "echo" \ t- spec / $ 2Spec.js "echo" bearbeitet: "echo" \ t- SpecRunner.html "Anderes Echo ' füge einen Namen für die Datei 'fi ;; "run") hinzu, wenn ["' which open '" =' / usr / bin / open '] dann öffne ./SpecRunner.html else echo "Bitte öffne SpecRunner.html in deinem Browser "fi ;; *) helfen;; esac sonst helfen; fi

Nun, mach weiter, probier es aus!

 mkdir projekt cd projekt jazz init jazz erstellt hund # edit src / Dog.js und spec / DogSpec.js jazz run

Wenn Sie mit diesem Projekt mehr Spaß haben möchten, können Sie es auf Github finden.


Fazit

So haben Sie es! Wir haben gerade ein Zwischenstufenshellskript geschrieben. das war jetzt nicht so schlimm, oder? Vergiss nicht, für meinen kommenden Tuts + Premium-Kurs dran zu bleiben. Sie lernen viel über viele der in diesem Artikel verwendeten Techniken sowie über unzählige andere. Viel Spass am Terminal!