Если я просто запустил read, он читает одну строку и сразу же выходит, когда нажата клавиша Enter.
$ read
typing something here
$
Однако, когда я передаю вход через трубку, например, из cat, read ведет себя по-другому и продолжает работать до тех пор, пока не встретит вторую строку новой строки:
$ cat | read
typing first line
typing second line
$
Может кто-нибудь объяснить, почему это так?
PS: Этот вопрос был вдохновлен тем, как подавать стандартный ввод и выгружать в файл одновременно?
Это не имеет ничего общего с новой строкой.
Если вы запустите свою команду с помощью 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(), однако если вы запустите его несколько раз, вы увидите как минимум два вызова и никогда не один.
Это не имеет ничего общего с новой строкой.
Если вы запустите свою команду с помощью 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(), однако если вы запустите его несколько раз, вы увидите как минимум два вызова и никогда не один.