Folyamatosan frissülő fáhl vizsgálata AWK-val?

Fórumok

Sziasztok!

A problémám a következő:
Van egy fájl, amely szimulációs eredményeket tartalmaz, és ami egy pipe-tól kapja az eredményeket.
Van mondjuk 100 szimuláció, akkor ez a fájl 100 soros lesz és a szimulációk alatt folyamatosan bővül.

Szeretnék valós időben a szimuláció működésébe beavatkozni, ehhez pedig az kellene, hogy awk-val minden frissülésnél át tudjam nézni ezt a bizonyos fájlt.

Tehát van arra lehetőség szerintetek, hogy minden egyes frissülés esetén lefusson egy awk script adott fájlon?

Minden segítséget nagyon köszönök!

Sziasztok!

Hozzászólások

Hát én nyomnám a logger-rel bele egy file-ba, aztán valamilyen realtime logviszgálóval nézetném, mondjuk szerintem a sec.pl a csúcs. Persze simán csak a sec.pl-t is rá lehet állítani, hogy megfelelő szabály esetén jelezzen.

De lehet "tail -f"-elve is awkázni, de hát ez azért....jajj

Hát szerintem meg egyszerűbb dolog ha mondjuk csak egy mintát és egy risztást kell beállítanod, vagy egy program futtatását egy konfigurációban és semmi mással nem törődni.
Ha változik a bement, vagy a kimenet alakul át, semmit nem kell csinálnod, mint az adott konfigban a mintát átírni. De változhat a reagálás mikéntje is. Én mondjuk az ilyenek helyett:

futtasd parancs | awk > nézem két szép szememmel...jajj le kell futtatnom program > futtat parancs > nézem az awk-s parancssoromat > jajj most más a kimenet, most másik parancsot kell lefuttatnom, hol is van, ja a /könyvtár/másik/script....hú ez megvolt...francba más a minta megint....másik script futtatása.....blablabla

jobban szeretem

ha [regexp minta] futtasd [parancs]
de ha [regexp minta] futtasd [parancs] ....

ezek után ha akarom nézem, ha akarom nemnézem a két szép szememmel.

Én a következőt csinálnám. A pipe-olt részt nem fájlba íratnám, hanem soronként feldolgoznám. Ezt kétféle módon is meg lehet csinálni:


ls | while read; do echo "olvasott ertek:"$REPLY; done

vagy létrehozhatsz egy fifo fájlt (man mkfifo), amibe ha beleirányítod, akkor egy másik scriptből

line=`head file.pipe -n 1`

módon kiszedhetsz belőle egy sort (ez addig vár, amíg nem kap egy új sort, ez kellene egy ciklusba berakni). Esetleg a

tee

paranccsal fájlba is írhatod, és a pipe-ra is, így a scriptet a fájlt nézné meg, de pipe-tól kapná az üzenetet, hogy át kell néznie.

Ezek mind event vezérelt megoldások, semmi folyamatos futás. Ha kell segítség szólj.

Azt feltételezem, hogy sorokat kapsz, és nem kell minden új karakternél lefutni a scriptednek. Két változatot küldök. Bár elsőre hasonlónak tűnnek, de van különbség: amikor a "read"-et használjuk és ráirányítjuk a kimenetet, akkor minden sornál lefut a scripted, ha a "head"-et használjuk, akkor előfordulhat, hogy egyszerre jön 3 sor, és csak egyszer fut le a scripted. Az előző biztonságosabb, de te tudod, hogy neked melyik kell. (Nekem kellett a "head"-es megoldás webcam képeknél, ha túl gyorsan jöttek a képek, akkor nem volt gond, ha párat nem jelenítettem meg, az viszont gond lett volna, ha fél napos lemaradásban lett volna.)

Kezdem azzal a megoldással, amit ajánlok.

parancs:

szimulacio | readbyline.sh

readbyline.sh:
#!/bin/bash
rm -f temp.txt
while read; do
        echo "readbyline.sh: read line: "$REPLY
        echo "Calling your script"
        echo $REPLY >> temp.txt
        ./your_script.sh temp.txt
done

A your_script.sh minden új sorra meghívódik, tehát a temp.txt minden hívásnál eggyel több sort fog tartalmazni.

A "head"-es megoldás nem túl elegáns, mert nem minden sornál fut le, de azért nézzük. A script:


head.sh:
#!/bin/bash
while true; do
        line=`head -n 1`
        echo "Calling your script, which might use output.txt"
       ./script.sh
done

Parancsok:


mkfifo output.pipe
szimulacio | tee output.pipe > output.txt

Egy másik terminálban:


./head.sh

Ezzel kész is vagyunk. Ez utóbbi esetben is használható az előző script, ha

./head

helyett ezt adod ki:


cat output.pipe | ./readbyline.sh

Remélem segített. Az mkfifoval létrehozott pipe-ot leginkább akkor találtam hasznosnak, ha a programod mindenképp fájlba akar írni (pl. mert C-ben írták, nincs kedved belenyúlni). Egyébként az átirányítgatással menni szokott minden.

Szia hud!

Nagyon köszönöm a segítséged.

Az első verzióhoz lenne kérdésem, de tulajdonképpen a másodikra is igaz.
Tehát nekem a program az eredményeket egy fájlba írja ki.
Így a szimulacio | readbyline.sh csak egyszer fut le, ahogy kiírja a program:
"Szimuláció befejeződött"

Tehát nem az eredményre fut le, hanem ilyen program üzenetre.

A programban így szerepel a kimeneti fájl:
.
.
.
./szimulacio > result
.
.
.

Erre van esetleg ötleted?

Köszi!

Ötletem mindig van. A program ezek szerint egy script fájl? Ha igen, akkor ha a

./szimulacio > result

részt kicserélhetnéd

./szimulacio

-ra. Ekkor minden a standard outputra menne. Az egyéb üzeneteket pedig küldhetnéd a stderr-re (remélem jól írom a példát):

echo "Szimulacio befejezodott"

helyett

echo >&2 "Szimulacio befejezodott"

. Ha ennek a programnak a kimenetelét átirányítod, akkor az stderr a képernyőre íródik ki.

Másik megoldás, ha a result fájl egy mkfifo-val létrehozott pipe.

Szia hud!

Sajnos nem működik tökéletesen, de biztos nem veszek észre valamit.
a

tail -f kimenet | awk -f sajat.awk

működik, ha pl. /d/ {echo $0} ból áll, akkor szépen megkapok mindent a képernyőre, de

fájlba írni már nem működik, a megadott kimenetei fájl üres lesz. Miért lehet?

Tehát pl:
tail -f kimenet | awk -f sajat.awk >kimenet
vagy a sajat.awk-n belül:
/d/ {echo $0>"kimenet"}

Ezek mind üres kimenet fájlt eredményeznek, de az érdekes, hogy maga a kimenet fájl létrejön.

Van tipped, hogy miért lehet ez?
Köszi!


Tehát pl:
tail -f kimenet | awk -f sajat.awk >kimenet
vagy a sajat.awk-n belül:
/d/ {echo $0>"kimenet"}

Ezek mind üres kimenet fájlt eredményeznek, de az érdekes, hogy maga a kimenet fájl létrejön.

az ugye nyilvánvaló, hogy a kimeneti fájl akkor van "kész", amikor az awk a működését befejezte. addig csak "készül", az awk az eredmény utolsó részét a memóriában tárolja, és csak a legvégén írja ki a fájlba.

mivel a tail -f sosem áll le, azért az awk sem fog sosem leállni. tehát a kimeneti fájl sosem készül el teljesen a diszken, a vége mindig csak az awk memóriájában lesz meg.

ha azt szeretnéd, hogy az awk valamely print után a memóriában tárolt dolgokat azonnal írja ki a kimenetre, akkor az fflush függvényt nézegesd közelebbről.

tail -f fájlnév | awk amit akarsz
A tail -f folyamatosan kiírja a fájl végét.

A tail -f a fájl végét, ahogy abba bekerül valami tolja a kimenetére, ha csőbe tolod, akkor az utána következő program bemenetén szépen megjelennek a fájlba írt sorok. Mind, egymás után.

Miért kéne csak az utolsó tíz sor? Ha az a feladat, hogy a legutolsó 10 sor alapján csinálj valamit, akkor az awk pont nem jó választás szerintem, bár a NR/10-zel lehet játszadozni, ez is igaz...

> Van egy fájl, amely szimulációs eredményeket tartalmaz, és ami egy pipe-tól kapja az eredményeket.

Valahogy így: 'szimuláció > file' ?

> awk-val minden frissülésnél át tudjam nézni ezt a bizonyos fájlt.

Ha csak az új sorokat: 'szimuláció | tee file | awk'

Valahogy így: 'szimuláció > file' ?

Igen, egy szkriptből meghívódik maga a program, ami már eleve named_pipe-on kap bemenetet és terveim szerint a valós idejű reagálás miatt named_pipe-ra kapja a kimenetet, de az lehetne egy "sima fájl" is aminek a változását követjük.

> awk-val minden frissülésnél át tudjam nézni ezt a bizonyos fájlt.

Ha csak az új sorokat: 'szimuláció | tee file | awk'

A tee parancsot eddig nem ismertem, csak hallomásból, de a unix man szerint:

tee - read from standard input and write to standard output and files

Tehát akkor ha itt mondjuk 1 karakter érkezik, akkor rögtön továbbküld 1-et, ha pedig 10 sor, akkor egyszerre 10 sort küld tovább?

akkor rögtön továbbküld 1-et

próbáld ki, de felhívnám a figyelmedet arra, hogy a legtöbb program alapból az stdio.h függvényeit használja, amik pufferelve írnak.
azaz amíg a puffer meg nem telik, vagy a program explicite nem kéri a puffer ürítését valamilyen módon (pl. a program futásának a végén a close() ezt megcsinálja), addig a kimenetre kerülő dolgok várakoznak szépen a memóriában, és addig a pipe-ban a következő láncszem nem is kapja meg.

namost a legtöbb standard unix utility nem rendelkezik olyan opcióval, amivel ezt a pufferelést ki lehetne kapcsolni, vagy akár csak rá lehetne venni a programot, hogy adott időközönként mindenképpen ürítse a kimeneti puffert.

Ágyúval verébre, de úgy érzem, az inotify is megemlítendő ebben a topicban.