Попробуйте head
команду:
HEAD(1) User Commands HEAD(1)
NAME
head - output the first part of files
SYNOPSIS
head [OPTION]... [FILE]...
DESCRIPTION
Print the first 10 lines of each FILE to standard output. With more
than one FILE, precede each with a header giving the file name. With
no FILE, or when FILE is -, read standard input.
head
позволяет указать количество строк. Обратитесь к странице руководства для получения дополнительной информации.
loop.py
:
#!/usr/bin/python`
i = 0
while True:
print "This is line " + str(i)
i += 1
loop.py
должен работать бесконечно, но если я передам его вывод head
, я получу:
$ ./loop.py | head
This is line 0
This is line 1
This is line 2
This is line 3
This is line 4
This is line 5
This is line 6
This is line 7
This is line 8
This is line 9
Traceback (most recent call last):
File "./loop.py", line 6, in <module>
print "This is line " + str(i)
IOError: [Errno 32] Broken pipe
Обратите внимание, что Traceback ...
часть error ( ) на самом деле stderr
, как демонстрирует выполнение ./loop.py 2> stderr.log | head
, поэтому вам не нужно беспокоиться о том, чтобы очистить вывод head.
Наконец, для поиска:
$ ./loop.py 2> /dev/null | head | grep -n "line 6"
7:This is line 6
Здесь, я перенаправлен stderr
из loop.py
вне пути , даже если мы уверены , что не будет вмешиваться в тексте обрабатывается head
иgrep
РЕДАКТИРОВАТЬ
TL; DR : Планировщик ЦП контролирует, насколько интенсивный процесс будет выполняться после head
завершения вывода.
После некоторого тестирования я обнаружил, что мое решение, хотя оно и снижает производительность loop.py
, не настолько надежно, как это можно сделать. С этими модификациями к my loop.py
, конвейерный вывод в head дает:
новыйloop.py
:
#!/usr/bin/env python
import sys
def doSomethingIntensive():
# actually do something intensive here
# that doesn't print to stdout
pass
i = 0
while True:
# printing to stderr so output is not piped
print >> sys.stderr, (
"Starting some calculation that "
"doesn't print to stdout")
doSomethingIntensive()
print >> sys.stderr, "About to print line " + str(i)
print "This is line " + str(i)
print >> sys.stderr, "Finished printing line " + str(i)
i += 1
и вывод:
$ ./loop.py | head
Starting some calculation that doesn't print to stdout
About to print line 0
Finished printing line 0
Starting some calculation that doesn't print to stdout
About to print line 1
Finished printing line 1
Starting some calculation that doesn't print to stdout
About to print line 2
Finished printing line 2
...
About to print line 247
Finished printing line 247This is line 0
This is line 1
This is line 2
This is line 3
This is line 4
This is line 5
This is line 6
This is line 7
This is line 8
This is line 9
Starting some calculation that doesn't print to stdout
About to print line 248
Finished printing line 248
...
About to print line 487
Finished printing line 487
Starting some calculation that doesn't print to stdout
About to print line 488
Traceback (most recent call last):
File "./loop.py", line 18, in <module>
print "This is line " + str(i)
IOError: [Errno 32] Broken pipe
Я скрыл некоторые результаты и оставил только соответствующие части. По сути, выходные данные показывают, что head
стандартные потоки ввода / вывода (и, я полагаю, все процессы) буферизируются.
Согласно этому ответу на SO , когда приемник ( head
) завершается, канал прерывается, и * только когда отправитель ( loop.py
) пытается выполнить запись в теперь разорванный канал *, сигнал SIGPIPE будет отправляться на него.
Поэтому, когда head
появилась возможность напечатать свой вывод, все это обнаружилось сразу, но только после того, как loop.py
продолжилось еще 247 строк. (Это связано с планированием процессов.) Более того, после того, как head
он напечатал свой вывод, но до его завершения, планировщик возобновил работу loop.py
, поэтому еще 250 строк (до 488) были записаны в канал, прежде чем канал был разорван.
Для лучших результатов мы можем использовать небуферизованный ввод / вывод (в этом случае небуферизованный вывод loop.py
). Вызывая интерпретатор python с -u
опцией, мы получаем:
$ python -u loop.py | head
Starting some calculation that doesn't print to stdout
About to print line 0
Finished printing line 0This is line 0
Starting some calculation that doesn't print to stdout
About to print line 1
Finished printing line 1This is line 1
Starting some calculation that doesn't print to stdout
About to print line 2
Finished printing line 2This is line 2
Starting some calculation that doesn't print to stdout
About to print line 3
Finished printing line 3This is line 3
Starting some calculation that doesn't print to stdout
About to print line 4
Finished printing line 4This is line 4
Starting some calculation that doesn't print to stdout
About to print line 5
Finished printing line 5This is line 5
Starting some calculation that doesn't print to stdout
About to print line 6
Finished printing line 6This is line 6
Starting some calculation that doesn't print to stdout
About to print line 7
Finished printing line 7This is line 7
Starting some calculation that doesn't print to stdout
About to print line 8
Finished printing line 8This is line 8
Starting some calculation that doesn't print to stdout
About to print line 9
Finished printing line 9
This is line 9
Starting some calculation that doesn't print to stdout
About to print line 10
Traceback (most recent call last):
File "loop.py", line 18, in <module>
print "This is line " + str(i)
IOError: [Errno 32] Broken pipe
Конечно, это просто, если ваша программа написана на python, так как вам не нужно вносить изменения в код. Однако, если он находится в C, и у вас есть источник для него, вы можете использовать функцию setvbuf()
в, stdio.h
чтобы установить в stdout
качестве небуферизованного:
loop.c
:
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
unsigned long factorial(int n)
{
return (n == 0) ? 1 : n * factorial(n - 1);
}
void doSomethingIntensive(int n)
{
fprintf(stderr, "%4d: %18ld\n", n, factorial(n));
}
int main()
{
int i;
if (!setvbuf(stdout, NULL, _IONBF, 0)) /* the important line */
fprintf(stderr, "Error setting buffer size.\n");
for(i=0; TRUE; i++)
{
doSomethingIntensive(i);
printf("This is line %d\n", i);
}
return 0;
}