Prečo v adresári nebeží cyklus for. Prečo sa cyklus for nevykonáva v adresári Loops v skriptoch bash

Domov / Nezapne sa

Pozor: V príspevku sú skryté výhody!

pre slučky

Shell bash podporuje cykly, ktoré vám umožňujú iterovať sekvencie hodnôt. Tu je základná štruktúra takýchto slučiek:

Pre var v zozname urob príkaz hotový

V každej iterácii cyklu sa do premennej var zapíše ďalšia hodnota zo zoznamu. Prvý prechod cyklu teda použije prvú hodnotu zo zoznamu. V druhej - druhej a tak ďalej - kým slučka nedosiahne posledný prvok.

Iterácia cez jednoduché hodnoty

Snáď najjednoduchším príkladom cyklu for v bash skriptoch je iterácia cez zoznam jednoduchých hodnôt:

#!/bin/bash pre var v prvej druhej tretine štvrtej piatej do echo Položka $var hotovo

Výsledky tohto skriptu sú uvedené nižšie. Jasne vidíte, že premenná $var obsahuje prvky zo zoznamu postupne. To sa deje, kým cyklus nedosiahne posledný z nich.



Jednoduché pre slučku

Upozorňujeme, že premenná $var si pri výstupe z cyklu zachováva svoju hodnotu, jej obsah je možné meniť a vo všeobecnosti s ňou môžete pracovať ako s každou inou premennou.

Iterácia cez zložité hodnoty

Zoznam použitý na inicializáciu cyklu for môže obsahovať nielen jednoduché reťazce pozostávajúce z jedného slova, ale aj celé frázy, ktoré obsahujú niekoľko slov a interpunkčných znamienok. Môže to vyzerať napríklad takto:

#!/bin/bash pre var v prvej "druhej" "tretej" "Urobím to" urobiť echo "Toto je: $var" hotovo

Toto sa stane, keď táto slučka prejde zoznamom. Ako vidíte, výsledok je celkom očakávaný.



Iterácia cez zložité hodnoty
TNW-CUS-FMP – propagačný kód na zľavu 10 % na naše služby, k dispozícii na aktiváciu do 7 dní“

Inicializácia slučky so zoznamom získaným z výsledkov príkazu

Ďalším spôsobom, ako inicializovať cyklus for, je odovzdať mu zoznam, ktorý je výsledkom príkazu. Tu sa na ich vykonanie a získanie výsledkov ich práce používa substitúcia príkazov.

#!/bin/bash file="myfile" pre var v $(cat $file) urobiť echo " $var" hotovo

Tento príklad používa príkaz cat, ktorý číta obsah súboru. Výsledný zoznam hodnôt sa odovzdá do slučky a zobrazí sa na obrazovke. Všimnite si prosím, že súbor, ku ktorému pristupujeme, obsahuje zoznam slov oddelených čiarkami.



Slučka, ktorá prechádza cez obsah súboru

Tu musíme počítať s tým, že takýto prístup, ak sa očakáva riadkové spracovanie dát, nebude fungovať pre súbor zložitejšej štruktúry, ktorého riadky môžu obsahovať niekoľko slov oddelených medzerami. Slučka spracuje jednotlivé slová, nie riadky.

Čo ak to vôbec nie je to, čo potrebujete?

Separátory polí

Dôvodom vyššie uvedenej funkcie je špeciálnosť premenná prostredia, ktorý sa nazýva IFS (Internal Field Separator) a umožňuje určiť oddeľovače polí. V predvolenom nastavení bash shell považuje nasledujúce znaky za oddeľovače polí:

  • Priestor
  • Znak tabulátora
  • Riadkový znak

Ak bash narazí na niektorý z týchto znakov v údajoch, predpokladá sa, že mu predchádza nasledujúca nezávislá hodnota v zozname.

Ak chcete problém vyriešiť, môžete dočasne zmeniť premennú prostredia IFS. Tu je návod, ako to urobiť v bash skripte, za predpokladu, že ako oddeľovač polí potrebujete iba nový riadok:

IFS=$"n"

Keď tento príkaz pridáte do svojho bash skriptu, bude fungovať podľa očakávania, pričom bude ignorovať medzery a tabulátory a ako oddeľovače polí bude zaobchádzať iba so znakmi nového riadku.

#!/bin/bash file="/etc/passwd" IFS=$"n" pre var v $(cat $file) urobiť echo " $var" hotovo

Ak je tento skript spustený, vypíše presne to, čo sa od neho vyžaduje, pričom v každej iterácii cyklu poskytne prístup k ďalšiemu riadku zapísanému do súboru.



Prechádzanie súboru po riadkoch v slučke for

Oddeľovačmi môžu byť aj iné znaky. Napríklad vyššie sme zobrazili obsah súboru /etc/passwd. Užívateľské údaje v riadkoch sú oddelené dvojbodkami. Ak potrebujete spracovať takéto reťazce v slučke, IFS možno nakonfigurovať takto:

Prechádzanie súbormi obsiahnutými v adresári

Jedným z najbežnejších použití slučiek for v bash skriptoch je prechádzať súbormi umiestnenými v adresári a spracovávať tieto súbory.

Tu je napríklad postup, ako zobraziť zoznam súborov a priečinkov:

#!/bin/bash pre súbor v /home/likegeeks/* urobte if [ -d "$file" ] potom echo "$file je adresár" elif [ -f "$file" ] potom echo "$file je súbor" je hotový

Shell bash podporuje cykly, ktoré vám umožňujú iterovať sekvencie hodnôt. Tu je základná štruktúra takýchto slučiek:

Pre var v zozname urob príkaz hotový
V každej iterácii cyklu sa do premennej var zapíše ďalšia hodnota zo zoznamu. Prvý prechod cyklu teda použije prvú hodnotu zo zoznamu. V druhej - druhej a tak ďalej - kým slučka nedosiahne posledný prvok.

Iterácia cez jednoduché hodnoty

Snáď najjednoduchším príkladom cyklu for v bash skriptoch je iterácia cez zoznam jednoduchých hodnôt:

#!/bin/bash pre var v prvej druhej tretine štvrtej piatej do echo Položka $var hotovo
Výsledky tohto skriptu sú uvedené nižšie. Jasne vidíte, že premenná $var obsahuje prvky zo zoznamu postupne. To sa deje, kým cyklus nedosiahne posledný z nich.


Jednoduché pre slučku

Upozorňujeme, že premenná $var si pri výstupe z cyklu zachováva svoju hodnotu, jej obsah je možné meniť a vo všeobecnosti s ňou môžete pracovať ako s každou inou premennou.

Iterácia cez zložité hodnoty

Zoznam použitý na inicializáciu cyklu for môže obsahovať nielen jednoduché reťazce pozostávajúce z jedného slova, ale aj celé frázy, ktoré obsahujú niekoľko slov a interpunkčných znamienok. Môže to vyzerať napríklad takto:

#!/bin/bash pre var v prvej "druhej" "tretej" "Urobím to" urobiť echo "Toto je: $var" hotovo
Toto sa stane, keď táto slučka prejde zoznamom. Ako vidíte, výsledok je celkom očakávaný.


Iterácia cez zložité hodnoty
TNW-CUS-FMP – propagačný kód na zľavu 10 % na naše služby, k dispozícii na aktiváciu do 7 dní“

Inicializácia slučky so zoznamom získaným z výsledkov príkazu

Ďalším spôsobom, ako inicializovať cyklus for, je odovzdať mu zoznam, ktorý je výsledkom príkazu. Tu sa na ich vykonanie a získanie výsledkov ich práce používa substitúcia príkazov.

#!/bin/bash file="myfile" pre var v $(cat $file) urobiť echo " $var" hotovo
Tento príklad používa príkaz cat, ktorý číta obsah súboru. Výsledný zoznam hodnôt sa odovzdá do slučky a zobrazí sa na obrazovke. Všimnite si prosím, že súbor, ku ktorému pristupujeme, obsahuje zoznam slov oddelených čiarkami.


Slučka, ktorá prechádza cez obsah súboru

Tu musíme počítať s tým, že takýto prístup, ak sa očakáva riadkové spracovanie dát, nebude fungovať pre súbor zložitejšej štruktúry, ktorého riadky môžu obsahovať niekoľko slov oddelených medzerami. Slučka spracuje jednotlivé slová, nie riadky.

Čo ak to vôbec nie je to, čo potrebujete?

Separátory polí

Dôvodom vyššie uvedenej funkcie je špeciálna premenná prostredia nazývaná IFS (Internal Field Separator), ktorá vám umožňuje špecifikovať oddeľovače polí. V predvolenom nastavení bash shell považuje nasledujúce znaky za oddeľovače polí:
  • Priestor
  • Znak tabulátora
  • Riadkový znak
Ak bash narazí na niektorý z týchto znakov v údajoch, predpokladá sa, že mu predchádza nasledujúca nezávislá hodnota v zozname.

Ak chcete problém vyriešiť, môžete dočasne zmeniť premennú prostredia IFS. Tu je návod, ako to urobiť v bash skripte, za predpokladu, že ako oddeľovač polí potrebujete iba nový riadok:

IFS=$"\n"
Keď tento príkaz pridáte do svojho bash skriptu, bude fungovať podľa očakávania, pričom bude ignorovať medzery a tabulátory a ako oddeľovače polí bude zaobchádzať iba so znakmi nového riadku.

#!/bin/bash file="/etc/passwd" IFS=$"\n" pre var v $(cat $file) urobiť echo " $var" hotovo
Ak je tento skript spustený, vypíše presne to, čo sa od neho vyžaduje, pričom v každej iterácii cyklu poskytne prístup k ďalšiemu riadku zapísanému do súboru.


Prechádzanie súboru po riadkoch v slučke for

Oddeľovačmi môžu byť aj iné znaky. Napríklad vyššie sme zobrazili obsah súboru /etc/passwd. Užívateľské údaje v riadkoch sú oddelené dvojbodkami. Ak potrebujete spracovať takéto reťazce v slučke, IFS možno nakonfigurovať takto:

Prechádzanie súbormi obsiahnutými v adresári

Jedným z najbežnejších použití slučiek for v bash skriptoch je prechádzať súbormi umiestnenými v adresári a spracovávať tieto súbory.

Tu je napríklad postup, ako zobraziť zoznam súborov a priečinkov:

#!/bin/bash pre súbor v /home/likegeeks/* urobte if [ -d "$file" ] potom echo "$file je adresár" elif [ -f "$file" ] potom echo "$file je súbor" je hotový
Ak ste si prešli túto sériu článkov, mali by ste porozumieť štruktúre konštruktu ak-potom, ako aj tomu, ako rozlíšiť súbor od priečinka. Ak je pre vás ťažké porozumieť vyššie uvedenému kódu, prečítajte si tento materiál znova.

Toto je výstup skriptu.


Zobrazenie obsahu priečinka

Všimnite si, ako inicializujeme slučku, konkrétne zástupný znak „*“ na konci adresy priečinka. Tento symbol si možno predstaviť ako zástupný znak, ktorý znamená: „všetky súbory s ľubovoľnými názvami“. umožňuje vám organizovať automatické nahradzovanie názvov súborov, ktoré zodpovedajú vzoru.

Pri testovaní podmienky v príkaze if uzatvárame názov premennej do úvodzoviek. Je to spôsobené tým, že názov súboru alebo priečinka môže obsahovať medzery.

C-štýl pre slučky

Ak poznáte programovací jazyk C, syntax na opis slučiek bash for sa vám môže zdať divná, pretože ste očividne zvyknutí opisovať slučky týmto spôsobom:

Pre (i = 0; i< 10; i++) { printf("number is %d\n", i); }
V bash skriptoch môžete použiť pre slučky, ktorých popis vyzerá veľmi podobne ako slučky v štýle C, aj keď existujú určité rozdiely. Cyklický diagram s týmto prístupom vyzerá takto:

For ((počiatočná hodnota premennej; podmienka pre ukončenie cyklu; zmena premennej))
V bash to môže byť napísané takto:

Pre ((a = 1; a< 10; a++))
Tu je pracovný príklad:

#!/bin/bash pre ((i=1; i<= 10; i++)) do echo "number is $i" done
Tento kód zobrazí zoznam čísel od 1 do 10.

Slučka v štýle C

pričom slučka

Konštrukt for nie je jediný spôsob, ako organizovať slučky v bash skriptoch. Tu môžete použiť aj slučky while. V takejto slučke môžete zadať príkaz na kontrolu určitej podmienky a vykonať telo cyklu, kým testovaná podmienka nevráti nulu alebo signál pre úspešné dokončenie určitej operácie. Keď podmienka cyklu vráti nenulovú hodnotu, čo znamená chybu, cyklus sa zastaví.

Tu je schéma organizácie slučiek while
zatiaľ čo príkaz na kontrolu stavu
robiť
ostatné tímy
hotovo

Pozrime sa na príklad skriptu s takýmto cyklom:

#!/bin/bash var1=5 while [ $var1 -gt 0 ] do echo $var1 var1=$[ $var1 - 1 ] hotovo
Na vstupe do cyklu sa kontroluje, či je premenná $var1 väčšia ako nula. Ak áno, vykoná sa telo cyklu, v ktorom sa jedna odpočíta od hodnoty premennej. Deje sa tak v každej iterácii a pred úpravou vytlačíme hodnotu premennej do konzoly. Akonáhle $var1 dosiahne hodnotu 0, cyklus sa zastaví.

Výsledok cyklu while

Ak neupravíte premennú $var1, skript sa ocitne v nekonečnej slučke.

Vnorené slučky

Môžete použiť ľubovoľné príkazy v tele cyklu, vrátane spúšťania iných cyklov. Takéto konštrukcie sa nazývajú vnorené slučky:

#!/bin/bash pre ((a = 1; a<= 3; a++)) do echo "Start $a:" for ((b = 1; b <= 3; b++)) do echo " Inner loop: $b" done done
Nižšie je uvedený výstup tohto skriptu. Ako vidíte, najskôr sa vykoná prvá iterácia vonkajšej slučky, potom tri iterácie vnútornej, po jej skončení prichádza do hry opäť vonkajšia slučka, potom opäť vnútorná.

Vnorené slučky

Spracovanie obsahu súboru

Najčastejšie sa na spracovanie súborov používajú vnorené slučky. Vonkajšia slučka teda iteruje cez riadky súboru a vnútorná už pracuje s každým riadkom. Tu je napríklad, ako vyzerá spracovanie súboru /etc/passwd:

#!/bin/bash IFS=$"\n" pre položku v $(cat /etc/passwd) urobte echo "Hodnoty v $entry –" IFS=: pre hodnotu v $entry urobte echo " $value" hotovo hotovo
V tomto skripte sú dve slučky. Prvý prechádza cez riadky pomocou znaku nového riadku ako oddeľovača. Interná je zaneprázdnená analýzou reťazcov, ktorých polia sú oddelené dvojbodkami.

Spracovanie údajov súboru

Tento prístup je možné použiť pri spracovaní súborov CSV alebo akýchkoľvek podobných súborov tak, že podľa potreby zapíšete znak oddeľovača do premennej prostredia IFS.

Riadenie cyklu

Možno ho po vstupe do cyklu budete musieť zastaviť, keď premenná cyklu dosiahne určitú hodnotu, ktorá nezodpovedá pôvodne zadanej podmienke ukončenia cyklu. Bude v takejto situácii potrebné čakať na normálne dokončenie cyklu? Samozrejme, že nie a v takýchto prípadoch prídu vhod nasledujúce dva príkazy:
  • prestávka
  • pokračovať

príkaz prerušiť

Tento príkaz vám umožňuje prerušiť vykonávanie cyklu. Môže byť použitý pre slučky for a while:

#!/bin/bash pre var1 v 1 2 3 4 5 6 7 8 9 10 urobte if [ $var1 -eq 5 ] potom zlomte fi echo "Číslo: $var1" hotovo
Takáto slučka za normálnych podmienok prejde celým zoznamom hodnôt zo zoznamu. V našom prípade sa však jeho vykonávanie preruší, keď sa premenná $var1 rovná 5.

Predčasné ukončenie cyklu for

Tu je to isté, ale pre cyklus while:

#!/bin/bash var1=1 while [ $var1 -lt 10 ] urob if [ $var1 -eq 5 ] then break fi echo "Iterácia: $var1" var1=$(($var1 + 1)) hotovo
Príkaz break, ktorý sa vykoná, keď $var1 dosiahne 5, preruší cyklus. Konzola zobrazí to isté ako v predchádzajúcom príklade.

pokračovať v príkaze

Keď sa s týmto príkazom stretnete v tele cyklu, aktuálna iterácia sa skončí skôr a začne sa ďalšia bez toho, aby sa cyklus opustil. Pozrime sa na príkaz continue v slučke for:

#!/bin/bash pre ((var1 = 1; var1< 15; var1++)) do if [ $var1 -gt 5 ] && [ $var1 -lt 10 ] then continue fi echo "Iteration number: $var1" done
Keď je splnená podmienka vnútri cyklu, to znamená, keď $var1 je väčší ako 5 a menší ako 10, shell vykoná príkaz continue. Výsledkom je preskočenie zostávajúcich príkazov v tele cyklu a prechod na ďalšiu iteráciu.

Príkaz continue v slučke for

Výstup spracovania beží v slučke

Dátový výstup zo slučky možno spracovať buď presmerovaním výstupu, alebo jeho odovzdaním do potrubia. To sa dosiahne pridaním príkazov na spracovanie výstupu za príkaz done.

Napríklad namiesto zobrazovania výstupov v slučke na obrazovke môžete všetko zapísať do súboru alebo odovzdať niekde inde:

#!/bin/bash pre ((a = 1; a< 10; a++)) do echo "Number is $a" done >myfile.txt echo "dokončené."
Shell vytvorí súbor myfile.txt a presmeruje výstup príkazu for do tohto súboru. Otvorme súbor a uistite sa, že obsahuje presne to, čo očakávame.

Presmerujte výstup slučky do súboru

Príklad: Vyhľadajte spustiteľné súbory

Využime to, čo sme už prebrali a napíšme niečo užitočné. Ak napríklad potrebujete zistiť, ktoré spustiteľné súbory sú dostupné v systéme, môžete skenovať všetky priečinky zaznamenané v premennej prostredia PATH. Už máme celý arzenál nástrojov, ktoré na to potrebujeme, len to musíme dať dokopy:

#!/bin/bash IFS=: pre priečinok v $PATH urobiť echo "$folder:" pre súbor v $folder/* urobiť if [ -x $file ] potom echo " $file" fi hotovo
Tento malý a jednoduchý skript nám umožnil získať zoznam spustiteľných súborov uložených v priečinkoch z PATH.

Vyhľadávanie spustiteľných súborov v priečinkoch z premennej PATH

Výsledky

Dnes sme hovorili o slučkách for a while v bash skriptoch, ako ich spúšťať a ako ich spravovať. Teraz viete, ako spracovať reťazce s rôznymi oddeľovačmi v slučkách, viete, ako presmerovať výstup údajov v slučkách do súborov, ako prezerať a analyzovať obsah adresárov.

Ak predpokladáme, že ste vývojár bash skriptov, ktorý o nich vie len to, čo je uvedené v tejto sérii článkov a v tomto druhom, tak už môžete napísať niečo užitočné. Pred nami je tretia časť, po pochopení ktorej sa naučíte, ako odovzdávať parametre a prepínače príkazového riadku do bash skriptov a čo s tým všetkým robiť.

Stručný popis rozdielu v typoch slučiek:

for - vykoná akciu, pokiaľ existujú objekty na vykonanie (napríklad čítanie streamu z stdin, súboru alebo funkcie);
kým - vykoná akciu do stave je pravda;
do - sa bude vykonávať dovtedy, kým stave sa nestane pravdou, t.j. zatiaľ je to falošné.

PRE slučku

Zoberme si túto verziu skriptu so slučkou:

$ cat loop.sh #!/bin/bash pre premennú v `ls -1` do echo "$variable" hotovo

Syntax je veľmi jednoduchá a je celkom jasne znázornená v príklade:

for (spustenie cyklu) premenná (deklarácia premennej, s ktorou budeme vykonávať akcie) v (odoslanie toku do cyklu) `ls -1` (príkaz, ktorý sa má vykonať a odovzdať do premennej $variable). Do a done sú „telo“ slučky, v rámci ktorého sa vykonajú hlavné akcie s prijatými údajmi a echo „$variable“ je skutočná akcia vykonaná slučkou.

Teraz trochu zmeníme príklad a namiesto explicitného zadania príkazu použijeme druhú premennú:

$ cat loop.sh #!/bin/bash ls=`ls -1` pre premennú v $ls do echo "$variable" hotovo

Teraz je príkaz ls -1 odovzdaný v samostatnej premennej, čo umožňuje flexibilnejšie pracovať so slučkou. Namiesto premennej v slučke môžete použiť aj funkciu:

$ cat loop.sh #!/bin/bash lsl () ( ls -1 ) pre premennú v `lsl` urobiť echo "$variable" hotovo

Hlavnou podmienkou cyklu for je, že sa vykoná, pokiaľ príkaz, ktorý mu bol odovzdaný, obsahuje objekty na akciu. Na základe vyššie uvedeného príkladu - pokiaľ má ls -1 súbory na zobrazenie - cyklus ich odovzdá premennej a vykoná "telo slučky". Hneď ako zoznam súborov v adresári skončí, cyklus dokončí svoje vykonávanie.

Urobme príklad trochu zložitejším.

Adresár obsahuje zoznam súborov:

$ ls -1 súbor1 súbor2 súbor3 súbor4 súbor5 loop.sh nofile1 nofile2 nofile3 nofile4 nofile5

Musíme z nich vybrať len tie, ktoré nemajú slovo „ č«:

$ cat loop.sh #!/bin/bash lsl=`ls -1` pre premennú v $lsl do echo "$variable" | grep -v "nie" hotovo $ ./loop.sh súbor1 súbor2 súbor3 súbor4 súbor5 loop.sh

Môžete tiež použiť podmienené výrazy v slučke ( podmienené výrazy) […] na kontrolu podmienok a príkaz break na prerušenie cyklu, ak sa podmienka spustí.

Zvážte tento príklad:

$ cat loop.sh #!/bin/bash lsl=`ls -1` pre premennú v $lsl urob, ak [ $premenná != "loop.sh" ] potom echo "$premenná" | grep -v "nie" else break fi hotovo

Cyklus bude prebiehať, kým nenájdete súbor loop.sh. Hneď ako vykonanie cyklu dosiahne tento súbor, cyklus sa preruší príkazom break:

$ ./loop.sh súbor1 súbor2 súbor3 súbor4 súbor5

Ďalším príkladom je použitie aritmetických operácií bezprostredne pred vykonaním tela cyklu:

$ cat loop.sh #!/bin/bash for ((počet=1; počet<11; count++)) do echo "$count" done

Tu nastavíme tri riadiace príkazy – počet=1, riadiacu podmienku – pričom počet je menší ako 11 a príkaz na vykonanie – počet +1:

slučky WHILE a UNTIL

Jednoduchý príklad, ktorý jasne ukazuje, ako funguje cyklus while:

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

Premennú $count nastavíme na nulu a potom spustíme cyklus whi le s podmienkou „keď je $count menší ako desať, vykonajte cyklus“. V tele cyklu vykonáme postfixový prírastok+1 k premennej $count a výsledok sa vytlačí na stdout.

Výsledok vykonania:

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

Akonáhle sa hodnota premennej $count stala 10, cyklus sa zastavil.

Dobrý príklad „nekonečnej“ slučky, ktorá ukazuje, ako funguje while:

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

Slučka do funguje podobne, ale v opačnom smere:

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

Tu nastavíme podobnú podmienku, ale namiesto „kým je premenná menšia ako 10“, zadáme „kým sa premenná nestane väčšou ako 10“. Výsledok vykonania:

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

Ak sa vyššie uvedený príklad „nekonečnej slučky“ vykoná pomocou príkazu do, nevypíše nič, na rozdiel od while:

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

pretože" stave"pôvodne" pravda"— telo cyklu sa nevykoná.

Rovnako ako v slučke for môžete používať funkcie počas a do. Napríklad slučka zo skutočného skriptu, ktorá kontroluje stav servera kocúr(PID sa preberá zo systému SLES, môže sa líšiť v iných systémoch), mierne zjednodušená verzia:

$ cat loop.sh #!/bin/bash check_tomcat_status () ( RUN=`ps aux | grep tomcat | grep -v grep | grep java | awk "(print $2)"` ) pričom check_tomcat_status vykonajte if [ -n "$ RUN" ] potom printf "UPOZORNENIE: Tomcat stále beží s PID $RUN."

Výsledok vykonania:

else printf "Tomcat zastavený, pokračuje...nn" break fi hotovo

$ ./loop.sh UPOZORNENIE: Tomcat stále beží s PID 14435 26548. VAROVANIE: Tomcat stále beží s PID 14435 26548. UPOZORNENIE: Tomcat stále beží s PID 14435 26548.UPOZORNENIE: Tomcat stále beží s PID5 Tomcat 265443 beží s PID 14435 26548. UPOZORNENIE: Tomcat stále beží s PID 14435 26548. VAROVANIE: Tomcat stále beží s PID 14435 26548. VAROVANIE: Tomcat stále beží s PID 14435

Plná verzia:

Check_tomcat_status () ( RUN=`ps aux | grep tomcat | grep -v grep | grep java | awk "(tlač $2)"`) while check_tomcat_status; urob if [ -n "$RUN" ] potom printf "UPOZORNENIE: Tomcat stále beží s PID $RUN. Zastaviť ho?" odpovedzte "Zastavuje sa Tomcat..." "Prebieha inštalácia..." && $CATALINA_HOME/bin/shutdown sh 2&>1 /dev/null || break sleep 2 if [ -n "$RUN" ] then printf "Tomcat stále beží. Zabiť ho?" odpoveď "Killing Tomcat..." "Prebieha inštalácia...n" && zabiť $RUN || prerušiť spánok 2 fi else printf "Tomcat zastavený, pokračuje...nn" break fi hotovo

Funkcia odpovede bola opísaná v článku, ale tu je použitá mierne vylepšená verzia:

Odpoveď () (pri čítaní odpovede; do echo case $response in |) printf "$1n" return 0 break ;;

5

|) printf "$2n" vráti 1 prerušenie ;;

*) printf "Prosím, zadajte Y(áno) alebo N(nie)!" esac hotovo )

Tu bolo možné použiť while aj till - ale nie cyklus for, pretože for by raz fungoval (prijal PID a skončil).

1) Váš skript je zakódovaný nebezpečným spôsobom. Po prvé, predpokladám, že používate shell Bash, pretože ste ho označili „/bash“ a „/for“. Vo svojej odpovedi budem citovať tohto vynikajúceho sprievodcu bashom, ktorý je pravdepodobne najlepším zdrojom na učenie sa bashu.

Konkrétne povedané, $(nájsť$ DIRWORK -typ d -názov funguje) a $(nájsť$ DIR -typ f) prejdú rozdelením slov, takže ak find nájde súbor s medzerami v názve, t. j. "názov súboru", výsledkom bude rozdelenie slov Bash odovzdá 2 argumenty príkazu for na iteráciu, t.j. jeden pre "súbor" a jeden pre "názov". V tomto prípade chcete dúfať, že dostanete "súbor: žiadny takýto súbor alebo adresár" a "názov: žiadny takýto súbor alebo adresár", namiesto toho, aby ste ich potenciálne poškodili, ak skutočne existujú.

2) Podľa konvencie sú premenné prostredia (PATH, EDITOR, SHELL, ...) a interné premenné shellu (BASH_VERSION, RANDOM, ...) plne veľké. Všetky ostatné názvy premenných musia byť malé. Keďže názvy premenných rozlišujú veľké a malé písmená, táto konvencia zabraňuje náhodnému prepísaniu environmentálnych a interných premenných.

Toto je bezpečnejšia verzia vášho skriptu, ktorú vám odporúčam použiť:

My_home="/root/mydir" my_dir=" $my_home/var" dir_work="$ my_home/Local" while IFS= read -r -d "" f; do # Hádam, že chceš ignorovať aj stderr; # odtiaľto pochádza 2>&1. if lsof -n "ne$f" | grep "" > /dev/null 2> then echo "hej , Ja "Už som vo väčšom bezpečí!"< <(find "$ dir_work" -type f -print0) while IFS= read -r -d "" f; do echo "2" done < <(find "$dir_work" -type d -name "work" -print0)

fi hotovo

Ako vidíte, premenná IFS je nastavená na prázdnu, čím sa bráni čítaniu orezať prednú a zadnú medzeru z riadku. Príkaz read používa prázdny riadok (-d "") ako oddeľovač na čítanie, kým nedosiahne hodnotu \0, teda nález musí byť m, takže použije voľbu -print0 na oddeľovanie svojich údajov pomocou \0 namiesto nového riadku, čo. , prekvapivo a zlomyseľne, môže byť súčasťou názvu súboru. Rozdelenie takéhoto \n súboru na dve časti poruší náš kód.

Predchádzajúca odpoveď, ktorá uvádzala, že nájsť... | pri čítaní mena; robiť...; done by sa malo použiť na čítanie find s výstup môže byť tiež zlý. Cyklus while beží v novom podshell s vlastnou kópiou premenných skopírovaných zo svojho rodiča. Táto kópia sa potom použije na čokoľvek, čo chcete. Po dokončení cyklu while sa kópia subshell zahodí a pôvodné premenné rodiča sa nezmenia.

0

"Nikdy nepoužívajte nahradenie príkazov akéhokoľvek druhu bez úvodzoviek." Toto je len hnidopišstvo, ale je možné použiť nahradenie príkazov bez úvodzoviek, keď nastavíte premennú: "niečo = $(základné meno" názov súboru s medzerami ")". - Smith John 22. apríla 13 2013-04-22 21:43:10

2

Pre i v $(nájsť$ DIRWORK -typ d -názov práce); urobiť echo "2" hotovo

bude prvý, kto vykoná tento riadok

Nájdite prácu $DIRWORK -typ d -name

počkajte, kým find dokončí spustenie a potom si dajte deň voľna a vložte ho späť do cyklu for

Pre i vo výstupe find; urobiť echo "2" hotovo

až potom sa spustí cyklus for.

Takže ak find trvá dlho, kým dokončí cyklus for, musí dlho čakať, kým sa môže spustiť.

Vyskúšajte dočasné príkazy hľadania interaktívne

$ čas nájsť $ DIRWORK -typ d -názov práce

a uvidíte, ako dlho to trvá.

Tiež si všimnite: na iteráciu názvov súborov by ste nemali používať cyklus for. Použite cyklus while s čítaním takto:

Nájsť $ DIRWORK -typ d -názov práce | pri čítaní mena; urobiť echo "2" hotovo

Bonus: paralelne s find . To znamená, že cyklus while dokončí jednu iteráciu hneď, ako find vypíše jeden riadok. Na dokončenie vykonania nie je potrebné čakať na nájdenie.

V tejto prednáške sa naďalej oboznamujeme bash. Chcel by som vám pripomenúť, že tieto prvky zvažujeme bash, čo nám pomôže pochopiť skripty operačného systému. Takýmito prvkami sú určite slučky a funkcie. Ak niekto študoval programovanie, potom nebudú žiadne ťažkosti s pochopením týchto otázok.

pre slučku

Cyklus pre V bash má dva typy. Najprv sa pozrime na klasickú verziu pre. Všeobecný pohľad je nasledovný:

Medzi prvkami pre A v je nastavená premenná, ktorá zase preberá hodnotu zo sekvencie hodnôt špecifikovaných medzi v A robiť. Medzi robiť A hotovo existujú príkazy, ktoré sa vykonajú vždy, keď premenná zmení svoju hodnotu. Cyklus sa zastaví, keď premenná nadobudne poslednú hodnotu zo sekvencie. Hodnoty v poradí sú oddelené medzerami.

Tu je praktický príklad:

Postupnosť hodnôt môže byť špecifikovaná rôznymi spôsobmi. Explicitne - ako v príklade vyššie, alebo pomocou iných premenných, alebo pomocou špeciálnych príkazov. Pozrime sa na niekoľko príkladov. Keďže hodnoty sú špecifikované oddelené medzerami, takými hodnotami môže byť akákoľvek premenná, ktorá obsahuje reťazec s medzerami:

Výsledok bude rovnaký ako v prvom príklade.

Ak potrebujete zadať postupnosť čísel, môžete použiť príkaz nasl a substitučný mechanizmus. Tím nasl vráti na obrazovku postupnosť číselných hodnôt. Syntax je jednoduchá a bude zrejmá z nižšie uvedeného príkladu:

výsledok:

Vráťme sa k druhému typu pre. Často v skriptoch nájdete takzvaný C-like variant pre, ktorý sa používa pre slučky založené na číslach. Pozrime sa na príklad:

Cyklus beží dovtedy, kým je podmienka testovaná vo výraze pravdivá. Hneď ako výraz vráti hodnotu false, cyklus zastaví vykonávanie.

Praktický príklad:

#!/bin/bash
i=1
zatiaľ čo [ $i -lt 7 ]
robiť
echo $i
nech i=i+1
hotovo

V našom príklade skontrolujeme, že premenná i je menšie ako (-lt) číslo 7 a ak áno, potom sa hodnota premennej zobrazí na obrazovke. Výraz nech i=i+1, zväčší premennú o jednu, znova skontroluje atď. nech povie tlmočníkovi, že argumenty by mali byť uznané ako číselné hodnoty. Tento riadok by sa dal napísať ako nech aj++(variant podobný c). Keď sa číslo zvýši o viac ako jeden, dá sa zapísať takto: nech i+=2- v tomto prípade i sa zvýši v prírastkoch po 2. Ďalšou možnosťou na zvýšenie premennej je použitie vstavanej kalkulačky (funguje len s celými číslami). Kalkulačka je prístupná cez dvojité zátvorky: i=$(($i+1)) alebo cez štvorcové: i=$[$i+1] Môžete tiež použiť kalkulačku na príkazovom riadku:

So slučkami musíte byť opatrní, aby ste neskončili s nekonečnou slučkou. Mimochodom na ladenie bash skripty, na ktoré môžete zmeniť prvý riadok #!/bin/bash -x alebo spustite skript pomocou príkazu bash -x:

igor@ubuntu:~/linux$ bash -x ./testfor.sh
+ i=1
+ ‘[’ 1 -gt 5 ‘]’
+ echo i=1
i=1
+ nech i=i+1
+ ‘[’ 2 -gt 5 ‘]’
+ echo i=2
i=2
+ nech i=i+1
+ ‘[’ 3 -gt 5 ‘]’
+ echo i=3
i=3
+ nech i=i+1
+ ‘[’ 4 -gt 5 ‘]’
+ echo i=4
i=4
+ nech i=i+1
+ ‘[’ 5 -gt 5 ‘]’
+ echo i=5
i=5
+ nech i=i+1
+ ‘[’ 6 -gt 5 ‘]’

Nezabudnite si precvičiť písanie malých skriptov, aby ste si upevnili pochopenie toho, ako fungujú slučky bash.

Funkcie v bash

Funkcie sa používajú v bash veľmi široký. Funkcie sú opísané dvoma spôsobmi: pomocou kľúčového slova funkciu a bez neho.

Prvý spôsob:

funkcia názov_funkcie
{
funkčné telo
}

Druhý spôsob:

function_name()
{
funkčné telo
}

Funkcia sa volá podľa mena kdekoľvek v skripte, ale až po opísaní samotnej funkcie. Funkciám možno odovzdávať aj parametre, ktoré sú za volaním funkcie (názvom) oddelené medzerou. Pozrime sa na príklad skriptu bash:

#!/bin/bash
funkčný základný náter
{
ak [ $# -ne 0 ]
potom
lokálne a=1
echo "Počet odovzdaných parametrov - $#"
pre mňa v $@
robiť
echo "$a-tý parameter je $i"
nech a++
hotovo
vrátiť 0
inak
echo "Parametre neboli odovzdané"
vrátiť 1
fi
}
echo „Zavolajte funkciu s parametrami:“
základný náter a b c
echo $?
echo „Zavolajte funkciu bez parametrov:“
primer
echo $?

V tomto príklade funkcia s názvom primer. Volanie funkcie s parametrami: základný náter a b c a bez parametrov: primer. V tele funkcie by vám mali byť známe všetky konštrukcie s výnimkou $# , $i A $@ .$# — vráti počet parametrov odovzdaných funkcii. V našom príklade to bude číslo 3 .$@ vráti všetky parametre v jednom riadku. V príklade by to bolo a b c. A cez $1 , $2 , $3 atď. Ku každému parametru môžete pristupovať jednotlivo. $? — obsahuje vykonávací kód posledného príkazu. V našom príklade kód vykonávania funkcie.

Funkcia môže vrátiť aj číselnú hodnotu prostredníctvom kľúčového slova vrátiť. Zvyčajne vrátia 0, ak sa funkcia vykonala bez chýb, alebo nenulovú hodnotu, ak sa niečo pokazilo. V príklade, ak je funkcia volaná s parametrami, vráti sa hodnota 0 a ak bola funkcia volaná bez parametrov, vráti sa kód 1.

Všetko o odovzdávaní parametrov funkcii funguje úplne rovnako pre skript. Parametre môžete tiež odovzdať skriptu a manipulovať s nimi rovnakým spôsobom pomocou $#, $@, $N. Z rovnakej kategórie je možnosť - $0 - ktorý vráti názov príkazu, ktorý spustil skript. Ak bol skript spustený príkazom ./script.sh, potom echo $0 vráti hodnotu ./script.sh, a ak na príkaz /home/igor/linux/script.sh, potom sa hodnota vráti /home/igor/linux/script.sh.

© 2024 ermake.ru -- O oprave PC - Informačný portál