<?xml version="1.0" encoding="utf-8"?> 
<rss version="2.0"
  xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
  xmlns:atom="http://www.w3.org/2005/Atom">

<channel>

<title>Лайвлупинг, медиапродакшн и все эти ваши компьютеры: заметки с тегом КЭНК</title>
<link>https://www.batishchev.ru/blog/tags/kenk/</link>
<description>Что такое КЭНК? Читайте манифест КЭНК в посте https://batishchev.ru/blog/all/krovavy-enterprayz-na-kolenke/</description>
<author></author>
<language>ru</language>
<generator>Aegea 11.4 (v4171)</generator>

<itunes:subtitle>Что такое КЭНК? Читайте манифест КЭНК в посте https://batishchev.ru/blog/all/krovavy-enterprayz-na-kolenke/</itunes:subtitle>
<itunes:image href="" />
<itunes:explicit></itunes:explicit>

<item>
<title>Детектим версию WordPress без регистрации и смс</title>
<guid isPermaLink="false">3709</guid>
<link>https://www.batishchev.ru/blog/all/detektim-versiyu-wordpress-bez-registracii-i-sms/</link>
<pubDate>Wed, 15 Oct 2025 17:57:59 +0300</pubDate>
<author></author>
<comments>https://www.batishchev.ru/blog/all/detektim-versiyu-wordpress-bez-registracii-i-sms/</comments>
<description>
&lt;p&gt;Пока большие свершения прячутся под NDA, расскажу небольшое ноу-хау про вордпресс.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/1669183742217244224.jpg" width="512" height="512" alt="" /&gt;
&lt;div class="e2-text-caption"&gt;Бессмертный девиз всех велосипедостроителей&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Для выявления уязвимостей вордпресса есть хороший инструмент &lt;a href="https://wpscan.com/"&gt;WPScan&lt;/a&gt; — тула, которая умеет показать проблемы в компонентах и настройке сайтов на базе WP. Даже с бесплатным тарифным планом Researcher и ограничением в 25 API вызовов в день, на небольших инфраструктурах или в личных целях вполне себе можно уместиться,  а для базовой диагностики и ключа апи не надо.&lt;/p&gt;
&lt;p&gt;Но что если по каким-то причинам WPScan вы пользоваться не хотите или не можете, а руками внутрь сайтов ходить неудобно, нельзя или некогда?&lt;/p&gt;
&lt;p&gt;Грубо оценить ситуацию можно по версии ядра движка. Её косвенно, но с достаточной точностью, можно узнать по версиям включаемых в код библиотек и стилей, которые чаще всего доступны в коде страниц (если админ не заморочился этим отдельно). Лучше смотреть в код админки, но можно и на главной странице поймать полезное. Как правило в коде есть какие-то из строчек, по которым версия выявляется, вот подобранный эмпирически список шаблонов (добавьте свои по вкусу):&lt;/p&gt;
&lt;pre&gt;
login.min.css?ver=
l10n.min.css?ver=
forms.min.css?ver=
buttons.min.css?ver=
dashicons.min.css?ver=
password-strength-meter.min.js?ver=
wp-util.min.js?ver=
user-profile.min.js?ver=
wp-emoji-release.min.js?ver=
style.min.css?ver=
meta name=«generator» content=«WordPress 
&lt;/pre&gt;
&lt;p&gt;Смотрим на примере рандомного сайта из интернетов по запросу „блог на WordPress“:&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;div class="fotorama" data-width="1814" data-ratio="4.3922518159806"&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/2025-10-14-wp.png" width="1814" height="413" alt="" /&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/2025-10-14-wp2.png" width="1814" height="413" alt="" /&gt;
&lt;/div&gt;
&lt;div class="e2-text-caption"&gt;Детектор Версии Вордпресса из пластилина и крышечек от колы&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Собираем всё что нашли, сортируем, выявляем самую старую. А дальше ищем её на ресурсе издателей WordPress — &lt;a href="https://api.wordpress.org/core/stable-check/1.0/"&gt;&lt;a href="https://api.wordpress.org/core/stable-check/1.0/"&gt;https://api.wordpress.org/core/stable-check/1.0/&lt;/a&gt;&lt;/a&gt;, и смотрим статус.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/2025-10-14-636.png" width="399" height="387" alt="" /&gt;
&lt;div class="e2-text-caption"&gt;Версия 6.3.6 — так себе уже версия!&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Почему это работает: идущие в комплекте стили и скрипты обычно обновляются вместе с ядром. А если на сайте старое ядро — то скорее всего админы не следят за апдейтами, и обновления плагинов уж тем более не ставят. А значит пришла пора прийти к админам с рекомендациями (или требованиями) обновить всё и засыпать дустом поверх.&lt;/p&gt;
&lt;p&gt;Естественно, всё вышеописанное нужно делать силами роботов с помощью того любимого микроскопа для автоматизации, который у вас под руками, благо кода тут на один экран. В результате у вас получится бесплатный DIY-велосипед в лучших традициях &lt;a href="https://batishchev.ru/blog/all/krovavy-enterprayz-na-kolenke/"&gt;КЭНК-подхода&lt;/a&gt;. Но лучше, конечно же, использовать нормальные инструменты.&lt;/p&gt;
&lt;p&gt;Слава роботам!&lt;/p&gt;
</description>
</item>

<item>
<title>Вестник бытовой ИБ-механизации</title>
<guid isPermaLink="false">2958</guid>
<link>https://www.batishchev.ru/blog/all/vestnik-bytovoy-ib-mehanizacii/</link>
<pubDate>Tue, 12 Aug 2025 19:13:35 +0300</pubDate>
<author></author>
<comments>https://www.batishchev.ru/blog/all/vestnik-bytovoy-ib-mehanizacii/</comments>
<description>
&lt;p&gt;Добрый вечер, товарищи! С вами вестник бытовой ИБ-механизации. Сегодня мы берем интервью у слесаря-механизатора авэыксов второй категории, Кенколая Овечкина. Кенколай, расскажите про своё рационализаторское предложение.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/2025-08-12-image-9.png" width="1280" height="731" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Кенколай: ну дак это, тык-мык, как его, ну вобщем мы таски ансиблой крутим, а тасок столько, что и не усмотреть. А потом бригадир приходит в конце квартала и говорит, мол так-растак, почему серваки не обновлены? Ну вот я и думаю, нешто я робота на павершелле не запилю, который отчёты по апихе из AWX забирать будет, проблемы в них находить, да тикеты в джиру отправлять? Ну, знамо дело, сходил на «/api/v2/jobs/?started__gte=$Since», джейсон десериализовал, статусы отфильтровал, проблемы регескпом по ’FAILED’ и ’UNREACHABLE’ нашел и разделил, ну и в тикетомёт это всё.&lt;/p&gt;
&lt;p&gt;Теперича один робот следит за тем как другой робот работает, и бригадира кожаного зовёт, ежели что не туда вильнуло. А ежели не вильнуло — то и спросу нет!&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/2025-08-12-image-8.png" width="1280" height="731" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Спасибо, Кенколай! Ничего не понятно, но очень интересно! А в следующем выпуске мы обсудим как следить за протухающими сертификатами при помощи скриптов и едрени фени!&lt;/p&gt;
</description>
</item>

<item>
<title>ExchangeDocSaver: еще одна история про людей и роботов</title>
<guid isPermaLink="false">1104</guid>
<link>https://www.batishchev.ru/blog/all/exchangedocsaver-esche-odna-istoriya-pro-lyudey-i-robotov/</link>
<pubDate>Thu, 05 Dec 2024 12:27:42 +0300</pubDate>
<author></author>
<comments>https://www.batishchev.ru/blog/all/exchangedocsaver-esche-odna-istoriya-pro-lyudey-i-robotov/</comments>
<description>
&lt;p&gt;Несколько лет назад, за кружкой крепкого чая у мангала, мой старинный друг пожаловался на одну из обязанностей на работе: при общении с контрагентами по электронной почте у них возникают артефакты этого общения — счета и прочие документы — которые нужно из почтовых сообщений сохранять на сетевой диск. Причем в компании исторически сложился процесс документооборота, когда эти файлы должны попасть в свое место в иерархии сетевого диска, где за них уже неистово хватаются другие отделы, а иерархия эта не самая простая (хотя будущее место документа определяется по номеру контракта однозначно, по схеме «ну это все знают»).&lt;/p&gt;
&lt;p&gt;В общем, выступает мой друг таким вот высокоинтеллектуальным сортировщиком и раскладывальщиком файликов, в фоне во время других (гораздо более сложных и изящных) задач по заключению договоров, преодолению препонов и прочих зарабатываний мильёнов. Ну натурально вот: придумал как привезти из стран заморских жирафа по частям, и чтобы по документам это была канарейка (задача безусловно творческая), а потом не забывай в течение пары месяцев доки по этому проекту из последующей переписки «правой кнопкой мыши — сохранить как — найти папку — блин где же она — а вот — сохранить»&lt;/p&gt;
&lt;p&gt;А что — говорю ему я, потягивая чай у мангала — задачка-то похоже автоматизируется. Можно научить роботов пырить в почтовый ящик по Exchange Web Services (EWS) Managed API, находить непрочитанные письма, понимать какие из них содержат нужные документы (а какие — нет), а также к какому контракту они относятся, ну а по номеру контракта и место на сетевом диске найти можно. Контракт конечно может быть в письме и вложениях непонятно где упомянут, но раз человек справляется с поиском — то и робота настропалить на это дело сможем.&lt;/p&gt;
&lt;p&gt;Естественно, согласно всем заветам планирования процессов разработки, реализация алгоритма заняла в три раза больше времени, чем задумывалось. Естественно, так как исходные письма посылают человеки, ошибающиеся и ненадёжные, и не все 100% сообщений оформляются как надо, часть писем (довольно малая) алгоритмом пропускается. Но в целом, за несколько дней рьяного &lt;a href="https://batishchev.ru/blog/tags/kenk/"&gt;кэнк-программинга&lt;/a&gt; с использованием наработанных ранее библиотек и с применением худших регулярок ever, был выпущен в прод робот, который начал 24 на 7 делать работу за человека. Робот, который не устаёт, не болеет и не обедает, который днём и ночью мгновенно реагирует на письма от контрагентов изо всех часовых поясов, который всегда кладёт файлы туда, куда надо, и позволяет человеку сфокусироваться на действительно сложных вещах.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/exchangedocsaver-esche-odna-istoriya-pro-lyudey-i-robotov.png" width="526" height="242" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;На днях, после полутора лет успешной эксплуатации, комплекс впервые потребовал доработки из-за смены формата номера контракта на предприятии. Я дополнил алгоритм детектирования ID контракта новым шаблоном, попутно поправил пару замеченных косяков (и чуть выиграл в производительности), выкатил обновление — и клиент снова доволен, надеюсь что на следующие Х лет.&lt;/p&gt;
&lt;p&gt;Детали реализации, код, ФИО счастливчика и название компании — под NDA, по очевидным причинам. Могу лишь сказать что при внимании к деталям и некотором опыте автоматизации под винду и Exchange, можно в таком направлении реализовать практически что угодно. Если вы ежедневно тратите время на работу с почтой, не решаемую обычным функционалом правил и другой автоматизации в почтовом клиенте — возможно, пришла пора переложить это на наших электрических братьев. Как-нибудь расскажу потом про конфеденциальную пересылку алертов из почты в телегу, тоже полезная штука.&lt;/p&gt;
&lt;p&gt;Кожаные заняты делом, кремнивые — рутиной. Обожаю такое.&lt;/p&gt;
&lt;p&gt;КЭНК! Слава роботам!&lt;/p&gt;
</description>
</item>

<item>
<title>Отключаем перезагрузку Windows при обновлениях</title>
<guid isPermaLink="false">1049</guid>
<link>https://www.batishchev.ru/blog/all/otklyuchaem-perezagruzku-windows-pri-obnovleniyah/</link>
<pubDate>Wed, 26 Jun 2024 16:29:18 +0300</pubDate>
<author></author>
<comments>https://www.batishchev.ru/blog/all/otklyuchaem-perezagruzku-windows-pri-obnovleniyah/</comments>
<description>
&lt;p&gt;В прошлый раз я рассказывал, как &lt;a href="https://batishchev.ru/blog/saga-o-perezagruzkah-ili-smekalka-protiv-vlasti-korporaciy/"&gt;победил самопроизвольную перезагрузку винды&lt;/a&gt; в производственной среде. Но дома проблема так же актуальна — бесит когда смотришь с утра, что посчиталось в монтажке с новым концертом любимой группы, например, а на тебя в ответ смотрит свежеперезагруженный комп.&lt;/p&gt;
&lt;p&gt;Итак, kenk-shift-active-hours или Бесконечный откладыватель авто-перезагрузки Windows при обновлениях&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;скрипт задаёт в качестве начала активных часов текущий час, а в качестве конца — время на 18 часов позже (это максимальная возможная длительность)&lt;/li&gt;
&lt;li&gt;в комплекте идёт инсталлер, который копирует скрипт в профиль пользователя и создает задачу в планировщике, стартующую скрипт автоматически каждые полчаса&lt;/li&gt;
&lt;li&gt;в итоге, система корректно сама ходит за апдейтами и устанавливает их, а также сигнализирует о необходимости перезагрузки для завершения обновления, но никогда не перезагружается сама&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Отмечу отдельно что для домашнего использования такое (потенциально) бесконечное откладывание ребута приемлемо, я достаточно ответственен чтобы в короткий (но удобный мне) срок перезагрузить тачку.&lt;/p&gt;
&lt;p&gt;Скрипт на гитхабе: &lt;a href="https://github.com/alexbatishchev/kenk-shift-active-hours"&gt;https://github.com/alexbatishchev/kenk-shift-active-hours&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;КЭНК!&lt;br /&gt;
Слава роботам!&lt;/p&gt;
</description>
</item>

<item>
<title>Сага о перезагрузках, или смекалка против власти корпораций</title>
<guid isPermaLink="false">1046</guid>
<link>https://www.batishchev.ru/blog/all/saga-o-perezagruzkah-ili-smekalka-protiv-vlasti-korporaciy/</link>
<pubDate>Tue, 18 Jun 2024 00:21:45 +0300</pubDate>
<author></author>
<comments>https://www.batishchev.ru/blog/all/saga-o-perezagruzkah-ili-smekalka-protiv-vlasti-korporaciy/</comments>
<description>
&lt;p&gt;Сегодняшний рассказ — на мои любимые темы: как заставить роботов работать за людей, и как победить неумолимые корпорации с помощью их же инструментов. А ещё это реальный эксклюзив и ноу-хау, до которого (кажется) ещё никто не задумывался. Устраивайтесь поудобнее.&lt;/p&gt;
&lt;p&gt;Предыстория такова: первой большой задачей на нынешнем проекте у меня было внедрить процесс обновления операционок на рабочих местах. Главная проблема тут в &lt;a href="https://bureau.ru/bb/soviet/20150505/"&gt;бесценности пользовательских данных&lt;/a&gt; и в том, как в борьбе за безопасность Microsoft перешла грань. Начиная с какого-то момента, штатными средствами и политиками Windows стало невозможно обеспечить обязательную, но бережную установку обновлений системы для клиентских ОС. Да, появились более наглядные нотификации, возможность задавать дедлайны, но в итоге, все варианты сводились к двум сценариям — либо апдейты не будут гарантированно установлены, либо автообновление будет работать, но комп может быть перезагружен в вообще говоря неудобное клиенту время. Самый отстой тут — перезагрузки по ночам или в другие моменты, когда комп что-то делает без активного участия человека — тут администраторы, программисты и прочие рендерщики видео по три часа в фоне начинают беситься, вспоминая потерянное на таких ребутах время и данные.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/wufb-update-deadline-warning.png" width="345" height="144" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Собственно, рабочую задачу я решил через отключение всех автоматических политик Microsoft и реализации собственного решения — агента, который работает на хостах, по удобному предприятию и сотрудникам расписанию ставит обновления, назначает и следит за сроками установки, адекватно напоминает о необходимости перезагрузки и вообще решает задачу бережно и результативно. Ключевая фишка — умные дедлайны, когда на установку обновлений пользователю отводится некоторое количество рабочих дней, а принудительная перезагрузка (если до неё дойдёт) не происходит пока пользователя нет у компа, и он не может сохранить свои данные. Ну а попутно появился инструмент инвентаризации и управления клиенсткими машинами. Когда-нибудь расскажу об этом отдельно, кодовое имя проекта «Светофор».&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/2024-06-14-3.png" width="364" height="599" alt="" /&gt;
&lt;div class="e2-text-caption"&gt;Уведомление, которым Светофор достаёт даже самого упорного пользователя&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Однако, с Windows 11 оставалась одна загвоздка — штатными средствами полностью запретить винде перезагружаться по собственному желанию, при включенной авто-установке апдейтов, не получилось. Были найдены и протестированы совсем уж некрасивые варианты типа модификации системных файлов и запрета самой винде их менять на уровне файловых прав, но это было грязно и неудобно для внедрения. До поры таких клиентов было немного, ситуация позволяла терпеть, однако недавно я сам перешёл на Windows 11, миграция в компании тоже стартовала, и проблема начала разрастаться.&lt;/p&gt;
&lt;p&gt;Я провёл очередной рисёрч на тему (оказалось что ничего за годы не изменилось), после чего сделал ещё один заход на проблему в КЭНК-парадигме, и тут в ночи перезагрузочного кошмара забрезжил-таки рассвет.&lt;/p&gt;
&lt;p&gt;Следим за руками: винда штатно смотрит на заданный в настройках Период Активности (Active Hours), и не ребутает компы во время него. Так отчего бы нам автоматически не сдвигать его постоянно так, чтобы период активности не заканчивался никогда?&lt;/p&gt;
&lt;p&gt;Быстрая проверка показала что соответствующие параметры хранятся в реестре и доступны на запись непривилегированным пользователям, и что система реально их регулярно перечитывает. А если параметры сдвигать вперёд постоянно, то неуправляемого саморебута после установки обновлений не случается совсем.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;div class="fotorama" data-width="1655" data-ratio="2.4701492537313"&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/2024-06-14-1.png" width="1655" height="670" alt="" /&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/2024-06-14-2.png" width="1655" height="670" alt="" /&gt;
&lt;/div&gt;
&lt;div class="e2-text-caption"&gt;вот они красавчики в реестре и в гуе&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Дальше — дело техники, добавил в Светофор небольшой модуль, он сдвигает Active Hours на компах пользователей, а перезагрузкой управляет сам.&lt;/p&gt;
&lt;p&gt;Компьютеры работают, человек кайфует, корпорации щёлкнуты по носу, ситуация под нашим контролем!&lt;/p&gt;
&lt;p&gt;А вот о том, как это может быть полезно простым домашним юзерам — расскажу в следующий раз.&lt;/p&gt;
&lt;p&gt;КЭНК!&lt;br /&gt;
Слава роботам!&lt;/p&gt;
</description>
</item>

<item>
<title>Робот-лесник и ёлка</title>
<guid isPermaLink="false">1044</guid>
<link>https://www.batishchev.ru/blog/all/robot-lesnik-i-yolka/</link>
<pubDate>Tue, 11 Jun 2024 21:25:10 +0300</pubDate>
<author></author>
<comments>https://www.batishchev.ru/blog/all/robot-lesnik-i-yolka/</comments>
<description>
&lt;p&gt;Сегодня расскажу про суровое, простое и полезное как топор в лесу кэнк-поделие, на разработку и запуск которого в пром ушло меньше часа времени.&lt;/p&gt;
&lt;p&gt;Вот ELK-стек, в который собираются некоторые данные. Конечно, мы следим за хостами фермы через мониторинг. Но хотелось бы и смотреть и за состоянием самого сервиса, и — главное — вовремя узнавать если что-то пошло не так.&lt;/p&gt;
&lt;p&gt;Выбираем сервак для размещения робота-лесника (в моём случае под виндой ибо фигачим быстро и грязно на павершеле). Пишем скрипт, в котором:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;читаем список FQDN нод нашей ёлки из конфига скрипта&lt;/li&gt;
&lt;li&gt;проходим по списку, проверяя доступность хостов по сети (через Test-NetConnection -port 9200). Если какая-то нода не пингуется или не отвечает по 9200 — алертим админу&lt;/li&gt;
&lt;li&gt;если есть хоть одна живая нода — запрашиваем у неё статус через API «&lt;a href="https://cluster.com/_cluster/health?pretty"&gt;https://cluster.com/_cluster/health?pretty&lt;/a&gt;». В полученном json пырим в «status», если он не «green» — запрашиваем более подробную диагностику через «&lt;a href="https://cluster.com/_nodes/process?pretty"&gt;https://cluster.com/_nodes/process?pretty&lt;/a&gt;» и тоже всё алертим админу.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/2024-06-10-health.png" width="862" height="301" alt="" /&gt;
&lt;div class="e2-text-caption"&gt;типовой результат запроса health&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;куда алертим? Ну лично мне удобней получать такое в почту и в специальный аварийный чят в телеге.&lt;/li&gt;
&lt;li&gt;повторяем проверку (дёргаем скрипт планировщиком на сервере с нужной периодичностью)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Итого, при проблемах с сервисом имеем своевременные оповещения, машины трудятся а человеки отдыхают.&lt;/p&gt;
&lt;p&gt;Думал оформить свой скриптец в виде готового продукта, но в целом тула вышла специфичная под мои требования и легко воспроизводимая в нужном виде под требования чужие, так что ограничусь общим алгоритмом и описанием идеи.&lt;/p&gt;
&lt;p&gt;КЭНК!&lt;br /&gt;
Слава роботам!&lt;/p&gt;
</description>
</item>

<item>
<title>Обновление Эгеи и грязные хаки</title>
<guid isPermaLink="false">1022</guid>
<link>https://www.batishchev.ru/blog/all/obnovlenie-egei-i-gryaznye-haki/</link>
<pubDate>Mon, 05 Feb 2024 19:58:44 +0300</pubDate>
<author></author>
<comments>https://www.batishchev.ru/blog/all/obnovlenie-egei-i-gryaznye-haki/</comments>
<description>
&lt;p&gt;Обновил движок блога до актуальной версии, а заодно победил старую проблему. Эгея умеет вписывать в вёрстку иллюстрации по ширине, но когда вставляешь в пост вертикальную фотку в большом разрешении, она ожидаемо расползается на несколько экранов (в большинстве популярных сейчас размеров мониторов) — а что, по ширине всё чётко же?! Получите, распишитесь.&lt;/p&gt;
&lt;p&gt;В прошлые годы пытался несколько раз победить проблемами средствами CSS, но моё кунфу здесь недостаточно сильно. Поэтому приходилось при публикации дополнительно контролировать размеры, делать отдельные версии фоток для блога — короче неудобно, некрасиво, технологично и оскорбительно по отношению к роботам (которые и должны выполнять такую работу).&lt;/p&gt;
&lt;p&gt;В этот раз, подгоняя тему оформления новой версии движка под себя, вспомнил про эту беду. Решил сделать ещё один заход, и ковырясь в вёрстке набрёл на код форматера Нисден, который отвечает в Эгее за рендеринг страниц. Увидел в нём код, меняющий слишком широкие картинки , и подумал, почему бы так же не пофиксить и возможный выход за границы по высоте?&lt;/p&gt;
&lt;p&gt;В итоге: грязный хак (10 строчек кода в двух модулях PictureRenderer.php и FotoramaRenderer.php), захардкоженая предельная высота в 800 пикселей (предельная ширина у Ильи вынесена в конфиг, и чтобы это повторить пришлось бы много что исправить и дописать), картинки вписываются в страницу, роботы работают а человеки отдыхают.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/lemon@2x.jpg" width="385" height="432" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Немного неудобно будет потом апгрейдиться, но предложить улучшение в код не могу — движок не опенсорсный.&lt;/p&gt;
</description>
</item>

<item>
<title>КЭНК: обновление генератора фонов для рабочего стола</title>
<guid isPermaLink="false">1008</guid>
<link>https://www.batishchev.ru/blog/all/kenk-obnovlenie-generatora-fonov-dlya-rabochego-stola/</link>
<pubDate>Sun, 31 Dec 2023 11:15:12 +0300</pubDate>
<author></author>
<comments>https://www.batishchev.ru/blog/all/kenk-obnovlenie-generatora-fonov-dlya-rabochego-stola/</comments>
<description>
&lt;p&gt;В последнее время всё чаще сталкиваюсь с необходимостью использовать в powershell вызовы системного API для реализации функционала, под который нет готовых командлетов. Разбираясь с решением очередной проблемы этим методом, вспомнил про &lt;a href="/blog/all/generator-kartinok-dlya-fona-rabochego-stola-serverov/"&gt;генератор фонов для RDP&lt;/a&gt;, который я когда-то пилил, и в котором до идеала не хватало авто-назначения сгенерённого фона, потому что такой функции я тогда не нашел. Ну думаю, через системное API уж точно кто-то сообразил как сделать — напомню, там у меня получилось задать картинку и параметры через реестр, а вот форсировать обновление без перезагрузки я не смог.&lt;/p&gt;
&lt;p&gt;Погуглил в эту сторону, нашел пару реализованных вариантов (&lt;a href="https://getps.dev/blog/change-desktop-wallpaper-with-powershell/"&gt;1&lt;/a&gt; и &lt;a href="https://www.joseespitia.com/2017/09/15/set-wallpaper-powershell-function/"&gt;2&lt;/a&gt;), и скопипиздил в скрипт код, так что теперь генерятор работает без ручного труда совершенно.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/kenk-bgimage-2023-12-31.png" width="969.33638443936" height="800" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://github.com/alexbatishchev/kenk-bgimage"&gt;Код на гитхабе&lt;/a&gt;. Слава роботам!&lt;/p&gt;
</description>
</item>

<item>
<title>Сервис isDayOff для нужд автоматизации</title>
<guid isPermaLink="false">988</guid>
<link>https://www.batishchev.ru/blog/all/servis-isdayoff-dlya-nuzhd-avtomatizacii/</link>
<pubDate>Wed, 07 Jun 2023 23:37:28 +0300</pubDate>
<author></author>
<comments>https://www.batishchev.ru/blog/all/servis-isdayoff-dlya-nuzhd-avtomatizacii/</comments>
<description>
&lt;p&gt;Несколько лет использую в работе сервис &lt;a href="https://www.isdayoff.ru/"&gt;isDayOff&lt;/a&gt;, который позволяет проверить дату на принадлежность к нерабочему дню, согласно официальным указам и распоряжениям.&lt;/p&gt;
&lt;p&gt;Я очень люблю автоматизацию, особенно — автоматический контроль за соблюдением правил и договоренностей в системах. Человеческий фактор невозможно полностью исключить, зато можно заставить дотошных и не устающих роботов контролировать, что человек сделал всё правильно. Однако, здесь кроется одна проблема — человеки, в отличие от роботов, уходят на выходные и государственные праздники. Согласно Первому закону робототехники, робот не может причинить вред человеку или своим бездействием допустить, чтобы человеку был причинён вред. А что может быть противней, чем тикет на исправление некритической проблемы, прилетевший в выходные? Да, можно запрограммировать, чтобы тикеты не прилетали в субботы и воскресенья — но что делать с праздниками и переносами выходных?&lt;/p&gt;
&lt;p&gt;isDayOff  простой как автомат Калашникова, и легко встраивается в скрипты и пайплайны автоматизации. В простейшем виде через &lt;a href="https://isdayoff.ru/today"&gt;https://isdayoff.ru/today&lt;/a&gt; можно узнать, является ли текущий день рабочим, ну а дополнительные параметры к запросу могут дать информацию о любой дате в прошлом и будущем (в разумных пределах) и даже о праздниках в соседних странах (поддерживаются Белоруссия, Казахстан и Украина).&lt;/p&gt;
&lt;p&gt;База сервиса активно поддерживается и приводится в соответствие законам, когда принимаются решения о переносах праздников и выходных. Чтобы не потерять функционал при возможном отключении сервиса (а в дивные новые времена обо всём начинаешь думать в разрезе «а что если забанят»), я обычно стараюсь в проектах использовать локальную базу на год вперед, сдампленную с сайта, и обновляющуюся ежемесячно — заодно, локальная копия базы снижает нагрузку на сервис, зачем зря напрягать бесплатное отличное решение.&lt;/p&gt;
&lt;p&gt;В целом всё просто и понятно. Например, в виде без кеширования запрос обычно посылаю через подготовленную функцию, с логикой обработки ситуации когда сервис недоступен&lt;/p&gt;
&lt;script src="https://gist.github.com/alexbatishchev/976d9cf2e33759a579086efa6ee999fc.js"&gt;&lt;/script&gt;
&lt;p&gt;С учетом простоты решения, его легко встраивать и в других ситуациях, когда требуется контролировать рабочий статус даты — уведомления, расписание резервного копирования, подсчёт количества рабочих дней до наступления дедлайна перезагрузки по обновлениям системы, и так далее.&lt;/p&gt;
&lt;p&gt;Слава роботам!&lt;/p&gt;
</description>
</item>

<item>
<title>Забрать своё из облаков: обновление вКачатора</title>
<guid isPermaLink="false">987</guid>
<link>https://www.batishchev.ru/blog/all/zabrat-svoyo-iz-oblakov-obnovlenie-vkachatora/</link>
<pubDate>Thu, 01 Jun 2023 14:52:34 +0300</pubDate>
<author></author>
<comments>https://www.batishchev.ru/blog/all/zabrat-svoyo-iz-oblakov-obnovlenie-vkachatora/</comments>
<description>
&lt;p&gt;Допилил небольшое, но важное дополнение для &lt;a href="https://batishchev.ru/blog/all/zabrat-svoyo-iz-oblakov-kenk-vk-enricher/"&gt;скрипта обогащения дампов профиля ВКонтакте&lt;/a&gt;. Эксплуатация предыдущей версии выявила существенный недостаток: видео с YouTube, импортированные в ВК, в разных разделах сайта фигурируют с разными ID (и разными URL). Выходит странненькое — по этим разным ссылкам открывается один и тот же объект (страницца) ВК, с теми же комментариями, лайками, и прочими атрибутами соцсети, и конечно же встроенный в объект ролик YouTube там тоже один и тот же, но ссылки на этот объект разные. И например, добавленное на стену видео, и то же видео, посланное в диалоге, будут иметь разные адреса. Поэтому старая версия скачивала, и складывала в папку видео несколько раз, что расходовало лишнее место (а у меня в избранные как-то попала даже девятичасовая прямая трансляция выхода в открытый космос с МКС).&lt;/p&gt;
&lt;p&gt;Идеально было бы научить скрипт сразу узнавать такие дубликаты по адресам, и не скачивать повторы вовсе, но как это сделать я придумать не смог. Зато можно скачать через yt-dlp оригинал с ютуба, и по его метаданным распознать дубль, сравнив с метаданными уже скачанных видео. Так и поступил — теперь скрипт сохраняет в простой json информацию по всем уже скачанным файлам, и при закачке дубля не сохраняет его на диск, заменяя ссылки в дампе на уже скачанный экземпляр. На моем дампе это значительно сократило объём выгрузки.&lt;/p&gt;
&lt;p&gt;Обновлённая версия уже на гитхабе: &lt;a href="https://github.com/alexbatishchev/kenk-vk-enricher"&gt;https://github.com/alexbatishchev/kenk-vk-enricher&lt;/a&gt;&lt;/p&gt;
</description>
</item>

<item>
<title>Powershell и странненькое с TimeSpan</title>
<guid isPermaLink="false">985</guid>
<link>https://www.batishchev.ru/blog/all/powershell-i-strannenkoe-s-timespan/</link>
<pubDate>Wed, 17 May 2023 22:29:53 +0300</pubDate>
<author></author>
<comments>https://www.batishchev.ru/blog/all/powershell-i-strannenkoe-s-timespan/</comments>
<description>
&lt;p&gt;Авторы Powershell, с одной стороны, многое в своём творении придумали системно и логично. С другой стороны, постоянно натыкаешься на странности, объяснения которым в области логики не найти.&lt;/p&gt;
&lt;p&gt;Любимый пример — класс TimeSpan, временной промежуток, отрезок времени между двумя датами. У объектов этого класса есть несколько свойств, отражающих заданный объектом промежуток времени в разных единицах измерения. И в перечне этих свойств неочевидная логика авторов языка проявляется в полной красе.&lt;/p&gt;
&lt;p&gt;Вот свойства Hours, Minutes, Seconds, Milliseconds. Интуитивно думаешь, что это — значение промежутка времени в часах, минутах, секундах, и миллисекундах. Довольно быстро наступаешь на эти грабли, и узнаёшь, что это кое-что другое, а именно количество часов в рамках дня, минут в рамках часа и тому подобное. То есть, если промежуток времени у вас в 1 день и 1 час, то Hours — не 25, а 1. А если между датами прошло 2 часа и 10 минут, то свойство Minutes будет не 2*60+10, а просто 10. Зачем это надо? Ну, наверное для чего-то может пригодиться, хотя я ни разу за много лет эти свойства не использовал. Зато, сколько ошибок в скриптах из-за неверного их понимания я встречал на стековерфлоу и в прочих местах в интернетах!&lt;/p&gt;
&lt;p&gt;Окей, столкнувшись с этим (или прочитав заранее в документации, что вряд ли), ты спустя какое-то время познаешь TotalHours, TotalMinutes, TotalSeconds и TotalMilliseconds, с той самой очевидной логикой «полное количество часов между датами» и так далее. Если между моментами времени прошло два с половиной часа, то это будет 2.5 TotalHours, 150 TotalMinutes и 9000 TotalSeconds. Ура, теперь-то всё понятно, можем смело фигачить!&lt;/p&gt;
&lt;p&gt;И вот в этот момент, к полному сил и умиротворённому программисту, из-за угла подходят в кепках и адидасе братюни Days и TotalDays, и объясняют, что понятий он не знает, и вообще зря на раён зашел. Ибо Days — это в в натуре полное количество дней (а не как можно было бы по аналогии предполагать, количество дней в рамках года). А TotalDays — это да, это полное количество дней, дробь (типа, аккуратно посчитанное, вкуриваешь?). А Days — грубо посчитанное. Но полное. Почему? Короч, так надо. Кстати, дай позвонить!&lt;/p&gt;
&lt;p&gt;И вот, сидишь, смотришь на это, и думаешь — а оно зачем вообще так?? Потом вздыхаешь, материшься, сверяешься  с документацией ещё раз, пишешь в коде правильное.&lt;/p&gt;
&lt;p&gt;Может показаться, что этот пост написан с целью излучить в пространство бессильную злобу — но на деле, это просто справочник. Я буду ходить сюда каждый раз, когда буду юзать TimeSpan, потому что запоминать подобное — просто портить себе мозг.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Дорогой Вася! Если тебе надо посчитать промежуток времени, юзай TotalDays, TotalHours, TotalMinutes, TotalSeconds и TotalMilliseconds, помни что они — вещественные, и означают то, что тебе нужно. А про другие свойства TimeSpan забудь!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;А для вас — картинка, иллюстрирующая всю дичь TimeSpan&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/ps-timespan.png" width="652" height="649" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Слава роботам!&lt;/p&gt;
</description>
</item>

<item>
<title>ArrayList и производительность массивов в Powershell</title>
<guid isPermaLink="false">981</guid>
<link>https://www.batishchev.ru/blog/all/arraylist-i-proizvoditelnost-massivov-v-powershell/</link>
<pubDate>Tue, 07 Feb 2023 16:51:56 +0300</pubDate>
<author></author>
<comments>https://www.batishchev.ru/blog/all/arraylist-i-proizvoditelnost-massivov-v-powershell/</comments>
<description>
&lt;p&gt;Powershell — язык весьма великодушный к программистам, почти всё в нём делается легко, интуитивно, и не требует особой подготовки и продумывания от автора кода. Однако, при выходе на объемные задачи начинают выстреливать некоторые вещи, которые для удобства изначально выполнены неэффективно.&lt;/p&gt;
&lt;p&gt;По одной из задач мне требовалось обрабатывать большие объемы данных (сотни тысяч и миллионы строк таблиц). На тестовых множествах всё работало хорошо, но на прод данных скрипт начинал работать непозволительно долго. Я провел профилирование и выяснил, что с ростом количества данных всё больше времени (с нелинейным ростом) начинает занимать операция добавления элемента в архив.&lt;/p&gt;
&lt;p&gt;$array = $array + $newElement — что может быть интуитивней? Оказалось, массивы в Powerhsell это имутабельные объекты, и поэтому предыдущий код фактически создает новый неизменяемый объект из всех элементов предыдущего массива и одного нового. Конечно, на больших объемах массивов такая операция будет занимать всё больше времени, и нелинейный рост вполне объясним. Этой неэффективности лишен специальный тип данных ArrayList — это тот же массив, разве что элементы добавлять самым очевидным способом через «плюс» в него нельзя.&lt;/p&gt;
&lt;p&gt;Вот код, на котором я проверил время работы цикла из добавления N случайных строк к массивам в умолчальном варианте и варианте ArrayList&lt;/p&gt;
&lt;script src="https://gist.github.com/alexbatishchev/a870321637f19fce59879015860bb50e.js"&gt;&lt;/script&gt;
&lt;p&gt;На 10 тысячах операций результаты примерно похожи — отличаются в десятки процентов. Но уже на сотне тысяч разница — на порядок. При этом время работы через ArrayList растет линейно вместе с количеством циклов, а у классических массивов — экспоненциально&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/photo_2023-02-07_17-28-08.jpg" width="889" height="446" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Вот такие тонкости вскрываются спустя годы работы с языком. С другой стороны, это хорошо характеризует его в положительном плане — сколько за это времени гигабайт csvшек и джейсонов было перелопачено без этих ваших ArrayList?!&lt;/p&gt;
</description>
</item>

<item>
<title>Забрать своё из облаков: kenk-vk-enricher 1.4</title>
<guid isPermaLink="false">979</guid>
<link>https://www.batishchev.ru/blog/all/zabrat-svoyo-iz-oblakov-kenk-vk-enricher-1-4/</link>
<pubDate>Wed, 11 Jan 2023 23:19:20 +0300</pubDate>
<author></author>
<comments>https://www.batishchev.ru/blog/all/zabrat-svoyo-iz-oblakov-kenk-vk-enricher-1-4/</comments>
<description>
&lt;p&gt;Допилил скрипт &lt;a href="https://batishchev.ru/blog/all/zabrat-svoyo-iz-oblakov-kenk-vk-enricher/"&gt;обогащения дампа Вконтакте&lt;/a&gt;. Теперь скрипт качает видео в разделах Видеозаписи, Стена и Сообщения — закачка идет через  &lt;a href="https://github.com/yt-dlp/yt-dlp"&gt;yt-dlp&lt;/a&gt;, перед использованием желательно обновить его до свежей версии, и залогиниться в ВК в одном из бразуеров на машине, тогда yt-dlp сможет использовать куки и больше видео будет доступно для скачивания. Также скачиваются аттачменты типа «файл» на стене и в сообщениях (те, что доступны по прямым ссылкам).&lt;/p&gt;
&lt;p&gt;Сейчас актуальной версией скрипта мой личный профиль выкачивается на почти 200 гб, сказываются видео файлы в переписке и на стене — часто репостились интересные чужие видосы, и всё вместе занимает прилично места. Ну да больше-не меньше.&lt;/p&gt;
&lt;p&gt;Скрипт на гитхабе: &lt;a href="https://github.com/alexbatishchev/kenk-vk-enricher"&gt;&lt;a href="https://github.com/alexbatishchev/kenk-vk-enricher"&gt;https://github.com/alexbatishchev/kenk-vk-enricher&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Слава роботам!&lt;/p&gt;
</description>
</item>

<item>
<title>Забрать своё из облаков: важные видео из YouTube — 2</title>
<guid isPermaLink="false">976</guid>
<link>https://www.batishchev.ru/blog/all/zabrat-svoyo-iz-oblakov-vazhnye-video-iz-youtube-2/</link>
<pubDate>Sat, 07 Jan 2023 20:20:29 +0300</pubDate>
<author></author>
<comments>https://www.batishchev.ru/blog/all/zabrat-svoyo-iz-oblakov-vazhnye-video-iz-youtube-2/</comments>
<description>
&lt;p&gt;Спустя &lt;a href="https://batishchev.ru/blog/all/zabrat-svoyo-iz-oblakov-vazhnye-video-iz-youtube/"&gt;полгода после запуска&lt;/a&gt; велосипедика для автокачания и сохранения важных видосов, провёл аудит его работы и немного допилил.&lt;/p&gt;
&lt;p&gt;Во-первых, за прошедшее время скриптом в архив было скачано несколько видосов, которые уже недоступны в интернете — часть удалили авторы, а часть сгинула вместе с каналами, удалёнными администрацией йутуба в баталиях нового чудного времени цензуры и культуры отмены. Помещать интересные (а особенно острые и потенциально скандальные) видосы в плейлист для сохранения стало привычкой.&lt;/p&gt;
&lt;p&gt;Во-вторых, всплыла интересная особенность этого вашего СЕО и кликбейт-традиций: авторы на ютубе нередко переименовывают ролики, иногда (как например вДудь) — после добавления субтитров и других изменений, а иногда — просто чтобы новые названия привлекали внимание зрителей и обманывали алгоритмы. Так как в шаблон именования файлов я внёс название ролика, это приводило к тому что часть роликов повторялась несколько раз — а видос с одного канала (крутой по содержанию документальный фильм про советскую мультипликацию, кстати), закачался аж 6 раз, в соответствии с каждым почти ежедневным переименованием.&lt;/p&gt;
&lt;p&gt;К счастью, в шаблон имени файла я с самого начала добавил ID ролика, и по ним дубликаты можно легко находить. Добил скрипт закачки несколькими строками, находящими в архиве файлы с одинаковыми ID внутри имён и удаляющие самые старые файлы — и дело в шляпе&lt;/p&gt;
&lt;p&gt;В-третьих, оказалось что место видосиками жрётся весьма стремительно — а я по старой привычке выбрал для хранения максимально возможное качество. Подумал над вопросом, и решил что в подавляющем большинстве случаев содержимое вполне воспринимается и в невысоком качестве, и в качестве разумного компромисса выбрал скачивать вариант 720p. В первую ночь видосики с новыми параметрами перекачались, дубликаты удалились, выигрыш по месту вышел очень приятный.&lt;/p&gt;
&lt;p&gt;Машины работают, человек счастлив. Вернусь к вопросу через следующие полгода&lt;/p&gt;
</description>
</item>

<item>
<title>Забрать своё из облаков:  kenk-vk-enricher</title>
<guid isPermaLink="false">975</guid>
<link>https://www.batishchev.ru/blog/all/zabrat-svoyo-iz-oblakov-kenk-vk-enricher/</link>
<pubDate>Thu, 05 Jan 2023 22:34:03 +0300</pubDate>
<author></author>
<comments>https://www.batishchev.ru/blog/all/zabrat-svoyo-iz-oblakov-kenk-vk-enricher/</comments>
<description>
&lt;p&gt;Причесал и опубликовал &lt;a href="https://github.com/alexbatishchev/kenk-vk-enricher"&gt;скрипт&lt;/a&gt;, докачивающий в дамп официальной выгрузки из ВКонтакте картинки в переписку (сообщения) и фотоальбомы. Фотки выкачиваются и складываются заодно внутрь дампа в папки с именами, соответствующими оригинальным альбомам, а если они были опубликованы с подписью (как например часто было при параллельной публикации в ИГ) — подпись сохраняется в отдельный текстовой файл рядом.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/kenk-vk-enricher.png" width="971" height="631" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;В дампе переписке  все файлы даются прямыми ссылками. А вот в дампе стены картинки прописаны ссылками вида &lt;a href="https://vk.com/photoXXXXXXXXX_XXXXXXXXX"&gt;https://vk.com/photoXXXXXXXXX_XXXXXXXXX&lt;/a&gt; — но тут был придуман хитрый ход, немного исправляющий ситуацию. Так как среди фотоальбомов есть «Фотографии на моей стене», то если сдампить их и из кода страницы выдернуть и прямые ссылки на файлы, и ссылки photoXXXXXXXXX_XXXXXXXXX (которые там есть), то можно закешировать это соответствие и подставить потом известные картинки в код выгрузки стены. К сожалению, так можно обойти только картинки, и только картинки ваши — репосты от других пользователей или групп так и останутся со ссылками на данные в серверах ВК. Как до них добраться без URL оригинальных файлов непонятно — с парсерами картинок ВК в интернете такая же беда как и с видео. Хотя жаль, стену со своими публикациями хотелось бы содрать в максимально полном виде, включая и репосты.&lt;/p&gt;
&lt;p&gt;За недолгое время с прошлой публикации yt-dlp успел разучиться качать видео из вк, и вновь научился этому в свежем апдейте — похоже что война апишников с реверс-инженерами идёт денно и нощно. С учетом этого, выкачку видео пока думаю не реализовывать.&lt;/p&gt;
&lt;p&gt;Забавное наблюдение — в дампе стены есть уже удалённые вами сообщения (с пометкой «Запись удалена»). Так приятно что заботливые товарищи всё хранят даже после удаления (евпочя).&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/kenk-vk-enricher2.png" width="645" height="468" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;КЭНК! Слава роботам!&lt;/p&gt;
</description>
</item>

<item>
<title>Ёлочные игрушки: собираем и анализируем в ELK состояние систем</title>
<guid isPermaLink="false">972</guid>
<link>https://www.batishchev.ru/blog/all/yolochnye-igrushki/</link>
<pubDate>Thu, 29 Dec 2022 02:10:46 +0300</pubDate>
<author></author>
<comments>https://www.batishchev.ru/blog/all/yolochnye-igrushki/</comments>
<description>
&lt;p&gt;Сегодня расскажу о том, как можно применять Elasticsearch, Logstash, и Kibana для сбора и анализа информации в различных задачах системного администрирования и управления информационной безопасностью на предприятии.&lt;/p&gt;
&lt;h2&gt;Ложь, наглая ложь и статистика&lt;/h2&gt;
&lt;p&gt;Часто в работе системы, которыми мы управляем, дают информацию о своем текущем состоянии, но не хранят (или хранят в неудобной или неполной форме) историю этого состояния. При этом, решая задачи по изменению и улучшению инфраструктуры, важно понимать не только где мы находимся, но и то, куда и с каким прогрессом мы движемся.&lt;/p&gt;
&lt;p&gt;Формулирование таких метрик и понимание их изменения помогает сразу по нескольким фронтам. Во-первых, исполнитель всегда может оценить прогресс и наглядно продемонстрировать руководству что и насколько улучшено (или ухудшено), с актуальными «здесь и сейчас» цифрами. Ура, нет больше ночных бдений «срочно предоставить к утру отчет о том что сделано по этой проблеме» — отчёты доступны здесь и сейчас в любой момент.&lt;/p&gt;
&lt;p&gt;Во-вторых, самому сотруднику для профилактики выгорания и получения обратной связи о своей работе важно иметь возможность оценить, что и как изменилось в результате его труда. Это особенно важно в деятельности по эксплуатации и настройке систем, где часто нет четкой финальной точки (типа «построил дом — завершил проект»), а есть бесконечный непрерывный процесс, и без понимания его прогресса может возникать впечатление что работа не приносит результатов, что она неисчерпаема и как будто топчется на месте.&lt;/p&gt;
&lt;p&gt;Предположим, внедряется процесс управления учетными записями в AD — настраиваются политики, вычищаются старые или ненужные записи, настраиваются параметры безопасности. Как оценить насколько сегодня ситуация лучше чем была месяц назад? Безопасник нашел и поставил задачу исправить N записей, за это время админы сделали M новых, что в целом по ситуации? Какова её оценка и как она изменилась?&lt;/p&gt;
&lt;p&gt;Другой практический пример — управление обновлениями Windows хостов при помощи WSUS. Насколько сегодня уровень покрытия инфраструктуры апдейтами лучше чем два месяца назад? Не стало ли хуже из-за раздолбайства смежных подразделений, или выхода апдейта с ошибками установки? Ситуация в целом исправляется или наоборот, движется в ад? А что, патчи в этом месяце раскатываются с обычной динамикой, или что-то идёт нештатно?&lt;/p&gt;
&lt;p&gt;Третий пример — некая система управления агентами на хостах, показывающая в реальном времени статус сервера (онлайн-оффлайн), но не хранящая истории этих состояний. Как узнать (с достаточной точностью в 1-2 часа) когда хост светился в системе в последний раз?&lt;/p&gt;
&lt;p&gt;Конечно, такую статистику по выбранным метрикам можно собирать по случаю вручную, строить графики в экселе или другом средстве ручной аналитики. Но зачем, если можно заставить работать роботов и получать актуальный результат автоматически и в любой момент?&lt;/p&gt;
&lt;h2&gt;Достаём подарки из-под ёлки&lt;/h2&gt;
&lt;p&gt;Основная идея этого kenk-велосипеда заключается в том, чтобы регулярно и автоматически собирать (или выгружать) из информационных систем данные, и после этого хранить и анализировать их с помощью ELK Stack.&lt;/p&gt;
&lt;p&gt;При этом появляется возможность анализировать состояние систем в исторической перспективе, видеть тренды изменений и контролировать соблюдение заданных ключевых показателей. Кроме того, появляется возможность собирать или генерировать другую информацию, недоступную через штатные средства управления этими системами — потому что перед загрузкой в ELK, данные можно дополнительно обработать, обогатить сведениями из других систем и так далее. Например, можно дополнить статистику из WSUS данными из учетной системы предприятия об ответственных за сервера, и иметь возможность сразу видеть кого нужно пнуть за необновлённый хост.&lt;/p&gt;
&lt;p&gt;В результате внедрения подобной системы у инженера или руководителя подразделения появляется инструмент, позволяющий видеть прогресс по процессам, а также искать данные состояния системы в исторической перспективе. Кроме того, данные из разных систем предприятия при этом обретают связь и дополнительный тюнинг в соответствии с ландшафтом инфраструктуры.&lt;/p&gt;
&lt;h2&gt;Картинки и примеры&lt;/h2&gt;
&lt;p&gt;Приведу пару визуальных примеров. В картинках ниже конкретные цифры (показатели) и временные отметки на скриншотах удалены по причине NDA&lt;/p&gt;
&lt;p&gt;Пример 1. Графики изменения во времени на группе хостов метрик «процент обновлённых назначенными патчами машин» и «процент машин, требующих перезагрузки для завершения обновления». Вы никогда не получите эти данные из WSUS, потому что он не хранит историю состояний хостов&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/photo_2022-12-26_22-45-33.jpg" width="821" height="411" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Пример 2. График изменения во времени на группе хостов количества установленных экземпляров Chrome разных версий. Здесь красиво видно, как по мере выпуска патчей одна версия Chrome сменяет на группе хостов другую. Вы не получите эти данные, если ваша система учёта ПО на хостах этого не умеет (данные для графика получены из отчетов Kaspersky Security Center)&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/photo_2022-12-26_22-51-08.jpg" width="585" height="484" alt="" /&gt;
&lt;/div&gt;
&lt;h2&gt;Общее описание архитектуры&lt;/h2&gt;
&lt;p&gt;Итак, как такое устроить?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;регулярно генерим по расписанию данные о системе (сгружаем из неё через апи или парсим штатные отчёты системы)&lt;/li&gt;
&lt;li&gt;обогащаем эти данные информацией из смежных систем и добавляем сведения и метрики, которых нет в исходных данных&lt;/li&gt;
&lt;li&gt;записываем всё в json файлы&lt;/li&gt;
&lt;li&gt;установленный на хосте-анализаторе filebeat подхватывает дамп и отсылает в Elasticsearch&lt;/li&gt;
&lt;li&gt;настроенные в Kibana дашборды отображают красоту и позволяют формировать отчёты играя параметрами (наборы хостов, время выборки, прочие фильтры)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;kenk-дисклеймер&lt;/h2&gt;
&lt;p&gt;Этот подход рожден и работоспособен в условиях, когда у вас есть набор информационных систем, возможности которых недостаточны для решения озвученных задач. Если ваша система всё это может (и в условиях дивной новой реальности вы можете эту систему продолжать покупать), сий велосипед не для вас.&lt;/p&gt;
&lt;p&gt;Также, в полном соответствии с kenk-доктриной, решение потребует кровавого программинга на коленке и применения прочих костыльно-пластилиновых технологий. Если вы не готовы к таким жертвам — решение не для вас&lt;/p&gt;
</description>
</item>

<item>
<title>КЭНК: безопасно храним секреты для скриптов PowerShell</title>
<guid isPermaLink="false">971</guid>
<link>https://www.batishchev.ru/blog/all/kenk-bezopasno-hranim-sekrety-dlya-skriptov-powershell/</link>
<pubDate>Wed, 02 Nov 2022 23:19:24 +0300</pubDate>
<author></author>
<comments>https://www.batishchev.ru/blog/all/kenk-bezopasno-hranim-sekrety-dlya-skriptov-powershell/</comments>
<description>
&lt;p&gt;Часто из скриптов PowerShell нужно обращаться к системам, требующим аутентификации — например, для парсинга данных о хостах из корпоративной системы мониторинга, или для выгрузки данных об уязвимостях из веб-портала системы обнаружения уязвимостей. Также нередко в этих случаях используются учетные записи с расширенными полномочиями во внешних системах, но в целом это не принципиально — любые секреты хочется хранить так, чтобы до них было невозможно добраться злоумышленнику.&lt;/p&gt;
&lt;p&gt;Понятно, что харкодить креды в источниках или держать их в конфигурационных файлах скрипта — дело пропащее. Даже если зарезать на уровне файловой системы доступ только для учетной записи, от которой должен стартовать скрипт, остаётся возможность администратору сервера эти права изменить и данные прочитать. Неаккуратненько  выходит ©.&lt;/p&gt;
&lt;p&gt;К счастью, в Windows есть магическая штука на этот случай — Secure Strings — волшебство которых в данном случае заключается в том, что они работают с учетом контекста учетной записи, от которой запущены. Поэтому, если задать пароль ($pw = Read-Host -AsSecureString)  прогнать его через ConvertFrom-SecureString  ($pw | ConvertFrom-SecureString) и результат записать в файл, то на выходе будет чудесная буквенно-цифровая белиберда. А обратно эту белиберду можно превратить в пароль  (Get-Content .\password.txt | ConvertFrom-SecureString), но только вот пароль правильным получится только если это преобразование работает от той же учетной записи, под которой шло прямое кодирование.&lt;/p&gt;
&lt;p&gt;При запуске скрипта на этом компьютере но от другой учетной записи, при запуске скрипта на другой машине, при смене пароля учетной записи — всегда расшифровка будет завершаться с ошибкой. Да, это создаёт неудобства при смене пароля сервисной учетной записи, от которой стартуют скрипты, и ключевую информацию нужно будет перегенерить — но зато спрятанные таким образом секреты точно завязаны на сохранность пароля от учетной записи и не могут быть прочитаны никем кроме неё.&lt;/p&gt;
&lt;p&gt;В своих проектах я использую свою маленькую библиотеку, позволяющую запросить и сохранить данные в ключевой файл в формате JSON, и читать данные из него в скриптах. Но в целом подход прозрачен и его можно реализовывать так как удобно&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/IMAGE-2022-11-03-00:14:55.jpg" width="690" height="218" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;В интернетах пишут, что в свежих версиях павершелла появились интеграции с системами хранения паролей, но до этого мои руки пока не дошли — привычное работает, роботы трудятся, люди отдыхают&lt;/p&gt;
&lt;p&gt;Пример кода, иллюстрирующий подход:&lt;/p&gt;
&lt;script src="https://gist.github.com/alexbatishchev/44be2d64097386e190468ec782d60697.js"&gt;&lt;/script&gt;
&lt;p&gt;Ссылки по теме:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.techtarget.com/searchitoperations/tutorial/How-to-secure-passwords-with-PowerShell"&gt;https://www.techtarget.com/searchitoperations/tutorial/How-to-secure-passwords-with-PowerShell&lt;/a&gt;&lt;br /&gt;
&lt;a href="https://www.travisgan.com/2015/06/powershell-password-encryption.html"&gt;https://www.travisgan.com/2015/06/powershell-password-encryption.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Слава Роботам! КЭНК!&lt;/p&gt;
</description>
</item>

<item>
<title>КЭНК: тихое удаление обновления Windows по номеру KB</title>
<guid isPermaLink="false">955</guid>
<link>https://www.batishchev.ru/blog/all/tihoe-udalenie-obnovleniya-windows-po-nomeru-kb/</link>
<pubDate>Mon, 15 Mar 2021 13:29:36 +0300</pubDate>
<author></author>
<comments>https://www.batishchev.ru/blog/all/tihoe-udalenie-obnovleniya-windows-po-nomeru-kb/</comments>
<description>
&lt;p&gt;Задача: тихо удалить с хоста обновление Windows по номеру KB.&lt;/p&gt;
&lt;p&gt;Какое-то время проблема легко решалась через wusa.exe /uninstall /kb:XXXXXX /quiet, но теперь в Windows 10 команда с ключом quiet просто игнорируется, а без ключа — задает много вопросов пользователю, что ожидаемо, но не подходит для решения задачи.&lt;/p&gt;
&lt;p&gt;В интернетах быстро гуглится &lt;a href="https://social.technet.microsoft.com/Forums/windows/en-US/f6594e00-2400-4276-85a1-fb06485b53e6/issues-with-wusaexe-and-windows-10-enterprise?forum=win10itprogeneral"&gt;способ&lt;/a&gt;, который хорош, но не универсален. Способ рассчитывает на то что KB будет упомянута в имени пакета для DISM, а это бывает не всегда — в примере ниже у двух последних обновлений номера KB в имени пакета нет.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/Screenshot-2021-03-15-110629.png" width="690" height="278" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Ситуацию усложняет то, что в разных локалях ОС команда dism выдает информацию на разных языках, да к тому же не структурированным объектом — а строкой. К счастью, из строки все же можно выцепить имя пакета, а по нему — запросить подробную информацию (тоже строкой), где номер KB есть (судя по моим тестам) всегда:&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/screen20210315116.png" width="930" height="657" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Итоговое решение задачи такое:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;смотрим список всех установленных обновлений и выдергиваем имена пакетов&lt;/li&gt;
&lt;li&gt;по каждому пакету смотрим расширенное описание и ищем в нём искомый номер KB&lt;/li&gt;
&lt;li&gt;если в описании найден нужный номер KB — пакет по его имени отправляется на деинсталляцию через DISM.exe /Online /Remove-Package /PackageName:$sFoundPackageName /quiet /norestart&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Короткий сниппет, иллюстрирующий подход:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;$sKBNumber = &amp;quot;4578968&amp;quot;
$aUpdts = dism /online /get-packages | ? {$_.Contains(&amp;quot;Package_for&amp;quot;)} | %{($_.Split(&amp;quot;:&amp;quot;))[1].Trim()}
foreach ($sUpdate in $aUpdts) {
$sInfo = (dism /online /get-packageinfo /packagename:$sUpdate) -join(&amp;quot;, &amp;quot;)
if ($sInfo.Contains($sKBNumber)) {
write-host &amp;quot;Found package $sUpdate for KB number $sKBNumber&amp;quot;
# uncomment below to uninstall package
# DISM.exe /Online /Remove-Package /PackageName:$sUpdate /quiet /norestart
}
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;КЭНК! Слава роботам!&lt;/p&gt;
</description>
</item>

<item>
<title>КЭНК: выгрузка фото из iCloud на Яндекс диск — 2</title>
<guid isPermaLink="false">953</guid>
<link>https://www.batishchev.ru/blog/all/kenk-vygruzka-foto-iz-icloud-na-yandeks-disk-2/</link>
<pubDate>Sun, 07 Feb 2021 16:28:22 +0300</pubDate>
<author></author>
<comments>https://www.batishchev.ru/blog/all/kenk-vygruzka-foto-iz-icloud-na-yandeks-disk-2/</comments>
<description>
&lt;p&gt;В &lt;a href="https://batishchev.ru/blog/all/kenk-iz-icloud-na-yandeks-disk/"&gt;прошлой серии&lt;/a&gt; велосипедостроения на тему переноса фоток в Яндекс.Диск была успешно решена проблема выгрузки и переименовывания файлов из iCloud в соответствии с датой. Однако, опыт эксплуатации процедуры показал её недостаток: перенесенные таким образом файлы *.heic Ядиском не располагались по альбомам в соответствии с датой, а сваливались в одну кучу дня импортирования.&lt;/p&gt;
&lt;p&gt;Пара вечеров была потрачена на анализ и сравнение *.heic файлов, импортированных яндексом с телефона самостоятельно, и обработанных мной вручную. К сожалению, никакого способа поправить теги даты так, чтобы яндекс их воспринял, не нашлось:  изменения внесенные exiftool или гуевыми программами типа XnView или FastStone результата не давали. Я заморочился, сравнил файлы преобразованные яндексом и свои, добился полного совпадения полей в выгрузке exiftool — и всё равно роботы яндекса делать красоту отказывались. Поэтому с *.heic файлами придуман обходной путь — конвертировать их в jpeg (те же теги, пробитые в jpeg, срабатывали отлично)&lt;/p&gt;
&lt;p&gt;Заодно кстати выяснилось, что яндексу важны метаданные в поле &lt;a href="https://exiftool.org/TagNames/EXIF.html"&gt;DateTimeOriginal&lt;/a&gt;: файлы с корректно заполненными DateCreated но не заполненными DateTimeOriginal он также датировал неправильно.&lt;/p&gt;
&lt;p&gt;Так вот, конвертация из heic в jpeg. Тут мне открылся неведомый мир цветовых профилей и прочих тонкостей. Оказалось что эппле пишет heic со своим чудо-профилем, который мало кто понимает и корректно показывает. Все распространённые свободные конверторы в джипег на выходе дают гораздо более бледные и светлые картинки, при этом встроенный просмотрщик macOS эти файлы показывает в исходном красивом цвете, а вот в других программах и на других платформах случается «ой». Перелопачена уйма форумов, нужное колдунство найдено — нужно не просто конвертировать heic в jpeg, но ещё и заменять цветовой профиль, а также корректировать гамму (значение корректировки я подобрал на глаз более-менее похожим, возможно тут будут нюансы на фотках разных насыщенностей)&lt;/p&gt;
&lt;p&gt;Вот что выходит с разными конвертациями и (что важно) при разных программах просмотра:&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;div class="fotorama" data-width="916.18257261411" data-ratio="1.1452282157676"&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/Screenshot-2021-02-07-at-16.10.25.png" width="916.18257261411" height="800" alt="" /&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/Screenshot-2021-02-07-at-16.10.33.png" width="915.94202898551" height="800" alt="" /&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/Screenshot-2021-02-07-at-16.10.43.png" width="630.86419753086" height="800" alt="" /&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/Screenshot-2021-02-07-at-16.13.06.png" width="914.28571428571" height="800" alt="" /&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/Screenshot-2021-02-07-at-16.13.41.png" width="641.48606811146" height="800" alt="" /&gt;
&lt;/div&gt;
&lt;div class="e2-text-caption"&gt;оригинальный heic в Preview macOS, конверченный ImageMagick jpeg без коррекции цвета в Preview macOS, он же в XnView, jpeg с коррекцией цвета в Preview macOS и в XnView&lt;/div&gt;
&lt;/div&gt;
&lt;h2&gt;Хорош рассусоливать, что вышло-то?&lt;/h2&gt;
&lt;p&gt;Итоговая на текущий момент процедура конвертации такова:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;перегнать все heic в jpeg при помощи ImageMagick, заменяя цветовой профиль на sRGB.icc и цветовое пространство на sRGB и корректируя гамму, стереть оригиналы&lt;/li&gt;
&lt;li&gt;пробить во все экспортированные файлы (и в том числе в джипеги, конвертированные из heic) метаданные из *.xmp&lt;/li&gt;
&lt;li&gt;видосикам пробить FileModifyDate из TrackCreateDate и переименовать&lt;/li&gt;
&lt;li&gt;там где у картинок DateTimeOriginal задан — переименовать файлы в соответствии с датой&lt;/li&gt;
&lt;li&gt;там где у картинок DateTimeOriginal не задан — пробить его из DateCreated и переименовать файлы в соответствии с датой&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Обработанные таким образом медиаматериалы корректно раскладываются яндекс диском в альбомы по времени и геолокации. Косяки и нюансы&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;не раскладываются по датам PNG (у меня это на 100% скриншоты) — ну да от них участия в генерации памятных сторис и прочей красоты не требуется.&lt;/li&gt;
&lt;li&gt;heic с Live Photos внутри конвертируются в два файла: картинка с дефолтным кадром и микро-mp4 с полной анимацией. Не парит опять же.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В полном соответствии с методологией КЭНК и принципами Hobby-as-Code процедура собрана в shell скрипт, ознакомиться с которым можно на github (уберите от консоли беременных детей и женщин): &lt;a href="https://github.com/alexbatishchev/kenk-yadisk-photomaster"&gt;https://github.com/alexbatishchev/kenk-yadisk-photomaster&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;КЭНК!&lt;br /&gt;
Слава роботам!&lt;/p&gt;
</description>
</item>

<item>
<title>КЭНК: выгрузка фото из iCloud на Яндекс диск</title>
<guid isPermaLink="false">76</guid>
<link>https://www.batishchev.ru/blog/all/kenk-iz-icloud-na-yandeks-disk/</link>
<pubDate>Sun, 27 Dec 2020 12:13:08 +0300</pubDate>
<author></author>
<comments>https://www.batishchev.ru/blog/all/kenk-iz-icloud-na-yandeks-disk/</comments>
<description>
&lt;p&gt;Технологии предоставляют людям всё больше готовых результатов, скрывая под капотом внутреннюю сложность и логику. Это здорово, потому что мы получаем кучу услуг и сервисов, не прилагая к этому усилий. Это плохо, потому что мы не управляем этими услугами, можем лишиться их в любой момент и, если не предпринимать дополнительных мер, не сможем ничего тут исправить.&lt;/p&gt;
&lt;p&gt;Например, иг — попробуйте штатными средствами, положенными по закону, выгрузить свои данные — и через боль и неудобства вы сможете сохранить жалкое подобие архива, а как красиво всё смотрится пока работает. Увели у вас аккаунт, заблокировали по какой-то уважительной для роботов причине — вы абсолютно беззащитны перед произволом обстоятельств и желаниями компании.&lt;/p&gt;
&lt;p&gt;Сегодняшний рассказ — о сервисе, который достался «забесплатно», но потом перестал работать, и о том как я добился получения привычного результата уже своими силами.&lt;/p&gt;
&lt;h2&gt;Что случилось и кто виноват&lt;/h2&gt;
&lt;p&gt;В мире победившей вычислительной фотографии я уже много лет снимаю на телефон и веду архив фото на телефоне. Это удобно, и всё связанное с повседневным фото завязано у меня на экосистему Apple. Однако, было бы глупо полагаться только на одного вендора, да и вручную выдёргивать фото из Apple для резервной копии не самый удобный вариант, поэтому как только Яндекс запустил фичу автоматической синхронизации фотографий на Яндекс.Диск, я сразу же начал ей пользоваться.&lt;/p&gt;
&lt;p&gt;Вышло удобно:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;фотографирую на телефон или планшет, имею синхронизированные фотки на всех личных устройствах и ноуте (на разных платформах приложение называется по разному, буду дальше использовать термин Айклауд как синоним определения «ну где там у эпплов всё лежит и красиво синхронизируется и показывается на всех девайсах»).&lt;/li&gt;
&lt;li&gt;Сразу после съемки или по напоминанию отмечаю в Айклауде сердечком лучшие фото и удаляю откровенный брак и шлак, на телефоне остаются материалы лучшие и «пусть просто для архива»&lt;/li&gt;
&lt;li&gt;Всё это время полное зеркало всех фото и видео с телефона автоматически синхронизируется с папкой Фотокамера в Яндекс диске (а она уже в свою очередь бэкапится как надо на NAS)&lt;/li&gt;
&lt;li&gt;раз в 2-3 месяца провожу чистку:&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;захожу в айклауд через приложение на ноуте или телефоне,&lt;/li&gt;
&lt;li&gt;скрываю все избранные (Library — альбом Favourites —  ⌘A — hide items),&lt;/li&gt;
&lt;li&gt;стираю все оставшиеся нескрытые (и не лайканые) фотки (Library — альбом photos — ⌘A — delete items),&lt;/li&gt;
&lt;li&gt;возвращаю все скрытые обратно (Library — альбом Hidden — ⌘A — unhide items)&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;переношу все фотки из папки Фотокамера Яндекс диска в долговременный архив, Яндекс на телефоне сам синхронизируется и обратно заливает в фотокамеру только избранные фотографии&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Таким образом я всегда имею две копии актуальных фоток (избранные + недавно сделанные) на яндексе и в айклауде, а также легко регулярно очищаю хранилище на устройствах от ненужных данных, оставляя только лучшие. Также благодаря этому умные алгоритмы Apple и Яндекса генерят мне истории и ролики-воспоминания на основе лучших фото и видео из поездок, с важных событий и тому подобное.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/2020-12-27-11.42.18.jpg" width="722" height="554" alt="" /&gt;
&lt;div class="e2-text-caption"&gt;Красиво переименованные и уложенные яндексдиском файлы&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Схема удобная, и работала она несколько лет, пока не случилась та самая упомянутая ранее потеря сервиса. В какой-то момент Яндекс поменял логику работы мобильного приложения — весной при очередной чистке я обнаружил, что он больше не перезакачивает в папку Фотокамера файлы, которые ранее в ней были, и после были мной удалены. Похоже что у себя они хранят хэши всех файлов, так как отредактированные после фотки в диск при такой схеме перезаливаются. Но неизменные — нет, а значит я больше не мог проводить синхронизацию лучших фото при регулярной чистке.&lt;/p&gt;
&lt;p&gt;В принципе, потеря небольшая, просто весь 2020-й Яндекс диск скидывал мне напоминания о событиях 19-го. Тем не менее, это натолкнуло меня на мысль о том, что случись что — у меня есть полный архив всех фото включая самые свежие, но архива лучших нет! На отбор их потрачено время, и теперь сведения этого отбора не защищены от потери.&lt;/p&gt;
&lt;p&gt;Казалось бы, чего тут сложного? Берём штатный способ выгрузки из Айклауда, сохраняем в папку избранные данные за нужный период — вуаля. Но тут вскрывается второй упомянутый ранее аспект — скрытая под капотом сложность.&lt;/p&gt;
&lt;p&gt;Айклауд (как и Яндекс) красиво показывает в ленте фото по датам и местам, умеет на основе этой метаинформации собирать истории и альбомы. При этом на уровне файлов творится дикая дичь — в зависимости от источника (фото сделано на телефон, сохранено из мессенджера, проявлено в Лайтруме на компе и прислано по почте, это скриншот экрана или сохранёнка с веб страницы), а также от типа файла (разные форматы видео и графики), метаданные о времени съемки, локации и другом хранятся в разных полях по разной логике. И вот выгруженные штатными средствами файлы именуются непонятно как, имеют странные даты съемки (ещё и отображаемые по-разному в зависимости от программы просмотра) — в общем никакой красоты, удобства и единообразия тут нет.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://www.batishchev.ru/blog/pictures/2020-12-27-11.48.08.jpg" width="1217.598097503" height="800" alt="" /&gt;
&lt;div class="e2-text-caption"&gt;Выгрузка из Айклауда. Ад и мешанина в именах, атрибутах и метаданных файлов. Дата съемки видео якобы неизвестна (но она есть, просто зашита глубоко)&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;В логику работы Айклауда все эти тонкости зашиты. В логику работы яндекса тоже — мобильное приложение при синхронизации переименовывает файлы по дате правильно, сохраняет геолокацию и всё прочее. Но теперь-то воспользоваться этой логикой яндекса мы не можем.&lt;/p&gt;
&lt;h2&gt;Что делать&lt;/h2&gt;
&lt;p&gt;Проводим НИР, применяем для решения задачи великий и могучий ExifTool. Общая схема такая:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;экспортируем данные из macOS Photo в оригинальном качестве и с записью дополнительных файлов xmp&lt;/li&gt;
&lt;li&gt;пробиваем с помощью ExifTool метаданные из xmp в медиафайлы&lt;/li&gt;
&lt;li&gt;проходимся по файлам набором команд ExifTool с разными параметрами в зависимости от типа файла и сохранённых в нём данных, чтобы переименовать их по дате&lt;/li&gt;
&lt;li&gt;раскладываем полученные файлы по каталогам дат (для удобства)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Собственно, на понимание того, в каких случаях как может храниться дата съемки, и экспериментальный подбор команд для третьего пункта, и ушло несколько часов этой субботы&lt;/p&gt;
&lt;p&gt;Зато теперь есть способ выгрузить лучшие материалы из Айклауда и разложить их красиво с сохранением метаданных, в том числе и положить в Яндекс диск для бэкапа и красивостей. Вторичная выгода — прокачка скилла и овладение инструментом ExifTool и скриптования на bash под macOS, теперь эти ваши экзифы и переименования файлов можем делать с закрытыми глазами и одной левой&lt;/p&gt;
&lt;h2&gt;Итог&lt;/h2&gt;
&lt;p&gt;Итоговый скрипт достаточно специфичен, чтобы его публиковать и отчуждать, но для истории сохраню здесь.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;# экспортируем фотки из macOS Photo в оригинальном качестве и с записью xmp, открываем терминал в этот каталог

# далее пробиваем параметры из xmp в графические файлы
find . -maxdepth 1  -not -iname &amp;quot;*.xmp&amp;quot; -exec bash -c 'file=&amp;quot;{}&amp;quot;; xmpname=${file%.*}.xmp; echo &amp;quot;$xmpname&amp;quot;; echo &amp;quot;$file&amp;quot;; exiftool -tagsfromfile &amp;quot;$xmpname&amp;quot; -xmp &amp;quot;$file&amp;quot; -overwrite_original' \;

# пробиваем атрибуты и переименовываем файлы по дате в зависимости от типа и содержимого

exiftool '-FileModifyDate&amp;lt;TrackCreateDate' '-FileName&amp;lt;TrackCreateDate' -d &amp;quot;%Y-%m-%d %H-%M-%S.%%f.%%e&amp;quot; *.mov -directory=out
exiftool '-FileModifyDate&amp;lt;TrackCreateDate' '-FileName&amp;lt;TrackCreateDate' -d &amp;quot;%Y-%m-%d %H-%M-%S.%%f.%%e&amp;quot; *.mp4 -directory=out

exiftool -v '-Filename&amp;lt;${datetimeoriginal}.%f.%e' -d &amp;quot;%Y-%m-%d %H-%M-%S&amp;quot; *.jpg -directory=out -if '($datetimeoriginal and (not ($datetimeoriginal eq &amp;quot;0000:00:00 00:00:00&amp;quot;))) and ($filetype eq &amp;quot;JPEG&amp;quot;)' 
exiftool -v '-Filename&amp;lt;${datetimeoriginal}.%f.%e' -d &amp;quot;%Y-%m-%d %H-%M-%S&amp;quot; *.jpeg -directory=out -if '($datetimeoriginal and (not ($datetimeoriginal eq &amp;quot;0000:00:00 00:00:00&amp;quot;))) and ($filetype eq &amp;quot;JPEG&amp;quot;)' 
exiftool -v '-Filename&amp;lt;${DateCreated}.%f.%e' -d &amp;quot;%Y-%m-%d %H-%M-%S&amp;quot; *.jpeg -directory=out -if '($DateCreated and (not ($DateCreated eq &amp;quot;0000:00:00 00:00:00&amp;quot;))) and ($filetype eq &amp;quot;JPEG&amp;quot;)'
exiftool -v '-Filename&amp;lt;${DateCreated}.%f.%e' -d &amp;quot;%Y-%m-%d %H-%M-%S&amp;quot; *.jpg -directory=out -if '($DateCreated and (not ($DateCreated eq &amp;quot;0000:00:00 00:00:00&amp;quot;))) and ($filetype eq &amp;quot;JPEG&amp;quot;)'


exiftool -v '-Filename&amp;lt;${datetimeoriginal}.%f.%e' -d &amp;quot;%Y-%m-%d %H-%M-%S&amp;quot; *.heic -directory=out -if '($datetimeoriginal and (not ($datetimeoriginal eq &amp;quot;0000:00:00 00:00:00&amp;quot;)))'

exiftool -v '-Filename&amp;lt;${datetimeoriginal}.%f.%e' -d &amp;quot;%Y-%m-%d %H-%M-%S&amp;quot; *.png -directory=out -if '($datetimeoriginal and (not ($datetimeoriginal eq &amp;quot;0000:00:00 00:00:00&amp;quot;)))'
exiftool -v '-Filename&amp;lt;${DateCreated}.%f.%e' -d &amp;quot;%Y-%m-%d %H-%M-%S&amp;quot; *.png -directory=out -if '($DateCreated and (not ($DateCreated eq &amp;quot;0000:00:00 00:00:00&amp;quot;)))'

exiftool -v '-Filename&amp;lt;${datetimeoriginal}.%f.%e' -d &amp;quot;%Y-%m-%d %H-%M-%S&amp;quot; *.gif -directory=out -if '($datetimeoriginal and (not ($datetimeoriginal eq &amp;quot;0000:00:00 00:00:00&amp;quot;))) and ($filetype eq &amp;quot;GIF&amp;quot;)' 
exiftool -v '-Filename&amp;lt;${DateCreated}.%f.%e' -d &amp;quot;%Y-%m-%d %H-%M-%S&amp;quot; *.gif -directory=out -if '($DateCreated and (not ($DateCreated eq &amp;quot;0000:00:00 00:00:00&amp;quot;))) and ($filetype eq &amp;quot;GIF&amp;quot;)'

# Чистим xmp
rm -f ./*.xmp

# перекладываем файлы в папки YYYY/YYYY-MM/
cd out
find . -maxdepth 1  -type f -exec bash -c 'file=$(basename &amp;quot;{}&amp;quot;); yearname=${file:0:4}; monthname=${file:5:2}; pathname=&amp;quot;$yearname/$yearname-$monthname&amp;quot;; mkdir -p &amp;quot;$pathname&amp;quot;; echo &amp;quot;$pathname&amp;quot;; mv &amp;quot;$file&amp;quot; &amp;quot;$pathname&amp;quot;/ ' \;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Полезные ссылки по теме&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://exiftool.org/metafiles.html"&gt;https://exiftool.org/metafiles.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/rjames86/33b9af12548adf091a26"&gt;https://gist.github.com/rjames86/33b9af12548adf091a26&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ninedegreesbelow.com/photography/exiftool-commands.html"&gt;https://ninedegreesbelow.com/photography/exiftool-commands.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.polaine.com/2015/01/fixing-photo-and-video-file-metadata-with-exiftool/"&gt;https://www.polaine.com/2015/01/fixing-photo-and-video-file-metadata-with-exiftool/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;КЭНК!&lt;br /&gt;
Слава роботам!&lt;/p&gt;
</description>
</item>


</channel>
</rss>