<?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>Pavluha.Net</title>
	<atom:link href="https://pavluha.net/feed" rel="self" type="application/rss+xml" />
	<link>https://pavluha.net</link>
	<description>Web-мастеринг. Кодинг. Манимейкинг</description>
	<lastBuildDate>Sat, 11 Jan 2025 20:38:36 +0000</lastBuildDate>
	<language>ru-RU</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.5.8</generator>
	<item>
		<title>freshclam ERROR: Update failed</title>
		<link>https://pavluha.net/freshclam-error-update-failed.html</link>
					<comments>https://pavluha.net/freshclam-error-update-failed.html#respond</comments>
		
		<dc:creator><![CDATA[Павлуха]]></dc:creator>
		<pubDate>Sat, 11 Jan 2025 20:38:36 +0000</pubDate>
				<category><![CDATA[Web-мастеринг]]></category>
		<guid isPermaLink="false">https://pavluha.net/?p=2525</guid>

					<description><![CDATA[<p>Можно скачать актуальную базу с https://database.clamav.net/daily.cvd через браузер и сохранить скачанный файл в /var/lib/clamav Но clamav мне ни разу не помог в поиске бэкдоров. Поиск бэкдоров по сигнатурам&#160;&#8212; это смешно. Лучше юзай бесплатную утилиту Kaspersky Virus Removal Tool (kvrt). Не &#8230; <a href="https://pavluha.net/freshclam-error-update-failed.html">Читать далее <span class="meta-nav">&#8594;</span></a></p>
The post <a href="https://pavluha.net/freshclam-error-update-failed.html">freshclam ERROR: Update failed</a> first appeared on <a href="https://pavluha.net">Pavluha.Net</a>.]]></description>
										<content:encoded><![CDATA[<p>Можно скачать актуальную базу с https://database.clamav.net/daily.cvd через браузер и сохранить скачанный файл в /var/lib/clamav<br />
Но clamav мне ни разу не помог в поиске бэкдоров. Поиск бэкдоров по сигнатурам&nbsp;&mdash; это смешно. Лучше юзай бесплатную утилиту Kaspersky Virus Removal Tool (kvrt). Не имба, но годно.</p>
<p><span id="more-2525"></span></p>
<p>Почему поиск бэкдоров по сигнатурам&nbsp;&mdash; это смешно? Ну, смотри: <code>$USER-&gt;Authorize(1);</code>&nbsp;&mdash; этот код авторизует тебя под админом на почти каждом сайте Битрикс, но также этот код триггернёт почти каждый антивирусный сканер. Но если записать этот код немного иначе: <code>$u = $USER; $u-&gt;Authorize(1);</code>&nbsp;&mdash; то, скорее всего, почти каждый антивирусный сканер, ориентированный на поиск по сигнатурам, обосрётся и пропустит данный код. И есть бесчисленное множество способов изменить этот код, чтобы он выполнялся аналогично, но не содержал известную сигнатуру, смекаешь?</p>
<p>И чем же в такой ситуации может быть лучше kvrt? Я затрудняюсь, я не отвечу. Скажу только, что на практике kvrt находит бэкдоры там, где clamav ничего не увидел.</p>The post <a href="https://pavluha.net/freshclam-error-update-failed.html">freshclam ERROR: Update failed</a> first appeared on <a href="https://pavluha.net">Pavluha.Net</a>.]]></content:encoded>
					
					<wfw:commentRss>https://pavluha.net/freshclam-error-update-failed.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Шлёпалка-напоминалка</title>
		<link>https://pavluha.net/shlyopalka-napominalka.html</link>
					<comments>https://pavluha.net/shlyopalka-napominalka.html#respond</comments>
		
		<dc:creator><![CDATA[Павлуха]]></dc:creator>
		<pubDate>Mon, 19 Jun 2023 13:03:48 +0000</pubDate>
				<category><![CDATA[Идеи]]></category>
		<category><![CDATA[Лайфхак]]></category>
		<category><![CDATA[Размышлизмы]]></category>
		<guid isPermaLink="false">https://pavluha.net/?p=2509</guid>

					<description><![CDATA[<p>Каждый раз, когда вы видите шлёпалку, помните, что вы становитесь лучше и делаете шаги к своему совершенствованию Шлёпалка-напоминалка может быть весьма полезным инструментом для напоминания себе о важных уроках и ошибках. Вот как вы можете исользовать шлёпалку-напоминалку: Создайте символическую шлёпалку: &#8230; <a href="https://pavluha.net/shlyopalka-napominalka.html">Читать далее <span class="meta-nav">&#8594;</span></a></p>
The post <a href="https://pavluha.net/shlyopalka-napominalka.html">Шлёпалка-напоминалка</a> first appeared on <a href="https://pavluha.net">Pavluha.Net</a>.]]></description>
										<content:encoded><![CDATA[<blockquote>
<p>Каждый раз, когда вы видите шлёпалку, помните, что вы становитесь лучше и делаете шаги к своему совершенствованию</p>
</blockquote>
<p>Шлёпалка-напоминалка может быть весьма полезным инструментом для напоминания себе о важных уроках и ошибках. Вот как вы можете исользовать шлёпалку-напоминалку:</p>
<p><span id="more-2509"></span></p>
<ul>
<li><strong>Создайте символическую шлёпалку</strong>: Можете выбрать какой-то предмет или символ, который будет напоминать вам о произошедшей ошибке или важном уроке. Это может быть игрушечная шлёпалка, картина или даже стикер, размещенный на вашем рабочем столе или вблизи компьютера.</li>
<li><strong>Визуализируйте ошибку</strong>: Когда вы видите свою символическую шлёпалку, она должна вызывать у вас воспоминания о конкретной ошибке или уроке, который вы извлекли из этой ситуации. Представьте себе прошлую ошибку и вспомните, как вы могли бы избежать её или что вы должны сделать по-другому в будущем.</li>
<li><strong>Установите ритуал</strong>: Создайте небольшой ритуал, связанный с вашей шлёпалкой-напоминалкой. Например, каждый раз, когда вы замечаете её, остановитесь на несколько мгновений, вспомните ошибку и скажите себе несколько слов, направленных на принятие этого урока и обещание себе делать лучше в будущем.</li>
<li><strong>Практикуйте позитивный рост</strong>: Вместо того, чтобы ругать себя или ощущать вину при виде шлёпалки-напоминалки, используйте её как инструмент для позитивного роста. Смотрите на неё как на символ вашей способности учиться и развиваться. Каждый раз, когда вы видите шлёпалку, помните, что вы становитесь лучше и делаете шаги к своему совершенствованию.</li>
</ul>
<p>Шлёпалка-напоминалка не только помогает вам сохранить в памяти уроки из прошлого, но и создаёт позитивное отношение к ошибкам, используя их как возможность для личного роста и развития.</p>
<p>Помимо шлёпалки-напоминалки, конструктивным подходом будет извлечение уроков из ошибки и использование её в качестве возможности для роста и развития. К примеру, стоит уделять пристальное внимание следующим аспектам:</p>
<ol>
<li><strong>Внимательность и проверка данных</strong>: Важно всегда быть внимательным и аккуратным при работе с кодом. Проверяйте входные данные, убедитесь, что вы используете правильные значения и переменные.</li>
<li><strong>Проверка и обновление конфигурации</strong>: Периодически перепроверяйте конфигурационные данные, такие как токены, ключи API и другие параметры, чтобы убедиться, что они актуальны и соответствуют вашим потребностям.</li>
<li><strong>Резервное копирование и сохранение данных</strong>: Если вы имеете дело с важными данными или настройками, убедитесь, что у вас есть соответствующие резервные копии. Это позволит вам восстановиться быстро, если что-то пойдет не так.</li>
<li><strong>Уроки из прошлого опыта</strong>: Важно извлекать уроки из своих предыдущих ошибок и не повторять их в будущем. Каждая ошибка может стать ценным уроком и помочь вам стать более опытным и надежным разработчиком.</li>
<li><strong>Умение принять и исправить ошибки</strong>: Важно принять факт, что ошибки случаются, и необходимо быть готовыми к их исправлению. Реакция на ошибки должна быть конструктивной и ориентированной на поиск решений, а не на самокритику и разочарование.</li>
</ol>
<p>Уделяя внимания этим пунктам в повседневной рутине, вы можете развить более внимательный и осторожный подход к разработке и управлению вашим кодом, что поможет вам избежать (по крайней мере, сократить число) ошибок в будущем.</p>The post <a href="https://pavluha.net/shlyopalka-napominalka.html">Шлёпалка-напоминалка</a> first appeared on <a href="https://pavluha.net">Pavluha.Net</a>.]]></content:encoded>
					
					<wfw:commentRss>https://pavluha.net/shlyopalka-napominalka.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Успеха всем, кому на это денег хватит</title>
		<link>https://pavluha.net/uspeha-vsem-komu-na-eto-deneg-hvatit.html</link>
					<comments>https://pavluha.net/uspeha-vsem-komu-na-eto-deneg-hvatit.html#respond</comments>
		
		<dc:creator><![CDATA[Павлуха]]></dc:creator>
		<pubDate>Tue, 31 Jan 2023 18:19:35 +0000</pubDate>
				<category><![CDATA[Размышлизмы]]></category>
		<category><![CDATA[Блогинг]]></category>
		<category><![CDATA[Хостинг]]></category>
		<guid isPermaLink="false">https://pavluha.net/?p=2490</guid>

					<description><![CDATA[<p>Иногда люблю походить по старым ссылкам в подписи комментариев&#160;&#8212; посмотреть, кто из ранее активных блогеров до сих пор пишет посты. Когда то было модно после каждого своего поста пройтись по стенд-алон блогам, покомментировать&#160;&#8212; напомнить о себе, и получить в ответ &#8230; <a href="https://pavluha.net/uspeha-vsem-komu-na-eto-deneg-hvatit.html">Читать далее <span class="meta-nav">&#8594;</span></a></p>
The post <a href="https://pavluha.net/uspeha-vsem-komu-na-eto-deneg-hvatit.html">Успеха всем, кому на это денег хватит</a> first appeared on <a href="https://pavluha.net">Pavluha.Net</a>.]]></description>
										<content:encoded><![CDATA[<p>Иногда люблю походить по старым ссылкам в подписи комментариев&nbsp;&mdash; посмотреть, кто из ранее активных блогеров до сих пор пишет посты. Когда то было модно после каждого своего поста пройтись по стенд-алон блогам, покомментировать&nbsp;&mdash; напомнить о себе, и получить в ответ десяток-другой комментариев на свой новый пост. Когда-то были модны стенд-алон блоги... Захожу сегодня на один такой блог с жизнеутверждающим названием &laquo;Успеха всем!&raquo; А там:</p>
<p><img fetchpriority="high" decoding="async" src="https://pavluha.net/wp-content/uploads/2023/02/2023-01-31_234841.png" alt="Успеха всем, у кого деньги на хостинг есть" width="1114" height="730" class="aligncenter size-full wp-image-2491" srcset="https://pavluha.net/wp-content/uploads/2023/02/2023-01-31_234841.png 1114w, https://pavluha.net/wp-content/uploads/2023/02/2023-01-31_234841-290x190.png 290w, https://pavluha.net/wp-content/uploads/2023/02/2023-01-31_234841-768x503.png 768w" sizes="(max-width: 1114px) 100vw, 1114px" /></p>
<p><span id="more-2490"></span></p>
<p>Картина для размышлений о жизни, об успехе, и вообще. Можно в музей. И назвать: &laquo;42&raquo;.</p>
<p>Начал писать пост и немного поменьжевался за рекламу хостинга Джино на скрине, потому что не в ней была подоплёка. Хотел замазать. Но не стал, т.к. с хостингом этим дружу уж не знаю сколько&nbsp;&mdash; лет 20. По крайней мере, парой кликов проверил, что первый запрос в суппорт им написал в 2008 году:</p>
<p><img decoding="async" src="https://pavluha.net/wp-content/uploads/2023/02/2023-02-01_002353.png" alt="запрос в суппорт Джино 2008" width="1166" height="654" class="aligncenter size-full wp-image-2493" srcset="https://pavluha.net/wp-content/uploads/2023/02/2023-02-01_002353.png 1166w, https://pavluha.net/wp-content/uploads/2023/02/2023-02-01_002353-290x163.png 290w, https://pavluha.net/wp-content/uploads/2023/02/2023-02-01_002353-768x431.png 768w" sizes="(max-width: 1166px) 100vw, 1166px" /></p>
<p>А они сейчас за обзоры &laquo;Джино.Плюсы&raquo; отсыпают. Мне вряд ли отсыпят, т.к. в условиях перечислены площадки, на которых обзоры засчитываются. И моего блога что-то среди этих площадок нет. Но я всё равно рискну и отправлю обзор на оценку, может просто кому-то приятней станет за свою команду.</p>
<p>Познакомил меня с Джином паренёк один из Аськи, который в те года админил бесплатный хостинг на Джине. Да, был такой, и я даже не спрашиваю, в какую лету канул и по какой причине. Всему своё время и всему свой конец. Это я про бесплатный хостинг, если что. А если говорить про паренька, то он был на 98% своей жизни увлечён работой, и когда узнал, что у меня есть сайты, то, конечно, поинтересовался моим хостером. А потом он показал, как просто у моего недохостера, лишь имея ssh доступ к одному только своему аккаунту, увидеть всех клиентов на сервере и все их сайты с исходными кодами. В то время любые админские слова были для меня чем-то &laquo;на эльфийском&raquo;. И, конечно, я вскоре начал пользоваться хостингом Джино: сначала бесплатным, потом и платным. И пользуюсь до сих пор.</p>
<p>Только сейчас подумал, что удивительно: за все годы не возникло ситуации, которая бы заставила задуматься о переезде с Джино. Хотя, за эти же годы я администрировал много сайтов на других хостингах, и там бывало всякое: от впадения в кому директора, на котором внезапно оказался единственный дубликат ключей от серверов (Мигурхост или Анкельхост&nbsp;&mdash; уже не помню) до рейдерского захвата дата-центра хостера (Айхор хостинг&nbsp;&mdash; вряд ли забуду). А Джино что?&nbsp;&mdash; Живет и здравствует. Ну и здоровья ему!</p>
<p>И, надеюсь, что ещё увижу в онлайне блог с жизнеутверждающим названием &laquo;Успеха всем!&raquo;</p>
<p>P.S. Да, насчёт отзыва как и предполагал, ну и ладно:</p>
<p><img decoding="async" src="https://pavluha.net/wp-content/uploads/2023/02/2023-02-01_140243.png" alt="Джино: отзыв отклонён" width="558" height="323" class="aligncenter size-full wp-image-2501" srcset="https://pavluha.net/wp-content/uploads/2023/02/2023-02-01_140243.png 558w, https://pavluha.net/wp-content/uploads/2023/02/2023-02-01_140243-290x168.png 290w" sizes="(max-width: 558px) 100vw, 558px" /></p>
<p>P.P.S. А &laquo;плюсы&raquo; за отзыв всё равно дали:</p>
<p><img loading="lazy" decoding="async" src="https://pavluha.net/wp-content/uploads/2023/02/2023-02-17_172946.png" alt="Джино плюсы за отзыв" width="650" height="563" class="aligncenter size-full wp-image-2505" srcset="https://pavluha.net/wp-content/uploads/2023/02/2023-02-17_172946.png 650w, https://pavluha.net/wp-content/uploads/2023/02/2023-02-17_172946-290x251.png 290w" sizes="(max-width: 650px) 100vw, 650px" /></p>The post <a href="https://pavluha.net/uspeha-vsem-komu-na-eto-deneg-hvatit.html">Успеха всем, кому на это денег хватит</a> first appeared on <a href="https://pavluha.net">Pavluha.Net</a>.]]></content:encoded>
					
					<wfw:commentRss>https://pavluha.net/uspeha-vsem-komu-na-eto-deneg-hvatit.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Биос или маленький проводочек?</title>
		<link>https://pavluha.net/bios-ili-malenkij-provodochek.html</link>
					<comments>https://pavluha.net/bios-ili-malenkij-provodochek.html#comments</comments>
		
		<dc:creator><![CDATA[Павлуха]]></dc:creator>
		<pubDate>Fri, 14 Oct 2022 16:35:25 +0000</pubDate>
				<category><![CDATA[Потеха]]></category>
		<category><![CDATA[Размышлизмы]]></category>
		<guid isPermaLink="false">https://pavluha.net/?p=2486</guid>

					<description><![CDATA[<p>Определённо: маленький проводочек, поскольку Биос представляет собой базовую систему ввода/вывода, которая обеспечивает эффективную работу аппаратного обеспечения ПК и его взаимосвязь с операционной системой. А маленький проводочек&#160;&#8212; это что? Это вам точно не скажет никто. Каждый, кто скажет, выскажет лишь своё &#8230; <a href="https://pavluha.net/bios-ili-malenkij-provodochek.html">Читать далее <span class="meta-nav">&#8594;</span></a></p>
The post <a href="https://pavluha.net/bios-ili-malenkij-provodochek.html">Биос или маленький проводочек?</a> first appeared on <a href="https://pavluha.net">Pavluha.Net</a>.]]></description>
										<content:encoded><![CDATA[<p>Определённо: маленький проводочек, поскольку Биос представляет собой базовую систему ввода/вывода, которая обеспечивает эффективную работу аппаратного обеспечения ПК и его взаимосвязь с операционной системой. А маленький проводочек&nbsp;&mdash; это что? Это вам точно не скажет никто. Каждый, кто скажет, выскажет лишь своё субъективное представление этого объекта, которое может (и, скорее всего, будет) отличаться от представления другого оратора.</p>The post <a href="https://pavluha.net/bios-ili-malenkij-provodochek.html">Биос или маленький проводочек?</a> first appeared on <a href="https://pavluha.net">Pavluha.Net</a>.]]></content:encoded>
					
					<wfw:commentRss>https://pavluha.net/bios-ili-malenkij-provodochek.html/feed</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title>DateTime::createFromFormat (&#039;U.u&#039;, microtime (true)) вместо DateTime Object иногда возвращает false</title>
		<link>https://pavluha.net/datetime-createfromformat-false.html</link>
					<comments>https://pavluha.net/datetime-createfromformat-false.html#respond</comments>
		
		<dc:creator><![CDATA[Павлуха]]></dc:creator>
		<pubDate>Fri, 19 Aug 2022 14:53:48 +0000</pubDate>
				<category><![CDATA[Web-мастеринг]]></category>
		<category><![CDATA[PHP]]></category>
		<guid isPermaLink="false">https://pavluha.net/?p=2458</guid>

					<description><![CDATA[<p>&#60;?php /* Если ты кодер, то, братишка, я тебе покушать принёс. Забирай вот этот вариант, который всегда возвращает DateTime Object и продолжай кодить, а дальнейшую рефлексию читать не обязательно: */ DateTime::createFromFormat(&#39;0.u00&#160;U&#39;,&#160;microtime())); /* Итак, сабж&#160;&#8212; не хочу повторять этот кусок вредоносного &#8230; <a href="https://pavluha.net/datetime-createfromformat-false.html">Читать далее <span class="meta-nav">&#8594;</span></a></p>
The post <a href="https://pavluha.net/datetime-createfromformat-false.html">DateTime::createFromFormat ('U.u', microtime (true)) вместо DateTime Object иногда возвращает false</a> first appeared on <a href="https://pavluha.net">Pavluha.Net</a>.]]></description>
										<content:encoded><![CDATA[<p><span id="more-2458"></span></p>
<style>.postid-2458 .entry-content{font-family: monospace}</style>
<div class="highlight_string"><span style="color: #000000"><span style="color: #0000BB">&lt;?php</span></span></div>
<p><span style="color: #FF8000">/*</span> Если ты кодер, то, братишка, я тебе покушать принёс. Забирай вот этот вариант, который всегда возвращает DateTime Object и продолжай кодить, а дальнейшую рефлексию читать не обязательно: <span style="color: #FF8000">*/</span></p>
<div class="highlight_string"><span style="color: #0000BB">DateTime</span><span style="color: #007700">::</span><span style="color: #0000BB">createFromFormat</span><span style="color: #007700">(</span><span style="color: #DD0000">&#39;0.u00&nbsp;U&#39;</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">microtime</span><span style="color: #007700">()));</span></div>
<p><span style="color: #FF8000">/*</span> Итак, сабж&nbsp;&mdash; не хочу повторять этот кусок вредоносного кода, который легко находится на stackoverflow по тематическим запросам в числе полезных ответов. Но почему вместо DateTime Object иногда получается false? Казалось бы, имеем функцию microtime, которая с параметром true возвращает float-значение: <span style="color: #FF8000">*/</span></p>
<div class="highlight_string"><span style="color: #000000"><span style="color: #007700">echo&nbsp;</span><span style="color: #0000BB">microtime</span><span style="color: #007700">(</span><span style="color: #0000BB">true</span><span style="color: #007700">);<br /></span><span style="color: #FF8000">#&nbsp;1660905894.429<br /></span></span></div>
<p><span style="color: #FF8000">/*</span> И есть метод createFromFormat, который с указанием формата &#39;U.u&#39; должен корректно распознать переданное значение &laquo;1660905894.429&raquo; и создать дату: <span style="color: #FF8000">*/</span></p>
<div class="highlight_string"><span style="color: #000000"><span style="color: #0000BB">print_r</span><span style="color: #007700">(</span><span style="color: #0000BB">DateTime</span><span style="color: #007700">::</span><span style="color: #0000BB">createFromFormat</span><span style="color: #007700">(</span><span style="color: #DD0000">&#39;U.u&#39;</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">1660905894.429</span><span style="color: #007700">));<br /></span><span style="color: #FF8000">#&nbsp;DateTime&nbsp;Object<br />#&nbsp;(<br />#&nbsp;[date]&nbsp;=&gt;&nbsp;2022-08-19&nbsp;10:44:54.429000<br />#&nbsp;[timezone_type]&nbsp;=&gt;&nbsp;1<br />#&nbsp;[timezone]&nbsp;=&gt;&nbsp;+00:00<br />#&nbsp;)</span></span></div>
<p><span style="color: #FF8000">/*</span> <strong>Но в 0.0003% случаев</strong> вместо объекта DateTime мы получим логическое false.</p>
<p>&laquo;Что эти ваши 0.0003%&nbsp;&mdash; вероятность этого ничтожно мала!&raquo;&nbsp;&mdash; Скажет гуманитарий и покинет чат кодеров. А специально для кодеров я написал пример, демонстрирующий, что даже такие редкие события могут приводить к <strong>3 ошибкам в секунду! Каждую секунду!</strong> <span style="color: #FF8000">*/</span></p>
<div class="highlight_string"><span style="color: #000000"><span style="color: #0000BB">$k&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$e&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$max_delta&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0</span><span style="color: #007700">;&nbsp;</span><span style="color: #0000BB">$min_delta&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">1</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">$t0&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">microtime</span><span style="color: #007700">(</span><span style="color: #0000BB">true</span><span style="color: #007700">);<br />while (</span><span style="color: #0000BB">true</span><span style="color: #007700">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$k</span><span style="color: #007700">++;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$t&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">microtime</span><span style="color: #007700">(</span><span style="color: #0000BB">true</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$date&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">DateTime</span><span style="color: #007700">::</span><span style="color: #0000BB">createFromFormat</span><span style="color: #007700">(</span><span style="color: #DD0000">&#39;U.u&#39;</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">$t</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!</span><span style="color: #0000BB">$date</span><span style="color: #007700">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$e</span><span style="color: #007700">++;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$delta&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">$t&nbsp;</span><span style="color: #007700">-&nbsp;(int)</span><span style="color: #0000BB">$t</span><span style="color: #007700">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$min_delta&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">min</span><span style="color: #007700">([</span><span style="color: #0000BB">$delta</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">$min_delta</span><span style="color: #007700">]);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$max_delta&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">max</span><span style="color: #007700">([</span><span style="color: #0000BB">$delta</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">$max_delta</span><span style="color: #007700">]);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">print_r</span><span style="color: #007700">([<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #DD0000">'delta'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">$delta</span><span style="color: #007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #DD0000">'min&nbsp;delta'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">$min_delta</span><span style="color: #007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #DD0000">'max&nbsp;delta'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">$max_delta</span><span style="color: #007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #DD0000">'e/k'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #DD0000">"</span><span style="color: #0000BB">$e</span><span style="color: #DD0000">&nbsp;/&nbsp;</span><span style="color: #0000BB">$k</span><span style="color: #DD0000">"</span><span style="color: #007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #DD0000">'probability'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">=&gt;&nbsp;(</span><span style="color: #0000BB">$e</span><span style="color: #007700">/</span><span style="color: #0000BB">$k</span><span style="color: #007700">*</span><span style="color: #0000BB">100</span><span style="color: #007700">).</span><span style="color: #DD0000">'&nbsp;%'</span><span style="color: #007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #DD0000">'errors&nbsp;per&nbsp;second'&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">$e</span><span style="color: #007700">/(</span><span style="color: #0000BB">$t</span><span style="color: #007700">-</span><span style="color: #0000BB">$t0</span><span style="color: #007700">),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #DD0000">'time'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">$t</span><span style="color: #007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #DD0000">'error'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">DateTime</span><span style="color: #007700">::</span><span style="color: #0000BB">getLastErrors</span><span style="color: #007700">(),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #DD0000">'alter'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">DateTime</span><span style="color: #007700">::</span><span style="color: #0000BB">createFromFormat</span><span style="color: #007700">(</span><span style="color: #DD0000">'U'</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">$t</span><span style="color: #007700">),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}</span></span></div>
<pre style="color:#D3D7CF;background:#2E3436">Array
(
    [delta] => 4.4107437133789E-5
    [min delta] => 6.9141387939453E-6
    [max delta] => 0.99995803833008
    [e/k] => 369 / 116160492
    [probability] => 0.00031766394377875 %
    [errors per second] => 2.2731272386197
    [time] => 1660905794
    [error] => Array
        (
            [warning_count] => 0
            [warnings] => Array
                (
                )

            [error_count] => 1
            [errors] => Array
                (
                    [10] => Data missing
                )

        )

    [alter] => DateTime Object
        (
            [date] => 2022-08-19 10:43:14.000000
            [timezone_type] => 1
            [timezone] => +00:00
        )
)
^C
[DateTime@createFromFormat]# php8.2 ./run.php <span style="display:inline-block;height:1em;width:.5em;vertical-align:middle;animation: 1s cursor-blink step-end infinite"></span>
<style>@keyframes cursor-blink{0%,100%{background:transparent none repeat scroll 0 0}50%{background:#D3D7CF none repeat scroll 0 0}}</style>
</pre>
<p><span style="color: #FF8000">/*</span> В этом примере видно, что во время выполнения скрипта возникают ошибки со скоростью 2.27 штук в секунду (на момент старта было около 3-х, но со временем производительность падает). Возникают они на таких значениях времени, полученных от функции microtime, когда дробная часть времени больше 0.99995006 или меньше 0.00004994&nbsp;&mdash; т.е близка к целому числу настолько, что получается число без точки: значение типа float имеет точность 14 цифр, 10 цифр занимает целая часть, потому на дробную часть остаётся 4 цифры. Потому вместо точного времени 1660905794.00004994 microtime вернёт 1660905794, а вместо 1660905794.99995006 вернет 1660905795&nbsp;&mdash; число без точки, которое не подходит под формат &#39;U.u&#39;, который ожидает метод createFromFormat.</p>
<p>Когда важна точность, а ошибки неприемлемы (у кодера это примерно точно всегда), надо использовать такой вариант: <span style="color: #FF8000">*/</span></p>
<div class="highlight_string"><span style="color: #0000BB">DateTime</span><span style="color: #007700">::</span><span style="color: #0000BB">createFromFormat</span><span style="color: #007700">(</span><span style="color: #DD0000">&#39;0.u00&nbsp;U&#39;</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">microtime</span><span style="color: #007700">()));</span></div>
<p><span style="color: #FF8000">/*</span> Этот вариант я крутил в бесконечном цикле больше 0.5 миллиарда раз, и ни одной ошибки не возникло, хотя были итерации с 000000, и 999999 в дробной части microtime. <span style="color: #FF8000">*/</span></p>
<p><span style="color: #FF8000">/*</span> P.S. Пришу на этот сайт, будто чужой забор обоссываю: редко и по особой нужде, и украдкой, чтобы процесс и результат по возможности никто не увидел. Ж) <span style="color: #FF8000">*/</span></p>The post <a href="https://pavluha.net/datetime-createfromformat-false.html">DateTime::createFromFormat ('U.u', microtime (true)) вместо DateTime Object иногда возвращает false</a> first appeared on <a href="https://pavluha.net">Pavluha.Net</a>.]]></content:encoded>
					
					<wfw:commentRss>https://pavluha.net/datetime-createfromformat-false.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Backit&#160;&#8212; всё?</title>
		<link>https://pavluha.net/backit-vsyo.html</link>
					<comments>https://pavluha.net/backit-vsyo.html#comments</comments>
		
		<dc:creator><![CDATA[Павлуха]]></dc:creator>
		<pubDate>Tue, 31 Aug 2021 05:13:37 +0000</pubDate>
				<category><![CDATA[Размышлизмы]]></category>
		<category><![CDATA[Backit]]></category>
		<category><![CDATA[кэшбэк]]></category>
		<guid isPermaLink="false">https://pavluha.net/?p=2438</guid>

					<description><![CDATA[<p>Дабы меня не обвинили в том, что попробовал первый раз без опыта и понимания получить кэшбэк в Backit&#160;&#8212; не получилось, тут же кидаю обидку. Скажу вам, что зареган в сервисе ещё с тех пор, когда он назывался Epn (название такое, &#8230; <a href="https://pavluha.net/backit-vsyo.html">Читать далее <span class="meta-nav">&#8594;</span></a></p>
The post <a href="https://pavluha.net/backit-vsyo.html">Backit — всё?</a> first appeared on <a href="https://pavluha.net">Pavluha.Net</a>.]]></description>
										<content:encoded><![CDATA[<p>Дабы меня не обвинили в том, что попробовал первый раз без опыта и понимания получить кэшбэк в Backit&nbsp;&mdash; не получилось, тут же кидаю обидку. Скажу вам, что зареган в сервисе ещё с тех пор, когда он назывался Epn (название такое, будто кто-то матюкнулся тихонько&nbsp;&mdash; хорошо, что поменяли). И вот моя история сотрудничества:</p>
<p><figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="614" height="398" src="https://pavluha.net/wp-content/uploads/2021/08/2021-08-31_111241.png" alt="" class="wp-image-2439" srcset="https://pavluha.net/wp-content/uploads/2021/08/2021-08-31_111241.png 614w, https://pavluha.net/wp-content/uploads/2021/08/2021-08-31_111241-290x188.png 290w" sizes="(max-width: 614px) 100vw, 614px" /><figcaption>Специально под кэшбэк сделана учётка в браузере, никаких блокираторов, чисток cookie, установлен плагин backit. Более 1000 р. успешных выводов кэшбэка.</figcaption></figure></p>
<p><span id="more-2438"></span></p>
<p>А месяц назад заказывал телефон с Алихи. Конечно, хотел с приятной мелочью в виде кэшбэка. Пацан к успеху шёл&nbsp;&mdash; не фортануло, не срослось. И &laquo;поиск потерянного заказа&raquo; ничего не дал:</p>
<p><figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="613" height="364" src="https://pavluha.net/wp-content/uploads/2021/08/2021-08-31_115811.png" alt="" class="wp-image-2440" srcset="https://pavluha.net/wp-content/uploads/2021/08/2021-08-31_115811.png 613w, https://pavluha.net/wp-content/uploads/2021/08/2021-08-31_115811-290x172.png 290w" sizes="(max-width: 613px) 100vw, 613px" /><figcaption>Кэшбэк отклонён&nbsp;&mdash; магазин AliExpress в Backit оказался без кэшбэка.</figcaption></figure></p>
<p><figure class="wp-block-pullquote is-style-default"><br />
<blockquote>
<p>Обновлено:</p>
<p><cite>Зарегистрировался в Летишопс, почитал их условия&nbsp;&mdash; написано, что кэшбэк не начисляется за заказы в магазине, например, &laquo;Официальный магазин Tmall&nbsp;&mdash; Техника&raquo;. А я как раз в Тимолле брал телефон. Что ж, похоже что в Бэките та же ситуация</cite></p></blockquote>
<p></figure></p>
<p>Ну что ж, как говорил дедушка Джованни, сдававший мне гест: &laquo;It is not dangerous, but not beautiful&raquo;. Есть же другие кэшбэк-сервисы. Напишите, пожалуйста, в комментариях альтернативу сервису Backit, с которым мы перестали понимать друг друга.</p>
<p>Интересно, кого я прошу? Кто вообще читает мой тухлый бложик? Но, может, хоть спаммеры набегут, разнообразят мой быт. Или работники служб восстановления репутации будут писать мне: &laquo;Удоли, сам дурак что у тебя не получилось&raquo;. Согласен, пишите.</p>The post <a href="https://pavluha.net/backit-vsyo.html">Backit — всё?</a> first appeared on <a href="https://pavluha.net">Pavluha.Net</a>.]]></content:encoded>
					
					<wfw:commentRss>https://pavluha.net/backit-vsyo.html/feed</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
		<item>
		<title>Хост-трекер на python&#160;&#8212; ежеминутный мониторинг доступности сайтов</title>
		<link>https://pavluha.net/host-treker-na-python-ezheminutnyj-monitoring-dostupnosti-sajtov.html</link>
					<comments>https://pavluha.net/host-treker-na-python-ezheminutnyj-monitoring-dostupnosti-sajtov.html#respond</comments>
		
		<dc:creator><![CDATA[Павлуха]]></dc:creator>
		<pubDate>Wed, 16 Sep 2020 21:02:11 +0000</pubDate>
				<category><![CDATA[Web-мастеринг]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[Хостинг]]></category>
		<guid isPermaLink="false">https://pavluha.net/?p=2425</guid>

					<description><![CDATA[<p>Disclamer. Это моя первая программа на пайтоне&#160;&#8212; предпочитаю изучать новое с постановки конкретной задачи, а в процессе углубляться в изучение. На мой взгляд, такой порядок интересней, чем провести часы за чтением туториала перед написанием &#171;хэлло, ворлд&#187;. Но если совсем не &#8230; <a href="https://pavluha.net/host-treker-na-python-ezheminutnyj-monitoring-dostupnosti-sajtov.html">Читать далее <span class="meta-nav">&#8594;</span></a></p>
The post <a href="https://pavluha.net/host-treker-na-python-ezheminutnyj-monitoring-dostupnosti-sajtov.html">Хост-трекер на python — ежеминутный мониторинг доступности сайтов</a> first appeared on <a href="https://pavluha.net">Pavluha.Net</a>.]]></description>
										<content:encoded><![CDATA[<p><strong>Disclamer.</strong> Это моя первая программа на пайтоне&nbsp;&mdash; предпочитаю изучать новое с постановки конкретной задачи, а в процессе углубляться в изучение. На мой взгляд, такой порядок интересней, чем провести часы за чтением туториала перед написанием &laquo;хэлло, ворлд&raquo;. Но если совсем не углубляться в изучение синтаксиса языка, то продуктом, скорее всего, станет глючный говнокод. Считаю, что я соблюдаю баланс между изучением теории и практикой, но сеньор девелопер может считать иначе. В общем, я предупредил, что содержимое поста может оказаться говнокодом, написанным по модели &laquo;AS IS&raquo;.<span id="more-2425"></span></p>
<p><b>TL;DR</b>. Код запускал на python3. Работоспособность на 2-й версии не проверял. В задачу входило использование только стандартных библиотек, чтобы код работал на дешёвом шаред-хостинге, где нет доступа к pip (позже я узнал, что на хостинге надо юзать pip с ключом <code>--user</code>, чтобы добавлять библиотеки пользователю с ограниченными правами).</p>
<p><strong>Задачи программы:</strong></p>
<ol>
<li>Обойти (запросить по http[s]) список url-адресов.</li>
<li>Если код http-ответа или ошибки отличается от полученного в прошлый раз, уведомить об этом в Телеграм и сохранить информацию в лог.</li>
</ol>
<p>Список адресов со статусами доступа и лог решил хранить в базе <strong>sqlite3</strong>, т.к. при всей простоте реализации это возможность хранить данные структурировано, использовать мощь языка запросов SQL и иметь возможность в дальнейшем дополнять функционал: например, добавить отчёты аптайма хостов.</p>
<p>Пока для поставленной задачи достаточно двух таблиц. 1-я для хранения url-адресов:</p>
<pre class="brush:sql">CREATE TABLE `hosts` ( `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, `url` TEXT, `msg` TEXT )</pre>
<p>2-я для для ведения лога:</p>
<pre class="brush:sql">CREATE TABLE `events` ( `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, `host_id` INTEGER NOT NULL, `event` TEXT, `time` TEXT NOT NULL )</pre>
<p>Следующий фрагмент python-кода позволяет подключиться к БД (если базы ещё нет, то автоматически создастся) и выполнить заданный SQL:</p>
<pre class="brush:python">import sqlite3
conn = sqlite3.connect("tracker.db")
cursor = conn.cursor()
cursor.execute("CREATE TABLE ...")
conn.commit()</pre>
<p>А так можно добавить хосты:</p>
<pre class="brush:python">hosts = [['http://host1.ru/'],['https://host2.ru/path']]
cursor.executemany("INSERT INTO hosts (url, msg) VALUES (?, 'New')", hosts)</pre>
<blockquote>
<p>Также для визуальной работы с базами sqlite3 есть удобная софтина на сайте sqlitebrowser.org</p>
</blockquote>
<p>Итак, таблицы готовы, список тестируемых хостов есть. Пишем основной скрипт. Для приготовления кода нам понадобятся:</p>
<pre class="brush:python">import sqlite3
from urllib import request, parse
from urllib.request import urlopen
from urllib.error import HTTPError
from datetime import datetime</pre>
<p>Мне требуется, чтобы при проверке url редирект воспринимался как ошибка. Ведь странно, если поставленный на мониторинг url вдруг стал пересылать на другой адрес. Для этой задачи поможет следующий код:</p>
<pre class="brush:python">class NoRedirectHandler(request.HTTPRedirectHandler):
    def redirect_request(self, req, fp, code, msg, headers, newurl):
        return None
noRedirect = request.build_opener(NoRedirectHandler)</pre>
<p>Теперь чувствительные к редиректу запросы я буду делать через <code>noRedirect.open()</code>, а остальные&nbsp;&mdash; стандартно через <code>urlopen()</code>.</p>
<p>Дело за малым&nbsp;&mdash; обойти список url, и если статус ответа изменился, отправить сообщение в Телеграм и сохранить новый статус. Для отправки в Телеграм послужит такая функция:</p>
<pre class="brush:python">def tg_send(msg):
    base_url = 'https://api.telegram.org/botXXX:YYY/sendMessage?chat_id=123456&amp;text='
    return urlopen(base_url+parse.quote_plus(msg)).status</pre>
<p>Здесь <code>XXX:YYY</code>&nbsp;&mdash; это токен вашего телеграм бота, полученный при его создании, а <code>123456</code>&nbsp;&mdash; id чата вашего аккаунта и бота, в этот чат бот будет отправлять сообщения (т.е. только вам). Узнать id чата можно перейдя по ссылке <code>https://api.telegram.org/botXXX:YYYY/getUpdates</code> (не забыв подставить в ссылку токен). После того, как вы напишете вашему боту любое сообщение, по этой ссылке вы увидите json-данные, в которых <code>"chat":{"id":123456,</code>&nbsp;&mdash; то, что вам нужно.</p>
<p>Приступаем к обходу списка url, соединяемся с базой:</p>
<pre class="brush:python">conn = sqlite3.connect("tracker.db")
conn.row_factory = sqlite3.Row
cursor = conn.cursor()</pre>
<p>Здесь <code>row_factory</code> нам нужно, чтобы к полученным из БД полям обращаться по их имени, а не по номеру. Далее&nbsp;&mdash; цикл перебора хостов:</p>
<pre class="brush:python">for host in cursor.execute("SELECT * FROM hosts").fetchall():
    url = host['url']
    try:
        response = urlopen(url, timeout=20)
    except (HTTPError) as e:
        msg = str(e)
    except Exception as e:
        msg = str(e.__class__.__name__)+': '+str(getattr(e, 'reason', e))
    else:
        msg = 'OK '+str(response.status)
    if host['msg'] == msg: continue
    cursor.execute("UPDATE hosts SET msg = ? WHERE id = ?", (msg, host['id']))
    cursor.execute("INSERT INTO events (host_id, event, time) VALUES (?, ?, ?)", (host['id'], msg, datetime.now()))
    conn.commit()
    tg_send(url+' '+msg)</pre>
<p>Если не использовать <code>.fetchall()</code> в запросе хостов, то цикл будет работать до первого случая обнаружения изменившегося статуса хоста (<code>msg</code>)&nbsp;&mdash; т.к. при этом мы пишем в таблицы и меняем <code>cursor</code>. Трудноуловимый баг, особенно когда только учишься в python. <code>timeout=20</code> нужен, чтобы не ждать дольше 20 секунд ответа от хоста. Я нетерпеливый. Если <code>msg</code> не изменился с прошлой проверки (такой же, как в БД у хоста), то с помощью <code>continue</code> переходим к следующему хосту, не выполняя дальнейшие инструкции. Если же <code>msg</code> изменился, делаем запрос на обновление записи в БД, на добавлление ивента, <code>conn.commit()</code> выполняет запросы, а <code>tg_send(url+' '+msg)</code> сообщает в телеграм.</p>
<p>Полученный <code>tracker.py</code> запускаем в консоли командой <code>python3 tracker.py</code>, если работает без ошибок, записываем в <code>crontab</code> на ежеминутное выполнение. И спим спокойные за свои сайты, пока сигнал тревоги не разбудит. Кстати, Телеграм, помимо простого API, мне нравится возможностью индивидуальной настройки уведомлений для каждого чата. В том числе, уведомления важных чатов можно сделать со звуком или вибрацией даже в беззвучном режиме телефона.</p>The post <a href="https://pavluha.net/host-treker-na-python-ezheminutnyj-monitoring-dostupnosti-sajtov.html">Хост-трекер на python — ежеминутный мониторинг доступности сайтов</a> first appeared on <a href="https://pavluha.net">Pavluha.Net</a>.]]></content:encoded>
					
					<wfw:commentRss>https://pavluha.net/host-treker-na-python-ezheminutnyj-monitoring-dostupnosti-sajtov.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Автоматическая проверка баз MySQL после перезагрузки сервера</title>
		<link>https://pavluha.net/avtomaticheskaya-proverka-baz-mysql-posle-perezagruzki-servera.html</link>
					<comments>https://pavluha.net/avtomaticheskaya-proverka-baz-mysql-posle-perezagruzki-servera.html#respond</comments>
		
		<dc:creator><![CDATA[Павлуха]]></dc:creator>
		<pubDate>Wed, 04 Mar 2020 05:52:07 +0000</pubDate>
				<category><![CDATA[Web-мастеринг]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[VPS]]></category>
		<guid isPermaLink="false">https://pavluha.net/?p=2416</guid>

					<description><![CDATA[<p>Такая проверка мне понадобилась после того, как настроил автоматическую перезагрузку сервера в том случае, когда он 2 минуты не отвечает на запросы. И в любом другом случае, когда осуществляется reboot, что-то может пойти не так, СУБД не завершит вовремя транзакции, &#8230; <a href="https://pavluha.net/avtomaticheskaya-proverka-baz-mysql-posle-perezagruzki-servera.html">Читать далее <span class="meta-nav">&#8594;</span></a></p>
The post <a href="https://pavluha.net/avtomaticheskaya-proverka-baz-mysql-posle-perezagruzki-servera.html">Автоматическая проверка баз MySQL после перезагрузки сервера</a> first appeared on <a href="https://pavluha.net">Pavluha.Net</a>.]]></description>
										<content:encoded><![CDATA[<p>Такая проверка мне понадобилась после того, как настроил автоматическую перезагрузку сервера в том случае, когда он 2 минуты не отвечает на запросы. И в любом другом случае, когда осуществляется reboot, что-то может пойти не так, СУБД не завершит вовремя транзакции, активная в момент перезагрузки таблица окажется повреждённой, и любые операции с участием этой таблицы обернутся фэйлом. А чаще всего достаточно mysqlcheck, чтобы вернуть сломанной таблице её нулевые.</p>
<p><span id="more-2416"></span></p>
<p>Для реализации сабжа достаточно залогиниться root-ом (в общем случае) по ssh и выполнить:</p>
<p><code>crontab -e</code></p>
<blockquote>
<p>Для самых маленьких: если откроется редактор vim (поймёте это по 2-м вопросам, которые зададите сами себе: &laquo;как тут что-то написать?&raquo;, &laquo;а как выйти отсюда?&raquo;). Наберите на клавиатуре заклинание от vim: <code>:q</code>+<code>Enter</code>, затем выполните <code>EDITOR=nano crontab -e</code></p>
</blockquote>
<p>В редакторе записей crontab добавьте такую:</p>
<pre class="brush:shell">@reboot sleep 5.5m &amp;&amp; mysqlcheck -pPASSWORD --auto-repair --optimize --all-databases &gt; /root/mysqlcheck.log 2&gt;/dev/null</pre>
<p>Вместо <code>PASSWORD</code>&nbsp;&mdash; ваш root-пароль к MySQL (именно пользователя БД, а не системного). Хранится этот пароль обычно в файле <code>/root/.my.cnf</code>&nbsp;&mdash; проверено в bitrixVM, ISPmanager, VestaCP.</p>
<p>В качестве бонуса можете подумать над вопросом, как прислать уведомление в том случае, когда выполнение mysqlcheck недостаточно. К примеру, когда в mysqlcheck.log обнаруживается такое:</p>
<blockquote>
<p>Repairing tables<br />
db.table<br />
error    : Can&#39;t create new tempfile: &#39;./db/table.TMD&#39;<br />
status   : Operation failed</p>
</blockquote>
<p>Давшему ответ на этот вопрос в комментариях, вечная ссылка и упоминание в посте.</p>The post <a href="https://pavluha.net/avtomaticheskaya-proverka-baz-mysql-posle-perezagruzki-servera.html">Автоматическая проверка баз MySQL после перезагрузки сервера</a> first appeared on <a href="https://pavluha.net">Pavluha.Net</a>.]]></content:encoded>
					
					<wfw:commentRss>https://pavluha.net/avtomaticheskaya-proverka-baz-mysql-posle-perezagruzki-servera.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Частичное ЧПУ на сайте WP</title>
		<link>https://pavluha.net/chastichnoe-chpu-na-sajte-wp.html</link>
					<comments>https://pavluha.net/chastichnoe-chpu-na-sajte-wp.html#respond</comments>
		
		<dc:creator><![CDATA[Павлуха]]></dc:creator>
		<pubDate>Wed, 19 Feb 2020 03:15:12 +0000</pubDate>
				<category><![CDATA[Web-мастеринг]]></category>
		<category><![CDATA[SEO]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[ЧПУ]]></category>
		<guid isPermaLink="false">https://pavluha.net/?p=2406</guid>

					<description><![CDATA[<p>В контексте SEO и вебмастеринга, ЧПУ означает &#171;человеко-понятный УРЛ&#187;. В английском аналогичная аббревиатура: SEF URL, т.е. &#171;SEO friendly URL&#187; (дружественный к поисковому продвижению URL). Такое название не случайно, т.к. URL наряду с заголовком и описанием страницы является одним из элементов, &#8230; <a href="https://pavluha.net/chastichnoe-chpu-na-sajte-wp.html">Читать далее <span class="meta-nav">&#8594;</span></a></p>
The post <a href="https://pavluha.net/chastichnoe-chpu-na-sajte-wp.html">Частичное ЧПУ на сайте WP</a> first appeared on <a href="https://pavluha.net">Pavluha.Net</a>.]]></description>
										<content:encoded><![CDATA[<p>В контексте SEO и вебмастеринга, ЧПУ означает &laquo;человеко-понятный УРЛ&raquo;. В английском аналогичная аббревиатура: SEF URL, т.е. &laquo;SEO friendly URL&raquo; (дружественный к поисковому продвижению URL). Такое название не случайно, т.к. URL наряду с заголовком и описанием страницы является одним из элементов, попадающих в поисковый сниппет, потому ключевое слово в URL существенно добавляет релевантности странице.</p>
<p><div id="attachment_2407" style="width: 557px" class="wp-caption aligncenter"><img aria-describedby="caption-attachment-2407" loading="lazy" decoding="async" class="size-full wp-image-2407" src="https://pavluha.net/wp-content/uploads/2020/02/Search-Engine-Friendly-URLs.jpg" alt="Search Engine Friendly URLs" width="547" height="322" srcset="https://pavluha.net/wp-content/uploads/2020/02/Search-Engine-Friendly-URLs.jpg 547w, https://pavluha.net/wp-content/uploads/2020/02/Search-Engine-Friendly-URLs-290x171.jpg 290w" sizes="(max-width: 547px) 100vw, 547px" /><p id="caption-attachment-2407" class="wp-caption-text">ЧПУ повышает релевантность страницы</p></div></p>
<p><span id="more-2406"></span></p>
<p>Потому ЧПУ&nbsp;&mdash; это <a href="https://pavluha.net/sposobyi-prodvizheniya-saytov.html">хорошо для SEO</a>, и на новом сайте настоятельно рекомендуется включать именно такую структуру адресов. Но на старом сайте могут быть тысячи страниц, и не всегда есть возможность перейти на новую структуру адресации без потерь. В этом случае для успешного продвижения некоторых страниц поможет частичное включение ЧПУ.</p>
<p>У меня недавно возникла такая необходимость. Как обычно, скорость решения имела приоритет над удобством, так родился следующий кусок кода, который я поместил в <code>/wp-content/mu-plugins/custom_sef_url.php</code></p>
<blockquote>
<p>Код php-файлов из папки mu-plugins выполняется независимо от подключенных тем и плагинов, на этапе загрузки страницы, когда ещё не загрузился и не сработал код плагинов и файла functions.php активной темы</p>
</blockquote>
<pre class="brush:php">&lt;?
function custom_sef_url() {
    return [
        8187 =&gt; 'site-security-control'
    ];
}

add_filter('request', function($query_vars) {
    $post_slug_by_id = custom_sef_url();
    if ($query_vars['p'] ?? 0 and $post_slug_by_id[$query_vars['p']] ?? 0) {
        $permalink = get_home_url().'/'.$post_slug_by_id[$query_vars['p']];
        wp_redirect($permalink, 301);
        die;
    }
    $post_id_by_slug = array_flip($post_slug_by_id);
	$request = ltrim(parse_url($_SERVER['REQUEST_URI'])['path'], '/');
	if($request and $post_id_by_slug[$request] ?? 0) {
		$query_vars['p'] = $post_id_by_slug[$request];
	}
	return $query_vars;
});
add_filter('post_link', function ($permalink, $post, $leavename) {
    $post_slug_by_id = custom_sef_url();
    if ($post_slug_by_id[$post-&gt;ID] ?? 0) {
        $permalink = get_home_url().'/'.$post_slug_by_id[$post-&gt;ID];
    }
    return $permalink;
}, 10, 3);</pre>
<p>В данном случае переход на ЧПУ срабатывает для поста с <code>ID = 8187</code>. URL до добавления этого кода: <code>/?p=8187</code>, URL после: <code>/site-security-control</code>, и конечно с помощью этого кода происходит редирект с кодом 301 (постоянное перенаправление) со старого URL на новый. Новые адреса добавляются в начало кода, например:</p>
<pre class="brush:php">&lt;?
function custom_sef_url() {
    return [
        8187 =&gt; 'site-security-control',
        555 =&gt;  'some-sef-url',
        777 =&gt;  'your-keywords-here',
    ];
}</pre>
<blockquote>
<p>В коде используется синтаксис php7, потому для работы на устаревшем php5 придётся кое-что подправить. Но у меня не продакшен, предназначенный для 99% охвата платформ, так что&nbsp;&mdash; <strong>as is</strong></p>
</blockquote>
<p>Как я уже говорил, удобство решения в этом случае мне было не принципиально, главное&nbsp;&mdash; функциональность. Пройдёмся кратко по функционалу. Здесь добавляется наш фильтр на событие <code>request</code> (когда мы запрашиваем контент из базы, нам нужно указать WP, что <code>some-sef-url</code>&nbsp;&mdash; это пост <code>555</code>). Для этого мы создаём переменную запроса <code>$query_vars['p']</code>, которую передаём ID страницы, если запрошен наш URL. А если запрос происходит по старому адресу (переменная <code>p</code> задана в URL), то нужно осуществить 301 редирект на <code>some-sef-url</code>. Также добавляется фильтр к функции <code>post_link</code>, которая отвечает за генерацию ссылок во всех элементах навигации, в т.ч. на карте сайта и <a href="https://pavluha.net/meta-teg-canonical-dlya-lyubyih-tipov-stranits-wp-a-ne-tolko-dlya-singular.html">в мета-теге rel="cannonical"</a>. Соответственно, при генерации ссылок нам желательно возвращать каноничную ссылку <code>/your-keywords-here</code> вместо <code>/?=777</code>. Для этого и служит фильтр. Вот, собственно, и всё.</p>
<p>Для удобства вы можете создать произвольное поле (<code>custom fields</code>), чтобы прописывать ЧПУ для нужных страниц во время их редактирования из интерфейса админки. Возможно, добавите уникальное ЧПУ <a href="https://pavluha.net/taksonomiya-ne-naydeno.html">для таксономии</a>. Уверен, если вам такой функционал необходим, то вы детишки взрослые и сами его допишете.</p>The post <a href="https://pavluha.net/chastichnoe-chpu-na-sajte-wp.html">Частичное ЧПУ на сайте WP</a> first appeared on <a href="https://pavluha.net">Pavluha.Net</a>.]]></content:encoded>
					
					<wfw:commentRss>https://pavluha.net/chastichnoe-chpu-na-sajte-wp.html/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>LMDE xfce&#160;&#8212; первое погружение</title>
		<link>https://pavluha.net/lmde-xfce-pervoe-pogruzhenie.html</link>
					<comments>https://pavluha.net/lmde-xfce-pervoe-pogruzhenie.html#comments</comments>
		
		<dc:creator><![CDATA[Павлуха]]></dc:creator>
		<pubDate>Thu, 16 Jan 2020 02:41:50 +0000</pubDate>
				<category><![CDATA[Web-мастеринг]]></category>
		<category><![CDATA[Компьютеринг]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[LMDE]]></category>
		<category><![CDATA[ssh]]></category>
		<category><![CDATA[VPS]]></category>
		<category><![CDATA[Xfce]]></category>
		<guid isPermaLink="false">https://pavluha.net/?p=2391</guid>

					<description><![CDATA[<p>Давно хотел пересесть с Винды на Линукс. Не скажу точно, зачем. Наверное, от избытка свободного времени и нехватки приключений в оффлайне. На виртуалку то и дело ставлю что-то новенькое, но даже изучение интерфейса приводит к столкновению с глюками и недопониманию. &#8230; <a href="https://pavluha.net/lmde-xfce-pervoe-pogruzhenie.html">Читать далее <span class="meta-nav">&#8594;</span></a></p>
The post <a href="https://pavluha.net/lmde-xfce-pervoe-pogruzhenie.html">LMDE xfce — первое погружение</a> first appeared on <a href="https://pavluha.net">Pavluha.Net</a>.]]></description>
										<content:encoded><![CDATA[<p>Давно хотел пересесть с Винды на Линукс. Не скажу точно, зачем. Наверное, от избытка свободного времени и нехватки приключений в оффлайне. На виртуалку то и дело ставлю что-то новенькое, но даже изучение интерфейса приводит к столкновению с глюками и недопониманию. В итоге, каждый раз задаю себе вопрос: &laquo;Зачем мне эта жопная боль?&raquo;&nbsp;&mdash; И виртуалка отправляется в утиль. Но в этот раз к очередному прыжку в тёмные воды Линукс подтолкнул практический смысл. Уже несколько лет я администрирую разные VPS с операционками Debian или CentOS. И решил, что будет удобнее коннектиться к VPS из близкой по архитектуре ОС, да и скиллы полезные закреплю. И это было отличное решение.</p>
<p><span id="more-2391"></span></p>
<p>Действительно, ОС Линукс во многом упростила работу с VPS, которые тоже на Линукс. Например, для упрощения соединения по ssh с сервером достаточно:</p>
<p><div id="attachment_2394" style="width: 195px" class="wp-caption alignleft"><img aria-describedby="caption-attachment-2394" loading="lazy" decoding="async" class="wp-image-2394 size-full" src="https://pavluha.net/wp-content/uploads/2020/01/Panel-s-ssh-dostupami.jpg" alt="" width="185" height="268" /><p id="caption-attachment-2394" class="wp-caption-text">Панель команд для соединения с VPS</p></div></p>
<ul>
<li>дать удалённому хосту понятное наименование в <code>~/.ssh/config</code> (например, <code>Host 0120</code>);</li>
<li>сгенерировать ключ командой <code>ssh-keygen</code>, затем закинуть его на сервер командой <code>ssh-copy-id 0120</code>;</li>
<li>после проделанной работы соединение по ssh с VPS происходит без пароля по ключу одной командой, которую легко запомнить: <code>ssh 0120</code>. Но если и эту команду затруднительно каждый раз вводить, можно сделать для неё ярлык или кнопку на панели. Также командой <code>sshfs 0120:/ /mnt/vps/0120 -o reconnect</code> можно примонтировать файловую систему VPS к своей системе и сделать удалённую систему такой же доступной, как флэшка.</li>
</ul>
<p><div id="attachment_2397" style="width: 796px" class="wp-caption aligncenter"><img aria-describedby="caption-attachment-2397" loading="lazy" decoding="async" class="size-full wp-image-2397" src="https://pavluha.net/wp-content/uploads/2020/01/sshfs-vps.jpg" alt="" width="786" height="499" srcset="https://pavluha.net/wp-content/uploads/2020/01/sshfs-vps.jpg 786w, https://pavluha.net/wp-content/uploads/2020/01/sshfs-vps-290x184.jpg 290w, https://pavluha.net/wp-content/uploads/2020/01/sshfs-vps-768x488.jpg 768w" sizes="(max-width: 786px) 100vw, 786px" /><p id="caption-attachment-2397" class="wp-caption-text">Удалённая ФС доступна как флэшка</p></div></p>
<blockquote>
<p>Это обзорная статья, а не туториал, потому перед использованием незнакомых команд сначала вбиваем их в поисковую строку Гугла. Есть нюансы.</p>
</blockquote>
<p>Не знаю, возможно ли получить такой же результат в Окошках при помощи софта и костылей, но вышеописанные фичи позволили мне преодолеть психологический барьер входа в Nix Based Systems и ощутить их мощь и красоту:</p>
<ul>
<li>на функциональном уровне, программы доступны для консольного ввода/вывода, что позволяет объединять их в кастомизируемые конгломераты;</li>
<li>на визуальном уровне, настраивается каждая буква и каждая пикча. При желании и умении искать, можно создать себе удобный пульт управления миром.</li>
</ul>
<p><img loading="lazy" decoding="async" src="https://pavluha.net/wp-content/uploads/2020/01/LMDE-xfce.jpg" alt="" width="1280" height="720" class="aligncenter size-full wp-image-2399" srcset="https://pavluha.net/wp-content/uploads/2020/01/LMDE-xfce.jpg 1280w, https://pavluha.net/wp-content/uploads/2020/01/LMDE-xfce-290x163.jpg 290w, https://pavluha.net/wp-content/uploads/2020/01/LMDE-xfce-768x432.jpg 768w" sizes="(max-width: 1280px) 100vw, 1280px" /><br />
В комментариях можем обсудить отдельные вопросы, коих у меня возник вагон после первого погружения в LMDE xfce. На часть их я уже нашёл ответы, а остальную часть ответов ещё предстоит найти. А какие вопросы заинтересовали вас? Также интересно узнать ваш опыт работы в Никсах.</p>The post <a href="https://pavluha.net/lmde-xfce-pervoe-pogruzhenie.html">LMDE xfce — первое погружение</a> first appeared on <a href="https://pavluha.net">Pavluha.Net</a>.]]></content:encoded>
					
					<wfw:commentRss>https://pavluha.net/lmde-xfce-pervoe-pogruzhenie.html/feed</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
	</channel>
</rss>
