我可以使用多少管道是否有限制?

时间:2015-12-27 01:50:30

标签: linux macos bash shell command-line

所以我之前问了一个问题,为ping添加了一个前缀。 (我的最后一个问题)给我留下了以下一行:

ping 8.8.8.8 |  while read line; do echo "$(date): $line"; done | grep time=

这很有效。我只有一个问题,我无法将其保存在文件中。我尝试了一下这样简单的重定向:

ping 8.8.8.8 |  while read line; do echo "$(date): $line"; done | grep time= >> googleping

但没有任何内容保存在文件中......

然后我尝试了这个:

ping 8.8.8.8 |  while read line; do echo "$(date): $line"; done | grep time= | tee -a googleping

用tee将其打印在屏幕上并将其保存在文件中......再次没有运气。

(但尝试过echo hello | tee -a googleping并且效果很好......)

然后我尝试了另一个while循环:

ping 8.8.8.8 |  while read line; do echo "$(date): $line"; done | grep time= | while read line; do echo $line; echo $line >> googleping; done

再没有运气......

那么一条线可以有多少管道和重定向?如果是这样的话,当我无法访问谷歌时,我仍然可以实现我的记录目标(我只是使用grep time=测试它以获得附加输出并使用grep -v time=来获取所有行无论错误如何,都没有时间在其中。)

所以要补充的是,最后我想在mac终端中进行,但我在ubuntu服务器和mac上尝试过,并且都不能使用上述任何方法。

我希望有人可以帮助我!

2 个答案:

答案 0 :(得分:9)

answer by hek2mgl解释了您的特定问题与管道数无关。

但要回答你标题中的问题(“我可以使用多少管道有限制吗?”),是 opened file descriptors < / strong>,但在目前的系统中,它在实践中非常大(数千)。 AFAIU,POSIX保证限制(可能只有20)。您的系统可能每个进程都有一个文件描述符限制,另一个文件描述符限制系统范围......

要设置或查询每个进程的文件描述符限制,您可以将setrlimit(2)a@a:~$ rails -v Rails 4.2.5 a@a:~$ ruby -v ruby 2.2.4p230 (2015-12-16 revision 53155) [x86_64-linux] a@a:~$ sudo mysql -v [sudo] password for a: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 39 Server version: 5.5.46-0ubuntu0.14.04.2 (Ubuntu) getrlimitRLIMIT_NOFILE内置ulimit一起使用,或者在您的交互式shell中bash内置limit。您还可以在Linux上阅读zsh(有关/proc/self/limits伪文件的更多信息,请参阅proc(5))。在我的Linux Debian系统上,每个进程有65536个最大文件描述符。

IIRC,/proc/给出了打开的文件描述符的最大数量。在我的系统上,现在是1632058。

当您达到文件描述符限制时,pipe(2)系统调用(例如,您的pipelines open(2)/proc/sys/fs/file-max的shell完成)将失败:

  

|该过程正在使用太多文件描述符。

     

EMFILE已打开文件总数的系统限制                 达到。

disk quota也可能因pipe(7)多余而失败...

  

ENFILE如果指定了EDQUOT,则该文件不存在,并且                 用户对文件系统的磁盘块或inode的配额有                 已经筋疲力尽。

另见Advanced Linux Programming并阅读fflush(3);当用C编程时,你应该适当而明智地使用org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator

答案 1 :(得分:2)

这与您使用的管道数量无关。由于输出缓冲,您不会立即看到tee的输出。当grep的输出转到管道而不是终端时,它会被块缓冲。如果你有足够的耐心,输出会在一段时间后出现(一旦缓冲区被刷新)。

此行为在libc中实现,除非程序显式处理它自己的缓冲。您可以使用stdbuf命令来影响此行为:

ping 8.8.8.8 \
  |  while read line; do echo "$(date): $line"; done \
  | stdbuf -o0 grep time= \
  | tee -a googleping

我正在使用grep调用stdbuf -o0,它将grep的输出缓冲区大小缩小为零长度。或者,您可以使用-oL生成行缓冲输出。

旁注:stdbuf适用于您的示例。但是,如果您仔细阅读stdbuf的手册页,您会注意到:

  

注意:如果COMMAND调整其标准流的缓冲('tee'确实如此          例如,然后它将覆盖由'std-更改的相应设置          BUF”。还有一些过滤器(如'dd'和'cat'等)不使用流          I / O,因此不受'stdbuf'设置的影响。

这就是我上面所说的。 stdbuf仅适用于不能自行处理缓冲的程序。 tee就是这样一个程序。这意味着如果您从发球台进一步管道,则无法使用stdbuf