Skrive et Shell-skript fra begynnelsen

Skrive skript kan være ganske skremmende, først og fremst fordi skallet ikke er det mest brukbare av språk som skal brukes. Imidlertid håper jeg å vise deg i denne opplæringen at skallskripting egentlig ikke er så tøft eller så skummelt som du kanskje forventer.

For denne opplæringen skriver vi et skript som gjør prosessen med å bruke Jasmine-testrammen litt enklere. Egentlig ville jeg ikke bruke dette skriptet i dag; Jeg ville bruke Grunt.js eller noe lignende. Imidlertid skrev jeg dette skriptet før Grunt var rundt, og jeg fant at det å skrive det viste seg å være en utmerket måte å bli mer komfortabel med skalskripting, så det er derfor vi bruker det.

Ett notat: denne veiledningen er løst knyttet til mitt kommende Tuts + Premium kurs, "Advanced Command Line Techniques." For å lære mer om stort sett alt i denne opplæringen, hold deg innstilt for kursets utgivelse. Heretter i denne opplæringen vil det bli referert til som "kurset".

Så, vårt skript, som jeg kaller jazz, vil ha fire hovedtrekk:

  • Den vil laste ned Jasmine fra nettet, pakke ut den og slette prøvekoden.
  • Det vil lage JavaScript-filer og tilhørende spesifikke filer, og pre-fill dem med litt malkode.
  • Det åpner testene i nettleseren.
  • Det vil vise hjelpeteksten, som skisserer ovenstående.

La oss begynne med skriptfilen.


Trinn 1 - Opprette filen

Skrive et skallskript er bare nyttig hvis du kan bruke det fra terminalen; For å kunne bruke dine tilpassede skript på terminalen, må du sette dem i en mappe som er i terminalen din STI variabel (du kan se din STI variabel ved å kjøre ekko $ PATH). Jeg har laget en ~ / Bin mappe (hvor ~ er hjemmekatalogen) på datamaskinen min, og det er der jeg liker å beholde egendefinerte skript (hvis du gjør det samme, må du legge til det på banen din). Så bare opprett en fil, kalt jazz, og legg det i mappen din.

Selvfølgelig må vi også gjøre den filen kjørbar. Ellers vil vi ikke kunne kjøre den. Vi kan gjøre dette ved å kjøre følgende kommando:

 chmod + x jazz

Nå som vi faktisk kan utføre skriptet, la oss legge til en svært viktig del. Alle skalskript skal begynne med en shebang). Som Wikipedia sier, bør dette være den første linjen i skriptet; den sier hvilken tolk eller skal, dette skriptet skal kjøres med. Vi skal bare bruke et grunnleggende standardskall:

 #! / Bin / sh

OK, med alt som er satt opp, er vi klare til å begynne å skrive den faktiske koden.


Trinn 2 - Skissering av Script Flow

Tidligere pekte jeg på hva de forskjellige funksjonene til vårt skalskript burde være. Men hvordan vil skriptet vite hvilken funksjon å kjøre? Vi bruker en kombinasjon av en shell-parameter og en saksoppgave. Når du kjører skriptet fra kommandolinjen, bruker vi en underkommando, slik:

 jazz init jazz lage SomeFile jazz run jazz hjelp

Dette burde se kjent, spesielt hvis du har brukt Git:

 git init git status git commit

Basert på den første parameteren (i det, skape, løpe, hjelp), vil vår saksdekning bestemme hva du skal løpe. Vi trenger imidlertid en standard sak: hva skjer hvis ingen første parameter er gitt, eller får vi en ukjent første parameter? I slike tilfeller vil vi vise hjelpeteksten. Så, la oss komme i gang!


Trinn 3 - Skrive hjelpeteksten

Vi begynner med hvis uttalelse som sjekker for vår første parameter:

 hvis [$ 1] deretter # gjør ting annet # vis hjelp fi

Du kan være litt forvirret først, fordi et skall hvis erklæring er ganske forskjellig fra et "vanlig" programmeringsspråk hvis uttalelse. For å få en bedre forståelse av det, se skjermbildet på betingede utsagn i kurset. Denne koden kontrollerer tilstedeværelsen av en første parameter ($ 1); hvis det er der, skal vi utføre deretter kode; ellers, Vi viser hjelpeteksten.

Det er en god idé å pakke ut hjelpeteksten i en funksjon, fordi vi må ringe det mer enn en gang. Vi må definere funksjonen før den blir kalt, så vi legger den øverst. Jeg liker dette, fordi nå, så snart jeg åpner filen, ser jeg dokumentasjonen for skriptet, som kan være en nyttig påminnelse når du vender tilbake til koden du ikke har sett på en stund. Uten videre ado, her er den hjelp funksjon:

 funksjonshjelp () echo "jazz - Et enkelt skript som gjør bruk av Jasmine-testrammen i et frittstående prosjekt litt enklere." ekko "echo" jazz init - inkludere jasmin i prosjektet "; ekko" jazz skape FunctionName - skaper ./src/FunctionName.js ./spec/FunctionNameSpec.js "; ekko" jazz run - kjører tester i nettleser ";

Bare erstatt det # vis hjelp funksjon med et anrop til hjelp funksjon.

 ellers hjelpe fi

Trinn 4 - Skrive saksoppgaven

Hvis det er en første parameter, må vi finne ut hvilken den er. For dette bruker vi en sak uttalelse:

 tilfelle "$ 1" i init) ;; skape) ;; løpe) ;; *) hjelp ;; ESAC

Vi sender den første parameteren til sak uttalelse; da bør den matche en av fire ting: "init", "create", "run" eller vårt wildcard, standard tilfelle. Legg merke til at vi ikke har et eksplisitt "hjelp" tilfelle: det er bare vårt standard tilfelle. Dette fungerer fordi alt annet enn "init", "create" og "run" ikke er kommandoer som vi gjenkjenner, så det burde få hjelpeteksten.

Nå er vi klare til å skrive funksjonskoden, og vi starter med jazz init.


Trinn 5 - Forbereder Jasmine med jazz init

Alle koden vi skriver her vil gå inn i vår i det) tilfelle, fra saksoppstillingen ovenfor. Det første trinnet er å faktisk laste ned den frittstående versjonen av Jasmine, som kommer i en zip-fil:

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

Vi ekko først en liten melding, og så bruker vi curl å laste ned postnummeret. De s flagget gjør det stille (ingen utgang) og O flagg lagrer innholdet i zip til en fil (ellers ville det rote det til standard ut). Men hva er det med det $ JASMINE_LINK variabel? Vel, du kan sette den faktiske koblingen til zip-filen der, men jeg foretrekker å sette den i en variabel av to grunner: Først holder den oss fra gjentatt del av banen, som du vil se om et minutt. For det andre, med den variabelen nær toppen av filen, gjør det enkelt å endre versjonen av Jasmine vi bruker: bare endre den ene variabelen. Her er den variable erklæringen (jeg legger den utenfor hvis uttalelse, nær toppen):

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

Husk, ingen mellomrom rundt likestillingen i den linjen.

Nå som vi har vår zip-fil, kan vi pakke ut den og forberede innholdet:

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

I to av disse linjene bruker vi basenavn $ JASMINE_LINK; de basename kommandoen reduserer bare en bane til basenavnet: så / til / file.zip blir bare file.zip. Dette tillater oss å bruke det $ JASMINE_LINK variabel for å referere til vår lokale zip-fil.

Når vi pakker ut, sletter vi den zip-filen, samt alle JavaScript-filene i src og spec kataloger. Dette er de utvalgte filene som Jasmine kommer med, og vi trenger dem ikke.

Deretter har vi et Mac-only problem å håndtere. Som standard, når du laster ned noe fra Internett på en Mac, når du prøver å kjøre den for første gang, blir du bedt om å bekrefte at du vil kjøre den. Dette er på grunn av det utvidede attributtet com.apple.quarantine at Apple legger på filen. Vi må fjerne dette attributtet.

 hvis hvilken xattr> / dev / null && ["xattr SpecRunner.html"=" com.apple.quarantine "] deretter xattr -d com.apple.quarantine SpecRunner.html fi

Vi begynner med å sjekke for tilstedeværelsen av xattr kommando, fordi den ikke eksisterer på enkelte Unix-systemer (jeg er ikke sikker, men det kan være et Mac-only-program). Hvis du så på kursbildet på betingelsene, vet du at vi kan overføre noen kommandoer til hvis; hvis det har en utgangsstatus for alt annet enn 0, det er falskt. Hvis hvilken finner xattr kommando, det vil gå ut med 0; Ellers vil det gå ut med 1. I begge tilfeller, hvilken vil vise noe utdata; Vi kan holde det fra å vise ved å omdirigere det til / Dev / null (dette er en spesiell fil som kasserer all data skrevet til den).

Den dobbelte ampersand er en boolsk AND; Det er der for den andre tilstanden vi vil sjekke. Det er, gjør det SpecRunner.html har det attributtet? Vi kan bare kjøre xattr kommandoen på filen, og sammenlign den med produksjonen til strengen vi forventer. (Vi kan ikke bare forvente at filen skal ha attributtet, fordi du faktisk kan slå denne funksjonen av i Mac OS X, og vi får en feil når du prøver å fjerne den hvis filen ikke har attributten).

Så hvis xattr er funnet og filen har attributtet, vil vi fjerne det, med d (for slette) flagg. Ganske enkelt, rett?

Det siste trinnet er å redigere SpecRunner.html. For tiden inneholder den skriptetiketter for JavaScript-filene som vi slettet; Vi bør også slette disse skriptene. Jeg kommer til å vite at disse skriptene spenner over linjene 12 til 18 i filene. Så, vi kan bruke stream editoren sed for å slette disse linjene:

 sed -i "" '12, 18d 'SpecRunner.html ekko "Jasmine initialisert!"

De Jeg flagg forteller sed å redigere filen på plass, eller for å lagre utdata fra kommandoen til samme fil vi passerte inn; Den tomme strengen etter flagget betyr at vi ikke vil sed å sikkerhetskopiere filen for oss hvis du ønsket det, kan du bare sette en filtillegg i den strengen (som .bak, å få SpecRunner.html.bak).

Til slutt lar vi brukeren vite at Jasmine har blitt initialisert. Og det er det for vår jazz init kommando.


Trinn 6 - Opprette filer med jazz opprette

Deretter skal vi la brukerne lage JavaScript-filer og tilhørende spesifikke filer. Denne delen av koden vil gå i "opprett" delen av sak uttalelse vi skrev tidligere.

 hvis [$ 2] deretter # opprett filer ellers ekko "vennligst ta med et navn på filen" fi

Når du bruker jazz opprette, vi må ta med et navn på filen som den andre parameteren: jazz opprette visning, for eksempel. Vi bruker dette til å lage src / View.js og spec / ViewSpec.js. Så, hvis det ikke er en andre parameter, vil vi minne brukeren om å legge til en.

Hvis det er et filnavn, begynner vi ved å lage disse to filene (inne i deretter del over):

 ekko "-funksjonen $ 2 () \ n \ n"> src / $ 2.js ekko "beskriv ('$ 2', funksjon () \ n \ n);" > spec / $ 2Spec.js

Selvfølgelig kan du sette hva du vil inn i din src fil. Jeg gjør noe grunnleggende her; så jazz opprette visning vil skape src / View.js med dette:

 funksjonsvisning () 

Du kan erstatte det først ekko linje med dette:

 echo "var $ 2 = (funksjon () \ n \ tvar $ 2Prototype = \ n \ n \ t; \ n \ n \ treturn \ n \ t \ tcreate: funksjon (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

Og så jazz opprette visning vil resultere i dette:

 var View = (funksjon () var ViewPrototype = ; return lage: funksjon (attrs) var o = Object.create (ViewPrototype); utvide (o, attrs); return o; ; ;

Så, virkelig, fantasien din er grensen. Selvfølgelig vil du at specfilen skal være standard Jasmine-spesifikasjonskoden, som er hva jeg har over; men du kan finjustere det, men du liker også.

Det neste trinnet er å legge til skriptetikettene for disse filene til SpecRunner.html. I begynnelsen kan dette virke vanskelig: hvordan kan vi legge til linjer til midten av en fil programmatisk? Igjen er det sed det gjør jobben.

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

Vi starter som vi gjorde før: redigere på plass uten sikkerhetskopiering. Så vår kommando: på linje 11, vil vi legge til de to følgende linjene. Det er viktig å unnslippe de to nye linjene, slik at de vises i teksten. Som du kan se, legger du bare inn disse to skriptene, akkurat det vi trenger for dette trinnet.

Vi kan ende med litt utgang:

 ekko "Opprettet:" ekko "\ t-skjerm / $ 2.js" ekko "\ tec / $ 2Spec.js" ekko "Redigert:" ekko "\ t- SpecRunner.html"

Og det er jazz opprette!


Trinn 7 - Kjører spesifikasjonene med jazz løp

Det siste trinnet er å faktisk kjøre testene. Dette betyr å åpne SpecRunner.html fil i en nettleser. Det er litt av en advarsel her. På Mac OS X kan vi bruke åpen kommandoen for å åpne en fil i standardprogrammet; Dette vil ikke fungere på andre operativsystemer, men det er slik jeg gjør det her. Dessverre er det ingen ekte plattforms måte å gjøre dette på, som jeg vet om. Hvis du bruker dette skriptet under Cygwin på Windows, kan du bruke det cygstart i stedet for åpen; ellers, prøv googling "[ditt OS] shell script open browser" og se hva du kommer opp med. Dessverre har noen versjoner av Linux (minst Ubuntu, i min erfaring) en åpen kommando det er for noe helt annet. Alt dette å si, kjørelengde med følgende kan variere.

hvis ["'som åpner'" = '/ usr / bin / open') åpner du SpecRunner.html annet ekko "Vennligst åpne SpecRunner.html i nettleseren din" fi

Nå vet du nøyaktig hva dette gjør: hvis vi har det åpen, vi åpner SpecRunner.html, ellers skriver vi bare en melding som forteller brukeren å åpne filen i nettleseren.

Opprinnelig, det hvis tilstanden så slik ut:

hvis som åpner> / dev / null

Som vi gjorde med xattr, det bare sjekket for eksistensen av åpen; Men siden jeg fant ut at det er et annet åpen kommandoen på Linux (selv på min Ubuntu-server, som ikke engang kan åpne en nettleser!), fant jeg det bedre å sammenligne stien til åpen program, siden Linux er på / Bin / åpen (igjen, i hvert fall på Ubuntu-serveren).

Alt dette ekstra ordlighet om åpen kan høres ut som en unnskyldning for min mangel på en god løsning, det peker faktisk på noe viktig om kommandolinjen. Ikke gjør feil ved å forstå terminalen ved å forstå en datamaskinens konfigurasjon. Denne opplæringen og det tilknyttede kurset har lært deg litt mer om Bash-skallet (og Z-skallet), men det betyr ikke at hver datamaskin du bruker, blir konfigurert det samme. Det er mange måter å installere nye kommandoer på (eller forskjellige versjoner av kommandoer), samt fjerne kommandoer. Huleutvikler.

Vel, det er hele skriptet! Her er det igjen, alt sammen:

 #! / bin / sh funksjon hjelp () echo "jazz - Et enkelt skript som gjør bruk av Jasmine testing rammeverket i et frittstående prosjekt litt enklere." ekko "" ekko "jazz init - inkludere jasmin i prosjektet"; ekko "jazz create FunctionName - oppretter ./src/FunctionName.js ./spec/FunctionNameSpec.js"; ekko "jazz run - kjører tester i nettleser";  JASMIME_LINK = "http://cloud.github.com/downloads/pivotal/jasmine/jasmine-standalone-1.3.1.zip" hvis [$ 1] så tilfelle "$ 1" i init) ekko "Downloading Jasmine ..." curl - sO $ JASMIME_LINK unzip -q 'basenavn $ JASMIME_LINK' rm 'basenavn $ JASMIME_LINK' src / *. js spec / *. js hvis hvilket xattr> / dev / null && ["'xattr SpecRunner.html'" = "com.apple .quarantine "] deretter xattr -d com.apple.quarantine SpecRunner.html fi sed -i" "" 12,18d "SpecRunner.html ekko" Jasmine initialisert! " ;; opprett) hvis [$ 2] deretter ekko "funksjon $ 2 () \ n \ n"> ./src/$2.js echo "beskriv ('$ 2', funksjon () \ nit ('kjører'); \ n );" > ./spec/$2Spec.js sed -i "" "11a \\ \\  "SpecRunner.html echo" Laget: "echo" \ t-src / $ 2.js "echo" \ tec / $ 2Spec.js "echo" Redigert: "echo" \ t- SpecRunner.html "annet ekko" vær så snill legg til et navn for filen 'fi ;; run') hvis ["'som åpner'" = '/ usr / bin / open') så åpne ./SpecRunner.html annet ekko "Vennligst åpne SpecRunner.html i nettleseren din "fi ;; *) hjelp ;;; esac annet hjelp; fi

Vel, fortsett, prøv det!

 mkdir prosjekt cd prosjekt jazz init jazz lage hund # rediger src / dog.js og spec / dogspec.js jazz run

Forresten, hvis du vil ha litt mer moro med dette prosjektet, kan du finne det på Github.


Konklusjon

Så der har du det! Vi har nettopp skrevet et mellomliggende nivå shell script; det var ikke så ille, nå var det? Ikke glem å holde øye med mitt kommende Tuts + Premium kurs; Du vil lære mye mer om mange av teknikkene som brukes i denne artikkelen, så vel som utallige andre. Ha det gøy på terminalen!