bash: pipe gondok

bash: pipe gondok

Hozzászólások

[quote:5c4576b3ad="j_szucs"]De: ha csak egy "cat"-ot is hozzáírok, vagy csak az utolsó sed parancsot kettébontom, hogy 11 pipe legyen, már elő is jön a probléma.

Ez rejtélyes számomra. És ha mondjuk batch-fájlokra bontod?
[quote:5c4576b3ad="j_szucs"]Most megnéztem még nagyobb bemeneti adatállománnyal úgy látom, mintha valami bufferelés lépne be: az adatok ár nem szép lassan, folyamatosan csordogálnak ki a pipe-ból mint egyébként, hanem adagokban.

Még az ütemezés is lehet az oka, de valszeg úgy tudsz rájönni, hogy ki a hibás, h szétbontogatod.
[quote:5c4576b3ad="j_szucs"]RLIMIT_NPROC: Ezt hogyan tudom lekérdezni/állítgatni szkriptből?

ha írsz egy C programot:[code:1:5c4576b3ad]main() {struct rlimit l;getrlimit(RLIMIT_NPROC,&l);
printf("(cur,max)= %d, %d\n", l.rlim_cur,l.rlim_max); }[/code:1:5c4576b3ad]
[quote:5c4576b3ad="j_szucs"]ulimit -a eredménye (kihagyva azt ami unlimited):
...
A fentiek közül melyik korlátozhatja 10-ben a pipe-ok számát?

állíts mindent unlimited-re, és megtudod, ez volt-e a ludas.
[quote:5c4576b3ad="j_szucs"]Egyébként rémlik nekem, mintha valamikor régen olvastam volna egy ilyen 10-es korlát létezéséről, de most sehol sem találom a forrást, a google most nem hoz le semmi hasznosat nekem (egyelőre).

erősen kétlem, nálam szépen megy:[code:1:5c4576b3ad]while true;do sleep 1;echo -n x;done |cat|cat|cat|cat|cat|cat|cat|cat|cat|cat|cat|cat|cat|cat|cat|cat|cat|cat|cat|cat|cat[/code:1:5c4576b3ad]

RLIMIT_NPROC (processzek max. száma) talán, lásd setrlimit(2).

Ez inkább kernel paraméter lehet.

ELaci

állíts mindent unlimited-re, és megtudod, ez volt-e a ludas.

Mindent "unlimited"-re állítottam, amit lehetett. Az "open files", és a "pipe size" értékek viszont nem állíthatók.
A helyzet változatlan.

ha írsz egy C programot:
Kód:
main() {struct rlimit l;getrlimit(RLIMIT_NPROC,&l);
printf("(cur,max)= %d, %d\n", l.rlim_cur,l.rlim_max); }

[code:1:43ea018c64]szucs@linux:~/getrlimit> ./getrlimit
(cur,max)= 2047, 2047[/code:1:43ea018c64]
A 2047-es korlát nem tűnik alacsonynak :(

Sok (a legtöbb?) program nem piszkálja a pufferelést, hanem a default-ot használja. Ezért pl. ha grep-et indítasz simán a terminálon, akkor minden találat azonnal meg fog jelenni (mert az stdout-ja terminálra vonatkozik, és ezért minimum line buffered). Ha ugyanezt a grep-et pipeline-ba szervezed, akkor a kimenete a default stdio buffer size (BUFSIZ v. "fstat(fileno(stream)).st_blksize", pl. 4K) méretű blokkokban fog megjelenni.

A jelen konkrét esetben a grep nemigen pufferelhet: az awk-ból úgy indítom, hogy minden hívása után rögtön lezárom a pipe "To" és "From" irányát is, azaz kénytelen az eredményt rögtön küldeni.

Némi további próbálgatás utánmost úgy tűnik, hogy megdőlt a "10 pipe"-os teóriám:
cat-ból például nagyjából akármennyit hozzáfűzhetek a parancshoz, nem lesz pufferelés.

Viszont rögtön pufferelés van, ha hozzáfűzök még egy sed, awk, vagy tr parancsot.

Különös: az első sed parancs még nem okoz pufferelést, a második meg igen...

És még egy érdekesség: az awk ebből a szempontból ugynúgy viselkedik, mint a sed: ugyanis ha az utolsó sed parancsot azonos funkciót teljesítő awk-ra cserélem, akkor még OK, de ha hozzáfűzök még egyet, ami csak ennyi: "| awk '{print $2 $1}'", rögtön élénk pufferelgetés kezdődik. :(

Van a sed-nek egy olyan opcioja, hogy --unbuffered... Hatha segit...

[quote:c395821520="j_szucs"]

Mindenesetre: minden pipeline-tag elé kiraktad az unbuffer-t (az utolsó kivételével)?

Nem. Először csak oda tettem, ahol már lassú a szkript, és ezért szükségesnek látszott; a legelső awk parancstól az utolsó előtti parancsig.
Ekkor a szkript működés helyett egy pillanat alatt kilépett. Ezután gyakorlatilag mindenféle kombinációban kipróbáltam, de olyan egy se volt, hogy a kimenet unbuffered-é vált volna.

Hat az unbuffer man-ja olyasmit mond, hogy a lanc mindegyik parancsa ele oda kell tenni... Es ez logikus is, mert ha egy helyrol is kihagyod, akkor sokat nem csinaltal.
A masik dolog, hogy unbuffered-e nem is kellett volna valjon. Line-buffered kellett volna legyen. Az unbuffer egy master/slave pszeudo-terminal part hasznal a pipe-olasra, ami miatt a libc startup kodja ugy veszi, mintha nem lenne atiranyitas, hanem a terminalra menne ki az output. Es akkor line-buffered-re allitja.

Van a sed-nek egy olyan opcioja, hogy --unbuffered... Hatha segit...

A sed-es problémát közben megkerültem úgy, hogy a "sed | tr " helyett egyetlen awk parancsot használok; így még unbuffered marad a dolog.

Csakhogy: ezt követi egy iconv, és máris jön a bufferelés :(

(Aztán ugye következne egy mbrola meg egy aplay is - de ezek egyelőre végképp reménytelennek látszanak).

Line-buffered kellett volna legyen.

Ha már itt kukacoskodunk, akkor én is pontosítalak: még line-buffered se "kellett volna" hogy legyen.
Ugyanis minden egyes program szíve joga eldönteni, hogy tty-ra milyen bufferezést használ/nem használ.

Es ez logikus is, mert ha egy helyrol is kihagyod, akkor sokat nem csinaltal.

Nem kell odatenni mind elé:
http://www.die.net/doc/linux/man/man1/unbuffer.1.html
És nem is lenne logikus.
Bőven elég azokat a parancsokat unbufferezni, ahol várhatóan az adat "átfolyás" olyan lassú, hogy kényelmetlenül sokat kellene várni a buffer megtelésére.

[quote:75f7a35786="j_szucs"]

Line-buffered kellett volna legyen.

Ha már itt kukacoskodunk, akkor én is pontosítalak: még line-buffered se "kellett volna" hogy legyen.
Ugyanis minden egyes program szíve joga eldönteni, hogy tty-ra milyen bufferezést használ/nem használ.

Nem epp az volt a problemad, hogy nem allitottak a hasznalt tool-ok (a sed kivetelevel) az output bufferinget? Ha pedig az volt, akkor pedig unbuffer hasznalata eseten igenis line-buffered kellett volna legyen.
[quote:75f7a35786="j_szucs"]

Es ez logikus is, mert ha egy helyrol is kihagyod, akkor sokat nem csinaltal.

Nem kell odatenni mind elé:
http://www.die.net/doc/linux/man/man1/unbuffer.1.html
És nem is lenne logikus.
Bőven elég azokat a parancsokat unbufferezni, ahol várhatóan az adat "átfolyás" olyan lassú, hogy kényelmetlenül sokat kellene várni a buffer megtelésére.

Persze. Vegul is oda teszel, ahova akarsz. De en mindegyik ele tennek, kiveve a sed ele. Csak azert, mert annyira illogikus.

erősen kétlem, nálam szépen megy:

Kód:

while true;do sleep 1;echo -n x;done |cat|cat|cat|cat|cat|cat|cat|cat|cat|cat|cat|cat|cat|cat|cat|cat|cat|cat|cat|cat|cat

Akkor próbáld ki ezt:
[code:1:27864a6e2e]while true;do sleep 1;echo -n "x"$'\n';done | sed 's/x/y/g'| sed 's/x/y/g'| sed 's/x/y/g'| sed 's/x/y/g'| sed 's/x/y/g'| sed 's/x/y/g'| sed 's/x/y/g'| sed 's/x/y/g'| sed 's/x/y/g'| sed 's/x/y/g'[/code:1:27864a6e2e]
Sőt, mint kiderült, nem is kell 10 sed parancs ahhoz jöjjön a pufferelés. Elég kettő.
A sed-nél még nem is gond, mert van -u paramétere. De mi van a többi paranccsal?

[quote:d265f6abd9="j_szucs"]
Akkor próbáld ki ezt:
[code:1:d265f6abd9]while true;do sleep 1;echo -n "x"$'\n';done | sed 's/x/y/g'| sed 's/x/y/g'| sed 's/x/y/g'| sed 's/x/y/g'| sed 's/x/y/g'| sed 's/x/y/g'| sed 's/x/y/g'| sed 's/x/y/g'| sed 's/x/y/g'| sed 's/x/y/g'[/code:1:d265f6abd9]
Sőt, mint kiderült, nem is kell 10 sed parancs ahhoz jöjjön a pufferelés. Elég kettő.

Igen, ezt mar leirtak, mitol van. Az elso sed-nek az stdout-ja mar nem tty, tehat mar nem line-buffered, hanem block-buffered...
[quote:d265f6abd9="j_szucs"]
A sed-nél még nem is gond, mert van -u paramétere. De mi van a többi paranccsal?

awk-ban tudsz fflush-t hasznalni
grep-nek van --line-buffering
iconv, ispell nemtoom
sajat_filter-t meg csinald ugy, hogy menjen :)

awk-ban tudsz fflush-t hasznalni
grep-nek van --line-buffering
iconv, ispell nemtoom
sajat_filter-t meg csinald ugy, hogy menjen

Közben találtam egy univerzális megoldást: az "expect" csomagban, ami (szerintem) a legtöbb disztribúcióban benne van, van egy "unbuffer" progi.
Az a progi bármelyik másik progival el tudja hitetni, hogy egy tty a kimenete, és így legalábbis line-buffered kimenetet produkál:
unbuffer sed
unbuffer awk
unbuffer iconv
...

Csak az a baj, hogy a legtöbb rendszeren az expect nincs alapból telepítve, így a szkriptnek lesz még egy függősége :(

Ha egy összetett parancssorba 10-nél több pipe-ot teszek, akkor a parancs láncolat megszűnik "real-time" lenni: megvárja, amíg az összes bemeneti adatot feldolgozza, és csak azután jelenik meg az utolsó parancs kimenetén az adat, méghozzá (szinte) egyszerre.

Csakhogy az összes adat feldolgozása hosszú idő, és ezért percekig úgy tűnik, mintha a szkript nem csinálna semmit; ráadásul ilyen hosszú késedelem abszolút megengedhetetlen.

Milyen korlátot lépek át a 11-ik pipe-al?
Lehet ezen valahogy segíteni?

Akkor jojjon az eszosztas: az "interaktivitas" nem fugg attol, amit irtal: a pipe-ok szama nem befolyasolja, egyszeruen az tortent, hogy 10 db bufferelo parancsot irtal egymas moge, amely mind buffereli a bemenetet, s hamarabb "elindul" az elso parancstol az eof, minthogy az utolso be tudna olvasni az elso input bufferet teljesen.

Mas: minek spawnolsz ennyi shellt? Kicsit utanajarsz (man sed), s az egesz esszeru megoldas:
[code:1:61f9e38381]input stream | sed -e 's/x/y/' -e 's/x/y/' -e 's/x/y/' -e 's/x/y/' -e 's/x/y/'[/code:1:61f9e38381]
Ez egyetlen sed processzt indit, mind gyorsasag, mint pedig az eredeti problema vonzataban jobban josz ki belole.

s hamarabb "elindul" az elso parancstol az eof, minthogy az utolso be tudna olvasni az elso input bufferet teljesen

És ha csak kettőt írok? Akkor is hamarabb jön az EOF?
Merthogy e szempontból - mint kiderült - a kettő pipe-olt sed ugyanúgy viselkedik mint a 10.

Mas: minek spawnolsz ennyi shellt? Kicsit utanajarsz (man sed),

Ne csak írj, olvass is.
Modjuk e téma első lapján a második hozzászólásom kódjának utolsó sorát. :)
Vagy esetleg azt a hozzászólást, amire az általad kifogásolt példát hoztam. Vagy esetleg csak a belőle idézett részt. Ha valamelyiket elolvasod, mindjárt világosabb lesz, mért úgy írtam ahogy írtam.

Talán egy named pipe máshogy fog viselkedni. (mkfifo)

ELaci

Eddig azt nem értettem, hogy ha a sed bufferelt, akkor miért csak a harmadik sed parancs hozzáírása után jelenik meg a bufferelés hatása? Miért nem késleltet már az első is?

Most viszont rájöttem: a dolog oka abban rejlik, hogy az awk parancs legalább egy nagyságrenddel lassabb, mint a többi parancs.
Az első sed bufferét a dcop parancs hamar feltölti, és ez így megy egészen az awk-ig.

Az awk parancs viszont már lassú, csak csorgatja a bájtokat, ezért az utána következő sed parancs buffere lassan telik meg. Amíg az a sed parancs tty-ra dolgozik, addig ez nem gond, mert line-buffered lesz, és egy sornyi adat még viszonylag hamar összegyűlik.
Amikor viszont utána írok bármilyen parancsot, akkor a második sed parancs full-buffered-é válik, és így várhatom az idők végezetéig amíg az awk parancs feltölti a bufferét.

Most már minden világos mint a nap. A megoldás az unbuffer parancs lesz.

Köszönöm mindenkinek a segítséget!

Szerkesztés: csak most próbáltam ki az unbuffer -p parancsot, és sehogy se működik :-(
Úgyhogy az iconv-ot végül az awk-ból kellett meghívni, hogy az fflush-t használni tudjam.

[quote:7e94a5913f="j_szucs"]Ha egy összetett parancssorba 10-nél több pipe-ot teszek, akkor a parancs láncolat megszűnik "real-time" lenni: megvárja, amíg az összes bemeneti adatot feldolgozza, és csak azután jelenik meg az utolsó parancs kimenetén az adat, méghozzá (szinte) egyszerre.

Hmmm... Hat ez nem igaz. Valamelyik lancbeli programmal lesz a baj. Nagyon egyszeruen ki tudod probalni: csinalj egy szkriptet, ami mondjuk 1 masodpercenkent kiir valami. Es pipe-old at ezt akarhany 'cat -' -on... Az eredmeny egybol megjelenik. Es ertelme sincs sok.
A bash fork-olas elott egyszeruen "beallitja" a file descriptor-okat. Neki utana mar sok koze nincs a dolgokhoz.

[quote:d5ca2695e7="cln"]Talán egy named pipe máshogy fog viselkedni. (mkfifo)

ELaci

Hat remelem, hogy a bash is pipe-ot hasznal... Az, hogy named vagy nem, nem kene szamitson...

[quote:9f1e9ee23f="j_szucs"]Milyen korlátot lépek át a 11-ik pipe-al?
Lehet ezen valahogy segíteni?

RLIMIT_NPROC (processzek max. száma) talán, lásd setrlimit(2).
igen, a bash pipe(2) hívást használ.

[quote:43a2c98494="j_szucs"]Ha egy összetett parancssorba 10-nél több pipe-ot teszek, akkor a parancs láncolat megszűnik "real-time" lenni: megvárja, amíg az összes bemeneti adatot feldolgozza, és csak azután jelenik meg az utolsó parancs kimenetén az adat, méghozzá (szinte) egyszerre.

Két ötletem van:

1. Rendezel. A sort azután kezd el beszélni, hogy EOF-ot olvasott.

2. Stdio buffer-ek (man setvbuf). Az stdio stream-ek alapértelmezés szerint így puffereltek: (a) ha a stream az stderr, akkor nem fully buffered, (b) ha a stream stdin v. stdout (kieg.: v. bármi, ld. fopen()) és biztos, hogy nem terminal device-ra vonatkozik (kb. errno = 0, !isatty(fileno(stream)) && !errno), akkor fully buffered.

Sok (a legtöbb?) program nem piszkálja a pufferelést, hanem a default-ot használja. Ezért pl. ha grep-et indítasz simán a terminálon, akkor minden találat azonnal meg fog jelenni (mert az stdout-ja terminálra vonatkozik, és ezért minimum line buffered). Ha ugyanezt a grep-et pipeline-ba szervezed, akkor a kimenete a default stdio buffer size (BUFSIZ v. "fstat(fileno(stream)).st_blksize", pl. 4K) méretű blokkokban fog megjelenni. Pl. 10 db ilyen grep összesen 40K-t tud felhalmozni.

10 db cat azért nem fog (nem próbáltam ki, tehát inkább azt mondom, hogy "ha nem fog, akkor azért nem fog") ilyesmit csinálni, mert (a) kézzel átállítja a pufferelést, (b) minden írás után fflush()-t hív, (c) nem használ stdio-t, hanem csak unistd syscall-okat (read/write).

Lásd: SUSv1 XSH (C435), 2.4 Standard I/O Streams

[quote:d8a5be34a4="kr304"]RLIMIT_NPROC (processzek max. száma) talán, lásd setrlimit(2).

inkább: man 1 bash, ott pedig: ulimit...

[quote:0c42b188a2="j_szucs"]Szerkesztés: csak most próbáltam ki az unbuffer -p parancsot, és sehogy se működik :-(

Nézted a man-ját? http://expect.nist.gov/example/unbuffer.man.html Én nem látok itt "-p" kapcsolót, de lehet, hogy nem ugyanarról az expect-ről beszélünk. Mindenesetre: minden pipeline-tag elé kiraktad az unbuffer-t (az utolsó kivételével)?

[quote:0c42b188a2="j_szucs"]A megoldás az unbuffer parancs lesz.

Igazából ezzel kapcsolatban szerettem volna felhívni a figyelmedet egy "apróságra": az expect (és az unbuffer is, ami az expect library-nak egy "triviális" kliensprogramja) nem "elhiteti" az áldozat programmal, hogy a standard stream-jei terminálra néznek, hanem valóban terminált rak alája: pszeudoterminált. A pszeudoterminál master végén ül az expect (ill. az unbuffer), a slave végén pedig a futtatott program. A fontos az, hogy a kettő között nem egy egyszerű pipe van, hanem a terminal driver, ami valójában egy parser.

Az unbuffer és az általa fork-olt program (logikai) kapcsolata megegyezik az sshd és az általa forkolt shell kapcsolatával, valamint az xterm és az általa forkolt shell kapcsolatával.

Egy terminál sok olyan jellemzővel bír, amivel egy pipe nem, ld. SUSv1 XBD (C434), chap. 9 General Terminal Interface; man tcsetattr(), info libc pseudo-terminals. Ugyan a pseudoterminal master végén ülő program is eszik különféle vezérlőszekvenciákat (pl. xterm-ben szín megváltoztatása, ablak fejlécének beállítása), de a két vég között is történik értelmezés.

[code:1:0c42b188a2]head -c 4096 /dev/urandom >orig
cat orig | cat >copy
unbuffer cat orig | cat >surprise
cmp orig copy
cmp orig surprise[/code:1:0c42b188a2]

Másik példa (pongyolán, és igazából csak feltételezés :)): ha nyomsz egy ^C-t (helyesebben azt, ami a terminálnak éppen a kurrens INTR karaktere), akkor a terminal driver a foreground process group-nak küld egy SIGINT-et (= mindegyik benne lévő processznek egyszerre). Egy pszeudoterminálon ugyanezt éri el az ember (feltételezek :)), ha az INTR-nek megfelelő karaktert beleírja a master végbe (ld. ISIG flag): az a foreground process group, amelyiknek a controlling terminal-ja a slave vég, kap egy SIGINT-et. (Konkrétan (feltételezve :), és "sok minden" függvényében): ha az unbuffer a saját stdin-jéről átpasszol egy INTR karaktert az általa indított programnak, akkor a terminal driver küld az utóbbinak egy SIGINT-et.)

Magyarul csak akkor használd, ha a közlekedő karakterek biztosan nem vezérlik a terminal drivert. Őszintén szólva nem tudom pontosan meghatározni, hogy e halmaz mitől függ és mi a legtágabb ilyen halmaz; azonban elképzelhető, hogy az iconv-nak vagy a bemenetén, vagy a kimenetén lesz valami nehezen emészthető (UTF-8 valamelyik charset-ed, nem?, már nem emlékszem).

IMHO, de aki jobban tudja, kérem ossza meg velem. (Lusta vagyok a fenti próbában a random bob helyére érvényes UTF-8 szöveget tenni.)

Ez így még jól működik (10 pipe):
[code:1:14790320a8]echo "Felolvasas"; (echo "\`"$'\n'; \
(if [ -n "$1" ]; then cat "$1" ; else dcop klipper klipper getClipboardHistoryItem 0 ; fi) \
| sajat_filter \
| awk -f $szamszuro) \
| iconv -c -f utf8 -t iso8859-2 \
| sed -e 's/\-/ \@aaaa/g' -e 's/\?/ \@aaab/g' -e 's/\./ \@aaac/g' -e 's/\,/ \@aaad/g'\
| ispell -a -d hungarian \
| grep -v -E "^$" | grep -v -E "^@" \
| iconv -c -f iso8859-2 -t utf8 \
| awk 'BEGIN {parancs = "xargs -i\"[]\" egrep -m 1 -i ^\"[]\" /h*/s*/D*/c*n/hunglish.utf8.txt"} \
$1~/^[*+-]$/ {print $2} $1~/^[#&]$/ { print $2 |& parancs; close(parancs, "to"); \
if ((parancs |& getline eredmeny) > 0) {print eredmeny ; close(parancs,"from") } \
else { close(parancs,"from"); valt=$2; \
sub("(nének|nével|néhez|nére|nétől|nén|nében|nétől|néék|nét|éknek\
|ban|ben|on|en|ön|ba|be|ra|re|ból|ből|nak|nek|tól|től|hoz|hez)$","",valt); \
if (valt==$2) {print $2;}else{rag=$2; sub(valt,"",rag); print valt |& parancs; close(parancs, "to"); \
if ((parancs |& getline eredmeny) > 0) \
{print eredmeny rag ;}else{print $2;} close(parancs,"from");}}}' \
| sed -e 's/.* //' -e 's/aaaa/\-/g' -e 's/aaab/\?/g' -e 's/aaac/\./g' -e 's/aaad/\,/g'[/code:1:14790320a8]
De: ha csak egy "cat"-ot is hozzáírok, vagy csak az utolsó sed parancsot kettébontom, hogy 11 pipe legyen, már elő is jön a probléma.
Most megnéztem még nagyobb bemeneti adatállománnyal úgy látom, mintha valami bufferelés lépne be: az adatok ár nem szép lassan, folyamatosan csordogálnak ki a pipe-ból mint egyébként, hanem adagokban.

RLIMIT_NPROC (processzek max. száma) talán, lásd setrlimit(2).

Ezt hogyan tudom lekérdezni/állítgatni szkriptből?

inkább: man 1 bash, ott pedig: ulimit...

ulimit -a eredménye (kihagyva azt ami unlimited):
[code:1:14790320a8]core file size (blocks, -c) 0
max locked memory (kbytes, -l) 32
open files (-n) 1024
pipe size (512 bytes, -p) 8
max user processes (-u) 2047
[/code:1:14790320a8]
A fentiek közül melyik korlátozhatja 10-ben a pipe-ok számát?
Egyébként rémlik nekem, mintha valamikor régen olvastam volna egy ilyen 10-es korlát létezéséről, de most sehol sem találom a forrást, a google most nem hoz le semmi hasznosat nekem (egyelőre).

lehet, hogy nem ugyanarról az expect-ről beszélünk.

Biztosan. A SuSE 9.3-hoz csomagolt unbuffernek van -p kapcsolója, amit akkor ajánl használni, ha egy egy pipe láncolat közepén használják az unbuffer-t.

Mindenesetre: minden pipeline-tag elé kiraktad az unbuffer-t (az utolsó kivételével)?

Nem. Először csak oda tettem, ahol már lassú a szkript, és ezért szükségesnek látszott; a legelső awk parancstól az utolsó előtti parancsig.
Ekkor a szkript működés helyett egy pillanat alatt kilépett. Ezután gyakorlatilag mindenféle kombinációban kipróbáltam, de olyan egy se volt, hogy a kimenet unbuffered-é vált volna.

azonban elképzelhető, hogy az iconv-nak vagy a bemenetén, vagy a kimenetén lesz valami nehezen emészthető (UTF-8 valamelyik charset-ed, nem?

Igen, utf-8-at használok.

Tulajdonképpen a probléma meg van oldva, mert az iconv jól működik az awk-ból hívva. Egy kicsit bonyolultabb és lassúbb lett tőle a szkript - de még abszolút elfogadható.

[quote:567f8a5760="lacos"]
Két ötletem van:

1. Rendezel. A sort azután kezd el beszélni, hogy EOF-ot olvasott.

Hat igen, ez eleg egyertelmu :)

[quote:567f8a5760="lacos"]
2. Stdio buffer-ek (man setvbuf). Az stdio stream-ek alapértelmezés szerint így puffereltek: (a) ha a stream az stderr, akkor nem fully buffered, (b) ha a stream stdin v. stdout (kieg.: v. bármi, ld. fopen()) és biztos, hogy nem terminal device-ra vonatkozik (kb. errno = 0, !isatty(fileno(stream)) && !errno), akkor fully buffered.

Sok (a legtöbb?) program nem piszkálja a pufferelést, hanem a default-ot használja. Ezért pl. ha grep-et indítasz simán a terminálon, akkor minden találat azonnal meg fog jelenni (mert az stdout-ja terminálra vonatkozik, és ezért minimum line buffered). Ha ugyanezt a grep-et pipeline-ba szervezed, akkor a kimenete a default stdio buffer size (BUFSIZ v. "fstat(fileno(stream)).st_blksize", pl. 4K) méretű blokkokban fog megjelenni. Pl. 10 db ilyen grep összesen 40K-t tud felhalmozni.

Hmmm... szerintem a lancban levo progik buffereinek a maximuma halmozodhat fel.

[quote:567f8a5760="lacos"]
10 db cat azért nem fog (nem próbáltam ki, tehát inkább azt mondom, hogy "ha nem fog, akkor azért nem fog") ilyesmit csinálni, mert (a) kézzel átállítja a pufferelést,

nope...
[quote:567f8a5760="lacos"](b) minden írás után fflush()-t hív,

nope...
[quote:567f8a5760="lacos"](c) nem használ stdio-t, hanem csak unistd syscall-okat (read/write).

bingo! :D