& Ldquo; & Rdquo чтения; команда ожидает дополнительной новой строки, если вход поступает через канал

Если я просто запустил read, он читает одну строку и сразу же выходит, когда нажата клавиша Enter.

$ read typing something here $

Однако, когда я передаю вход через трубку, например, из cat, read ведет себя по-другому и продолжает работать до тех пор, пока не встретит вторую строку новой строки:

$ cat | read typing first line typing second line $

Может кто-нибудь объяснить, почему это так?

PS: Этот вопрос был вдохновлен тем, как подавать стандартный ввод и выгружать в файл одновременно?

3
задан 2 September 2017 в 12:30

2 ответа

Это не имеет ничего общего с новой строкой.

Если вы запустите свою команду с помощью strace, вы обнаружите, что cat получит SIGPIPE в конце , перед закрытием:

$ strace cat | read ... someOutput ... +++ killed by SIGPIPE +++ Команда cat запускается. Затем вы вводите что-то в первый раз и нажимаете Enter. То, что вы набрали, будет отправлено на канал read. cat все еще работает и ждет EOF. Вы вводите что-то еще, а затем нажмите Enter agian. На этот раз его нельзя передать на read, потому что нет read больше ожидающего ввода (он был закрыт после первого канала), если вы не запустили его следующим образом: cat | while read line; do echo $line; done; cat получит SIGPIPE и закрывается. Процесс получает SIGPIPE, когда он пытается записать в канал (с именем или нет) или сокет типа SOCK_STREAM, у которого нет читателя. [1]

Прием SIGPIPE происходит после того, как произойдет вторая труба.

Например, рассмотрим команду yes, потому что команда типа yes передает что-то быстро и многократно: ! d18] yes | read

он закрывается сразу после второго канала, обратите внимание на два вызова write():

close(3) = 0 write(1, "y\ny\ny\ny\ny\ny\ny\ny\ny\n"..., 8192) = 8192 write(1, "y\ny\ny\ny\ny\ny\ny\ny\ny\n"..., 8192) = -1 EPIPE (Broken pipe) --- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=3542, si_uid=1000} --- +++ killed by SIGPIPE +++

Хотя, поскольку команда yes выполняется слишком быстро, вы можете см. более двух вызовов write(), однако если вы запустите его несколько раз, вы увидите как минимум два вызова и никогда не один.

2
ответ дан 18 July 2018 в 07:33

Это не имеет ничего общего с новой строкой.

Если вы запустите свою команду с помощью strace, вы обнаружите, что cat получит SIGPIPE в конце , перед закрытием:

$ strace cat | read ... someOutput ... +++ killed by SIGPIPE +++ Команда cat запускается. Затем вы вводите что-то в первый раз и нажимаете Enter. То, что вы набрали, будет отправлено на канал read. cat все еще работает и ждет EOF. Вы вводите что-то еще, а затем нажмите Enter agian. На этот раз его нельзя передать на read, потому что нет read больше ожидающего ввода (он был закрыт после первого канала), если вы не запустили его следующим образом: cat | while read line; do echo $line; done; cat получит SIGPIPE и закрывается. Процесс получает SIGPIPE, когда он пытается записать в канал (с именем или нет) или сокет типа SOCK_STREAM, у которого нет читателя. [1]

Прием SIGPIPE происходит после того, как произойдет вторая труба.

Например, рассмотрим команду yes, потому что команда типа yes передает что-то быстро и многократно: ! d18] yes | read

он закрывается сразу после второго канала, обратите внимание на два вызова write():

close(3) = 0 write(1, "y\ny\ny\ny\ny\ny\ny\ny\ny\n"..., 8192) = 8192 write(1, "y\ny\ny\ny\ny\ny\ny\ny\ny\n"..., 8192) = -1 EPIPE (Broken pipe) --- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=3542, si_uid=1000} --- +++ killed by SIGPIPE +++

Хотя, поскольку команда yes выполняется слишком быстро, вы можете см. более двух вызовов write(), однако если вы запустите его несколько раз, вы увидите как минимум два вызова и никогда не один.

2
ответ дан 24 July 2018 в 18:49
  • 1
    Поэтому, если я правильно вас понимаю, это имеет какое-то отношение к буферизации строк, т. Е. [F1] пытается отправить целые строки через канал, как только нажата клавиша ENTER. read завершает работу после первой строки, но cat уведомляет только о том, что когда он пытается использовать трубу снова, не раньше? – Byte Commander 2 September 2017 в 12:33
  • 2
    Да, во второй раз, когда он пытается подключить вторую строку, он получает SIGPIPE и закрывается. – Ravexina 2 September 2017 в 12:36
  • 3
    Uhm ... но я только узнал, что cat на самом деле не зациклирован на линии вообще: superuser.com/a/896684/418736 - теперь я смущен. – Byte Commander 2 September 2017 в 12:45
  • 4
    Вы пытались запустить strace cat | read? Или запустить strace cat и отправить SIGPIPE (kill -13) в свой PID? Я не уверен в буферизации, но из проверки выходов strace, вот как это работает. – Ravexina 2 September 2017 в 12:59
  • 5
    Я пробовал это, а также думаю, что это выглядит как некая буферизация строк, но, видимо, cat не должен этого делать. Я не знаю. – Byte Commander 2 September 2017 в 13:12

Другие вопросы по тегам:

Похожие вопросы: