Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: lukas016 11. 08. 2012, 01:42:15

Název: Bash script
Přispěvatel: lukas016 11. 08. 2012, 01:42:15
Dobry den.

Potreboval by som nejaku radu ohladom pisania v bashi. Pracujem na scripte, ktory prebera v 5 minutovych intervaloch udaje z iných PC pomocou ssh protokolu. Pre urychlenie prace som spravil 2 scripty, kde jeden je hlavny, ktory vybera IP adresu PC a vola dalsi script, ktory uz prevezme zaznam. Ak sa precita posledny zaznam tak script 5 minut pocka a zacne odznovu. Lenze tu som narazil na problem lebo script uspavam pomocou prikazu sleep 5m. A ak sa niektory z vyvolanych podscriptov neukonci vcas tak sa proste nevykona dobre. Script volam ./script.sh "$IPADRESA" &

Za odpoved vopred dakujem.
Název: Re:Bash script
Přispěvatel: branchman2 11. 08. 2012, 01:55:45
Nepotrebujes nieco ako toto?
Kód: [Vybrat]
./script.sh "$IP" &
PID=$!
...
wait "$PID"

Ak nie, tak sa skus vyjadrit zrozumitelnejsie (idealne aj s ukazkami kodu), o co ide. Nejaky sleep totiz vobec nie je ovplyvneny tym, ako dopadli ine prikazy, ked tym nie je podmieneny.
Název: Re:Bash script
Přispěvatel: David 11. 08. 2012, 15:38:44
Vykasli se na sleep a ten prvni skript spoustej cronem
Název: Re:Bash script
Přispěvatel: Zopper 11. 08. 2012, 22:39:58
Pokud je problém v tom, že se po sleep spoustí nějaký skript, který přitom ještě nedoběhl, pak cron nic nevyřeší. Buď bych sledoval stav potomků přes PID, a ukončoval každý skript až když neběží žádný potomek (á la procesy/vlákna), nebo bych si udělal nějaký zámek ve filesystému (/tmp/muj_super_program_bezi) při spuštění, do místa, které je zaručně posledním bodem všech skriptů dal jeho smazání, a na začátku pak kontrolovat, jestli už zámek neexistuje. :)

Název: Re:Bash script
Přispěvatel: branchman2 12. 08. 2012, 00:35:07
Podla mna treba sledovat stav potomkov cez PID, ako som pisal. Zamok je sice mozne spravit, ale pre dlhsie trvajuce operacie by takyto spinlock len zral CPU (alebo by cakal zbytocne vela pri sleepoch medzi kontrolami). Naproti tomu wait uspi proces, takze sa nevytazuje CPU a zaroven sa spi len primerane dlho.
Název: Re:Bash script
Přispěvatel: Zopper 12. 08. 2012, 12:14:00
Ovšem sledovat PID můžu jen, když si to budu sám pouštět ve smyčce. Pokud by přišlo na cron, nemám moc jak to řešit jinak, než dočasným souborem jako zámkem. Leda tak ještě mít skript, co na nějaký signál (SIGUSR1?) zkusí spustit potomky a sám běží trvale - a ten signál mu přijde z cronu.
Název: Re:Bash script
Přispěvatel: lukas016 12. 08. 2012, 21:48:28
Kód: [Vybrat]
#!/bin/bash
for (( PRC=1; $PRC-120; PRC=$PRC+1 )) #cyklus pre citanie riadkov suborov zacina na prvom riadku
do
{
IPADRESA="$(sed -n "${PRC}"p zoznam9)" #precita riadok zo suboru s IP adresami
if [ "$IPADRESA" == "" ] #ak precita prazdnu hodnotu zo suboru, zastavy script na 5 minut a zacne odznovu
then
{
sleep 5m;
PRC="0"
};
else
{
./vypisy.sh "$IPADRESA" &
};
fi;
};
done;
Tu je kód hlavného scriptu. Cez crond by sa to dalo spravit, alebo pomocou suboru.
Název: Re:Bash script
Přispěvatel: lukas016 13. 08. 2012, 01:12:50
Este by ma zaujimalo ak by som to spravil cez crond a nechal ukoncit cyklus (script) pri prazdnej hodnote. Tak by som ukoncil rodicovsky script a tym padom aj vsetky scripty ktore dany script spustil, cim by som svoj problem nevyriesil. Dalo by sa to opravit tak ze by som odstranil & ale zas chcem aby boli vypisy v priblizne jednom case spravene. Takze co by bolo vyhodnejsie spravit to cez PID? alebo kontrolny subor. Script vypis sa vyvola priblizne 120 krat. S tym ze posledny vyvolany sa moze skoncit skor aj ako prvy.
Název: Re:Bash script
Přispěvatel: Zopper 14. 08. 2012, 09:18:55
Asi kombinace. Cron spustí master-script. Ten si ověří, jestli už někde neběží (zámek) a pokud ne, spustí ty podskripty. Jejich stav sleduje přes PID a čeká, než se všechny ukončí. Pak zámek odstraní.
Název: Re:Bash script
Přispěvatel: lukas016 15. 08. 2012, 03:24:58
Uvazoval som ze to spravim tak, ze cronom vyvolam master script pri starte OS, a potom master script bude dozerat na ukoncenie vyvolanych podscriptov a zaroven sa bude uspavat pomocou prikazu sleep alebo by som nastavil v crone presny cas kedy sa ma spustat cim by som vynechal sleep. Script teraz preberie vsetky PID a zapise ich do jednej premenej. Ak sa $IPADRESA rovna NULL tak sa zacne kontrolovat ci sa vyvolane scripty ukoncili a ak ano tak sa master script uspi na 5m a potom ide od zaciatku. Cely jeden cyklus aj s kontrolou PID zaberia max 3 minuty. A cyklus sa asi bude opakovat v 10 minutovych intervaloch. Moze to byt takto riesene? alebo by som mal spravit aj ochranu pomocou suboru?
Kód: [Vybrat]
#!/bin/bash
for (( PRC=1; $PRC-130; PRC=$PRC+1 )) #cyklus pre citanie riadkov suborov zacina na prvom riadku
do
{
IPADRESA="$(sed -n "${PRC}"p zoznam9)" #precita riadok zo suboru s IP adresami
if [ "$IPADRESA" == "" ] #ak precita prazdnu hodnotu zo suboru zacne zistovat ci sa vyvolane scripty ukoncili
then
{
for (( PRCPID=0; $PRCPID-130; PRCPID=$PRCPID+1 )) #cyklus pre overovanie PID
    do
    {
if [ "${PIDs[*]}" == "" ] #ak je su vsetky vyvolane scripty ukoncene uspi sa na 5m a potom zacne znovu
then
{
echo "SPIM"
sleep 5m;
PRCPID="129";
        PRC="0";
};
else
{
if [ "${PIDs["$PRCPID"]}" == "" ]; #ak dojde za poslednu premenu vrati sa na zaciatok
then
{
    PRCPID="-1";
};
else
{
OVERPID="$(top -p "${PIDs["$PRCPID"]}" -n 1 | awk '{ print $2 }' | tail -2 | sed -n 1p | tr -d "\r ")" #preberie hodnotu beziaceho PID
echo "$OVERPID"
if [ "$OVERPID" == "PID" ] #ak vyvolany script uz nebezi OVERIP nadobuda hodnotu PID
then
{
PIDs=($(echo "${PIDs[*]}" | sed "s/"${PIDs[$PRCPID]}"//g")) #Vymaze PID ukonceneho scriptu z premenej
echo "${PIDs[*]}"
};
fi;
};
fi;
};
fi;
    };
done;
};
else
{
./vypisy.sh "$IPADRESA" &
PID=$!
echo "$IPADRESA $PID" >>PID
PIDs=(""${PIDs[*]}" "$PID"");
};
fi;
};
done;
exit 0
Název: Re:Bash script
Přispěvatel: Zopper 15. 08. 2012, 09:07:34
Pokud máš jistotu, že to těch 10 minut nikdy nemůže zůstat viset, případně ti to riziko nestandardní situace nevadí, tak zámek přidávat nemusíš.

Když v v master script budeš mít nějaké časování, tak to nedávej do cronu, ten to bude pouštět opakovaně dál! (Ale možná jsi myslel rc.local a jen napsal cron :) )

PS: Použít FOR pro nekonečný cyklus, a navíc se změnou řídící proměnné v těle - to je opravdu, opravdu ošklivá věc, která by se dělat vážně neměla!!!  >:( >:( >:( Jestli nechceš cron, tak to celé zabal do jednoho cyklu typu while(1) - a sleep dej taky mimo ten for.
Název: Re:Bash script
Přispěvatel: lukas016 15. 08. 2012, 17:59:49
No s while nemam dobre skusenosti preto radsej robim s for. Ale prepisal som to do while ale neviem preco ak dam len citat subor a vypisat $IPADRESA tak sa vypise cely subor ale ak uz volam script vypisy.sh tak sa precita len cast suboru. Takze nieco v scripte vypisy mi musi ukoncit cyklus while ale pri cykle FOR mi to nerobilo.
Kód: [Vybrat]
while read IPADRESA
  do
{
echo "$IPADRESA"
./vypisy.sh "$IPADRESA" &
PID=$!
if [ "$LIMIT" == "20" ]
then
{
ID=$(($ID+1));
LIMIT="1";
};
fi;
PIDs["$ID"]=""${PIDs["$ID"]}""$PID",";
LIMIT=$(($LIMIT+1));
KONLIM["$ID"]="$LIMIT"
};
done < zoznam8
Název: Re:Bash script
Přispěvatel: Zopper 15. 08. 2012, 19:41:27
Nepochopil jsi mě...  Já ti radil něco takového:
Kód: [Vybrat]
while(1){
 for( ... ){
  ...
 }
sleep();
}
Jde o to, že když vidím FOR, čekám přesný počet opakování, známý v okamžiku prvního vstupu do podmínky, nic jiného. Je to prostě dost vžitá konvence, která by se měla dodržovat. Hledat, kde všude se ta změna řídící proměnné uprostřed kódu může nějak projevit není vždycky snadné, mate to a akorát zvyšuje riziko chyb.
V tomto případě se sice moc neděje, ale je důležité, udělat si správné návyky.
Název: Re:Bash script
Přispěvatel: lukas016 17. 08. 2012, 20:20:22
Dakujem za radu. Zatial to asi spravim po svojom lebo s BASH sa este len ucim a script je lahky chyby by nemali nastat. A nemohol by si mi odporucit nejake knihy alebo stranky kde by som sa mohol dobre naucit BASH?
Název: Re:Bash script
Přispěvatel: Zopper 17. 08. 2012, 20:55:12
Co se samotného Bashe týče, tak já používám manuál a různá howto. Bash ale používám spíš okrajově na pomoc/automatizaci některých činností, rozhodně v něm nijak zvlášť netvořím. Moje poznámky nicméně nebyly specifické pro Bash, ale obecné, platné pro většinu jazyků, s kterými přijdeš do styku. Takže bych si rozhodně přečetl něco jako Umění Programování od Knutha, bude se ti to hodit. ;-)
Název: Re:Bash script
Přispěvatel: q 17. 08. 2012, 21:34:04
PS: Použít FOR pro nekonečný cyklus, a navíc se změnou řídící proměnné v těle - to je opravdu, opravdu ošklivá věc, která by se dělat vážně neměla!!!  >:( >:( >:(
Kód: [Vybrat]
$ grep -iR 'for\s*(\s*;\s*;\s*)' /usr/src/linux-source-3.0
2268
Noobs...
Název: Re:Bash script
Přispěvatel: aaa158 17. 08. 2012, 22:00:56
Dakujem za radu. Zatial to asi spravim po svojom lebo s BASH sa este len ucim a script je lahky chyby by nemali nastat. A nemohol by si mi odporucit nejake knihy alebo stranky kde by som sa mohol dobre naucit BASH?
http://tldp.org/LDP/abs/html/
Název: Re:Bash script
Přispěvatel: Zopper 18. 08. 2012, 09:27:34
Kód: [Vybrat]
$ grep -iR 'for\s*(\s*;\s*;\s*)' /usr/src/linux-source-3.0
2268
Noobs...
Jednak jsem napsal "nemělo", ne "nedělá" :) a jednak
Kód: [Vybrat]
for(;;) je ještě něco jiného, než
Kód: [Vybrat]
for(i=0;i<100;i++) {
// hromada kódu a vnořených podmínek
i=x;
// další hromada kódu
}
Prázdný for je na první pohled vidět. Podmíněné úpravy uvnitř těla jsou vidět blbě.

Programátor se má hlavně naučit programovat podle standardů a porušovat by je měl, až když ví, co dělá, z jakého důvodu (přinese to zrychlení, ... ?) a jaké to porušení může mít vedlejší následky.