Att skapa ett enkelt script

Här diskuterar vi skal, kommandon och klassiska linuxverktyg.
Trill

Att skapa ett enkelt script

Inlägg av Trill »

Ett  shellscript är i princip lite terminalkommandon i en textfil som du senare kör. Här under visar jag hur man kan skapa ett enkelt script.

-----------------------------------------------------------

Börja med att högerklicka någonstans på skrivbordet och tryck på "Skapa dokument - Ny fil". Öppna filen.
För att vårt script ska fungera så skriver vi #!/bin/bash högst upp i scriptet.
Efter det så vill vi att scriptet ska säga någonting så vi skriver
echo "Detta är vårt första script"
Nu kommer vårt script att skriva det när scriptet startas. Ett litet steg för scriptet men ett stort steg för scriptaren.;) (Om man vill ha mellanrum så skriver man echo "")
Och i script så kan man välja att göra olika saker men jag väljer nu idag att skriva ett script där jag kan välja att starta flera hemsidor. Jag skriver lite kort den siffra man ska skriva in för att komma in på en viss sida

echo "1 -> UbuntuSE"
echo "2 -> UbuntuSE forum"
echo "3 -> blank"



Efter det så skriver jag
read svar

Och det gör jag för att datorn ska snappa upp det som kommer. Nu vet datorn att den ska snappa upp det som skrivs in men den vet inte vad den ska göra med det som skrivs in. Med denna understående kodsnutt så berättar vi för datorn att den ska starta ubuntus hemsida med hjälp av firefox om $svar = 1.


if [ "$svar" = "$1" ]; then
firefox http://www.ubuntu-se.org/

Med tanke på att if är om på så Svenska så blir ju allting rätt logiskt, eller hur?;)

Såhär ser vår kod ut just nu:

#!/bin/bash
echo "Detta är vårt första script"
echo "1 -> UbuntuSE forum"
echo "2 -> UbuntuSE"
echo "3 -> blank"
read svar
if [ "$svar" = "1" ]; then
firefox http://www.ubuntu-se.org/


Vi fortsätter att utveckla och lägger också till de andra sidorna. Men nu använder vi "elif" istället för "if".

Nu ska vi lägga till detta eftersom vi vill ha möjlighet att öppna Ubuntus forum och en blank sida.
elif [ "$svar" = "2" ]; then
firefox http://www.ubuntu-se.org/forum
elif [ "$svar" = "3" ]; then
firefox about:blank


Koden är nu rätt färdigt och det är bara småsaker vi ska lägga till.
En av dessa småsaker vi ska använda oss av är "&" tecknet. Den får kommandona att köras i bakgrunden vilket är bra eftersom skriptet då inte ligger kvar i terminalen och blocker terminalen. (Tack Deepthought).

Vi lägger till & och såhär ser koden ut nu:
#!/bin/bash
echo "Detta är vårt första script"
echo "1 -> UbuntuSE"
echo "2 -> UbuntuSE forum"
echo "3 -> blank"
read svar
if [ "$svar" = "1" ]; then
firefoxhttp://www.ubuntu-se.org/ &
elif [ "$svar" = "2" ]; then
firefox http://www.ubuntu-se.org/forum &
elif [ "$svar" = "3" ]; then
firefox about:blank &


Vi lägger också till
exit
fi
På slutet.

Slutgiltig kod:

#!/bin/bash
echo "Detta är vårt första script"
echo "1 -> UbuntuSE"
echo "2 -> UbuntuSE forum"
echo "3 -> blank"
read svar
if [ "$svar" = "1" ]; then
firefox http://www.ubuntu-se.org/ &
elif [ "$svar" = "2" ]; then
firefox http://www.ubuntu-se.org/forum &
elif [ "$svar" = "3" ]; then
firefox about:blank &
exit
fi


Se så enkelt det var.:)

Viktigt!!: För att filen ska kunna köras så skriver du in detta i terminal fönstret:
sudo chmod +x sök/vägen/till/filen. För att sen starta scriptet så cdar du dig fram till mappen där scriptet ligger och skriver in
./scriptnamn. I mitt fall blir det:
cd Desktop
./hej
[


Små tips :
Om du vill att två kommandon ska köras på samma rad så skriver du kommando && kommando
Om du vill att ett program ska öppna en fil så skriver du sökvägtillprogrammet sökvägtillsakenprogrammetskaöppna
Om du vill infoga kommentarer i skriptet så använd #följt av text.
johan_pirate

SV: Att skapa ett enkelt script

Inlägg av johan_pirate »

Jag börjat lite smått med skript och tycker det är väldigt smidigt med din lilla guide här.

tackar :)
Användarvisningsbild
Barre
Inlägg: 2298
Blev medlem: 13 dec 2006, 10:23
OS: Ubuntu
Ort: Stockholm
Kontakt:

SV: Att skapa ett enkelt script

Inlägg av Barre »

Alltid kul att diskutera programmering :)

en fråga.
om man väljer 3, about:blank. varför är det en exit där?

Det finns ju alltid miljoner sätt att göra samma sak med script/programmering (är ju faktiskt tjusningen med det).
Mitt förslag är att använda array istället för en if/elsif, på så sätt är det enklare att bygga ut med fler alternativ.

tex.

Kod: Markera allt

#!/bin/bash
#meny array
Dest=("http://www.ubuntu-se.org/" "http://www.ubuntu-se.org/forum/" "about:blank")

# Skriv ut menyvalen.
for (( i = 0 ; i < ${#Dest[@]} ; i++ ))
do
  echo "$i -> ${Dest[$i]}"
done
read svar

firefox ${Dest[$svar]} & 
Det som är kvar att göra i scriptet är att hantera felhanteringen, alltså om användaren väljer ett alternativ som inte finns :)
Senast redigerad av 1 Barre, redigerad totalt 8 gånger.
________________________________________________________________
twitter @ BarreGargamel
blogg @ Gargamel.NU
Trill

SV: Att skapa ett enkelt script

Inlägg av Trill »

@johan_pirate: Tackar

@barre

Jag själv är ingen riktig höjdare på scripting och håller just nu på att försöka lära mig for och while. Men nåja, borde det inte bara vara att lägga in ett else för att den ska skicka ut felmeddelanden om någon skriver in adjaisdjksda?

Angående exit så kommer jag inte riktigt ihåg varför jag gjorde så... :-[

Din egen kod verkar händigare men jag ville visa if som jag tycker är väldigt logiskt och bra.

Den rad jag fastnar på i din kod är denna:
for (( i = 0 ; i < ${#Dest[ @]} ; i++ ))

Att den använder sig av rad 3 förstår jag men jag förstår inte riktigt hur den binder 0/1/2 till de olika sidorna...
Användarvisningsbild
Barre
Inlägg: 2298
Blev medlem: 13 dec 2006, 10:23
OS: Ubuntu
Ort: Stockholm
Kontakt:

SV: Att skapa ett enkelt script

Inlägg av Barre »

Tjena Trill.
Jag skall försöka att vara lite pedagogisk som du :)

På den första raden deklarerar jag en variabel som är en array

Kod: Markera allt

Dest=("http://www.ubuntu-se.org/" "http://www.ubuntu-se.org/forum/" "about:blank")
En skulle man kunna säga är en lista som innehåller olika värden.
”Dest” är själva listan, den innehåller i vårat fall 3 stycken värden, jag skulle kunna ersätta den första raden med detta.

Kod: Markera allt

Dest[0] = "http://www.ubuntu-se.org/"
Dest[1] = "http://www.ubuntu-se.org/forum/"
Dest[2] = "about:blank"
Vilket skulle ge exakt samma resultat.
För att skriva ut någon av dessa variabler så skriver man

Kod: Markera allt

 echo ${Dest[1]} 
Detta skulle skriva ut http://www.ubuntu-se.org/forum/  på skärmen.

Efter det så gör jag en ”for loop”.

Kod: Markera allt

for (( i = 0 ; i < ${#Dest[@]} ; i++ ))
Det som står mellan parentesen är egentligen tre utryck som avgör hur länge programmet skall stanna i loopen och köra programkoden som står mellan do och done
Så här kan man förklara for loopen:
((startvärde; vilkor; gör varje gång))
inte så bra översättning, men ändå ;)
* startvärde, här talar vi om att när vi startar loopen så är variabeln i = 0
* villkor, här talat vi om att så länge $i är mindre än antalet element i vår array Dest så skall vi stanna i loopen (${#Dest[ @]} är kommandot för att returnera antalet element i vår array, i vårat fall kommer talet 3 att returneras
.)
* gör varje gång, detta utryck kommer att köras varje gång vårt vilkor är sant, alltså i < ${#Dest[ @]}. i++ betyder att den skall ta vardet av vad i är och lägga på ett. Alltså bara ett enklare sätt än att skriva i=i+1.

Så när loopen startar så kommer $i att vara 0, vårt villkor är i < ${#Dest[ @]}, d.v.s kör loopen om i är mindre än antalet element i vår array Dest: 0<3. Detta är sant, så vi kommer att köra koden mellan do och done
När vi gjort detta en gång så kommer vi lägga på 1 till i (i++) så att i nu har värdet 1 och sen kontrollera villkoret igen.
kör loopen om i är mindre än antalet element i vår array Dest: 1<3. Detta är sant, så vi kommer att köra koden mellan do och done
När vi gjort detta en gång så kommer vi addera i med 1 (i++) så att i nu har värdet 1 och sen kontrollera villkoret igen.
o.s.v.

Koden i själva loopen består av enbart en rad i vårat fall

Kod: Markera allt

 echo "$i -> ${Dest[$i]}"
Eftersom $i är 0 första gången så kommer det stå echo ”0 -> ${Dest[0]}” dvs. att den programmet kommer att skriva ut det förta elementet i arary Dest vilket är http://www.ubuntu-se.org/  i vårat exempel.
Nästa gång vi kör loopen kommer $i att vara 1 och då kommer

Kod: Markera allt

 echo "$i -> ${Dest[$i]}"
att vara

Kod: Markera allt

 echo ”1 -> ${Dest[1]}”

På så sätt behöver vi inte köra några förändringar i koden om vi vill addera fler val i vårt ”firefox start skript”.
Genom att enbart lägga till element i vår array så kommer loopen att sköta resten.

Kod: Markera allt

Dest=("http://www.ubuntu-se.org/" "http://www.ubuntu-se.org/forum/" "about:blank")
Dest[3]="http://www.google.se/"
Dest[4]="http://www.ubuntu.com/"

for (( i = 0 ; i < ${#Dest[@]} ; i++ ))
do
  echo "$i -> ${Dest[$i]}"
done
read svar
firefox ${Dest[$svar]} & 
Jag vet att jag inte är den mest pedagogiska personen på detta forum, men jag försöker..
Har du några frågor, så tveka inte att fråga.
________________________________________________________________
twitter @ BarreGargamel
blogg @ Gargamel.NU
Trill

SV: Att skapa ett enkelt script

Inlägg av Trill »

Bra skrivet!

Hoppas jag har förstått allting nu. 8)

Ska kolla lite mera sakligt sen men nu känns det som om bitarna börjar falla på sin plats.
Användarvisningsbild
DeepThought
Inlägg: 2769
Blev medlem: 19 dec 2006, 11:07
OS: Arch Linux
Ort: Göteborg

SV: Att skapa ett enkelt script

Inlägg av DeepThought »

Jag tänkte jag skulle skriva ett litet script som startar AWN vid uppstart, men bara om det inte redan körs!

Tänkte att jag då skulle ha en if-sats, men kan inte alls den här typen av scripting, så jag behöver lite hjälp. Är det något sådant här det får bli?

Kod: Markera allt

#!/bin/sh

if [ ! `ps -A | grep 'avant'` ] ; then
        avant-window-navigator
fi
WE WILL ALWAYS BE SO MUCH MORE HUMAN THAN WE WISH TO BE...
Användarvisningsbild
Kerath
Inlägg: 630
Blev medlem: 25 jan 2007, 19:51
OS: Arch Linux

SV: Att skapa ett enkelt script

Inlägg av Kerath »

För att göra scriptet till ett kommando så att du slipper leta dig fram till detsamma varje gång kan du skriva följande:

Kod: Markera allt

cd /sökväg/till/script
sudo cp script /bin/
Byt givetvis ut "script" mot namnet på filen. Hoppas det underlättar! ;)
- Är det en rättighet att förbli okunnig?
- Jag vet inte, men jag vägrar ta reda på det!

Human logic: 'I want to fight for world peace, give me a gun!'
Användarvisningsbild
Barre
Inlägg: 2298
Blev medlem: 13 dec 2006, 10:23
OS: Ubuntu
Ort: Stockholm
Kontakt:

SV: Att skapa ett enkelt script

Inlägg av Barre »

DeepThought skrev: Jag tänkte jag skulle skriva ett litet script som startar AWN vid uppstart, men bara om det inte redan körs!

Tänkte att jag då skulle ha en if-sats, men kan inte alls den här typen av scripting, så jag behöver lite hjälp. Är det något sådant här det får bli?

Kod: Markera allt

#!/bin/sh

if [ ! `ps -A | grep 'avant'` ] ; then
        avant-window-navigator
fi
Tjenis DeepThought

Så här har jag löst en liknande if sats.
Kanske lite omständligt, men den gör sitt jobb... :)
Först tänkte jag beskriva lite tanken bakom-..

det jag först vill göra är att få en "ren" lista med bara binärnamnet på alla processer som körs.
Det gör jag med kommandot
ps -A -o comm
-A = Alla processer
-o comm = visa enbart kommandot processen kör.

när jag har den listan så kan jag specificera vilket process jag letar efter lite mer detaljerat.
Jag kan då "grep"a hela kommandot
ps -A -o comm | grep '^avant$'
^ = raden skall början, m.a.o. det får inte finnas någonting före avant
$ =raden skall avslatas med avant, m.a.o. får det inte finnas några tecken efter avant.
på så sätt så grep:s enbart raden som innehåller avant och inget annat.

lägger jag sen till ett -c som parameter till grep så retunerar grep antalet rader istället för att skriva ut raden. På så sätt kan jag skriva if satsen med ett tal.

Kod: Markera allt

if [ `ps -A -o comm | grep -c '^avant$'` = "1" ]; then
    avant-window-navigator
fi
att det är ` omkrig  `ps -A -o comm | grep -c '^avant$'` i if satsen betyder att det som är mellan `` skall exekveras först innan den försöker kontrollera if satsen.
Så om avant körs kommer  `ps -A -o comm | grep -c '^avant$'` att retunera 1, om den inte körs kommer  `ps -A -o comm | grep -c '^avant$'` retunera 0.
nu hänger det på att processen heter avant och inget mer, och att du inte kör fler än 1 avant :)
självklart är grep case sensitive
Senast redigerad av 1 Barre, redigerad totalt 14 gånger.
________________________________________________________________
twitter @ BarreGargamel
blogg @ Gargamel.NU
Användarvisningsbild
DeepThought
Inlägg: 2769
Blev medlem: 19 dec 2006, 11:07
OS: Arch Linux
Ort: Göteborg

SV: Att skapa ett enkelt script

Inlägg av DeepThought »

Tackar vänligast Barre! ;D

Fungerade finfint, och slutresultatet blev så här, helt enkelt:

Kod: Markera allt

if [ `ps -A -o comm | grep -c '^avant'` = "0" ]; then
        avant-window-navigator
fi
WE WILL ALWAYS BE SO MUCH MORE HUMAN THAN WE WISH TO BE...
Användarvisningsbild
Konservburk
Inlägg: 5919
Blev medlem: 07 apr 2007, 22:28

SV: Att skapa ett enkelt script

Inlägg av Konservburk »

Barre skrev: det jag först vill göra är att få en "ren" lista med bara binärnamnet på alla processer som körs.
Det gör jag med kommandot
ps -A -o comm
-A = Alla processer
-o comm = visa enbart kommandot processen kör.

när jag har den listan så kan jag specificera vilket process jag letar efter lite mer detaljerat.
Jag kan då "grep"a hela kommandot
ps -A -o comm | grep '^avant$'
^ = raden skall början, m.a.o. det får inte finnas någonting före avant
$ =raden skall avslatas med avant, m.a.o. får det inte finnas några tecken efter avant.
på så sätt så grep:s enbart raden som innehåller avant och inget annat.
Man kan göra motsvarande med kommandot pgrep:

Kod: Markera allt

pgrep '^avant$'
Barre skrev: att det är ` omkrig  `ps -A -o comm | grep -c '^avant$'` i if satsen betyder att det som är mellan `` skall exekveras först innan den försöker kontrollera if satsen.
Nu är grep (och pgrep) så smarta att de sätter returvärde
beroende på om de hittade något eller inte. Det är därför
helt onödigt med `` i det här fallet.

I if-satsen blir det istället så här:

Kod: Markera allt

if ! ps -A -o comm | grep '^avant$' >&-; then
        avant-window-navigator
fi
...eller ännu bättre:

Kod: Markera allt

if ! pgrep ^avant$' >&-; then
        avant-window-navigator
fi
Det går också att strunta helt i if-satsen:

Kod: Markera allt

pgrep ^avant$' >&- || avant-window-navigator

Det finns dock flera problem med hela detta angreppssätt.

Vad händer om flera olika användare vill köra AWN samtidigt ?
Eller om någon annan process än AWN råkar heta 'avant' ?
Eller om andra/framtida versioner av AWN inte alls har 'avant'
som processnamn ?

Jag skulle därför istället ha använt mig av en lock-fil.
Något i stil med detta:

Kod: Markera allt

#!/bin/sh

LOCK_FILE=/tmp/"`whoami`".AWN.lock
fuser -s "$LOCK_FILE" && exit 1
exec 9>"$LOCK_FILE" avant-window-navigator
Samma wrapper-skript med förklarande kommentarer:

Kod: Markera allt

#!/bin/sh

# Välj en användar-unik ("`whoami`") lock-fil
LOCK_FILE=/tmp/"`whoami`".AWN.lock

# Avsluta wrapper-skriptet med felkod (exit 1)
# om lock-filen redan används (fuser -s "$LOCK_FILE")
fuser -s "$LOCK_FILE" && exit 1

# Ersätt wrapper-skriptet (exec)
# med ett ny AWN-process (avant-window-navigator)
# som anväder lock-filen (9>"$LOCKFILE")
exec 9>"$LOCK_FILE" avant-window-navigator
Användarvisningsbild
Barre
Inlägg: 2298
Blev medlem: 13 dec 2006, 10:23
OS: Ubuntu
Ort: Stockholm
Kontakt:

SV: Att skapa ett enkelt script

Inlägg av Barre »

DrKonservburk.... wow & tack :)

Man lär sig något nytt varje dag... pgrep har jag missat helt..

En påse karma till dig för att du tog dig tid att beskriva och förklara detta...
________________________________________________________________
twitter @ BarreGargamel
blogg @ Gargamel.NU
Skriv svar

Återgå till "Terminalforum"