Skriver en Shell Script från början

Skrivande skalskript kan vara ganska skrämmande, främst eftersom skalet inte är det mest användarvänliga av språk att använda. Men jag hoppas att visa dig i denna handledning att skalskriptning egentligen inte är så tuff eller så skrämmande som du kan förvänta dig.

För denna handledning skriver vi ett manus som gör processen med att använda Jasmine-testramen lite enklare. Egentligen skulle jag inte använda det här skriptet idag; Jag skulle använda Grunt.js eller något liknande. Men jag skrev det här skriptet innan Grunt var runt, och jag fann att skriva det visade sig vara ett utmärkt sätt att bli bekvämare med shell scripting, så det är därför vi använder det.

En anteckning: Denna handledning är löst associerad med min kommande Tuts + Premium kurs, "Advanced Command Line Techniques." För att lära dig mer om ganska mycket vad som helst i den här handledningen, håll dig uppdaterad för kursens release. Härefter beskrivs i denna handledning "kursen".

Så, vårt manus, som jag kallar jazz, kommer att ha fyra huvudfunktioner:

  • Den laddar ner Jasmine från webben, pakar ut den och tar bort provkoden.
  • Det kommer att skapa JavaScript-filer och deras associerade specfiler och förfylla dem med lite mallkod.
  • Det öppnar testen i webbläsaren.
  • Det kommer att visa hjälptexten, som skisserar ovanstående.

Låt oss börja med skriptfilen.


Steg 1 - Skapa filen

Att skriva ett skalskript är endast användbart om du kan använda det från terminalen; För att kunna använda dina anpassade skript på terminalen måste du placera dem i en mapp som finns i terminalen VÄG variabel (du kan se din VÄG variabel genom att springa echo $ PATH). Jag har skapat en ~ / Bin mapp (var ~ är hemkatalogen) på min dator, och det är där jag gillar att behålla anpassade skript (om du gör detsamma måste du lägga till den på din väg). Så, skapa bara en fil som heter jazz, och lägg det i din mapp.

Självklart måste vi också göra den filen körbar. annars kommer vi inte att kunna köra den. Vi kan göra detta genom att springa följande kommando:

 chmod + x jazz

Nu när vi faktiskt kan utföra skriptet, låt oss lägga till en mycket viktig del. Alla skalskript ska börja med en shebang). Som Wikipedia säger, bör detta vara den första raden i manuset; det anges vilken tolk eller skal, det här skriptet ska köras med. Vi ska bara använda ett grundläggande standardskal:

 #! / Bin / sh

Okej, med allt som är upprättat, är vi redo att börja skriva själva koden.


Steg 2 - Att beskriva Script Flow

Tidigare påpekade jag vad de olika funktionerna i vårt skalskript borde vara. Men hur vet man huruvida manuskriptet ska fungera? Vi använder en kombination av en skalparameter och en fallbeskrivning. När vi kör skriptet från kommandoraden använder vi ett underkommando, så här:

 jazz init jazz skapa SomeFile jazz run jazz hjälp

Detta borde se ut, särskilt om du har använt Git:

 git init git status git commit

Baserat på den första parametern (i det, skapa, springa, hjälp), vårt fall uttalande kommer att bestämma vad som ska köras. Vi behöver dock ett standardfall: vad händer om ingen första parameter ges, eller får vi en okänd första parameter? I så fall visar vi hjälptexten. Så, låt oss börja!


Steg 3 - Skriva hjälptexten

Vi börjar med om uttalande som kontrollerar vår första parameter:

 om [$ 1] sedan # gör saker annat # visa hjälp fi

Du kanske är lite förvirrad först, för ett skal om uttalandet är ganska annorlunda än ett "vanligt" programmeringsspråk om påstående. För att få en bättre förståelse för det, titta på screencasten på villkorliga uttalanden i kursen. Denna kod kontrollerar förekomst av en första parameter ($ 1); Om det är där, ska vi utföra sedan koda; annan, vi ska visa hjälptexten.

Det är en bra idé att lägga ut hjälptexten i en funktion, eftersom vi behöver ringa det mer än en gång. Vi behöver definiera funktionen innan den heter, så vi lägger den högst upp. Jag gillar det här, för nu, när jag öppnar filen ser jag dokumentationen för skriptet, vilket kan vara en bra påminnelse när jag återvänder till koden du inte har sett på ett tag. Utan ytterligare ado, här är hjälp fungera:

 Funktionshjälp () echo "jazz - Ett enkelt manus som gör att Jasmine-testramverket används i ett fristående projekt lite enklare." echo "echo" jazz init - inkludera jasmin i projektet "echo" jazz skapa FunctionName - skapar ./src/FunctionName.js ./spec/FunctionNameSpec.js "; echo" jazz run - kör test i webbläsare ";

Nu, ersätt bara det # visa hjälp funktion med ett samtal till hjälp fungera.

 annars hjälp fi

Steg 4 - Skriva ärendet

Om det finns en första parameter måste vi ta reda på vilken den är. För detta använder vi en fall påstående:

 fallet "$ 1" i init) ;; skapa) ;; springa) ;; *) hjälp ;; esac

Vi skickar den första parametern till fall påstående; då borde det matcha en av fyra saker: "init", "skapa", "springa" eller vårt jokertecken, standardfall. Observera att vi inte har ett explicit "hjälp" -fall: det är bara vårt standardfall. Detta fungerar, för allt annat än "init", "skapa" och "run" är inte kommandon som vi känner igen, så det borde få hjälptexten.

Nu är vi redo att skriva funktionskoden, och vi börjar med jazz init.


Steg 5 - Förbereder Jasmine med jazz init

Alla koden vi skriver här kommer att gå inom vårt i det) fallet från fallet ovanstående. Det första steget är att faktiskt ladda ner den fristående versionen av Jasmine, som kommer i en zip-fil:

 echo "Downloading Jasmine ..." curl -sO $ JASMINE_LINK

Vi först echo ett litet meddelande, och då använder vi ringla för att ladda ner zip. De s flaggan gör det tyst (ingen utgång) och O flaggan sparar innehållet i zip-filen till en fil (annars skulle det leda det till standard). Men vad är det med det $ JASMINE_LINK variabel? Tja, du kan sätta den faktiska länken till zip-filen där, men jag föredrar att lägga den i en variabel av två anledningar: För det första håller vi oss från att repetera en del av sökvägen, som du ser om en minut. För det andra, med den variabeln nära toppen av filen, gör det enkelt att ändra den version av Jasmine vi använder: ändra bara den ena variabeln. Här är den variabla deklarationen (jag lägger den utanför om uttalande, nära toppen):

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

Kom ihåg, inga mellanslag runt jämliksignalen i den linjen.

Nu när vi har vår zip-fil kan vi pakka ut det och förbereda innehållet:

 unzip -q basnamn $ JASMINE_LINK rm-rf basnamn $ JASMINE_LINK src / *. js spec / *. js

I två av dessa linjer använder vi basnamn $ JASMINE_LINK; de basnamn kommandot minskar bara en sökväg till basnamnet: så sökväg / till / file.zip blir bara file.zip. Detta låter oss använda det $ JASMINE_LINK variabel för att referera till vår lokala zip-fil.

När vi unzip tar vi bort den zip-filen, liksom alla JavaScript-filer i src och spec kataloger. Det här är de samplingsfiler som Jasmine kommer med, och vi behöver dem inte.

Därefter har vi ett problem med Mac-bara att hantera. Som standard, när du laddar ner något från Internet på en Mac, när du försöker köra det för första gången, blir du ombedd att bekräfta att du vill köra den. Detta beror på det utökade attributet com.apple.quarantine att Apple lägger på filen. Vi måste ta bort det här attributet.

 om vilken xattr> / dev / null && ["xattr SpecRunner.html"=" com.apple.quarantine "] sedan xattr -d com.apple.quarantine SpecRunner.html fi

Vi börjar med att söka efter närvaron av xattr kommando, eftersom det inte finns på vissa Unix-system (jag är inte säker, men det kan vara ett Mac-bara program). Om du såg kursbildsskärmen på villkor, vet du att vi kan skicka några kommandon till om; om det har en utträdesstatus för allt annat än 0, Det är falskt. Om som finner xattr kommando, kommer det att gå ut med 0; annars kommer det att gå ut med 1. I vilket fall, som kommer att visa viss utmatning; Vi kan hålla det från att visa genom att omdirigera det till / Dev / null (det här är en speciell fil som kasserar alla data skrivna till den).

Den dubbla ampersand är en booleska AND; Det är där för det andra villkoret vi vill kolla. Det är, gör SpecRunner.html har det attributet? Vi kan helt enkelt springa xattr kommandot på filen och jämföra det med utgången till den sträng som vi förväntar oss. (Vi kan inte bara förvänta oss att filen ska ha attributet eftersom du faktiskt kan stänga av den här funktionen i Mac OS X och vi får ett fel när du försöker ta bort det om filen inte har attributet).

Så om xattr hittas och filen har attributet, vi tar bort det, med d (för att ta bort) flagga. Ganska enkelt, rätt?

Det sista steget är att redigera SpecRunner.html. För närvarande innehåller det skript taggar för de JavaScript-filer som vi raderade. Vi ska också ta bort dessa skript taggar. Jag råkar veta att dessa skript taggar spänner linjer 12 till 18 i filerna. Så vi kan använda streamredigeraren sed att radera de här raderna:

 sed -i "" '12, 18d 'SpecRunner.html echo "Jasmine initialiserad!"

De jag flaggan berättar sed att redigera filen på plats, eller för att spara utmatningen från kommandot till samma fil vi passerade in; Den tomma strängen efter flaggan betyder att vi inte vill ha sed att säkerhetskopiera filen för oss om du ville ha det, kan du bara lägga en filtillägg i den strängen (som .bak, att få SpecRunner.html.bak).

Slutligen låter vi användaren veta att Jasmine har initierats. Och det är det för vårt jazz init kommando.


Steg 6 - Skapa filer med jazz skapa

Därefter kommer vi att låta våra användare skapa JavaScript-filer och deras associerade specfiler. Denna del av koden kommer att gå i avsnittet "skapa" av fall uttalande vi skrev tidigare.

 om [$ 2] sedan # skapa filer annat echo "var vänlig fyll i ett namn på filen" fi

När man använder jazz skapa, Vi måste inkludera ett namn på filen som andra parameter: jazz skapa View, till exempel. Vi använder detta för att skapa src / View.js och spec / ViewSpec.js. Så, om det inte finns någon andra parameter, kommer vi påminna användaren att lägga till en.

Om det finns ett filnamn börjar vi med att skapa de två filerna (inuti sedan del ovan):

 echo "-funktionen $ 2 () \ n \ n"> src / $ 2.js echo "beskriver ('$ 2', funktion () \ n \ n);" > spec / $ 2Spec.js

Självklart kan du lägga vad du vill ha i din src fil. Jag gör något grundläggande här; så jazz skapa View kommer skapa src / View.js med detta:

 funktion Visa () 

Du kan ersätta det först eko linje med detta:

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

Och då jazz skapa View kommer att resultera i detta:

 var View = (funktion () var ViewPrototype = ; returnera skapa: funktion (attrs) var o = Object.create (ViewPrototype); förläng (o, attrs); returnera o;; ;

Så, verkligen, din fantasi är gränsen. Självklart vill du att specfilen ska vara standard Jasmine spec-kod, vilket är vad jag har ovan; men du kan tweak det men du vill också.

Nästa steg är att lägga till skript taggar för dessa filer till SpecRunner.html. Först kan det här vara svårt: hur kan vi lägga till rader i mitten av en fil programmerat? Återigen är det sed det gör jobbet.

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

Vi börjar som vi gjorde tidigare: redigera på plats utan säkerhetskopiering. Då vårt kommando: på rad 11 vill vi lägga till de två följande raderna. Det är viktigt att komma undan de två nya linjerna så att de kommer att visas i texten. Som du kan se, lägger du bara in de två skript taggarna, exakt vad vi behöver för det här steget.

Vi kan sluta med viss produktion:

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

Och det är jazz skapa!


Steg 7 - Att köra specifikationerna med jazzkörning

Det sista steget är att faktiskt köra testen. Det innebär att öppna SpecRunner.html filen i en webbläsare. Det är lite av en försiktighet här. På Mac OS X kan vi använda öppna Kommando att öppna en fil i standardprogrammet. Det här fungerar inte på något annat operativsystem, men det är så jag gör det här. Tyvärr finns det ingen riktig plattformsplattform för att göra det, som jag vet om. Om du använder det här skriptet under Cygwin på Windows kan du använda det cygstart istället för öppna; annars, försök med googling "[your OS] shell script open browser" och se vad du kommer upp med. Tyvärr har vissa versioner av Linux (åtminstone Ubuntu, enligt min erfarenhet) en öppna kommando som är för något helt annat. Allt detta att säga, din körsträcka med följande kan variera.

om ["'som öppnar'" = '/ usr / bin / open') öppnar du SpecRunner.html annars echo "Vänligen öppna SpecRunner.html i din webbläsare" fi

Nu vet du exakt vad det här gör: om vi har öppna, vi öppnar SpecRunner.html, annars skriver vi bara ett meddelande som säger att användaren ska öppna filen i webbläsaren.

Ursprungligen det om skick såg ut så här:

om vilket öppet> / dev / null

Som vi gjorde med xattr, det kontrolleras bara för förekomsten av öppna; emellertid, sedan jag fick reda på att det finns en annorlunda öppna kommandot på Linux (även på min Ubuntu-server, som inte ens kan öppna en webbläsare!), tyckte jag att det var bättre att jämföra sökvägen för öppna program, eftersom Linux är på / Bin / öppen (igen, åtminstone på Ubuntu-servern).

Allt detta extra ordlighet om öppna kan låta som en ursäkt för min brist på en bra lösning, det pekar faktiskt på något viktigt om kommandoraden. Misstag inte förstå terminalen när du förstår en dators konfiguration. Denna handledning och tillhörande kurs har lärt dig lite mer om Bash-skalet (och Z-skalet), men det betyder inte att varje dator du använder kommer att konfigureras på samma sätt. Det finns många sätt att installera nya kommandon (eller olika versioner av kommandon), samt ta bort kommandon. Grottautvecklare.

Tja, det är hela skriptet! Här är det igen, alla tillsammans:

 #! / bin / sh-funktion hjälp () echo "jazz - Ett enkelt manus som gör det enklare att använda Jasmine-testramverket i ett fristående projekt." echo "" echo "jazz init - inkludera jasmin i projektet"; echo "jazz skapa FunctionName - skapar ./src/FunctionName.js ./spec/FunctionNameSpec.js"; echo "jazz run - kör test i webbläsare";  JASMIME_LINK = "http://cloud.github.com/downloads/pivotal/jasmine/jasmine-standalone-1.3.1.zip" om [$ 1] då fallet "$ 1" i init) echo "Downloading Jasmine ..." curl - sO $ JASMIME_LINK unzip -q 'basnamn $ JASMIME_LINK' rm 'basnamn $ JASMIME_LINK' src / *. js spec / *. js om vilket xattr> / dev / null && ["'xattr SpecRunner.html'" = "com.apple .quarantine "] sedan xattr -d com.apple.quarantine SpecRunner.html fi sed -i" "" 12,18d "SpecRunner.html echo" Jasmine initialiserad! " ;; skapa) om [$ 2] sedan echo "-funktionen $ 2 () \ n \ n"> ./src/$2.js echo "beskriv ('$ 2', funktion () \ nit ('kör'); \ n );" > ./spec/$2Spec.js sed -i "" "11a \\ \\  "SpecRunner.html echo" Skapat: "echo" \ tshirt / $ 2.js "echo" \ t-spec / $ 2Spec.js "echo" Redigerat: "echo" \ t- SpecRunner.html "annars echo" tack lägg till ett namn på filen 'fi ;; run') om ["'som öppnar'" = '/ usr / bin / open') och öppna sedan ./SpecRunner.html annat echo "Vänligen öppna SpecRunner.html i din webbläsare "fi ;;) hjälp ;;; esac annan hjälp; fi

Tja, fortsätt, prova!

 mkdir projekt cd projekt jazz init jazz skapa hund # redigera src / dog.js och spec / dogSpec.js jazz run

Förresten, om du vill ha lite roligare med det här projektet, kan du hitta det på Github.


Slutsats

Så där har du det! Vi har just skrivit en mellanliggande skalskript det var inte så dåligt nu var det? Glöm inte att hålla dig inställd på min kommande Tuts + Premium kurs; du lär dig mycket mer om många av de tekniker som används i denna artikel, liksom otaliga andra. Ha kul på terminalen!