grep: writing output: Broken pipe

Rynor

stay hungry
grep: writing output: Broken pipe

Уважаемые! Не уверен, связано ли это с программированием на PHP, но сабж лезет при использовании popen для парсинга лога, так что звиняйте :)

Запрос через popen делается типа такого: cat file.log | grep -E '\|[0-9]*\|(1|2|...|N)\|'
Файл парсится в полтора гига.
Длина строк - до кило.

PHP:
if ($fp = popen($cmd, 'r')){
   while(!feof($fp)) {
      $s = trim(fgets($fp));
//здесь всяко-разно
   }
}
pclose($fp);
Если вы сталкивались с такой проблемой и знаете, как её побороть, прошу помочь.
Интересует также не особо тормозные альтернативы, пока что вижу чтение через fopen - fgets и разбор самим PHP, но вроде как это сильно тормозно.

Заранее спасибо за помошь.

ps PHP 5.0.4/ALT (cli)

-~{}~ 30.05.06 15:16:

Альтернатива в виде fopen получилась никакой, попробовал, хотя ясно, что полтора гига файла файл будет фигачиться в память, что даёт:
PHP Fatal error: Allowed memory size of 52428800 bytes exhausted (tried to allocate 1025 bytes) in ...

-~{}~ 30.05.06 16:25:

Разобрался откуда проблема - оказывается, popen жрёт память так же, как и fopen.... низачот.
[30.05.2006 16:16:09] getMemoryUsage(): 52.427.128 bytes
Когда натыкается на предел памяти, разумеется, начинает болеть.

Как бы мне это обойти?
 

zarus

Хитрожопый макак
Считывать и обрабатывать файл кусками не пробовали?
 

Rynor

stay hungry
Это на крайняк. Сдаётся мне, туплю где-то я.
popen не должен так забивать память... нелогично это... равно как и fopen. То есть они читают файл как раз кусками.

Проверил тестовым скриптом - popen() и его дальнейший функционал точно не жрёт память, как она была вначале:
getMemoryUsage(): 193.312 bytes
так и осталась после отработки 100000 строк из файла
getMemoryUsage(): 196.152 bytes

В общем, пошел искать тёмный лик утечки в коде %/
 

whirlwind

TDD infected, paranoid
Rynor Уверены что вам здесь PHP пайпы делает?
+ Не проще ли

PHP:
grep -E '\|[0-9]*\|(1|2|...|N)\|' file.log | myphpparser.php
???

-~{}~ 30.05.06 17:38:

PS. если будете продолжать через popen, будет нелишним глянуть [m]escapeshellcmd[/m]
 

Rynor

stay hungry
по поводу пайпа - без понятий
спасибо за хинт, по поводу проще - надо попробовать, но...
меня устраивает текущий функционал, кроме одного описанного выше момента
дело в том, что это один из многих аналогичных скриптов
и до этого у меня особых проблем с ними не было, хотя пару раз уже натыкался на данные грабли
вот на третий терпение лопнуло :)

escapeshellcmd в данном случае излишне, но буду иметь введу :)

-~{}~ 30.05.06 18:13:

Нашёл, что жрёт память, моя функция отладки %/

PHP:
function e_($v, $flag = '') {

	if (empty($flag)) {

		if (defined('ECHO2CON') && ECHO2CON) {echo $v . "\n";}
		if (defined('ECHO2LOG') && ECHO2LOG) {return trigger_error($v);}

	}else{
		if ($flag & EF_ECHO) {echo $v . "\n";}
		if ($flag & EF_LOG) {return trigger_error($v);}
	}

	return true;
}
а точнее, жрёт, когда флаг подходит для записи через trigger_error... вот так открытие, у меня эта функция повсеместно заюзана :(
 

whirlwind

TDD infected, paranoid
...Вообще странный конечно подход... Зачем идти "искать тёмный лик утечки в коде %/", вместо того, что бы добавить пару строк в существующий код. Всего то надо: открыть непосредственно лог, прочитать строку, проверить ее preg_match-ем на указанный РЕ (или сразу отпарсить), сделать то, что нужно.
 

Rynor

stay hungry
а я что делаю? :)
у меня скрипт работает как в режиме popen, так и в режиме fopen, как вашей душе угодно. просто кроме собственно "открыть-прочитать-проверить-etc" существуют вкрапления логирования/отладки, иногда очень интенсивные.
вот это вркапление по имени e_ меня счас и тюкает по башке... по 100-300 байт отъедает за проход, а там их 5М...
а профайлить учиться надо, конечно, не парился с памятью ищё никогда особо
 

whirlwind

TDD infected, paranoid
Ну не совсем удачно отцитировал. Я имел в виду, что алгоритм не очень удачный, а не то что баги искать не надо :)
 

Rynor

stay hungry
Алгоритм в порядке.
И trigger_error в порядке.
Как я убедился за свои несколько лет программинга - самые подлые ошибки - это опечатки и невнимательность.
У меня в devel классе отладки висела строчка, генерящая в память массивом все записи, проходящие через trigger_error.
Она-то память и забивала.
Тьфу, полдня убил.
Но хоть отрефакторил уйму кода - и то хлеб %)
Пошёл учить профайлинг.
whirlwind, благодарю за помощь, спасибо!
 
Сверху