Nieuws:

Welkom, Gast. Alsjeblieft inloggen of registreren.
Heb je de activerings-mail niet ontvangen?

Auteur Topic: [opgelost] Bash pipe probleem  (gelezen 1631 keer)

[opgelost] Bash pipe probleem
« Gepost op: 2011/03/19, 22:51:19 »
Ik heb een probleem met het pipen van output van het AWK commando naar een volgend commando. Als in de onderstaande code de derde pipe weglaat, dus die na het awk commando, dan komt de correcte output op het scherm te staan. Maar wanneer ik nu probeer deze output naar een volgend commando te pipen of naar een file te sturen is het net of de output in het niets verdwijnt. Dus als de tweede "tee" is toegevoegd met pipe, dan verschijnt er niets meer op het scherm, en ook het testbestand blijft leeg.

Ik snap er niets van.  ??? Iemand een idee?

tail  -f -n +$((lastnr + 1)) "$data_in_path"|\
tee -a "$data_out_path"|\
awk -v table="$table" -F ',' '{ printf ("INSERT INTO %s (dataindex,time,autosend,maintenance,visitors,exp_status,temperature,humidity,light,weight,distance,speed,locM1,locM2,locM3,locM4,locM5) VALUES(", table); for (i=1;i<NF;i++) {printf "%s,", $i;} printf "%s);\n",$NF; }'|\
tee -a "$PWD/test"

Hier is de totale code.

#!/bin/bash
# Script to send data from sensorboard to main server

# set the following variables to the correct values
usernum="10"
data_in_path="${PWD}/data-received.cvs"
data_out_path="${PWD}/data-send.cvs"

# other variables, don't change
database="datadb"         # databasename
table="data${usernum}"    # tablename
lastsendline=""           # to store last send line
lastnr="0"                # to store line number of last send line

if [ -f "$data_out_path" ]; then
  lastsendline=$(tail -n 1 "$data_out_path")
  lastnr=$(sed -n "/$lastsendline/=" "$data_in_path")
fi
echo $lastnr


tail  -f -n +$((lastnr + 1)) "$data_in_path"|\
tee -a "$data_out_path"|\
awk -v table="$table" -F ',' '{ printf ("INSERT INTO %s (dataindex,time,autosend,maintenance,visitors,exp_status,temperature,humidity,light,weight,distance,speed,locM1,locM2,locM3,locM4,locM5) VALUES(", table); for (i=1;i<NF;i++) {printf "%s,", $i;} printf "%s);\n",$NF; }'|\
tee -a "$PWD/test"
« Laatst bewerkt op: 2011/03/21, 22:46:43 door Thomas de Graaff »

Re: Bash pipe probleem
« Reactie #1 Gepost op: 2011/03/20, 00:03:24 »
Die regel ziet er ook wel uit alsof je er makkelijk een foutje in kan maken met al die quotes binnen quotes  =D Maar als het gewoon correct naar het scherm wordt gestuurd dan ligt het daar niet aan. Heb je al eens geprobeerd om het tee commando door iets anders te vervangen en kijken of de input daar wel doorheen komt? Ik heb nog niet zoveel verstand van bash icm pipes e.d. maar je zou ipv tee ook cat kunnen gebruiken als test.

Re: Bash pipe probleem
« Reactie #2 Gepost op: 2011/03/20, 00:08:11 »
Ik heb idd. al andere commando's geprobeerd, dat bleek niets uit te maken. Inmiddels ben ik wel iets verder. Het ligt blijkbaar aan de combinatie van "tail -f"  en "awk". Zodra ik de "-f" optie bij tail weghaal werkt de pipe na het awk commando wel zoals het hoort. Hoe dit op te lossen, daar ben ik nog niet uit, want ik heb juist wel de -f optie nodig..

Hoe het precies werkt weet ik niet, maar ik denk dat awk eerst alle lijnen verzameld alvorens aan de slag te gaan met het verwerken, en doet deze dat niet lijn voor lijn. Dat zou dan verklaren waarom de optie -f van tail niet werkt in combinatie met awk en een pipe na awk.

edit:

Het volgende scriptje werkt inderdaad ook niet:
#!/bin/bash

tail -f "$PWD/data-received.cvs"|\
awk '{print $0}'|\
tee -a "$PWD/test"

Dat geeft wel aan dat het probleem de combinatie van tail -f en awk is denk ik.
« Laatst bewerkt op: 2011/03/20, 00:52:22 door Thomas de Graaff »

Re: Bash pipe probleem
« Reactie #3 Gepost op: 2011/03/20, 00:39:35 »
Ik heb eerst even moeten uitzoeken wat tail uberhaupt doet maar nu snap ik iig wat je bedoelt ;) Wat wel vreemd is is dat awk wel naar het scherm kan printen als ik het goed begrijp, ook na een tail -f ? Wat is het verschil tussen een pipe en direct naar het scherm wat dat betreft?

Re: Bash pipe probleem
« Reactie #4 Gepost op: 2011/03/20, 00:43:53 »
Awk kan idd. wel naar het scherm printen, ook na een tail -f. Maar zodra je de output van awk dan wilt pipen werkt het niet meer. De redenatie in mijn bovenstaande bericht dat awk niet lijn voor lijn zou verwerken klopt dus ook niet, want wanneer er geen pipe na het awk commando komt, verwerkt deze gewoon iedere nieuwe regel die wordt toegevoegd aan het bestand dat met tail -f wordt gevolgd.

Ik snap er niets van om eerlijk te zijn. :)

De output van awk gaat normaal naar standaard output. Dat is in het algemeen het scherm. Wat een pipe doet is standaard output opvangen, en doorsturen naar de standaard input van het volgende commando. Ik snap dus niet waarom dat niet werkt in dit geval.
« Laatst bewerkt op: 2011/03/20, 00:46:44 door Thomas de Graaff »

Re: Bash pipe probleem
« Reactie #5 Gepost op: 2011/03/20, 16:25:36 »
Inmiddels heb ik op een engelstalig forum een antwoord gekregen op dit probleem. Het is toch wat ik in eerste instantie al dacht, awk verwerkt niet regel voor regel, maar buffert een aantal regels tot de buffer vol zit, en verwerkt ze dan pas. Dit kan je voorkomen door gawk te gebruiken, en dan het commando fflush. Dit zorgt ervoor dat awk de output buffer direct leegt zodat deze naar de pipe verstuurd wordt.

tail -f "$PWD/data-received.cvs"|\
gawk '{print $0; fflush();}'|\
tee -a "$PWD/test"