2014-01-07 10 views
1

Я пытаюсь использовать coproc, и я сталкиваюсь с трудностями, скорее всего, с буферизацией. У меня есть сложная команда, которая принимает линейно ориентированный ввод из stdin и печатает строку в stdout на строку ввода. В командной строке эта команда работает нормально на основе строки, но когда я помещаю ее в coproc и считываю из ${COPROC[0]} FD, считываемые блоки.Линия буферизации в bash coproc

Я могу воссоздать это поведение с paste, но не с cat. Я ожидаю, что paste и cat в значительной степени сделают то же самое, когда не будут переданы никакие параметры. Это тот случай, когда работает непосредственно в командной строке:

$ cat 
Hello World!<RETURN> 
Hello World!^D 
$ paste 
Hello World!<RETURN> 
Hello World!^D 
$ 

(RETURN и ^D добавлены для иллюстрации)

Но когда я положил их в , они ведут себя по-разному - cat строго линию буферизации , в то время как paste, кажется, работает с гораздо большим буфером:

$ coproc cat 
$ echo 'Hello world!' >&${COPROC[1]} 
$ read -ru ${COPROC[0]} line; echo $line 
Hello world! 
$ kill $COPROC_PID 
[3]+ Terminated    coproc COPROC cat 
$ 
$ coproc paste 
[3] 42657 
$ echo 'Hello world!' >&${COPROC[1]} 
$ read -ru ${COPROC[0]} line; echo $line 
#### read blocks here until ^C#### 

Я думаю, что причина этого заключается в том, что paste объявление только в режиме буферизации, в зависимости от того, с чем он подключен, тогда как cat всегда находится в режиме буферизации линии.

Есть ли способ заставить paste (или другую общую команду) быть буферизированной в копий?


После того, как немного больше экспериментов я обнаружил, что может воссоздать подобное поведение без с и вместо этого просто трубопровода между cat и paste:

$ cat | cat 
Hello World!<RETURN> 
Hello World!^D 
$ cat | paste 
Hello World!<RETURN> 
Hello World!^D 
$ paste | cat 
Hello World!<RETURN> 
#### command blocks here until ^C#### 

(RETURN и ^D добавлены для иллюстрации)

  • Сначала мы прокладываем cat по cat и g и др линии буферизация всего пути, хотя
  • Далее мы труба cat к paste, а также получить линии буферной всего путь, хотя
  • Наконец мы труба paste к cat и не получить линии буферизации

Это, как представляется, указывают, что paste будет транслировать буфер в своем стандартном режиме в интерактивном режиме, но в противном случае он будет использовать гораздо больший буфер.

ответ

0

Один из способов, чтобы заставить линии буферизация использовать инструмент stdbuf Coreutils, если таковые имеются:

stdbuf позволяет изменять буферные операции трех стандартных потоков ввода/вывода, связанных с программой.

Для coproc случая:

$ coproc stdbuf -oL paste 
[3] 42751 
$ echo 'Hello world!' >&${COPROC[1]} 
$ read -ru ${COPROC[0]} line; echo $line 
Hello world! 
$ kill $COPROC_PID 
[3]+ Terminated    coproc COPROC stdbuf -oL paste 
$ 

Для простой трубы paste к cat случае:

$ stdbuf -oL paste | cat 
Hello World!<RETURN> 
Hello World!^D 
$