Vraag Hoe een filter op realtime uitvoer van `tail-f` toe te passen?


tail -f path

Het bovenstaande zal direct wijzigingen aan het bestand uitvoeren, maar ik wil een filter toepassen op de uitvoer, alleen laten zien als er een sleutelwoord is xxx in het.

Hoe dit te benaderen?


48
2017-07-05 09:13


oorsprong


Door antwoorden te markeren als geaccepteerd, kunnen anderen die je vragen en antwoorden lezen, weten welk antwoord hen waarschijnlijk zal helpen als ze een vergelijkbare vraag of probleem hebben. U kunt uw eerdere vragen opnieuw bekijken door op uw gebruikersnaam te klikken. - Dennis Williamson


antwoorden:


Met Unix kunt u de uitvoer van het ene programma naar het andere overbrengen.

Dus om staart te filteren, kunt u grep gebruiken:

tail -f path | grep your-search-filter

67
2017-07-05 09:17



Maar laten we zeggen dat je 100 lijnen in de staart hebt (einde van het bestand), en deze lijnen zijn degene die je wilt filteren. Uw oplossing - TraderJoeChicago
Als u alleen de laatste 100 regels van een bestand wilt doorzoeken, probeert u tail -100 path | grep xxx - AddersUK


Kort antwoord: tail -f somefile | grep somepattern

Dit heeft echter de neiging tekort te schieten. Stel dat u een bestand volgt dat vaak wordt geroteerd (als het een foutopsporingslog is, kan het meerdere keren worden geroteerd). In dat geval tail -F is jouw vriend. Ik laat je het verschil opzoeken.

Maar tail -f en tail -F print eerst een aantal regels, wat vaak ongewenst is in deze use-case, dus voeg in dit geval toe -n0

tail -F -n0 somefile | grep somepattern

Dat komt goed, tot je wat andere filtering wilt doen, en dan moet je oppassen voor buffering. stdout is standaard in de regel gebufferd bij het schrijven naar een terminal maar wanneer volledig gebufferd bij het schrijven naar een pijp. Dus het volgende zal lijnen uitzenden zodra ze worden gevonden, omdat tail is expliciet regelgebufferd (of zijn uitvoer aan het einde van elke regel), en grep is ook regelgebufferd omdat de uitvoer naar uw terminal gaat:

tail -F -n0 somefile | grep somepattern

Maar dan besluit je om zoiets te gebruiken awk of cut om de uitvoer verder te verwerken.

tail -F -n0 somefile | grep somepattern | awk '{print $3}'

En nu vraag je je af waar je uitvoer heen is gegaan ... afhankelijk van het aantal logs, zul je merken dat je wel output krijgt, maar het zal een pagina per keer zijn, omdat nu de stdout van grep werkt op volledig gebufferde wijze, en zo awk ontvangt deze ingang 4 kB tegelijk (standaard).

In dit geval kunt u vertellen grep om altijd de stdout-regel te bufferen met behulp van de --line-buffered keuze.

tail -F -n0 somefile | grep --line-buffered somepattern | ...

De meeste opdrachten hebben echter geen analoog --line-buffered. In het geval van meer scriptbare tools, kunt u een functie gebruiken om de uitvoer te spoelen (bijv awk, de functie is fflush(), die dezelfde naam heeft als zijn C-tegenhanger, tools als Perl en Python hebben iets dergelijks).

Met mensen zoals cut je hebt waarschijnlijk geen geluk; ... maar u kunt proberen te zoeken unbuffer, dat is denk ik iets geboden door de expect toolchain (ik heb het nog nooit gebruikt).

Ik hoop dat je dit nuttig hebt gevonden.

cheers, Cameron


12
2017-08-02 10:46



Ik stel de uitleg erg op prijs waarom dit werkt in de lijngebufferde modus. Dat is een uitstekend inzicht, dank u. - Green
@Green bedankt voor de feedback - Cameron Kerr


en je kunt meerdere pipes en greps gebruiken, en dingen uitsluiten met grep -v, case-ongevoeligheid krijgen met grep -i, etc.

d.w.z.: tail -100f / var / log / messages | grep -V ACPI | grep -i ata

begin met het verwijderen van 100 lijnen vanaf het einde en blijf tailing, sluit eerst alle regels uit met ACPI en toon vervolgens lijnen met ata, ATA of een combinatie daarvan.

Een andere handige is de ABC-opties, voor de regels After, Before en Context (regels voor en na).


2
2017-07-05 20:12