我试图了解退出SSH会话时stdout和stderr后台进程会发生什么。我了解SIGHUP,子进程等等,但我对以下内容感到困惑:
如果我跑: (虽然是真的;做日期;睡0.5;完成)| tee foo |猫>吧 然后杀死cat进程然后tee进程终止,因为它不能再写入管道。您可以使用ps观察此事。
但如果我跑: (虽然是真的;做日期;睡0.5;完成)| tee foo&认 并且退出我的SSH会话,我可以观察到一切都继续正常运行"永远"。所以,不管怎么说,发球过程的标准必须“继续”#34;即使我的朋友必须离开。
有人可以解释第二个例子中会发生什么吗?
(是的,我知道我可以显式重定向后台进程的stdout / stderr / stdin。)
答案 0 :(得分:1)
这是tee
将输出发送到stdout和打开文件的关键循环:
while (1)
{
bytes_read = read (0, buffer, sizeof buffer);
if (bytes_read < 0 && errno == EINTR)
continue;
if (bytes_read <= 0)
break;
/* Write to all NFILES + 1 descriptors.
Standard output is the first one. */
for (i = 0; i <= nfiles; i++)
if (descriptors[i]
&& fwrite (buffer, bytes_read, 1, descriptors[i]) != 1)
{
error (0, errno, "%s", files[i]);
descriptors[i] = NULL;
ok = false;
}
}
密切关注这一部分:
if (descriptors[i]
&& fwrite (buffer, bytes_read, 1, descriptors[i]) != 1)
{
error (0, errno, "%s", files[i]);
descriptors[i] = NULL;
ok = false;
}
它表明发生错误时,tee
不会自行关闭,只是取消设置文件描述符descriptors[i] = NULL
并继续读取数据,直到EOF
或输入错误除{ {1}}。
EINTR
命令或任何将输出发送到连接到date
的管道的命令都不会终止,因为tee
仍然会读取其数据。只有数据不会出现在文件tee
之外的任何地方。即使没有提供文件参数,foo
仍会读取其数据。
这是tee
在与终端断开连接时/proc/**/fd
的样子:
tee
这一个来自连接到它的管道的过程:
0 -> pipe:[431978]
1 -> /dev/pts/2 (deleted)
2 -> /dev/pts/2 (deleted)
您可以看到0 -> /dev/pts/2 (deleted)
1 -> pipe:[431978]
2 -> /dev/pts/2 (deleted)
的{{1}}和tee
已经是EOL,但它仍在运行。