Infinite while loop i ett BASH-skript. BASH: beskrivning av for, while, tills loopar och exempel på användning Exempel: sökning efter körbara filer


Författare: Paul Cobbaut
Publiceringsdatum: 16 oktober 2014
Översättning: A. Panin
Översättningsdatum: 21 december 2014

Kapitel 22. Slingor i skript

testkommando

Testkommandot låter dig avgöra om ett uttryck är sant eller falskt. Låt oss börja med att testa om heltalsvärdet 10 är större än heltalsvärdet 55. $ test 10 -gt 55 ; echo $? 1$

Testkommandot returnerar 1 om uttrycket är falskt. Och, som du kommer att se i följande exempel, returnerar testkommandot 0 om uttrycket utvärderas till sant. $ test 56 -gt 55 ; echo $? $0

Om du är mer bekväm med att arbeta med strängarna sant och falskt kan du använda testkommandot som visas nedan. $ test 56 -gt 55 && echo true || echo false true $ test 6 -gt 55 && echo true || eko falskt falskt

Testkommandot kan också ersättas av hakparenteser, så kommandona i exemplet nedan är exakt desamma som kommandona i exemplet ovan. $ [ 56 -gt 55 ] && echo true || echo false true $ [ 6 -gt 55 ] && echo true || eko falskt falskt

Nedan finns exempel på implementeringar av vissa kontroller. Se mantestsidan för en översikt över ytterligare egenskaper genomförande av olika kontroller. [ -d foo ] Finns katalog foo? [ -e bar ] Finns barfilen? [ "/etc" = $PWD ] Är /etc ekvivalent med värdet på $PWD ? [ $1 != "hemlig" ] Skiljer sig värdet på den första skriptparametern från den hemliga strängen? [ 55 -lt $bar ] Är heltalsvärdet 55 mindre än värdet på $bar ? [ $foo -ge 1000 ] Är värdet på $foo större än eller lika med heltalsvärdet 1000 ? ["abc"< $bar ] Будет ли строка abc расположена выше значения переменной $bar в списке после сортировки? [ -f foo ] Является ли foo обычным файлом? [ -r bar ] Является ли bar läsbar fil? [foo -nt bar] Är foo nyare än bar? [ -o nounset ] Är alternativet för nounset shell aktiverat?

Kontrollera operatörer kan kombineras med operatörer motsvarande logiska operationer"OCH" och "ELLER". paul@RHEL4b:~$ [ 66 -gt 55 -a 66 -lt 500 ] && echo true || echo false true paul@RHEL4b:~$ [ 66 -gt 55 -a 660 -lt 500 ] && echo true || echo false false paul@RHEL4b:~$ [ 66 -gt 55 -o 660 -lt 500 ] && echo true || eko falskt sant

Villkorligt hopp om så annat

If then else-konstruktionen är avsedd att välja ett kodalternativ. Om ett visst villkor är sant kommer någon kod att exekveras, annars kommer någon annan kod att exekveras. Exemplet nedan kontrollerar om det finns en fil, varefter, om antagandet om filens existens bekräftas, ett motsvarande meddelande visas. #!/bin/bash om [ -f isit.txt ] sedan echo filen isit.txt existerar! annars hittades inte ekofilen isit.txt! fi

I händelse av att vi sparar denna kod skript i en fil med namnet "choice", kan det köras på samma sätt. $ ./choice-filen isit.txt hittades inte! $ touch isit.txt $ ./choice-filen isit.txt finns! $

Villkorligt hopp om då elif

Du kan posta ny operatör villkorligt hopp om inne i ett annat block med hjälp av elif-operatorn. Nedan är ett enkelt exempel på en sådan post. #!/bin/bash count=42 om [ $count -eq 42 ] eko "42 är ett giltigt värde." elif [ $count -gt 42 ] eko sedan "Too many." annars ekar "Inte tillräckligt." fi

för slinga

Exemplet nedan visar syntaxen för en klassiker för loop i bash-skalet. för i in 1 2 4 do echo $i done

Ett exempel på att använda en for-loop i kombination med ett inline-skalanrop. #!/bin/ksh för räknare i `seq 1 20` gör ekoräkning från 1 till 20, aktuellt värde $counter vilo 1 klar

Ett skript helt likt det som presenteras ovan kan skapas utan att använda ett inbäddat kommandoskal genom att använda bash-skal-deklarationen för en rad värden (från värde...till värde). #!/bin/bash för räknare in (1..20) gör ekoräkning från 1 till 20, aktuellt värde $counter vila 1 klar

Denna för loop använder en mekanism för att söka efter filer efter mönster (implementerad som en del av kommandoexpansionsmekanismen). Om instruktionerna ovan postas direkt i kommandorad, kommer det att fungera på samma sätt. kahlan@solexp11$ ls count.ksh go.ksh kahlan@solexp11$ för fil i *.ksh ; gör cp $file $file.backup ; gjort kahlan@solexp11$ ls count.ksh count.ksh.backup go.ksh go.ksh.backup

medan loop

Nedan är ett enkelt exempel på användning av en while-loop. i=100; medan [$i -ge 0]; gör echo Nedräkning från 100 till 0, aktuellt värde $i; låt jag--; Gjort

Oändliga loopar kan implementeras med while true eller while:-deklarationer, där symbolen: motsvarar den saknade operationen i Korn-skalet och bash. #!/bin/ksh # ändlös loop medan: gör echo hej sömn 1 klar

Tills loop

Nedan är ett enkelt exempel på hur man använder en till-loop. låt i=100; tills [$i -le 0]; gör echo Nedräkning från 100 till 1, aktuellt värde $i; låt jag--; Gjort

Övning: Tester och loopar i skript

3. Utveckla ett skript som använder en while-loop för att räkna från 3 till 7.

4. Utveckla ett skript som använder en tillslinga för att räkna ner från 8 till 4.

5. Utveckla ett skript som kommer att räkna filer med filtillägget .txt i den aktuella katalogen.

6. Använd if-satsen i det skapade skriptet för att få det att fungera korrekt om det inte finns några filer med filtillägget .txt i den aktuella katalogen.

Den korrekta proceduren för att slutföra en praktisk uppgift: kontroller och loopar i skript

1. Utveckla ett skript som använder en for-loop för att räkna från 3 till 7.

#!/bin/bash för i in 3 4 5 6 7 do echo Räknar från 3 till 7, nuvarande värde $i done

2. Utveckla ett skript som använder en for-loop för att räkna från 1 till 17 000.

Bash-skalet stödjer loopar, vilket gör att du kan iterera över sekvenser av värden. Det är vad det är grundläggande struktur sådana cykler:

För var i listan gör kommandot gjort
I varje iteration av loopen kommer variabeln var att skrivas till nästa värde från lista. Det första passet i slingan kommer därför att använda det första värdet från listan. I den andra - den andra, och så vidare - tills slingan når det sista elementet.

Itererar över enkla värden

Det kanske enklaste exemplet på en for-loop i bash-skript är att iterera över en lista med enkla värden:

#!/bin/bash för var i första andra tredje fjärde femte gör echo $var-objektet gjort
Resultaten av detta skript visas nedan. Du kan tydligt se att variabeln $var innehåller element från listan sekventiellt. Detta händer tills cykeln når den sista av dem.


Enkel för loop

Observera att $var-variabeln behåller sitt värde när du lämnar loopen, dess innehåll kan ändras och i allmänhet kan du arbeta med den som vilken annan variabel som helst.

Itererar över komplexa värden

Listan som används för att initiera for-slingan kan inte bara innehålla enkla strängar som består av ett ord, utan även hela fraser som innehåller flera ord och skiljetecken. Det kan till exempel se ut så här:

#!/bin/bash för var i första "det andra" "det tredje" "I'll do it" gör echo "Detta är: $var" gjort
Detta är vad som händer efter att den här slingan har gått igenom listan. Som du kan se är resultatet ganska väntat.


Itererar över komplexa värden
TNW-CUS-FMP - kampanjkod för 10% rabatt på våra tjänster, tillgänglig för aktivering inom 7 dagar"

Initiera en loop med en lista som erhålls från resultatet av kommandot

Ett annat sätt att initiera en for-loop är att skicka en lista till den, som är resultatet av ett kommando. Här används kommandosubstitution för att utföra dem och få resultatet av deras arbete.

#!/bin/bash file="myfile" för var in $(cat $file) do echo " $var" done
Det här exemplet använder kommandot cat, som läser innehållet i en fil. Den resulterande värdelistan skickas in i slingan och visas på skärmen. Observera att filen vi har tillgång till innehåller en lista med ord separerade av rader, inga mellanslag används.


En loop som går igenom innehållet i en fil

Här måste vi ta hänsyn till att ett sådant tillvägagångssätt, om rad-för-rad databehandling förväntas, inte kommer att fungera för en fil med en mer komplex struktur, vars rader kan innehålla flera ord separerade med mellanslag. Slingan kommer att bearbeta enskilda ord, inte rader.

Tänk om detta inte alls är vad du behöver?

Fältavskiljare

Anledningen till ovanstående funktion är det speciella miljöfaktor, som kallas IFS (Internal Field Separator) och låter dig ange fältseparatorer. Som standard betraktar bash-skalet följande tecken som fältavgränsare:
  • Plats
  • Tab-tecken
  • Radmatningskaraktär
Om bash stöter på något av dessa tecken i data, antar det att det föregås av nästa oberoende värde i listan.

För att lösa problemet kan du tillfälligt ändra IFS-miljövariabeln. Så här gör du det i ett bash-skript, förutsatt att du bara behöver en ny rad som fältseparator:

IFS=$"\n"
När du väl har lagt till det här kommandot i ditt bash-skript kommer det att fungera som förväntat, och ignorerar mellanslag och tabbar och behandlar endast nyradstecken som fältavgränsare.

#!/bin/bash file="/etc/passwd" IFS=$"\n" för var i $(cat $file) gör echo " $var" gjort
Om det här skriptet körs kommer det att mata ut exakt vad som krävs av det, vilket ger åtkomst till nästa rad som skrivs till filen i varje iteration av loopen.


Rad för rad genomgång av en fil i en for-loop

Separatorer kan också vara andra tecken. Till exempel ovan visade vi innehållet i filen /etc/passwd. Användardata på rader separeras med kolon. Om du behöver bearbeta sådana strängar i en loop, kan IFS konfigureras så här:

Gå igenom filer som finns i en katalog

En av de vanligaste användningsområdena för loopar i bash-skript är att gå igenom filer som finns i en katalog och bearbeta dessa filer.

Så här listar du till exempel filer och mappar:

#!/bin/bash för fil i /home/likegeeks/* gör om [ -d "$file" ] sedan eko "$file är en katalog" elif [ -f "$file" ] sedan eko "$file är en fil" fi klar
Om du förstod det tidigare materialet i den här artikelserien bör du förstå strukturen för om-då-konstruktionen, samt hur man skiljer en fil från en mapp. Om du tycker att det är svårt att förstå ovanstående kod, läs detta material igen.

Detta är vad skriptet kommer att mata ut.


Visar innehållet i en mapp

Var uppmärksam på hur vi initierar slingan, nämligen jokertecken"*" i slutet av mappadressen. Denna symbol kan ses som ett jokertecken som betyder: "alla filer med valfritt namn." det låter dig organisera automatiskt utbyte filnamn som matchar mönstret.

När vi testar ett villkor i en if-sats, omsluter vi variabelnamnet inom citattecken. Detta görs eftersom fil- eller mappnamnet kan innehålla mellanslag.

C-stil för slingor

Om du är bekant med programmeringsspråket C kan syntaxen för att beskriva bash för loopar verka konstigt för dig, eftersom du uppenbarligen är van vid att beskriva loopar så här:

För (i = 0; i< 10; i++) { printf("number is %d\n", i); }
I bash-skript kan du använda för loopar, vars beskrivning liknar loopar i C-stil, även om det finns vissa skillnader. Cykeldiagrammet med detta tillvägagångssätt ser ut så här:

För ((initialvärde för variabel; villkor för slutslinga; ändring av variabel))
I bash kan det skrivas så här:

För ((a = 1; a< 10; a++))
Här är ett fungerande exempel:

#!/bin/bash för ((i=1; i<= 10; i++)) do echo "number is $i" done
Den här koden matar ut en lista med nummer från 1 till 10.

Looping i C-stil

medan loop

For-konstruktionen är inte det enda sättet att organisera loopar i bash-skript. Du kan även använda while-slingor här. I en sådan slinga kan du ange ett kommando för att kontrollera ett visst villkor och exekvera slingans kropp tills villkoret som testas ger noll, eller en signal för framgångsrikt slutförande av en viss operation. När slingvillkoret returnerar ett värde som inte är noll, vilket betyder ett fel, kommer slingan att stanna.

Här är ett diagram över organisationen av while-slingor
medan tillståndskontrollkommandot
do
andra lag
Gjort

Låt oss ta en titt på ett exempelskript med en loop så här:

#!/bin/bash var1=5 medan [ $var1 -gt 0 ] gör echo $var1 var1=$[ $var1 - 1 ] klar
Vid ingången till slingan kontrolleras om variabeln $var1 är större än noll. Om så är fallet exekveras slingans kropp, där en subtraheras från variabelns värde. Detta händer i varje iteration, och vi skriver ut variabelns värde till konsolen innan den ändras. Så snart $var1 når värdet 0, stannar slingan.

Resultat av while-slingan

Om du inte modifierar $var1-variabeln kommer detta att göra att skriptet hamnar i en oändlig loop.

Kapslade loopar

Du kan använda alla kommandon i slingans kropp, inklusive att starta andra loopar. Sådana konstruktioner kallas kapslade loopar:

#!/bin/bash för ((a = 1; a<= 3; a++)) do echo "Start $a:" for ((b = 1; b <= 3; b++)) do echo " Inner loop: $b" done done
Nedan är vad det här skriptet kommer att mata ut. Som du kan se exekveras först den första iterationen av den yttre slingan, sedan tre iterationer av den inre, efter att den är klar kommer den yttre slingan i spel igen, sedan den inre igen.

Kapslade loopar

Bearbetar filinnehåll

Oftast används kapslade loopar för att bearbeta filer. Så den yttre slingan itererar över filens linjer, och den inre arbetar redan med varje linje. Här är till exempel hur bearbetningen av filen /etc/passwd ser ut:

#!/bin/bash IFS=$"\n" för inmatning i $(cat /etc/passwd) do echo "Värden i $entry –" IFS=: för värde i $entry do echo " $value" done Gjort
Det finns två loopar i det här skriptet. Den första korsar linjerna med hjälp av nyradstecknet som avgränsare. Den interna är upptagen med att analysera strängar vars fält är separerade med kolon.

Fildatabearbetning

Detta tillvägagångssätt kan användas vid bearbetning av CSV-filer, eller liknande filer, genom att skriva avgränsningstecknet i IFS-miljövariabeln efter behov.

Cykelhantering

Kanske, efter att ha gått in i slingan, måste du stoppa den när slingvariabeln når ett visst värde som inte motsvarar det initialt angivna villkoret för att avsluta slingan. I en sådan situation, kommer det att vara nödvändigt att vänta på det normala slutförandet av cykeln? Naturligtvis inte, och i sådana fall kommer följande två kommandon att vara användbara:
  • ha sönder
  • Fortsätta

bryt kommando

Detta kommando låter dig avbryta exekveringen av en loop. Den kan användas för både for och while loopar:

#!/bin/bash för var1 i 1 2 3 4 5 6 7 8 9 10 gör om [ $var1 -eq 5 ] sedan bryt fi eko "Number: $var1" gjort
En sådan slinga kommer under normala förhållanden att gå igenom hela listan med värden från listan. Men i vårt fall kommer dess exekvering att avbrytas när $var1-variabeln är lika med 5.

Lämnar en for loop tidigt

Här är samma sak, men för while-slingan:

#!/bin/bash var1=1 medan [ $var1 -lt 10 ] gör om [ $var1 -eq 5 ] sedan bryta fi eko "Iteration: $var1" var1=$(($var1 + 1)) gjort
Breakkommandot, som körs när $var1 når 5, bryter slingan. Konsolen kommer att visa samma sak som i föregående exempel.

fortsätta kommandot

När detta kommando påträffas i slingans kropp slutar den aktuella iterationen tidigt och nästa börjar utan att lämna slingan. Låt oss titta på kommandot fortsätt i en for-loop:

#!/bin/bash för ((var1 = 1; var1< 15; var1++)) do if [ $var1 -gt 5 ] && [ $var1 -lt 10 ] then continue fi echo "Iteration number: $var1" done
När villkoret inuti slingan är uppfyllt, det vill säga när $var1 är större än 5 och mindre än 10, kör skalet fortsätt-kommandot. Detta resulterar i att man hoppar över de återstående kommandona i slingans kropp och går vidare till nästa iteration.

Kommandot fortsätt i en for-loop

Bearbetar utdata som körs i en slinga

Datautmatning från en loop kan bearbetas genom att antingen omdirigera utmatningen eller skicka den till en pipeline. Detta görs genom att lägga till utdatabearbetningskommandon efter done-satsen.

Till exempel, istället för att visa på skärmen vad som matas ut i en loop, kan du skriva allt till en fil eller skicka det någon annanstans:

#!/bin/bash för ((a = 1; a< 10; a++)) do echo "Number is $a" done >myfile.txt eko "finished."
Skalet kommer att skapa filen myfile.txt och omdirigera utdata från for-satsen till den filen. Låt oss öppna filen och se till att den innehåller exakt vad vi förväntar oss.

Omdirigera looputgång till fil

Exempel: Sök efter körbara filer

Låt oss använda det vi redan har täckt och skriva något användbart. Om du till exempel behöver ta reda på vilka körbara filer som är tillgängliga på systemet, kan du skanna alla mappar som är registrerade i miljövariabeln PATH. Vi har redan hela den arsenal av verktyg som vi behöver för detta, vi behöver bara sätta ihop allt:

#!/bin/bash IFS=: för mapp i $PATH gör echo "$folder:" för fil i $folder/* gör om [ -x $file ] sedan eko " $file" fi klar
Detta skript, litet och enkelt, gjorde det möjligt för oss att få en lista över körbara filer lagrade i mappar från PATH.

Söker efter körbara filer i mappar från PATH-variabeln

Resultat

Idag har vi pratat om for and while-loopar i bash-skript, hur man kör dem och hur man hanterar dem. Nu vet du hur man bearbetar strängar med olika avgränsare i loopar, du vet hur man omdirigerar datautdata i loopar till filer, hur man visar och analyserar innehållet i kataloger.

Om vi ​​antar att du är en utvecklare av bash-skript som bara vet om dem vad som sägs i den första delen av denna artikelserie, och i den här andra, så kan du redan skriva något användbart. Framåt är den tredje delen, efter att ha förstått vilken du kommer att lära dig hur du skickar parametrar och kommandoradsväxlar till bash-skript, och vad du ska göra med allt.

En kort beskrivning av skillnaden i looptyper:

for - kommer att utföra en åtgärd så länge det finns objekt att exekvera (till exempel läsa en ström från stdin, en fil eller en funktion);
medan - utför åtgärden tills skickär sant;
tills - kommer att utföras så länge som skick kommer inte att bli sant, d.v.s. för nu är det falskt.

FÖR Loop

Låt oss överväga den här versionen av skriptet med en loop:

$ cat loop.sh #!/bin/bash för variabel i `ls -1` gör eko "$variable" gjort

Syntaxen är mycket enkel och visas ganska tydligt i exemplet:

for (starta slingan) variabel (deklarera en variabel som vi kommer att utföra åtgärder på) i (skicka ett flöde till slingan) `ls -1` (kommando som ska köras och skickas till variabeln $variabel). Gör och gjort är "kroppen" av slingan, inom vilken huvudåtgärderna kommer att utföras på mottagen data, och eko "$variabel" är den faktiska åtgärden som utförs av slingan.

Låt oss nu ändra exemplet lite, och istället för att explicit specificera kommandot, använder vi den andra variabeln:

$ cat loop.sh #!/bin/bash ls=`ls -1` för variabel i $ls do echo "$variable" done

Nu skickas kommandot ls -1 i en separat variabel, vilket gör att du kan arbeta med slingan mer flexibelt. Istället för en variabel i en loop kan du också använda en funktion:

$ cat loop.sh #!/bin/bash lsl () ( ls -1 ) för variabel i `lsl` gör eko "$variable" gjort

Huvudvillkoret för for-loopen är att den kommer att exekveras så länge som kommandot som skickas till den innehåller objekt för åtgärd. Baserat på exemplet ovan - så länge som ls -1 har filer att visa - kommer loopen att skicka dem till en variabel och exekvera "loop body". Så snart listan med filer i katalogen slutar, kommer loopen att slutföra sin exekvering.

Låt oss göra exemplet lite mer komplicerat.

Katalogen innehåller en lista med filer:

$ ls -1 fil1 fil2 fil3 fil4 fil5 loop.sh nofil1 nofil2 nofil3 nofil4 nofil5

Vi behöver bara välja bland dem som inte har ordet " Nej«:

$ cat loop.sh #!/bin/bash lsl=`ls -1` för variabel i $lsl gör eko "$variable" | grep -v "nej" gjort $ ./loop.sh fil1 fil2 fil3 fil4 fil5 loop.sh

Du kan också använda villkorliga uttryck i en loop ( villkorliga uttryck) […] för att kontrollera villkoren och break-satsen för att avbryta slingan om villkoret utlöses.

Tänk på det här exemplet:

$ cat loop.sh #!/bin/bash lsl=`ls -1` för variabel i $lsl gör om [ $variable != "loop.sh" ] sedan upprepa "$variable" | grep -v "nej" annars break fi gjort

Slingan fortsätter tills filen loop.sh påträffas. Så snart exekveringen av loopen når denna fil kommer loopen att avbrytas av break-kommandot:

$ ./loop.sh fil1 fil2 fil3 fil4 fil5

Ett annat exempel är användningen av aritmetiska operationer omedelbart innan slingans kropp körs:

$ cat loop.sh #!/bin/bash för ((count=1; count<11; count++)) do echo "$count" done

Här ställer vi in ​​tre kontrollkommandon - count=1, ett styrande villkor - medan count är mindre än 11, och ett kommando att utföra - count +1:

WHILE och TILL slingor

Ett enkelt exempel som tydligt visar hur while-slingan fungerar:

$ cat loop.sh #!/bin/bash count=0 medan [ $count -lt 10 ] do ((count++)) echo $count done

Vi ställer in $count-variabeln till noll och kör sedan whi le-loopen med villkoret "medan $count är mindre än tio, exekvera loopen." I slingans kropp utför vi postfix-ökning+1 till variabeln $count och resultatet skrivs ut till stdout.

Utföranderesultat:

$ ./loop.sh 1 2 3 4 5 6 7 8 9 10

Så snart värdet på $count-variabeln blev 10, stoppades slingan.

Ett bra exempel på en "oändlig" loop som visar hur medan fungerar:

$ cat loop.sh #!/bin/bash count=10 medan [ 1 = 1 ] gör ((count++)) echo $count done $ ./loop.sh ... 5378 5379 5380 5381 5382 5383 ^C

Till-slingan fungerar på liknande sätt, men i motsatt riktning:

$ cat loop.sh #!/bin/bash count=0 tills [ $count -gt 10 ] do ((count++)) echo $count done

Här ställer vi in ​​ett liknande villkor, men istället för "medan variabeln är mindre än 10" anger vi "tills variabeln blir större än 10." Utföranderesultat:

$ ./loop.sh 1 2 3 4 5 6 7 8 9 10 11

Om exemplet ovan på en "ändlös loop" körs med till, kommer det inte att mata ut något, till skillnad från medan:

$ cat loop.sh #!/bin/bash count=10 tills [ 1 = 1 ] gör ((count++)) echo $count done $ ./loop.sh $

Därför att " skick"ursprungligen" Sann"— slingans kropp kommer inte att exekveras.

Precis som i for-slingan kan du använda funktioner i while och till. Till exempel en loop från ett verkligt skript som kontrollerar serverstatus Hankatt(PID tas från systemet SLES, kan skilja sig åt i andra system), en något förenklad version:

$ cat loop.sh #!/bin/bash check_tomcat_status () ( RUN=`ps aux | grep tomcat | grep -v grep | grep java | awk "(skriv ut $2)"` ) medan check_tomcat_status gör om [ -n "$ RUN" ] sedan printf "VARNING: Tomcat körs fortfarande med PID $RUN." else printf "Tomcat stannade, fortsätter...nn" break fi klar

Utföranderesultat:

$ ./loop.sh VARNING: Tomcat körs fortfarande med PID 14435 26548. VARNING: Tomcat kör fortfarande med PID 14435 26548. VARNING: Tomcat körs fortfarande med PID 14435 26548. VARNING: Tomcat körs fortfarande med PID 14435: Tomcat fortfarande körs med PID 14435: Tomcat 26548 fortfarande. körs med PID 14435 26548. VARNING: Tomcat körs fortfarande med PID 14435 26548. VARNING: Tomcat körs fortfarande med PID 14435 26548. VARNING: Tomcat körs fortfarande med PID 14435

Full version:

Check_tomcat_status () ( RUN=`ps aux | grep tomcat | grep -v grep | grep java | awk "(skriv ut $2)"` ) medan check_tomcat_status; gör om [ -n "$RUN" ] sedan printf "VARNING: Tomcat körs fortfarande med PID $RUN. Stoppa det? " svara "Stoppar Tomcat..." "Gör installationen..." && $CATALINA_HOME/bin/shutdown sh 2&>1 /dev/null || bryt sömn 2 om [ -n "$RUN" ] sedan printf "Tomcat körs fortfarande. Döda den?" svara "Killing Tomcat..." "Proceeding installation...n" && kill $RUN || break sleep 2 fi else printf "Tomcat stannade, fortsätter...nn" paus fi klar

Svarsfunktionen beskrevs i artikeln, men här används en något förbättrad version:

Svar () ( medan du läser svar; gör ekofallet $respons i |) printf "$1n" return 0 break ;; |) printf "$2n" returnera 1 paus ;; *) printf "Snälla, ange Y(yes) or N(no)! " esac done )

Här var det möjligt att använda både while och till - men inte en for-loop, eftersom for skulle ha fungerat en gång (fått PID och avslutat).

Slingor är en extremt bekväm sak när du skriver program eller skript, snarare till och med nödvändigt. De tillåter oss att exekvera ett visst avsnitt av koden ett visst antal gånger. Naturligtvis har bash flera typer av slingor. Vi kommer att beskriva cyklerna för i, för, stund, tills. Även om för in och for anses olika syntaxer av samma uttalande, skiljer de sig enligt min mening från varandra mer än medan från till.

Slinga med disk för in:

Cykel för in Detta är en slinga med en räknare. Kodblocket som finns i slingans kropp upprepas så många gånger som det finns värden i listan över for in-operatorn, och med varje upprepning räknarvariabeln (här kallas den var, men naturligtvis du kan kalla det vad du vill) har värdet av nästa element i listan.
Om nyckelordet do är på samma rad som ordet för, måste du sätta ett semikolon efter listan med argument (före gör).
Vart och ett av elementen<список>kan innehålla flera argument. Detta är användbart vid bearbetning av grupper av parametrar. I det här fallet, för att tvinga fram analys av vart och ett av argumenten i<списке>, måste du använda uppsättningsinstruktionen
Du kan använda en variabel som en lista i en for-loop.
I<списке>For-loopen kan använda filnamn, som i sin tur kan innehålla jokertecken. Detta kan vara mycket användbart när du arbetar med ett stort antal filer.
Om<список>inte anges i for-loopen, används variabeln $@ som den - en lista med kommandoradsargument.
När du skapar en lista med argument kan du använda kommandosubstitution i en for-loop.
Utdata från slingan kan omdirigeras från stdout till en fil eller någon annanstans (du kan lära dig mer om detta genom att titta på I/O-omdirigering).

Syntax:
för var in<список>
do
<выполняемые команды>
Gjort

Exempel:
för namn i namn1 namn2 namn3 namn4
do
echo $namn
Gjort

Slingoperatör för har ett annat sätt att skriva - mycket lik syntaxen för for-operatorn i C-språket. I det här fallet, när räknarna initieras, ställs initialvärdena för variabler eller en variabel in och efter varje pass av loopen villkoret är markerad, om kontrollen returnerar sant, så börjar nästa pass i slingan. I blocket<приращение счётчиков>värdet på våra variabla räknare måste nödvändigtvis ändras (inte nödvändigtvis uppåt) så att när vi kontrollerar villkoret, förr eller senare får vi värdet false, annars kommer slingan aldrig att ta slut. Ett mycket bekvämt och viktigast av allt bekant alternativ om någon operation behöver upprepas ett visst antal gånger.

Med en liknande syntax:
för ((<инициализация счётчиков>; <проверка условия>; <приращение счётчиков>))
do
<выполняемые команды>
Gjort

Exempel:
för ((var=1; var<= LIMIT ; var++))
do
echo $var
Gjort

medan loop:

Detta är en ganska enkel konstruktion som kontrollerar skicket bakom operatören medan och om detta villkor är sant, exekverar det blocket av kommandon som finns mellan orden gör och gjort och fortsätter sedan igen med att kontrollera villkoret. Om kontrollen returnerar falskt, avslutas cykeln och följande kommandon börjar utföras: Gjort. Det är absolut nödvändigt att säkerställa det<проверка условия>beroende på koden som körs i slingan; annars, om resultatet av kontrollen inte ändras, kommer du att få en oändlig slinga.
Standardinmatningsenheten för en while-loop kan omdirigeras till en fil med hjälp av omdirigeringskommandot< в конце цикла.

Syntax:
medan<Проверка условия>
do
<Блок команд, обязательно меняющий переменные влияющие на проверку условия>
Gjort

Exempel:
medan [ $var0 -eq 100 ]
do
echo $var
var++
Gjort

Operatör medan kan ha flera villkor. Men bara den sista av dem avgör möjligheten att fortsätta cykeln. I det här fallet kommer syntaxen för loopoperatorn att skilja sig från den vanliga.
Syntax(Jag upprepar ännu en gång att endast det sista villkoret påverkar utförandet av slingan) :
medan
<условие1>
<условие2>

<условиеN>
do
<выполняемые команды - тело цикла>
Gjort

Till loop:

Operatör fram tillsär mycket lik while, utvärderar den också villkoret, men exekverar slingans kropp om resultatet av beräkningen är falskt. Det kan verka ovanligt, men tills utvärderar tillståndet före det första passet av slingan, som medan, och inte efter det. Som med for/in loopar, när du placerar nyckelordet do på samma rad som loop-deklarationen, måste du infoga ett ";"-tecken. innan gör.
Liksom i föregående fall är det viktigt att komma ihåg att tillståndet måste bero på operationerna i loopkroppen, annars kommer vårt skript aldrig att slutföras.

Syntax:
fram tills<Проверка условия>
do
<Блок команд, обязательно меняющий переменные влияющие на проверку условия>
Gjort

Exempel:
tills [ $var0 -gt 100] # Villkoret kontrolleras i början av iterationen.
do
echo $var
var--
Gjort

Det räcker nog för nu. :)

  • Tillbaka
  • Fram

Nya artiklar:

  • Nätverksupptäckt aktiveras inte i Windows 7/8/2008/2012
  • Fel: Det här programmet kunde inte startas eftersom det inte kunde hitta eller ladda Qt-plattformens plugin "windows".
  • Konfigurerar automatisk omstart av rphost.exe-arbetsprocesser på 1C 8.3-servern
  • Hur man minskar storleken på transaktionsloggen (.ldf) i MS SQL 2008/20012

    MS SQL, som alla anständiga industriella DBMS, tillsammans med databasen, håller transaktionsloggar som gör att du kan återställa tillståndet ...

0 Meeran Bala-Kumaran

Jag försöker verkligen förstå varför detta medan loop aldrig slutar, när loopen startar är min LOC-variabel inställd på Testing/ vilket är katalogen jag skapade för att testa det här programmet har följande layout:

Jag vill att slingan ska sluta när alla kataloger har haft "räkne"-funktionen.
Här är vad jag försökte;

Jag kollade räknefunktionen och den skapar inte en oändlig loop

Jag försökte köra algoritmen manuellt

PARSE=1 LOC=$LOC/ count AVAILABLEDIR=$(ls $LOC -AFl | sed "1 d" | grep "/$" | awk "( print $9 )") medan [ $PARSE = "1" ] gör om [[ $(AVAILABLEDIR[@]) == "" ]]; sedan PARSE=0 fi DIRBASE=$LOC för a i $(AVAILABLEDIR[@]); gör LOC="$(DIRBASE)$(a)" LOCLIST="$LOCLIST $LOC" räkning gjort för en i $(LOCLIST[@]); gör TMPAVAILABLEDIR=$(ls $a -AFl | sed "1 d" | grep "/$" | awk "( print $9 )") PREPEND=$a om [[ $(TMPAVAILABLEDIR[@]) == "" ] ]; fortsätt sedan fi för a i $(TMPAVAILABLEDIR[@]); gör TMPAVAILABLEDIR2="$TMPAVAILABLEDIR2 $(PREPEND[@])$(a)" klar NEWAVAILABLEDIR="$NEWAVAILABLEDIR $TMPAVAILABLEDIR2" klar AVAILABLEDIR=$NEWAVAILABLEDIR NEWAVAILABLEDIR="" LOC="" klar

Jag kämpar verkligen och all input skulle uppskattas mycket, jag har försökt ta reda på det här under de senaste två timmarna.

bash infinite-loop

4 svar

Du bör prova att köra skriptet med argumentet -x eller skriva det på första raden:

#!/bin/bash -x

Sedan berättar han allt han gör.

I det här fallet kan du märka två fel:

    Du laddar aldrig om TMPAVAILABLEDIR2

    Du gör också ls på vanliga filer.

Om du verkligen måste undvika rekursion, prova detta, helt utan rekursion:

#!/bin/bash count() ( ekoräknare "$1" ) todo=(Testning) medan test $(#todo[@]) != 0 do doit=("$(todo[@])") todo= () för dir i "$(doit[@])" gör för inmatning i "$dir"/* # om dir är tom, visar detta en post med namnet "*" testa -e "$entry" || fortsätt # hoppa över posten "*" i en tom dir count "$entry" test -d "$entry" || fortsätt todo+=("$entry") klar gjort klar

Men berätta för mig varför du inte kan använda rekursion? Är detta någon form av allergi? Svära? Finns det några lokala lagar mot rekursiv programvara där du bor?

Du skrev att du vill utföra en "räkning" på alla klipp. Kolla in sökalternativen:

Hitta $LOC -typ d | medan du läser dir; gör cd $LOC cd $(dir) count klar

eller kortare (när din funktionsräknare tar katalog som parameter 1)

Hitta $LOC -typ d | xargs räknas

Nu ser jag att du inte vill använda find eller ls -R (rekursiv funktion). Då bör du göra din egen rekursiva funktion som

Funktionen parseDir ( ls -d */ $1 | medan du läser dir; räkna parseDir $1/$dir klar )

Jag har ingen aning om detta kommer att fungera, men det är en intressant fråga som jag inte kunde sluta tänka på. Lycka till

Medan sant ; gör för ord i "$(echo *)" ; gör om [[ -d "$ord" ]] ; sedan d[$((i++))]="$PWD"/"$word" elif [[ -f "$word" ]] ;sedan f[$((j++))]="$PWD"/"$ word" fi gjort [[ $k -gt $i ]] && cd .. cd "$d[$((k++))]" || paus gjord