当我退出时,后台进程stdout和stderr会发生什么?

时间:2014-08-19 17:28:35

标签: linux bash ssh

我试图了解退出SSH会话时stdout和stderr后台进程会发生什么。我了解SIGHUP,子进程等等,但我对以下内容感到困惑:

如果我跑: (虽然是真的;做日期;睡0.5;完成)| tee foo |猫>吧 然后杀死cat进程然后tee进程终止,因为它不能再写入管道。您可以使用ps观察此事。

但如果我跑: (虽然是真的;做日期;睡0.5;完成)| tee foo&认 并且退出我的SSH会话,我可以观察到一切都继续正常运行"永远"。所以,不管怎么说,发球过程的标准必须“继续”#34;即使我的朋友必须离开。

有人可以解释第二个例子中会发生什么吗?

(是的,我知道我可以显式重定向后台进程的stdout / stderr / stdin。)

1 个答案:

答案 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,但它仍在运行。