<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Alex Volkov &#187; Скрипты</title>
	<atom:link href="http://alexvolkov.ru/category/web/skripty/feed" rel="self" type="application/rss+xml" />
	<link>http://alexvolkov.ru</link>
	<description>cat /var/log/life.log &#124; grep -E &#34;life&#124;work&#124;etc&#34;</description>
	<lastBuildDate>Wed, 22 Feb 2012 17:00:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Профилирование и отладка PHP скриптов</title>
		<link>http://alexvolkov.ru/php-debugging-and-profiling.html</link>
		<comments>http://alexvolkov.ru/php-debugging-and-profiling.html#comments</comments>
		<pubDate>Thu, 09 Feb 2012 14:28:19 +0000</pubDate>
		<dc:creator>Alex Volkov</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Скрипты]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[profiling]]></category>
		<category><![CDATA[xdebug]]></category>

		<guid isPermaLink="false">http://alexvolkov.ru/?p=1998</guid>
		<description><![CDATA[Отладка скриптов вообще дело крайне нужное и полезное. Кроме основной задачи &#8212; поиска и удаления ошибок, отладка прямо улучшает качество и работоспособность программы в целом. Выловленные баги, исправленная логика &#8212; все это делает программу стабильнее в работе, что весьма желанная цель при ее написании. Все ниженаписанное основывается на моем опыте, так что воспринимайте это как [...]]]></description>
			<content:encoded><![CDATA[<p>Отладка скриптов вообще дело крайне нужное и полезное. Кроме основной задачи &#8212; поиска и удаления ошибок, отладка прямо улучшает качество и работоспособность программы в целом. Выловленные баги, исправленная логика &#8212; все это делает программу стабильнее в работе, что весьма желанная цель при ее написании. Все ниженаписанное основывается на моем опыте, так что воспринимайте это как мое имхо ))</p>
<p><em>Если жмакнуть одну из этих кнопочек, то увидеть скрытый контент!</em></p>
<p><a href="http://twitter.com/share"  class="twitter-share-button" data-counturl="http://alexvolkov.ru/php-debugging-and-profiling.html"  data-url="http://alexvolkov.ru/php-debugging-and-profiling.html"  data-count="horizontal" >Tweet</a> <span style="display:inline-block; width:100px;"></span> <g:plusone callback="display_like_content" href="http://alexvolkov.ru/php-debugging-and-profiling.html"></g:plusone><div id='google_after_like' style='display:none;clear:both;width:100%;;'>Тут особо ничего интересного нет, я просто хотел потестить один плуг для вп, который обещает huge traffic waves.

Так что сорри за облом ожиданий и спасибо кнопку! :))</div><span id="more-1998"></span></p>
<p>Итак, какие бывают ошибки и как их можно отловить.</p>
<p>1. Самые простые и самые распространённые &#8212; это ошибки, связанные с чудным свойством php &#8212; динамической типизацией. Помимо того, что иногда просто упускаешь из виду, что там и в каком формате у тебя хранится, php сам подкидывает сюрпризы вида true при сравнении &#171;qwerty&#187; == 0 и другие чудеса автоматического приведения типов и подобные им брейнфаки.</p>
<p>Если точно известно место, где переменная перестает себя вести, как от нее ожидают, то я особо не мудрствую и ставлю var_dump(переменная). Если догадка подтверждается, то исправляем косяк и идем дальше.</p>
<p>Но не всегда получается определить точное место расхождения значения с ожидаемым. Расхождение это может быть зарыто глубоко в дебри кода, либо наоборот, находится на самом видном месте.</p>
<p>Так же бывает, что переменная меняет значение из-за нарушенной логики приложения. Например, присвоение идет внутри локальной видимости вложенной функции или неверно построенного цикла. Наружу передается не тот результат, который ждешь, хотя с виду все правильно. Просто не там открыл или закрыл скобку и все изменяется причудливым образом.</p>
<p>Такую красоту довольно трудно отловить руками, особенно в крупных приложениях. Поэтому лучше воспользоваться дебаггером. Во всяких умных книжках довольно часто пишут про <a href="http://pecl.php.net/package/apd">APD</a>, хвалят его, но дата его последнего релиза за 2004 год как-то меня настораживает. В багтрекере пишут, что под 5.3 не хочет он работать, у меня из груши не встал, поэтому я забил на него.</p>
<p>Трассировку скрипта можно сделать xdebug&#8217;ом. Он часто бывает установлен, но как модуль PHP, а для нормальной работы нужно, чтобы он стоял как Zend module.  По установке все итак расписано в нете, не буду повторяться.</p>
<p>Xdebug генерирует отчет, который показвает последовательно, кто, куда, зачем обратился. Есть специальные парсилки логов, но мне удобнее читать сырые отчеты, потому как в консоли особо красоту не получишь, а через веб я не умею отлаживать. Выдается вот такая красота:</p>
<pre class="brush:plain">3	67	0	0.013521	394468	drXdebugTraceFileParser-&gt;parseLine	1		/home/alex/tmp/trace.php	123	1	$line = '2\t3\t1\t0.000772\t328656\n'
4	68	0	0.013588	394584	explode	0		/home/alex/tmp/trace.php	149	2	'\t'	'2\t3\t1\t0.000772\t328656\n'
4	68	1	0.013630	395376
4	69	0	0.013666	395348	count	0		/home/alex/tmp/trace.php	150	1	array (0 =&gt; '2', 1 =&gt; '3', 2 =&gt; '1', 3 =&gt; '0.000772', 4 =&gt; '328656\n')
4	69	1	0.013716	395348
4	70	0	0.013757	395436	array_pop	0		/home/alex/tmp/trace.php	178	1	array (0 =&gt; '{main}', 1 =&gt; 'ini_set')
4	70	1	0.013800	395408
4	71	0	0.013823	395332	drXdebugTraceFileParser-&gt;addToFunction	1		/home/alex/tmp/trace.php	180	5	$function = 'ini_set'	$time = 4.3E-5	$memory = 236	$nestedTime = 0	$nestedMemory = 0
5	72	0	0.013900	395376	in_array	0		/home/alex/tmp/trace.php	194</pre>
<p>&nbsp;</p>
<p>Этого достаточно, чтобы проследить логику хода выполнения и отследить косяки. Забыл еще сказать, что xdebug можно подключать на лету. Обычно я выключаю и дебаггер и профайлер в php.ini, а в нужном скрипте просто включаю их вместе или по очереди через</p>
<pre class="brush:php">ini_set('xdebug.default_enable', 1);
ini_set('xdebug.profiler_enable', 1);</pre>
<p>Это быстро, не нужно никаких дополнительных телодвижений. Xdebug еще можно подключать на кучу разных IDE, даже вроде в денвере он есть.Таким нехитрым образом можно отловить большинство ошибок и невнимательностей в коде. Естественно, что изначально задуманную кривую логику так не исправить.</p>
<p>2. Второй тип ошибок гораздо сложнее отловить. Они также появляются вследствии зевков и невнимательностей, но проявляют себя не сразу, а по наступлению определенных условий. Например, время работы или количество итераций или появление определенного числа в арифметических операциях или наоборот, его непоявление.Еще ошибки могут возникать из-за изменений среды окружения, например форк апача завершил свою сессию и скинул скрипт или крон запускает что-то, что отъело всю память и скрипт просто не может запуститься.</p>
<p>Таких условий может быть множество, всех их обьеденяет одна черта &#8212; они не проявляются сразу при запуске, поэтому при анализе лога дебаггера ничего подозрительного выявить нельзя.</p>
<p>Тут приходит на помощь замечательная утилита &#8212; strace. Я одно время мучился с тем, что апач раз в 24 часа убивал свои потоки, а с ними и скрипты, из-под которых они были запущены. Так вот был настроен сервер. Нашли ошибку, когда подключились с другого терминала непосредственно к скрипту и слушали его через strace. Там и увидели, что скрипт ловит SIGTERM. <a href="http://alexvolkov.ru/examples-of-using-strace-to-debug-scripts.html">Как использовать strace</a> я уже писал. Позволяет исследовать реальную работу скрипта в реальном времени и видит все, что с ним происходит. Вывод можно перенаправить в файл и потом проанализировать. Еще есть схожая утилита, называет ptrace. Все они родные для nix систем. <a href="http://habrahabr.ru/blogs/php/129982/">Некоторые чуваки с хабры</a> используют для схожих целей сишный дебаггер. Кому в чем удобней&#8230;</p>
<p>3. Третий тип ошибок заключается в том, что память начинает резко утекать куда-то и нужно выяснить куда. Они также возникают из-за невнимательности или усталости и получаются чудеса типа файл инклюдится в бесконечном цикле или переменная набирает и набирает обьемиз-за того, что ее не обнулили предварительно.  Все это конечно можно отловить и через strace, но лучше использовать для этого профайлер xdebug&#8217;а.</p>
<p>Также этот способ следует использовать в целях профилактики, чтобы держать под контролем количество вызовов, открытий файлов и размеров переменных. Сам xdebug конечно не отдает все в удобноваримом виде, но под чтение его отчетов есть куча утилит. Я пользуюсь<a href="http://derickrethans.nl/xdebug-and-tracing-memory-usage.html"> этим скриптом</a>. Он выдает отчеты вида</p>
<pre class="brush:plain">function            #calls time memory time memory
------------------------------------------------------------
ini_set                  3 0.0002      584 0.0002      584
fix_string               1 0.0010      264 0.0009      184
xdebug_call_file         1 0.0001       48 0.0001       48
xdebug_call_function     1 0.0000       32 0.0000       32
var_dump                 1 0.0002        0 0.0002        0
xdebug_memory_usage      1 0.0000        0 0.0000        0
xdebug_call_line         1 0.0000        0 0.0000        0
{main}                   1 0.0018      480 0.0003     -368</pre>
<p>Здесь уже можно отследить и вызовы  и время. Запускаю его обычно в конце работы, чтобы посмотреть, не напортачил ли я чего в коде. Также использую его при оптимизации для оценки результатов</p>
<p>Вот такие нехитрые способы, надеюсь, помогут спасти время и нервы при отладке скриптов. Если есть у кого свои методики &#8212; велкам в коменты, буду рад услышать.</p>
<p>P.S. Если кто знает, как завести APD под 5.3, отпишитесь плз!</p>
<p>P.P.S <a href="https://www.progclub.org/blog/2012/01/10/profiling-a-php-script/">Тут вот чувак просто тру-самурай</a>, целый квест прошел чтобы найти ошибку. Шрифт жесть.</p>
<p>Там строку 967 в файле php_apd.c надо закоментить и все заработает.</p>
<p>И чтобы сделать читалку логов, надо скомпиленную pprofp скопировать в /usr/bin и создать ссылку на php в /usr/local/bin/</p>
<h2  class="related_post_title">На закуску.</h2><ul class="related_post"><li><a href="http://alexvolkov.ru/problems-with-the-serialization-of-arrays.html" title="Проблемы с сериализацией массивов">Проблемы с сериализацией массивов</a></li><li><a href="http://alexvolkov.ru/class-to-work-with-the-service-reduction-options.html" title="Класс для работы с сервисами сокращения ссылок">Класс для работы с сервисами сокращения ссылок</a></li><li><a href="http://alexvolkov.ru/a-simple-way-to-test-the-process-on-the-existence-of.html" title="Простой способ проверки процесса на существование">Простой способ проверки процесса на существование</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://alexvolkov.ru/php-debugging-and-profiling.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Вложенные SQL запросы: одновременное добавление одинарных и множественных строк в INSERT</title>
		<link>http://alexvolkov.ru/embedded-sql-statements-the-simultaneous-addition-of-single-and-multiple-rows-in-the-insert.html</link>
		<comments>http://alexvolkov.ru/embedded-sql-statements-the-simultaneous-addition-of-single-and-multiple-rows-in-the-insert.html#comments</comments>
		<pubDate>Tue, 04 Oct 2011 09:11:12 +0000</pubDate>
		<dc:creator>Alex Volkov</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Скрипты]]></category>
		<category><![CDATA[Mysql]]></category>
		<category><![CDATA[nested queries]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://alexvolkov.ru/?p=1892</guid>
		<description><![CDATA[Понадобилось для одной задачи сделать выборку из таблицы А по определенным условиям и вставить ее в таблицу B. Можно особо не заморачиваться, сделать SELECT  в переменную, потом пройтись циклом по INSERT и все. Но это не очень красивое решение. Очень запросов много + на переменные память расходуется. Проще использовать вложенные запросы, они же nested queries. [...]]]></description>
			<content:encoded><![CDATA[<p>Понадобилось для одной задачи сделать выборку из таблицы А по определенным условиям и вставить ее в таблицу B.<br />
Можно особо не заморачиваться, сделать SELECT  в переменную, потом пройтись циклом по INSERT и все.</p>
<p>Но это не очень красивое решение. Очень запросов много + на переменные память расходуется. Проще использовать вложенные запросы, они же nested queries. Но тут возникает проблемка -  если вставлять  только данные из INSERT, то все ок, но если добавлять еще и какие-нибудь неизменные значения, то выдается <em>Subquery returned more than 1 value.<br />
</em><br />
Чтобы не обьяснять на пальцах &#8212; сама таблица B</p>
<pre class="brush:sql">CREATE TEMPORARY TABLE `B` (
  `status` TINYINT(4) NULL DEFAULT NULL ,
  `pair` TEXT NULL DEFAULT NULL ,
)
ENGINE = MyISAM
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;</pre>
<p>Копируем из таблицы A и вставляем в B так</p>
<pre class="brush:sql">INSERT INTO `B` (`pair`)
            SELECT `pair` FROM `A` ORDER BY RAND() LIMIT 100;</pre>
<p>Если поле status имеет неизменное значение, например 123, то просто вот так уже не вставить</p>
<pre class="brush:sql">INSERT INTO `B` (`status`, `pair`) VALUES (
            (SELECT `pair` FROM `A` ORDER BY RAND() LIMIT 100),
            123);</pre>
<p>Не совсем красивое решение нашел</p>
<pre class="brush:sql">UPDATE `B` SET `status` = '123' WHERE 1=1;</pre>
<p>Но хотелось бы в одну строку все заделать. Отпишитесь плиз в коментах, кто знает, как реализовать.</p>
<h2  class="related_post_title">На закуску.</h2><ul class="related_post"><li><a href="http://alexvolkov.ru/the-script-for-tuning-mysql.html" title="Скрипт для тюнинга MYSQL">Скрипт для тюнинга MYSQL</a></li><li><a href="http://alexvolkov.ru/mysql-rand-how-to-get-a-random-line-from-db.html" title="MYSQL RAND(), как получить рандомную строку из БД">MYSQL RAND(), как получить рандомную строку из БД</a></li><li><a href="http://alexvolkov.ru/robkijj-tar.html" title="Робкий tar )">Робкий tar )</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://alexvolkov.ru/embedded-sql-statements-the-simultaneous-addition-of-single-and-multiple-rows-in-the-insert.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Класс для работы с сервисами сокращения ссылок</title>
		<link>http://alexvolkov.ru/class-to-work-with-the-service-reduction-options.html</link>
		<comments>http://alexvolkov.ru/class-to-work-with-the-service-reduction-options.html#comments</comments>
		<pubDate>Mon, 28 Mar 2011 13:32:33 +0000</pubDate>
		<dc:creator>Alex Volkov</dc:creator>
				<category><![CDATA[Скрипты]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://alexvolkov.ru/?p=1869</guid>
		<description><![CDATA[Небольшой класс, возвращает сокращенную ссылку. Можно обращаться как напрямую к конкретному сервису, так и выбранному рандомно через Shorteners-&#62;any(). Есть возможность указать прокси. Работает с bit.ly goo.gl is.gd tinyurl.com dlmn.org ndurl.com qr.cx gatorurl.com jmb.tw linkee.com mtny.mobi cli.gs &#60;?php error_reporting(1); class Shorteners { public $proxy = null; public function bitly($url) { $connectURL = 'http://api.bit.ly/v3/shorten?login=masstest&#38;apiKey=R_44403eb439622dd59ba2598255f30824&#38;uri=' . urlencode($url) . [...]]]></description>
			<content:encoded><![CDATA[<p>Небольшой класс, возвращает сокращенную ссылку. Можно обращаться как напрямую к конкретному сервису, так и выбранному рандомно через Shorteners-&gt;any(). Есть возможность указать прокси.</p>
<p>Работает с</p>
<ol>
<li>bit.ly</li>
<li>goo.gl</li>
<li>is.gd</li>
<li>tinyurl.com</li>
<li>dlmn.org</li>
<li>ndurl.com</li>
<li>qr.cx</li>
<li>gatorurl.com</li>
<li>jmb.tw</li>
<li>linkee.com</li>
<li>mtny.mobi</li>
<li>cli.gs</li>
</ol>
<pre class="brush:php">&lt;?php

error_reporting(1);

class Shorteners {

    public $proxy = null;

    public function bitly($url) {
        $connectURL = 'http://api.bit.ly/v3/shorten?login=masstest&amp;apiKey=R_44403eb439622dd59ba2598255f30824&amp;uri=' . urlencode($url) . '&amp;format=txt';
        return $this-&gt;curl_get_result($connectURL, NULL);
    }

    public function googl($url) {
        $connectURL = 'http://goo.gl/api/shorten';
        $post_fields = "security_token=null&amp;url=" . urlencode($url);
        $res = $this-&gt;curl_get_result($connectURL, $post_fields);
        $obj = json_decode($res);
        $ans = (!empty($res)) ? $obj-&gt;{'short_url'} : false;
        return $ans;
    }

    public function isgd($url) {
        $connectURL = 'http://is.gd/api.php?longurl=' . urlencode($url);
        return $this-&gt;curl_get_result($connectURL, NULL);
    }

    public function tinyurl($url) {
        $connectURL = 'http://tinyurl.com/api-create.php?url=' . urlencode($url);
        return $this-&gt;curl_get_result($connectURL, NULL);
    }

    public function dlmn($url) {
        $connectURL = 'http://dlmn.org/submit/?url=' . urlencode($url) . '&amp;ajax=false';
        $page = $this-&gt;curl_get_result($connectURL, NULL);
        preg_match("/&lt;input id=\"dlmn-loc\" value=\"(.*?)\"/si", $page, $out);
        if (strlen($out[1]) &lt; 3) {
            return false;
        } else {
            $answer = (empty($out[1])) ? false : "http://" . $out[1];
            return $answer;
        }
    }

    public function crum($url) {
        $connectURL = 'http://crum.bs/api.php?function=simpleshorten&amp;url=' . urlencode($url);
        return $this-&gt;curl_get_result($connectURL, NULL);
    }

    public function ndurl($url) {
        $connectURL = 'http://www.ndurl.com/api.generate/?url=' . urlencode($url) . '&amp;type=web';
        $res = $this-&gt;curl_get_result($connectURL, NULL);
        $obj = json_decode(stripslashes($res));
        $obj = $obj-&gt;data;
        $ans = (!empty($res)) ? $obj-&gt;{'shortURL'} : false;
        return $ans;
    }

    public function qr($url) {
        $connectURL = 'http://qr.cx/api/?longurl=' . urlencode($url);
        return $this-&gt;curl_get_result($connectURL, NULL);
    }

    public function gatorurl($url) {
        $connectURL = 'http://gatorurl.com/api/rest.php?url=' . urlencode($url);
        return $this-&gt;curl_get_result($connectURL, NULL);
    }

    public function jmb($url) {
        $connectURL = 'http://jmb.tw/api/create/?newurl=' . urlencode($url);
        return $this-&gt;curl_get_result($connectURL, NULL);
    }

    public function linkee($url) {
        $connectURL = 'http://api.linkee.com/1.0/shorten?input=' . urlencode($url);
        $res = $this-&gt;curl_get_result($connectURL, NULL);
        $obj = json_decode($res);
        $ans = (!empty($res)) ? $obj-&gt;{'result'} : false;
        return $ans;
    }

    public function mtny($url) {
        $connectURL = 'http://mtny.mobi/api/?url=' . urlencode($url) . '&amp;ismobile=false&amp;type=simple';
        return $this-&gt;curl_get_result($connectURL, NULL);
    }

    public function cligs($url) {
        $connectURL = 'http://cli.gs/cligs/new';
        $post = "URL=" . urlencode($url);
        $page = $this-&gt;curl_get_result($connectURL, $post);
        preg_match("/Your new clig has been created/si", $page, $out);
        if (strlen($out[0]) &lt; 3) {
            return false;
        } else {
            preg_match("#http://twitter.com/home\?status=(.*?)\"#si", $page, $out);
            $answer = (empty($out[1])) ? false : $out[1];
            return $answer;
        }
    }

    public function any($url) {
        $func = get_class_methods($this);
        $sh = $func[array_rand($func, 1)];
        return $this-&gt;$sh($url, NULL);
    }

    private function curl_get_result($url, $postdata) {
        $ch = curl_init();
        $timeout = 5;
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
        if (isset($postdata)) {
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
        }
        if ($this-&gt;proxy) {
            //var_dump( $this-&gt;proxy );
            curl_setopt($ch, CURLOPT_PROXY, $this-&gt;proxy);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, "60");
            curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
            curl_setopt($ch, CURLOPT_TIMEOUT, "60");
        } else {
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, "30");
            curl_setopt($ch, CURLOPT_TIMEOUT, "30");
        }
        $data = curl_exec($ch);
        curl_close($ch);

        return trim($data);
    }

}

$test = new Shorteners();
$url = "http://rambler.ru";
$class_methods = get_class_methods('Shorteners');
foreach ($class_methods as $method):
    echo $test-&gt;$method . "\r\n";
endforeach;
?&gt;</pre>
<h2  class="related_post_title">На закуску.</h2><ul class="related_post"><li><a href="http://alexvolkov.ru/php-debugging-and-profiling.html" title="Профилирование и отладка PHP скриптов">Профилирование и отладка PHP скриптов</a></li><li><a href="http://alexvolkov.ru/problems-with-the-serialization-of-arrays.html" title="Проблемы с сериализацией массивов">Проблемы с сериализацией массивов</a></li><li><a href="http://alexvolkov.ru/a-simple-way-to-test-the-process-on-the-existence-of.html" title="Простой способ проверки процесса на существование">Простой способ проверки процесса на существование</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://alexvolkov.ru/class-to-work-with-the-service-reduction-options.html/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Простой способ проверки процесса на существование</title>
		<link>http://alexvolkov.ru/a-simple-way-to-test-the-process-on-the-existence-of.html</link>
		<comments>http://alexvolkov.ru/a-simple-way-to-test-the-process-on-the-existence-of.html#comments</comments>
		<pubDate>Thu, 24 Mar 2011 18:43:25 +0000</pubDate>
		<dc:creator>Alex Volkov</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Скрипты]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://alexvolkov.ru/?p=1866</guid>
		<description><![CDATA[Для простых многопоточных систем очень часто используют запуск в фоновом режиме.  Запускают их примерно вот так: php script.php &#38; И управление процессом от юзера уходит, отловить такой процесс из другого скрипта уже не получится. А если процесс выполняет какую то одну и ту же задачу с интервалом по крону, и нужно, чтобы при запуска нового [...]]]></description>
			<content:encoded><![CDATA[<p>Для простых многопоточных систем очень часто используют запуск в фоновом режиме.  Запускают их примерно вот так:</p>
<pre class="brush:shell">php script.php &amp;</pre>
<p>И управление процессом от юзера уходит, отловить такой процесс из другого скрипта уже не получится. А если процесс выполняет какую то одну и ту же задачу с интервалом по крону, и нужно, чтобы при запуска нового процесса старый был убит? Поймать его можно аццкой смесью bash + php:</p>
<pre class="brush:php">$killPid = exec("ps ux | awk '/script_name.php/ &amp;&amp; !/awk/ {print $2}'");//находим пид процесса
      if($killPid)//если есть, киляем
	  exec ("kill ".$killPid);
exec('php script_name.php &amp;');//запускаем новый</pre>
<h2  class="related_post_title">На закуску.</h2><ul class="related_post"><li><a href="http://alexvolkov.ru/consider-how-many-lines-of-code-in-a-php-project.html" title="Считаем, сколько строк кода в php проекте.">Считаем, сколько строк кода в php проекте.</a></li><li><a href="http://alexvolkov.ru/examples-of-using-strace-to-debug-scripts.html" title="Примеры использования strace для отладки скриптов">Примеры использования strace для отладки скриптов</a></li><li><a href="http://alexvolkov.ru/watchdog-dlya-svoikh-skriptov-ili-proverka-sostoyaniya-processa.html" title="Watchdog для своих скриптов или проверка состояния процесса">Watchdog для своих скриптов или проверка состояния процесса</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://alexvolkov.ru/a-simple-way-to-test-the-process-on-the-existence-of.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Примеры использования strace для отладки скриптов</title>
		<link>http://alexvolkov.ru/examples-of-using-strace-to-debug-scripts.html</link>
		<comments>http://alexvolkov.ru/examples-of-using-strace-to-debug-scripts.html#comments</comments>
		<pubDate>Tue, 22 Mar 2011 16:47:41 +0000</pubDate>
		<dc:creator>Alex Volkov</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Скрипты]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[strace]]></category>

		<guid isPermaLink="false">http://alexvolkov.ru/?p=1835</guid>
		<description><![CDATA[Strace &#8212; это встроенный перехватчик системных вызовов и сигналов в линуксе. Основная его цель &#8212; это перехват информации относительно какого-то процесса. Крайне незаменимая штука при отладке скриптов, особенно закодированных. Пример использования &#8212; есть один сервис, который я написал, и обьявилась там проблема &#8212; каким-то неведомым образом права на файл, куда пишется лог, начали выставляться криво. [...]]]></description>
			<content:encoded><![CDATA[<p>Strace &#8212; это встроенный перехватчик системных вызовов и сигналов в линуксе. Основная его цель &#8212; это перехват информации относительно какого-то процесса. Крайне незаменимая штука при отладке скриптов, особенно закодированных.</p>
<p>Пример использования &#8212; есть один сервис, который я написал, и обьявилась там проблема &#8212; каким-то неведомым образом права на файл, куда пишется лог, начали выставляться криво. А именно: вместо положенных rw &#8212; rw &#8212; rw стали w &#8212; wx &#8212; wT. Проблема тут в том, что надо указывать права при смене не как:</p>
<pre class="brush:php">chmod('file.txt', '0666'); или
chmod('file.txt', 666);</pre>
<p>в этом случае 0666 будет string, а вот так:</p>
<pre class="brush:php">chmod('file.txt', intval('666', 8));</pre>
<p>Так они уже будут в корректной форме.</p>
<p>Вернемся к проблеме. Нужно было найти, кто ставит на файл неверные права. Вот так можно отловить все вызовы определенного файла:</p>
<pre class="brush:shell">strace php ./script.php 2&gt;&amp;1 | grep file.txt</pre>
<p>Ответ будет вида:</p>
<pre class="brush:shell">open("/path/to/file.txt", O_RDWR|O_CREAT|O_APPEND|O_LARGEFILE, 0666) = 4
chmod("/path/to/file.txt", 0666) = 0</pre>
<p>Вот так можно отмониторить все обращения к файлу<br />
<span id="more-1835"></span><br />
Однако у меня была проблема с записью при запуске через апача, т.е. скрипт запускался не от моего пользователя. Тут можно отмониторить по pid процесса, но нужен рут.</p>
<pre class="brush:shell">strace -p 123 2&gt;&amp;1 | grep file.txt</pre>
<p>Гашение вывода 2&gt;&amp;1 позволит не читать тонны ненужной инфы. Но для хардкорных дебаггеров можно убрать.</p>
<p>Еще вот примеры использования strace, <a href="http://www.hokstad.com/5-simple-ways-to-troubleshoot-using-strace.html">перевел отсюда</a></p>
<p>Смотрим, какие конфиги читает скрипт:</p>
<pre class="brush:shell">$ strace -e open php 2&gt;&amp;1 | grep php.ini
open("/usr/local/bin/php.ini", O_RDONLY) = -1 ENOENT (No such file or directory)
open("/usr/local/lib/php.ini", O_RDONLY) = 4</pre>
<p>Смотрим, почему скрипт не может открыть определенный файл:</p>
<pre class="brush:shell">$ strace -e open,access 2&gt;&amp;1 | grep your-filename</pre>
<p>Что процесс делает в данный момент:</p>
<pre class="brush:shell">root@dev:~# strace -p 15427
Process 15427 attached - interrupt to quit
futex(0x402f4900, FUTEX_WAIT, 2, NULL
Process 15427 detached</pre>
<p>Следующий пример очень полезен &#8212; показывает на что тратится процессорное время скриптом:</p>
<pre class="brush:shell">root@dev:~# strace -c -p 11084
Process 11084 attached - interrupt to quit
Process 11084 detached
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 94.59    0.001014          48        21           select
  2.89    0.000031           1        21           getppid
  2.52    0.000027           1        21           time
------ ----------- ----------- --------- --------- ----------------
100.00    0.001072                    63           total
root@dev:~#</pre>
<p>При таком вызове он будет отображать данные до тех пор, пока принудительно его не завершить.</p>
<p>Можно запросить  раскладку от начала до конца:</p>
<pre class="brush:shell">root@dev:~# strace -c &gt;/dev/null ls
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 23.62    0.000205         103         2           getdents64
 18.78    0.000163          15        11         1 open
 15.09    0.000131          19         7           read
 12.79    0.000111           7        16           old_mmap
  7.03    0.000061           6        11           close
  4.84    0.000042          11         4           munmap
  4.84    0.000042          11         4           mmap2
  4.03    0.000035           6         6         6 access
  3.80    0.000033           3        11           fstat64
  1.38    0.000012           3         4           brk
  0.92    0.000008           3         3         3 ioctl
  0.69    0.000006           6         1           uname
  0.58    0.000005           5         1           set_thread_area
  0.35    0.000003           3         1           write
  0.35    0.000003           3         1           rt_sigaction
  0.35    0.000003           3         1           fcntl64
  0.23    0.000002           2         1           getrlimit
  0.23    0.000002           2         1           set_tid_address
  0.12    0.000001           1         1           rt_sigprocmask
------ ----------- ----------- --------- --------- ----------------
100.00    0.000868                    87        10 total</pre>
<p>Вот такая полезная штука. Man strace, одним словом!</p>
<p>&nbsp;</p>
<h2  class="related_post_title">На закуску.</h2><ul class="related_post"><li><a href="http://alexvolkov.ru/a-simple-way-to-test-the-process-on-the-existence-of.html" title="Простой способ проверки процесса на существование">Простой способ проверки процесса на существование</a></li><li><a href="http://alexvolkov.ru/wordpress-i-memcache-2.html" title="Wordpress и memcache 2">Wordpress и memcache 2</a></li><li><a href="http://alexvolkov.ru/skripty-dlya-morfologicheskogo-analiza-teksta.html" title="Скрипты для морфологического анализа текста.">Скрипты для морфологического анализа текста.</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://alexvolkov.ru/examples-of-using-strace-to-debug-scripts.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Размножение строк &#8212; функция генерации всех возможных значений из шаблона {}</title>
		<link>http://alexvolkov.ru/reproduction-lines-the-generation-function-of-all-possible-values-of-the-template.html</link>
		<comments>http://alexvolkov.ru/reproduction-lines-the-generation-function-of-all-possible-values-of-the-template.html#comments</comments>
		<pubDate>Thu, 17 Mar 2011 18:55:36 +0000</pubDate>
		<dc:creator>Alex Volkov</dc:creator>
				<category><![CDATA[Скрипты]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://alexvolkov.ru/?p=1824</guid>
		<description><![CDATA[Понадобилась такая функция, решил размять мозги. Функция понимает в качестве разделителя запятые, &#124;,  ;. Вызов показан в конце. &#60;?php function mashUp($str){ preg_match_all("/{(.*?)}/", $str, $out); $headArr = $out[1]; for($i = 0; $i &#60; sizeof($headArr); $i++) { $valArr = preg_split("/(\&#124;&#124;,&#124;;&#124; )/", $headArr[$i]); ($i == 0)? $sTotal = count($valArr) : $sTotal = $sTotal * count($valArr); $varr[] = $valArr; [...]]]></description>
			<content:encoded><![CDATA[<p>Понадобилась такая функция, решил размять мозги. Функция понимает в качестве разделителя запятые, |,  ;. Вызов показан в конце.</p>
<pre class="brush:php">&lt;?php

function mashUp($str){
preg_match_all("/{(.*?)}/", $str, $out);
$headArr = $out[1];

for($i = 0; $i &lt; sizeof($headArr); $i++)
{
	$valArr = preg_split("/(\||,|;|	)/", $headArr[$i]);
	($i == 0)? $sTotal = count($valArr) : $sTotal = $sTotal * count($valArr);
	$varr[] = $valArr;
}
for($i = 0; $i &lt; $sTotal; $i++){
	$strings[$i] = $str;
}
foreach($headArr as $num =&gt; $val):
	$currPos = 0;	//позиция ключа в $varr
		for($i = 0; $i &lt; $sTotal; $i++)
		{
			if($i == 0):
					if($num == 0)
					{
						$sChange = ( $sTotal / ( count($varr[$num]) ) );
					}
						else
					{
						($old)? $sChange = $old : $sChange = $sChange;
 						$sChange = ($sChange / (count($varr[$num])));
					}

					if(count($varr[$num]) &lt; 2){
						$old = $sChange;
						$sChange = $sTotal;
						}
					if($num == (count($headArr) - 1))
					{
						$sChange = 1;
					}
					$sNum = $sChange;
			endif;

			if($sNum == 0){
					$sNum = $sChange - 1;
					$currPos++;
				} else {
					$sNum--;
				//$currPos++;
				}

			if($currPos &gt; (count($varr[$num]) - 1))
			$currPos = 0;
			preg_match("/{(.*?)}/", $strings[$i], $res, PREG_OFFSET_CAPTURE, 0);
			$strings[$i] = preg_replace("!".preg_quote($res[0][0])."!si", $varr[$num][$currPos], $strings[$i]);
		}
endforeach;
return($strings);
}
$str = "some {1a|2a,3a;4a	5a} strings {1b|2b|3b} that {1c} need to {1d|2d} post {test|example|primer}";
echo maashUp($str);
?&gt;</pre>
<h2  class="related_post_title">На закуску.</h2><ul class="related_post"><li><a href="http://alexvolkov.ru/php-debugging-and-profiling.html" title="Профилирование и отладка PHP скриптов">Профилирование и отладка PHP скриптов</a></li><li><a href="http://alexvolkov.ru/problems-with-the-serialization-of-arrays.html" title="Проблемы с сериализацией массивов">Проблемы с сериализацией массивов</a></li><li><a href="http://alexvolkov.ru/class-to-work-with-the-service-reduction-options.html" title="Класс для работы с сервисами сокращения ссылок">Класс для работы с сервисами сокращения ссылок</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://alexvolkov.ru/reproduction-lines-the-generation-function-of-all-possible-values-of-the-template.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MYSQL RAND(), как получить рандомную строку из БД</title>
		<link>http://alexvolkov.ru/mysql-rand-how-to-get-a-random-line-from-db.html</link>
		<comments>http://alexvolkov.ru/mysql-rand-how-to-get-a-random-line-from-db.html#comments</comments>
		<pubDate>Tue, 09 Nov 2010 10:56:03 +0000</pubDate>
		<dc:creator>Alex Volkov</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[Скрипты]]></category>
		<category><![CDATA[Mysql]]></category>
		<category><![CDATA[Е]]></category>

		<guid isPermaLink="false">http://alexvolkov.ru/?p=1789</guid>
		<description><![CDATA[Чем дольше занимаюсь кодингом, тем чаще втыкаюсь в такие вещи, которые сто раз уже использовал, а на 101 сломал голову. Есть таблица, в ней N тысяч записей, нужно вытащить одну рандомно, кой-чего с ней сделать, и если все ок то ее использовать, если нет то вернуть на место с соответствующей отметкой и взять другую, пока [...]]]></description>
			<content:encoded><![CDATA[<p>Чем дольше занимаюсь кодингом, тем чаще втыкаюсь в такие вещи, которые сто раз уже использовал, а на 101 сломал голову.</p>
<p>Есть таблица, в ней N тысяч записей, нужно вытащить одну рандомно, кой-чего с ней сделать, и если все ок то ее использовать, если нет то вернуть на место с соответствующей отметкой и взять другую, пока не будет найдена подходящая по условиям.<br />
Я, особо не мудря, делаю цикл while до условия, пока не найдена подходящая запись. В цикле такой запрос к БД</p>
<pre class="brush:sql">SELECT * FROM `table` WHERE 1 ORDER BY RAND() LIMIT 1</pre>
<p>По задумке, это возвращает каждый раз новую запись. Но у mysql есть такая приятная особенность &#8212; она кеширует запросы и в цикле каждый будет возвращаться одно и тоже поле. Наверно, если разрывать соединение, тогда будет возвращаться разное число. Я таких вещей в душе не знал, поэтому немного удивился, погуглив, что это самый дибильный способ вытащить рандомную запись из базы. На очень больших БД это завесит сервер напрочь.</p>
<p>Вариант получше заключался в том, чтобы вытащить максимальное значение записей и получить рандомное число в его пределах, затем запросить из базы строку с LIMIT рандомное число.</p>
<pre class="brush:sql">//запрос макс количества записей в переменную
SELECT FLOOR(RAND() * COUNT(*)) AS `offset` FROM `table`

//далее запрос с этой переменной
SELECT * FROM `table` LIMIT $somevar, 1</pre>
<p>Он же по тестам получился самый быстрый.</p>
<p>Еще один способ заключается в том, чтобы запросить по определенному полю, например id, указав точное число для него.</p>
<pre class="brush:as3">SELECT * FROM `table` WHERE id &gt;= (SELECT FLOOR( MAX( id ) * RAND( ) ) FROM `proxy` ) ORDER BY id LIMIT 1</pre>
<p>Все варианты расписаны <a href="http://akinas.com/pages/en/blog/mysql_random_row/">тут</a>.</p>
<p>Единственное, что не устроило во втором варианте, это два запроса к базе.</p>
<h2  class="related_post_title">На закуску.</h2><ul class="related_post"><li><a href="http://alexvolkov.ru/embedded-sql-statements-the-simultaneous-addition-of-single-and-multiple-rows-in-the-insert.html" title="Вложенные SQL запросы: одновременное добавление одинарных и множественных строк в INSERT">Вложенные SQL запросы: одновременное добавление одинарных и множественных строк в INSERT</a></li><li><a href="http://alexvolkov.ru/the-script-for-tuning-mysql.html" title="Скрипт для тюнинга MYSQL">Скрипт для тюнинга MYSQL</a></li><li><a href="http://alexvolkov.ru/robkijj-tar.html" title="Робкий tar )">Робкий tar )</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://alexvolkov.ru/mysql-rand-how-to-get-a-random-line-from-db.html/feed</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Подстановка ссылок в текст в процентном соотношении.</title>
		<link>http://alexvolkov.ru/podstanovka-ssylok-v-tekst-v-procentnom-sootnoshenii.html</link>
		<comments>http://alexvolkov.ru/podstanovka-ssylok-v-tekst-v-procentnom-sootnoshenii.html#comments</comments>
		<pubDate>Mon, 23 Aug 2010 20:30:02 +0000</pubDate>
		<dc:creator>Alex Volkov</dc:creator>
				<category><![CDATA[Скрипты]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://alexvolkov.ru/?p=1730</guid>
		<description><![CDATA[Накидал вот простенькую функцию, которая запихивает в текст ссылки. Т.е. берется текстовый файл и туда пихаются ссылочки с плотностью, например, 7%.  Функция простенькая, писал себе под один проект. Наверно, весь функционал редбаттона по отдельности скоро напишу, надо свой дорген замутить. Переменные вызова: $text, сам текст в который пихаются ссылки. string $prc, int, процент плотности ссылок. [...]]]></description>
			<content:encoded><![CDATA[<p>Накидал вот простенькую функцию, которая запихивает в текст ссылки. Т.е. берется текстовый файл и туда пихаются ссылочки с плотностью, например, 7%.  Функция простенькая, писал себе под один проект. Наверно, весь функционал редбаттона по отдельности скоро напишу, надо свой дорген замутить.</p>
<p>Переменные вызова:<br />
$text, сам текст в который пихаются ссылки. string<br />
$prc, int, процент плотности ссылок.<br />
$links, array, массив со ссылками вида http://site.ru<br />
$nobr, bool, 1 или 0. Если, например, текста 500кб а ссылок 3, указывает, обрубать ли текст после последней ссылки(1) или оставить все 500кб с 3 ссылками.</p>
<p>Листинг:</p>
<pre class="brush:php">function AddLinksToText($text, $prc, $links, $nobr){
	$pos = 0;
	$string = "";
	$totalLinks = count($links);
	$Words = explode(" ", $text);
	$totalWords = count($Words);
	$needText = $totalLinks * $prc;

	if($totalWords &lt; $needText){
			$prc = floor($totalWords / $totalLinks); //calculate recommended percentage if haven't enough text
			echo @date("r")." not enough text, decrease density to ".$prc."%\r\n";
			$needText = $totalLinks * $prc;
		} else {
			echo @date("r")." working with text, density is ".$prc."%\r\n";
		}
	foreach($links as $num=&gt;$lnk){
					$pos += $prc;
					$Words[$pos] = "&lt;a href=\"".$lnk."\"&gt;".$Words[$pos]."&lt;/a&gt;";
				}
	if(!isset($nobr)){
		$tmp = array_slice($Words, 0, $needText + 3);
		} else {
		$tmp = $Words;
		}

	//return string
	foreach($tmp as $somevar){
		$string .= $somevar." ";
	}
	return $string;	

}</pre>
<h2  class="related_post_title">На закуску.</h2><ul class="related_post"><li><a href="http://alexvolkov.ru/php-debugging-and-profiling.html" title="Профилирование и отладка PHP скриптов">Профилирование и отладка PHP скриптов</a></li><li><a href="http://alexvolkov.ru/problems-with-the-serialization-of-arrays.html" title="Проблемы с сериализацией массивов">Проблемы с сериализацией массивов</a></li><li><a href="http://alexvolkov.ru/class-to-work-with-the-service-reduction-options.html" title="Класс для работы с сервисами сокращения ссылок">Класс для работы с сервисами сокращения ссылок</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://alexvolkov.ru/podstanovka-ssylok-v-tekst-v-procentnom-sootnoshenii.html/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Заливка файлов на радикал PHP</title>
		<link>http://alexvolkov.ru/zalivka-fajjlov-na-radikal-php.html</link>
		<comments>http://alexvolkov.ru/zalivka-fajjlov-na-radikal-php.html#comments</comments>
		<pubDate>Fri, 26 Feb 2010 07:25:04 +0000</pubDate>
		<dc:creator>Alex Volkov</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[Скрипты]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[radikal]]></category>

		<guid isPermaLink="false">http://alexvolkov.ru/?p=1569</guid>
		<description><![CDATA[Если нет желания забивать сервер картинками, то данный скриптец поможет. Он грузит картинку с веба (урл) на радикал, возвращает адрес картинки на радикале. $postdata = "upload=yes&#38;F=&#38;URLF=".$imagelink."&#38;O=yes&#38;M=640&#38;JQ=85&#38;J=yes&#38;IM=7&#38;VM=180&#38;R=0&#38;VE=yes&#38;V=Увеличить&#38;X=&#38;FS="; $page = FetchUrl("http://www.radikal.ru/action.aspx", $postdata, NULL, NULL, NULL); preg_match("!id=\"input_link_1\" value=\"(.*?)\"!si", $page, $imageUrl); $imageUrl = $imageUrl[1]; FetchUrl моя универсальная функция для курла, я ее под все подряд юзаю, поэтому там много [...]]]></description>
			<content:encoded><![CDATA[<p>Если нет желания забивать сервер картинками, то данный скриптец поможет. Он грузит картинку с веба (урл) на радикал, возвращает адрес картинки на радикале.</p>
<pre class="brush:c-sharp">
$postdata = "upload=yes&amp;F=&amp;URLF=".$imagelink."&amp;O=yes&amp;M=640&amp;JQ=85&amp;J=yes&amp;IM=7&amp;VM=180&amp;R=0&amp;VE=yes&amp;V=Увеличить&amp;X=&amp;FS=";
$page = FetchUrl("http://www.radikal.ru/action.aspx", $postdata, NULL, NULL, NULL);
preg_match("!id=\"input_link_1\" value=\"(.*?)\"!si", $page, $imageUrl);
$imageUrl = $imageUrl[1];</pre>
<p>FetchUrl моя универсальная функция для курла, я ее под все подряд юзаю, поэтому там много левого кода. При желании можно поудалять половину.</p>
<pre class="brush:c-sharp">function FetchUrl($url, $postvars, $timeout, $ref, $blank){
 sleep($timeout);                         
 echo @date("r")." fetching $url\r\n";              
 $ch = curl_init();   
 if(isset($postvars)){
 echo @date("r")." $postvars\r\n";                    
 curl_setopt($ch, CURLOPT_POST, 1);
 curl_setopt($ch, CURLOPT_POSTFIELDS, $postvars);
 }
//        curl_setopt($ch, CURLOPT_PROXY, $proxy);
 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);       
//        curl_setopt($ch, CURLOPT_HEADER, true);           
 curl_setopt($ch, CURLOPT_TIMEOUT,15);               
 curl_setopt($ch, CURLOPT_ENCODING, 'gzip');         
 curl_setopt($ch, CURLOPT_COOKIEJAR, "c1.txt");    
 curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (X11; U; Linux x86_64; ru; rv:1.9.1.6) Gecko/20091201 SUSE/3.5.6-1.1.1 Firefox/3.5.6 FirePHP/0.3");     
 curl_setopt($ch, CURLOPT_COOKIEFILE, "c1.txt");     
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);  
 curl_setopt($ch, CURLOPT_URL, trim($url));
 curl_setopt($ch, CURLOPT_AUTOREFERER, TRUE);
 curl_setopt($ch, CURLOPT_REFERER, $ref);                                                                  
 $result = curl_exec($ch);     
 if($blank == "1"){    
     $result = preg_replace("/\n/", "", $result);
     $result = preg_replace("/\r/", "", $result);
 }
 curl_close($ch);                                                                                        
 return $result;                                                                                              
 }
</pre>
<h2  class="related_post_title">На закуску.</h2><ul class="related_post"><li><a href="http://alexvolkov.ru/ftp-curl.html" title="FTP + CURL">FTP + CURL</a></li><li><a href="http://alexvolkov.ru/zagruzka-izobrazhenijj-na-imageshost-po-kurlu.html" title="Загрузка изображений на imageshost по курлу">Загрузка изображений на imageshost по курлу</a></li><li><a href="http://alexvolkov.ru/postim-v-tvitter-cherez-kurl.html" title="Постим в твиттер через курл">Постим в твиттер через курл</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://alexvolkov.ru/zalivka-fajjlov-na-radikal-php.html/feed</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Многопоточность в php</title>
		<link>http://alexvolkov.ru/mnogopotochnost-v-php.html</link>
		<comments>http://alexvolkov.ru/mnogopotochnost-v-php.html#comments</comments>
		<pubDate>Thu, 21 Jan 2010 19:20:18 +0000</pubDate>
		<dc:creator>Alex Volkov</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Скрипты]]></category>

		<guid isPermaLink="false">http://alexvolkov.ru/?p=1522</guid>
		<description><![CDATA[Оффициальной нет, сразу скажу. Есть только многочисленные костылики. Примеры, в основном, будут полезны в сео софте. Встала вобщем задача передо мной &#8212; накатать многопоточный нескажу что, причем не просто многопоточный, а чтобы еще и потоками можно было управлять, как в том же делфи. То есть, чтобы можно было поток остановить, запустить, запауазить, возобновить и потоки [...]]]></description>
			<content:encoded><![CDATA[<p>Оффициальной нет, сразу скажу. Есть только многочисленные костылики. Примеры, в основном, будут полезны в сео софте.</p>
<p>Встала вобщем задача передо мной &#8212; накатать многопоточный нескажу что, причем не просто многопоточный, а чтобы еще и потоками можно было управлять, как в том же делфи. То есть, чтобы можно было поток остановить, запустить, запауазить, возобновить и потоки еще должны оповещать о своем состоянии, мол в данный момент выполняю то-то.<span id="more-1522"></span></p>
<p>Собсно, теория реализации.</p>
<p>Два скрипта &#8212; один поток, второй запускалка потоков. Поток делает свои дела, запускалка вычисляет, сколько потоков запустить и с какими параметрами.</p>
<p>Пример первый, запускает 20 потоков, если общее количество потоков ниже чем 10</p>
<pre class="brush:c-sharp;">&lt;?php 

while(2 &gt; 1):

$thCount = exec("ps a | thread.php | wc -l");
echo $thCount."\r\n";
 if($thCount &lt; 10){
 for($i = 0; $i &lt; 20; $i++){
 echo "launch thread\r\n";
 passthru("(php -f thread.php &amp; ) &gt;&gt; /dev/null 2&gt;&amp;1");
 //sleep(1);
 }
 } else {
 sleep(5);
}
endwhile;

?&gt;</pre>
<p>Получается хрень, которая дозапускает потоки время от времени по условию. Потоков всегда разное число в разные промежутки времени и остановить их никак нельзя. Но, если некритичны все эти вещи, цикл вполне неплохо работает. Подходит, например, всякие регеры. При допилке можно держать нужное количество потоков с погрешностью +- 1. Для этого нужно просто динамически вычислять число запускаемых потоков. Да, и ps показывает три работающих потока при таком вызове, даже если нет ни одного. Один дает греп, второй сам скрипт, третий фиг знает кто. </p>
<p>Вариант 2.</p>
<p>Тут уже захотелось сделать более гибкую штуку. А именно &#8212; взять например 1к урлов и раздать их поровну N потокам.</p>
<pre class="brush:c-sharp;">&lt;?php

$threads = 10;
$base = file("base.txt");

$perThread = ceil(count($base) / $threads);

for($i = 0; $i &lt; $threads; $i++){
 if($i == 0) { passthru("(php -f thread.php '0|".$perThread."' &amp; ) &gt;&gt; /dev/null 2&gt;&amp;1");    }
 if($i == $threads-1) { passthru("(php -f thread.php '".$perThread * $i."|".count($base)."' &amp; ) &gt;&gt; /dev/null 2&gt;&amp;1");    }
 if(($i !== 0)&amp;&amp;($i !== $threads-1)) {
 $start = $perThread * $i + 1;
 $end = $start -1 + $perThread;
 passthru("(php -f thread.php '".$start."|".$end."' &amp; ) &gt;&gt; /dev/null 2&gt;&amp;1");    
 }
}
?&gt;</pre>
<p>Данный пример запускает поток с параметрами, который тот потом достает из массива $argv и использует. Такое вот разделение труда.</p>
<p>Взаимодействие между потоком и &#171;мамой&#187;.<br />
Тут у меня только теория. Думаю реализовать это через файлы. Поток создает файл с именем своей сессии (номера, пида), мама читает оттуда. Чтобы вывести инфу о потоках красиво и наглядно, думаю заюзать <a href="http://ru2.php.net/manual/en/book.ncurses.php">ncurses</a>. Это сишная либа, на ней сделаны midnight commander, top.  Доступна не только для пхп. </p>
<p>Изменения состояний потоков.<br />
Так и не придумал. Можно попробовать через теже файлы, но это надо после каждой строчки кода потока вставлять проверку файла на наличии там указаний. Скорость само собой упадет. Да и при таких реализациях мама убивается только вручную.</p>
<p>Саня, он же <a href="http://clear.helldude.ru/">похапэ дуд</a> , сразу обрубил &#8212; Я бы такие задачи не решал на php. Я тоже посматриваю в сторону других языков, думаю выучить что-то типа си, но пока я выучу, мне наверно уже ничего не надо будет. Есть вариант на питоне. И как раз в ридере попалась статья одного камрада, который начал изучать его и <a href="http://seorepa.com/archives/2010/01/21/607">привел примерчик</a>.<br />
Вариант ,как по мне, не очень, бесконечные потоки и в пхп можно пускать. Но в посте увидел <a href="http://python4seo.ru/?p=67">ссылочку</a>, третий примерчик очень похож на то, что надо. Плюс питона еще в том, что в нем можно использовать графические либы типа gtk или qt, а это уже полноценные проги для енд-юзера а не софт для консольных гиков.</p>
<hr/>
<a href="http://alexvolkov.ru/wordpress-i-memcache-2.html">memcached php</a><br />
<a href="http://alexvolkov.ru/ustanovka-memcached-dlya-wordpress.html">установка memcached</a><br />
<a href="http://alexvolkov.ru/20-ajax-skriptov-dlya-sajjta.html">скрипт опроса ajax</a></p>
<h2  class="related_post_title">На закуску.</h2><ul class="related_post"><li>Ничего нет похожего на этот пост, он неповторим</li></ul>]]></content:encoded>
			<wfw:commentRss>http://alexvolkov.ru/mnogopotochnost-v-php.html/feed</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
	</channel>
</rss>
<!-- This Quick Cache file was built for (  alexvolkov.ru/category/web/skripty/feed ) in 0.55905 seconds, on May 18th, 2012 at 10:19 am UTC. -->
<!-- This Quick Cache file will automatically expire ( and be re-built automatically ) on May 18th, 2012 at 11:19 am UTC -->
