<?xml version = "1.0" encoding = "UTF-8"?>
<rss
  xmlns:yandex="http://news.yandex.ru"
  xmlns:media="http://search.yahoo.com/mrss/"
  xmlns:turbo="http://turbo.yandex.ru"
  version="2.0">
<channel>
<title><![CDATA[ Tech-Research.ru ]]></title>
<description><![CDATA[ Исследования и опыты в технологиях ]]></description>
<link>https://tech-research.ru</link>
<language>ru</language>
<turbo:analytics type="Yandex" id="52842826"></turbo:analytics>
<image>
    <url>https://tech-research.ru/favicon.png</url>
    <title>Tech-Research.ru</title>
    <link>https://tech-research.ru</link>
</image>
<lastBuildDate>2026-04-11T16:27:43 +0500</lastBuildDate>

    <item turbo="true">
        <title><![CDATA[ Как я испытал 4к 32 дюймовый 144гц монитор... ]]></title>
        <link>https://tech-research.ru/kak-ia-ispytal-4k-32-diuimovyi-144ghts-monitor/</link>
        <turbo:topic><![CDATA[ Как я испытал 4к 32 дюймовый 144гц монитор... ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/kak-ia-ispytal-4k-32-diuimovyi-144ghts-monitor/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2026-02-07T19:56:54 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2026/02/-----------.png" class="kg-image" alt="" loading="lazy" width="1280" height="960" srcset="https://tech-research.ru/content/images/size/w600/2026/02/-----------.png 600w, https://tech-research.ru/content/images/size/w1000/2026/02/-----------.png 1000w, https://tech-research.ru/content/images/2026/02/-----------.png 1280w" sizes="(min-width: 720px) 720px"></figure><p>Один товарищ продает свой монитор Philips 329M1RV, и пока он его продает, я попросил на тест, если понравится, то заберу. Но, спойлер - не понравилось.</p><p>Есть KVM-switch, т.е. переключает юсб от компа на ноут и всю периферию, есть подсветка как на телевизорах этой же марки, заряжает ноут, достаточно удобный монитор, 500 нит яркости, в помещении уже на 70% слепит...</p><p>Еще у этого монитора шикарные характеристики - 32 дюйма, 144 герц, 8 битный IPS, 4к разрешение... Но нужен ли конкретно мне этот монитор?</p><p>Начинаю тестировать, подключаю один ноутбук - выдает 60 герц при 4к, видимо не тянет, подключаю другой - аналогично, может быть шнур слабенький.</p><p>Подключаю комп, ну выкручиваю 144 герц, слышу как кулеры постоянно работающие бесшумпно начали чуть сильнее крутиться... Если в интерфейсе скролить, крутить, что то шевелить то тут выше 60 герц уже плавность не поднимается. </p><p>Если смотреть ролики то тоже незаметно, в фильмах между 24 киношными герцами и 60 разница очень сильная, а вот между 60 и 144 не заметил (использовал SVP).</p><p>Про 4к тоже немного спорный момент - когда монитор стоит в метре от моих глаз, то не особо заметна разница, каких то там пикселей не вижу и на 2к мониторе.</p><p>Про размер 32 дюйма, ну как будто 27 это идеально по высоте, а 32 нужно немного гулять глазами по кадру.</p><p>Про потребление тоже - если 2к 27 дюймовик тратит около 20-30 ватт, то 4к 32 уже около 70-80 ватт при сравнимой яркости, сколько тратит столько и греется, нагревается прямо как мой телевизор, при включении и выключении немного похрустывает корпусом.</p><p>Дальше уже возникают немного неприятные моменты, либо у меня не самый качественный провод DisplayPort, либо он ловит какие то наводки, но вот то что идеально работает на 2к 60, то будет работать с артефактами на 4к 144.</p><p>Про заводскую калибровку тоже, мониторы DELL обычно откалиброваны как и макбуки, т.е. цвета красивые, ничего не синит, не желтит, а вот на филипсе картинка синит, приходилось заходить в настройки и подкручивать.</p><p>В общем я понял что для такого монитора нужны повышенные требования к источнику, половина моих устройств не смогут выдать больше 60 герц на 4к, увеличенная нагрузка на железо, а в финале нужно иметь сценарии эксплуатации при которых ощутима разница. Я не играю и похоже не пойму всех преимуществ, но мой ноутбук при воспроизведении такого видео на таком экране ощутимо разогрелся.</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Dell Latitude 3410 - топ за свои деньги ]]></title>
        <link>https://tech-research.ru/dell-latitude-3410-top-za-svoi-dienghi/</link>
        <turbo:topic><![CDATA[ Dell Latitude 3410 - топ за свои деньги ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/dell-latitude-3410-top-za-svoi-dienghi/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2025-10-03T14:26:16 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Многие компании сбывают оптом целыми мешками бизнес-ноутбуки 5 летней давности, один из таких Dell Latitude 3410, изначально ноутбук обычный офисный: 8 гиг оперативки, 256 SSD, Core i5</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2025/10/-----------.png" class="kg-image" alt="" loading="lazy" width="790" height="837" srcset="https://tech-research.ru/content/images/size/w600/2025/10/-----------.png 600w, https://tech-research.ru/content/images/2025/10/-----------.png 790w" sizes="(min-width: 720px) 720px"></figure><p>Но если так поглядеть, то процессор 10210U еще вполне бодрый для сегодняшних лет и еще лет на 5 может хватить для написания кода, интернета, просмотра фильмов, даже сервачок можно слепить.</p><p>Оптимальная цена на барахолках не более 14 тыс за комплектацию 8 оперативки + 256 SSD.</p><h2 id="%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D0%B0-%D0%BE%D1%85%D0%BB%D0%B0%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D1%8F">Система охлаждения</h2><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2025/10/------------1.png" class="kg-image" alt="" loading="lazy" width="1249" height="958" srcset="https://tech-research.ru/content/images/size/w600/2025/10/------------1.png 600w, https://tech-research.ru/content/images/size/w1000/2025/10/------------1.png 1000w, https://tech-research.ru/content/images/2025/10/------------1.png 1249w" sizes="(min-width: 720px) 720px"></figure><p>Достаточно открутить только 4 болтика в обратном порядке 4, 3, 2, 1 и термотрубка с радиатором снимается, после чего можно поменять термопасту и продуть ребра радиатора.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2025/10/------------2.png" class="kg-image" alt="" loading="lazy" width="858" height="508" srcset="https://tech-research.ru/content/images/size/w600/2025/10/------------2.png 600w, https://tech-research.ru/content/images/2025/10/------------2.png 858w" sizes="(min-width: 720px) 720px"></figure><p>После обслуживания видим что при тех же нагрузках нагрев до 79 градусов, а не 100, уже на 20 градусов холоднее, это при том что на картинке изображен стресс-тест, такая нагрузка в обычной жизни почти никогда не бывает... При обычном наборе кода или офисной работе будет около 46-50 градусов практически с выключенным вентилятором.</p><p>Термопрофиль у ноутбука чем то похож на макбук, он разгоняет вентилятор только когда хорошо нагрелся, при просмотре видео может вообще бесшумно работать. Но в биосе есть настройки управления температурой</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2025/10/------------3.png" class="kg-image" alt="" loading="lazy" width="1280" height="960" srcset="https://tech-research.ru/content/images/size/w600/2025/10/------------3.png 600w, https://tech-research.ru/content/images/size/w1000/2025/10/------------3.png 1000w, https://tech-research.ru/content/images/2025/10/------------3.png 1280w" sizes="(min-width: 720px) 720px"></figure><ul><li>Оптимальный - всё стандартно и производительность и тишина, но при нагрузке разгоняется.</li><li>Холодный - тут похоже вентилятор прибавляется чтобы держать температуру процессора ниже, но кулеры разгоняет сильнее. И при этом замедляет проц.</li><li>Тихий - тут так понимаю вентилятор тише, но температура будет выше, процессор тоже замедляется.</li><li>Ультра производительность - тут видимо и процессор на пиковых значениях и вентилятор...</li></ul><p>Я пока этим не игрался, оптимальные значения дают пиковую мощность под 40 ватт кратковременно, но как только проц нагревается его бусты уменьшаются, а потом начинает работать вентилятор...</p><h2 id="%D0%B1%D0%B0%D1%82%D0%B0%D1%80%D0%B5%D0%B9%D0%BA%D0%B0"> Батарейка</h2><p>В биосе есть настройка скорости зарядки и сохранения батарейки</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2025/10/------------4.png" class="kg-image" alt="" loading="lazy" width="1280" height="960" srcset="https://tech-research.ru/content/images/size/w600/2025/10/------------4.png 600w, https://tech-research.ru/content/images/size/w1000/2025/10/------------4.png 1000w, https://tech-research.ru/content/images/2025/10/------------4.png 1280w" sizes="(min-width: 720px) 720px"></figure><p>Тут можно быструю зарядку включить или выключить, можно включить использование только внешнего источника... Можно настроить уровни при которых начинается зарядка и прекращается, чтобы ноутбук постоянно не подзаряжался до 100 и не разряжался до 99%.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2025/10/------------6.png" class="kg-image" alt="" loading="lazy" width="1934" height="1325" srcset="https://tech-research.ru/content/images/size/w600/2025/10/------------6.png 600w, https://tech-research.ru/content/images/size/w1000/2025/10/------------6.png 1000w, https://tech-research.ru/content/images/size/w1600/2025/10/------------6.png 1600w, https://tech-research.ru/content/images/2025/10/------------6.png 1934w" sizes="(min-width: 720px) 720px"></figure><p>Базовая батарейка на 40 втч с маркировкой <strong>jk6y6 </strong>- на данный момент она стоит около 1500-2000 руб</p><p>Но можно пожертвовать слотом для 2.5 диска и поставить расширенную на 53ВтЧ, примерно за 3000-3500 руб, ее маркировка <strong>H5CKD</strong></p><p>Базовой батарейки хватает примерно на 4-5 часов при максимальной яркости и просмотре локального 1080р видео, а расширенной до 6-7 часов.</p><p>Думаю, можно и 10 часов выжать, если включить экономию энергии, убавить яркость и просто читать код.</p><h2 id="%D0%B7%D0%B0%D0%BC%D0%B5%D0%BD%D0%B0-ssd">Замена SSD</h2><p>Базово стоит маленький ссд на 256 гиг, в принципе и его хватает, он NVME, но при желанеии он легко меняется на полноразмерные модели, крепление выполнено на защелке и можно переставлять посадочное место под разную длину m2 накопителей.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2025/10/------------7.png" class="kg-image" alt="" loading="lazy" width="1280" height="960" srcset="https://tech-research.ru/content/images/size/w600/2025/10/------------7.png 600w, https://tech-research.ru/content/images/size/w1000/2025/10/------------7.png 1000w, https://tech-research.ru/content/images/2025/10/------------7.png 1280w" sizes="(min-width: 720px) 720px"></figure><p></p><h2 id="%D1%87%D1%82%D0%BE-%D0%B5%D1%89%D0%B5-%D0%B1%D1%8B-%D0%B7%D0%B0%D0%BC%D0%B5%D0%BD%D0%B8%D1%82%D1%8C">Что еще бы заменить?</h2><p>Традиционно, хотелось бы заменить матрицу, тут она 6 битная и по яркости ну примерно 200-250 нит, если будет нечего делать то буду продолжать развлечения...</p><p></p><h2 id="%D1%84%D0%B8%D0%BD%D0%B0%D0%BB">Финал</h2><p>Могу сказать что этот ноутбук намного качественнее всяких массовых моделей, это корпоративный сегмент, комплектующие к нему продаются везде. Сам ноут выполнен хоть и в пластике, но достаточно премиально, например, он включается при открытии крышки, есть подсветка клавиатуры. Биос имеет очень много разных настроек. Ну и бонусом, в материнке будет вшит ключик Windows 10 Pro, одна только лицензия чего стоит.</p><p>Ноут умеет заряжаться по type-c</p><p>На 20 вольтах </p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2025/10/------------8.png" class="kg-image" alt="" loading="lazy" width="960" height="1280" srcset="https://tech-research.ru/content/images/size/w600/2025/10/------------8.png 600w, https://tech-research.ru/content/images/2025/10/------------8.png 960w" sizes="(min-width: 720px) 720px"></figure><p>И даже на 33 ваттной зарядке от 8 вольт и даже от повербанка, который выдает 24-25 ватт</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2025/10/------------9.png" class="kg-image" alt="" loading="lazy" width="656" height="521" srcset="https://tech-research.ru/content/images/size/w600/2025/10/------------9.png 600w, https://tech-research.ru/content/images/2025/10/------------9.png 656w"></figure> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Что с ютубом, какие планы? ]]></title>
        <link>https://tech-research.ru/chto-s-iutubom-kakiie-plany/</link>
        <turbo:topic><![CDATA[ Что с ютубом, какие планы? ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/chto-s-iutubom-kakiie-plany/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2024-07-29T21:55:26 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Определенное время был запал, хотелось пилить видосы, канал плавно развивался, даже удалось накопить более тысячи подписчиков, на самых популярных видео было около 300 тыс просмотров.</p><p>Но чем дальше, тем менее интересно это всё стало. На ютубе отключили монетизацию, мой старый блог из 2010 года был закопан гуглом, непонятно что с ним случилось, но все картинки пропали, навигация сломалась, больше я не доверяю облачным сервисам и всё буду крутить на своих ресурсах.</p><p>Сам формат блога как статей тоже мне показался не очень удобным, вместо него будет wiki со структурированным контентом, этот блог останется, но основное наполнение будет в вики, там буду расписывать все свои опыты с железом и софтом. Помимо этого будет еще git репозиторий с моими проектами и документацией к ним git.tech-research.ru </p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2024/07/-----------.png" class="kg-image" alt loading="lazy" width="1087" height="564" srcset="https://tech-research.ru/content/images/size/w600/2024/07/-----------.png 600w, https://tech-research.ru/content/images/size/w1000/2024/07/-----------.png 1000w, https://tech-research.ru/content/images/2024/07/-----------.png 1087w" sizes="(min-width: 720px) 720px"></figure> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Диски постоянно стрекочут головками mdadm, ext4 ]]></title>
        <link>https://tech-research.ru/diski-postoianno-striekochut-gholovkami/</link>
        <turbo:topic><![CDATA[ Диски постоянно стрекочут головками mdadm, ext4 ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/diski-postoianno-striekochut-gholovkami/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2024-06-15T13:16:06 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Дело было так, диски у меня достаточно шумные, внутри каждого диска по 3 блока головок, т.е. три механизма, дисков 4 штуки в одном NAS Terramaster.</p><p>И вот завершился 4х дневный ребилд всего этого массива из 4х дисков по 18 террабайт, но шум никуда не уходит, диск не просто тукает, как он любит, а именно хрустит, стрекочет, что-то на нем происходит.</p><p>Но я ведь ничего даже не разместил на диске, он абсолютно пустой, но </p><pre><code>mdamd -D /dev/md0</code></pre><p>Выдает постоянно</p><blockquote>State :  active</blockquote><p>Хотя, должно быть</p><blockquote>State : clean</blockquote><p>Т.е. в состоянии active что-то читается/пишется, а clean значит диск всё записал и уже в режиме ожидания.</p><p>Поставил утилиту для анализа</p><pre><code>apt install blktrace</code></pre><p>Дальше запустил трассировку операций на диск</p><pre><code>btrace -w 600 -a write /dev/md0</code></pre><p>И в выхлопе такое</p><pre><code>  9,0    2       79     9.271989366  1127  Q  WS 27648858368 + 1024 [ext4lazyinit]
  9,0    2       80     9.507989774  1127  Q  WS 27648859392 + 1024 [ext4lazyinit]
  9,0    2       81     9.509846860     0  C  WS 27648859392 + 768 [0]
  9,0    1       61     9.510479277     0  C  WS 27648860160 + 256 [0]
  9,0    2       82     9.727989922  1127  Q  WS 27648860416 + 1024 [ext4lazyinit]
  9,0    1       62     9.728802836     0  C  WS 27648860416 + 768 [0]
  9,0    1       63     9.728803092     0  C  WS 27648861184 + 256 [0]
  9,0    2       83     9.947990731  1127  Q  WS 27648861440 + 1024 [ext4lazyinit]
  9,0    2       84     9.949847960     0  C  WS 27648861440 + 768 [0]
  9,0    2       85     9.949848155     0  C  WS 27648862208 + 256 [0]
  9,0    2       86    10.167990861  1127  Q  WS 27648862464 + 1024 [ext4lazyinit]
  9,0    1       64    10.168814270     0  C  WS 27648862464 + 768 [0]
  9,0    1       65    10.168814521     0  C  WS 27648863232 + 256 [0]
  9,0    2       87    10.387989454  1127  Q  WS 27648863488 + 1024 [ext4lazyinit]
  9,0    2       88    10.389847586     0  C  WS 27648863488 + 768 [0]
  9,0    2       89    10.389847764     0  C  WS 27648864256 + 256 [0]
  9,0    2       90    10.607989529  1127  Q  WS 27648864512 + 1024 [ext4lazyinit]
  9,0    1       66    10.608804887     0  C  WS 27648864512 + 768 [0]
  9,0    1       67    10.608805140     0  C  WS 27648865280 + 256 [0]
  9,0    2       91    10.827989865  1127  Q  WS 27648865536 + 1024 [ext4lazyinit]
  9,0    2       92    10.829849387     0  C  WS 27648865536 + 768 [0]
  9,0    2       93    10.829849569     0  C  WS 27648866304 + 256 [0]
  9,0    2       94    11.047989739  1127  Q  WS 27648866560 + 1024 [ext4lazyinit]
  9,0    1       68    11.048803128     0  C  WS 27648866560 + 768 [0]
  9,0    1       69    11.048803372     0  C  WS 27648867328 + 256 [0]
  9,0    2       95    11.267989663  1127  Q  WS 27648867584 + 1024 [ext4lazyinit]</code></pre><p>Оказывается, инсталлятор линукса форматирует диск достаточно быстро без всяких доп. опций, но потом очень медленно и лениво диск продолжает какие-то операции, это может продолжаться несколько недель на больших томах.</p><p>Выходом было переформатировать диск с опциями <code>-E lazy_itable_init=0,lazy_journal_init=0</code></p><p>Т.е. файловая система создается минут 10-15, но после форматирования абсолютно все дела сделаны и все 4 диска могут отдыхать в простое. У меня еще конечно дополнительные опции форматирования конкретно под мой массив для оптимизации скорости и спараметрами рейда и уменьшенным резервированием.</p><pre><code> mkfs.ext4 -v -m 0.01 -b 4096 -E lazy_itable_init=0,lazy_journal_init=0,stride=128,stripe-width=256 /dev/md0</code></pre><p>Теперь диски относительно тихие, только диск мотора и технология PWL</p><blockquote>WD называет это профилактическим выравниванием износа (PWL); стреловидная головка для распределения смазки и предотвращения износа в конкретном месте. То есть добавленный шум — это функция, которую вы не можете отключить. Щелчки и лязг характерны для всех новых приводов WD.</blockquote> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Сбор статистики посещения сайта по IP ]]></title>
        <link>https://tech-research.ru/sbor-statistiki-posieshchieniia-saita-po-ip/</link>
        <turbo:topic><![CDATA[ Сбор статистики посещения сайта по IP ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/sbor-statistiki-posieshchieniia-saita-po-ip/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2024-05-19T01:23:59 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Например, форма обратной связи находится по адресу /feedback, туда часто заходят спам-боты, которых я блокирую в индивидуальном порядке, обычно такие боты находятся на VPS-серверах</p><pre><code>cat /var/log/nginx/access.log | grep /feedback | awk '{print $1}' | sort -n | uniq -c | sort -nr</code></pre><p>Чтобы понять какой фирме принадлежит адрес - поможет команда whois</p><pre><code>whois 5.165.2.147 |grep "org-name:" | uniq</code></pre><p>А можно совместить и слепить вот такое</p><pre><code> cat /var/log/nginx/access.log | grep /feedback | awk '{print $1}' | uniq | while read -r line; do whois $line; done| grep org-name | uniq</code></pre><p>На выходе получаем типа такого</p><blockquote>org-name:       Biterika Group LLC<br>org-name:       JSC "ER-Telecom Holding" Yekaterinburg Branch</blockquote><p>Сразу видно что среди наших посетителей появились битерика или например AWS, Google cloud и другие хостинги, значит к нам приходят боты.</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Проблемы с wifi (wifi6) на Samsung s23 ultra ]]></title>
        <link>https://tech-research.ru/probliemy-s-wifi-na-samsung-s23-ultra/</link>
        <turbo:topic><![CDATA[ Проблемы с wifi (wifi6) на Samsung s23 ultra ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/probliemy-s-wifi-na-samsung-s23-ultra/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2023-12-19T18:31:45 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Многие люди сталкиваются с проблемой подключения к wifi на новых телефонах самсунг, проблема известна уже почти как год, никакие обновления ее не решают. Проявляется следующим образом - иногда перестает работать интернет, т.е. открываешь приложение и пишет что нет связи, иногда эта проблема плавает, т.е. связь то пропадает, то появляется, иногда просто навсегда пропадает интернет, при этом в шторке подключение активное, помогает выключение вай-фай и заново включение. Попробуем разобраться в этой проблеме.</p><h2 id="%D0%B2%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5">Введение</h2><p>Сразу скажу что проблема плавает и очень зависит от региона для которого произведен телефон и вашего роутера. Если ваш роутер не поддерживает wifi6, то 100% проблем у вас не будет. Если 2.4Ггц, то тоже будет всё отлично.</p><p>В настоящее время в магазинах могут быть телефоны из самых разных стран и они адаптированы под местные нормы.</p><h2 id="%D0%BF%D1%80%D0%B8%D1%87%D0%B8%D0%BD%D1%8B">Причины</h2><p>Точной причины я сказать пока не могу, но мои эксперименты дают некоторое понимание о влиянии разных режимов работы точки доступа.</p><p>При максимально современном режиме работы wifi-сети захватывается не один канал 5Ггц, а сразу 4 при ширине канала в 80 Мгц, плюсом используется диапазон 2.4 в параллель.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2023/12/-----------.png" class="kg-image" alt loading="lazy" width="894" height="633" srcset="https://tech-research.ru/content/images/size/w600/2023/12/-----------.png 600w, https://tech-research.ru/content/images/2023/12/-----------.png 894w" sizes="(min-width: 720px) 720px"></figure><p>Видимо, в зависимости от региона производства или других особенностей, некоторые каналы 5ггц не поддерживаются, и когда все эти каналы двух диапазонов одновременно участвуют в подключении, то происходят или частые потери пакетов или отключение или другие эффекты.</p><h2 id="%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D1%8F">Решения</h2><p>Первым делом выключите в настройках телефона рандомный mac-адрес, да, это способствует некой защите и приватности, но на роутере тонкие настройки обычно производятся с привязкой устройства по физическому адресу, к тому же пинговать проще когда статический IP, а не присваивается каждый раз динамически.</p><p>Второе - выключите все опции энергосбережения сети и адаптивного переключения на мобильную сеть.</p><p>Третье - перед экспериментами лучше сделать сброс Bluetooth и wifi.</p><h3 id="%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B5-124-ghz">Решение 1 - 2.4 Ghz</h3><p>Первое решение достаточно действенное и эффективное, но имеет ряд недостатков, на роутере можно зарегистрировать беспроводного клиента и запретить ему подключение к 5Ггц, тогда только один телефон из всех устройств будет иметь скорость не 600+ мегабит, а только 150, этого в целом достаточно для большинства задач и остальные устройства не пострадают в скорости.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2023/12/------------1.png" class="kg-image" alt loading="lazy" width="921" height="775" srcset="https://tech-research.ru/content/images/size/w600/2023/12/------------1.png 600w, https://tech-research.ru/content/images/2023/12/------------1.png 921w" sizes="(min-width: 720px) 720px"><figcaption>настройка клиента на keenetic giga</figcaption></figure><p>В ходе испытаний, в течение 2х суток не было потерь пакетов в пинге, задержки около 100-200мс, что вполне приемлемо, но не идеально...</p><h3 id="%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B5-2%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B8%D1%82%D1%8C-%D0%BA%D0%B0%D0%BD%D0%B0%D0%BB-%D0%BD%D0%B0-5ghz">Решение 2 - изменить канал на 5Ghz</h3><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2023/12/------------2.png" class="kg-image" alt loading="lazy" width="516" height="205"></figure><p>Нужно учитывать, что ширина более 20мгц захватывает несколько соседних каналов, поэтому можно поиграться с граничными диапазонами, у меня был 56й канал, поставил 36, ситуация значительно улучшилась, теперь не 3000мс задержки, а около 500-800... Но иногда бывают проблемы.</p><p>Думаю, что это самое правильное решение, т.к. и скорость максимальная, и потерь не 10%, а только 1%, но тут нужно экспериментировать, ставим пинг на несколько часов, проверяем максималку через speedtest, у пингов может улучшиться задержка, но при этом скорость упасть, параллельно советую тестировать на других устройствах сети - смартфоны, ноутбуки, чтобы никому не сделать хуже.</p><h3 id="%D1%80%D0%B5%D1%88%D0%B5%D0%BD%D0%B8%D0%B5-3%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5-%D1%88%D0%B8%D1%80%D0%B8%D0%BD%D1%8B">Решение 3 - изменение ширины</h3><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2023/12/------------3.png" class="kg-image" alt loading="lazy" width="531" height="304"></figure><p>При изменении ширины опять же страдает скорость, если с 80 на 40 поменять, то скорость падает с 600мегабит до 300 по воздуху, при этом на всех устройствах сразу.</p><h2 id="%D0%B2%D1%8B%D0%B2%D0%BE%D0%B4%D1%8B">Выводы</h2><p>Изменение ширины канала, переключение 802.11ax-&gt;802.11ac (на wifi5) значительно повышает стабильность, но уменьшает скорость для всех</p><p>Изменение на 2.4ггц еще сильнее уменьшает скорость и повышает стабильность, но другие клиенты не страдают.</p><p>Изменение канала на 5Ггц самое удачное решение, но нужно подбирать канал.</p><p>Успешный эксперимент на одном телефоне не может гарантировать такой же успех на другом, т.к. есть вероятность региона продажи, во всех странах действуют разные правила по допустимым частотам, каналам и т.д., и вероятно радиомодули настроены по-разному или применяются разные модификации.</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Orange pi zero 3 ]]></title>
        <link>https://tech-research.ru/orange-pi-zero-3/</link>
        <turbo:topic><![CDATA[ Orange pi zero 3 ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/orange-pi-zero-3/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2023-09-30T17:53:51 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Прикупил себе на днях парочку одноплатных компьютеров Orange pi zero 3 на 4 гига.</p><p>Последний раз я игрался с Raspberry pi 2 и 3, и технологии за эти годы значительно продвинулись. И памяти 4 гига вместо одного или 2х, и питание type-c, и сеть гигабитная</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2023/09/------------1.png" class="kg-image" alt loading="lazy" width="960" height="1280" srcset="https://tech-research.ru/content/images/size/w600/2023/09/------------1.png 600w, https://tech-research.ru/content/images/2023/09/------------1.png 960w" sizes="(min-width: 720px) 720px"></figure><h2 id="%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D0%BE%D0%B9-%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B">Установка операционной системы</h2><p>Вам понадобится флешка microsd и кардридер, желательно прикупить microHDMI-HDMI проводок для наладки.</p><p>На официальном сайте качаем образ Ubuntu, для наших нужд нужна серверная версия без графического интерфейса</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2023/09/------------2.png" class="kg-image" alt loading="lazy" width="635" height="171" srcset="https://tech-research.ru/content/images/size/w600/2023/09/------------2.png 600w, https://tech-research.ru/content/images/2023/09/------------2.png 635w"></figure><p>Форматируем флешку утилитой <a href="https://www.sdcard.org/downloads/formatter/?ref=tech-research.ru">SD Memory Card Formatter</a></p><p>Далее распаковываем скаченный образ 7zip, внутри должен быть файл img</p><p>Качаем утилиту <a href="https://win32diskimager.org/?ref=tech-research.ru">Win32 disk imager</a>, указываем путь до img, указываем диск и жмем write</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2023/09/------------3.png" class="kg-image" alt loading="lazy" width="505" height="374"></figure><p>Дальше вставляем флешку контактами в сторону платы, и всё должно заработать, но это пока не всё.</p><p>При первом старте система сама делает ресайз, в результате чего раздел занимает всё место на диске</p><h3 id="%D0%B2%D0%B0%D1%80%D0%B8%D0%B0%D0%BD%D1%82-%D0%BF%D0%BE%D0%B4%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F-%D1%87%D0%B5%D1%80%D0%B5%D0%B7-%D0%BE%D1%82%D0%BB%D0%B0%D0%B4%D0%BE%D1%87%D0%BD%D1%8B%D0%B9-%D0%BF%D0%BE%D1%80%D1%82-%D0%B1%D0%B5%D0%B7-%D0%BC%D0%BE%D0%BD%D0%B8%D1%82%D0%BE%D1%80%D0%B0">Вариант подключения через отладочный порт без монитора</h3><p>Иногда достаточно неудобно отлаживать систему, подключаться к сети, надо клавиатуру переткнуть со своего компа и монитор и в процессе гугления туда обратно переключаться, но если у вас есть программатор или usb-ttl конвертер, такие модули на том же озоне можно купить за 150 рублей.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2023/09/------------4.png" class="kg-image" alt loading="lazy" width="960" height="1280" srcset="https://tech-research.ru/content/images/size/w600/2023/09/------------4.png 600w, https://tech-research.ru/content/images/2023/09/------------4.png 960w" sizes="(min-width: 720px) 720px"></figure><p>На плате апельсинки есть три пина RX, TX и GND, нужно подключить RX и TX крест-накрест, т.е. на программаторе RX подключаем к TX на одноплатнике, а TX наоборот к RX и GND соединяем.</p><!--kg-card-begin: markdown--><table>
<thead>
<tr>
<th>Программатор</th>
<th>Одноплатник</th>
</tr>
</thead>
<tbody>
<tr>
<td>RX</td>
<td>TX</td>
</tr>
<tr>
<td>TX</td>
<td>RX</td>
</tr>
<tr>
<td>GND</td>
<td>GND</td>
</tr>
</tbody>
</table>
<!--kg-card-end: markdown--><p></p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2023/09/------------5.png" class="kg-image" alt loading="lazy" width="960" height="1280" srcset="https://tech-research.ru/content/images/size/w600/2023/09/------------5.png 600w, https://tech-research.ru/content/images/2023/09/------------5.png 960w" sizes="(min-width: 720px) 720px"></figure><p>Далее, смотрим в диспетчере устройств номер com-порта</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2023/09/------------6.png" class="kg-image" alt loading="lazy" width="485" height="98"></figure><p>Открываем программу Putty, выбираем serial, прописываем наш COM6, скорость 115200</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2023/09/------------7.png" class="kg-image" alt loading="lazy" width="450" height="443"></figure><p>Теперь можем видеть процесс загрузки, настроить сеть. работать в консоли как по ssh, но при этом имея полный доступ к локальному терминалу как с монитором и клавиатурой</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2023/09/------------8.png" class="kg-image" alt loading="lazy" width="1054" height="516" srcset="https://tech-research.ru/content/images/size/w600/2023/09/------------8.png 600w, https://tech-research.ru/content/images/size/w1000/2023/09/------------8.png 1000w, https://tech-research.ru/content/images/2023/09/------------8.png 1054w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2023/09/------------9.png" class="kg-image" alt loading="lazy" width="650" height="512" srcset="https://tech-research.ru/content/images/size/w600/2023/09/------------9.png 600w, https://tech-research.ru/content/images/2023/09/------------9.png 650w"></figure><h2 id="%D0%BF%D0%B5%D1%80%D0%B2%D1%8B%D0%B5-%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B8">Первые настройки</h2><h3 id="wifi">Wifi</h3><blockquote>Пароль root = orangepi</blockquote><p>Воспользуемся нетворк-манагером и его консольным интерфейсом</p><h4 id="%D0%BF%D0%B5%D1%80%D0%B2%D1%8B%D0%B9-%D0%B2%D0%B0%D1%80%D0%B8%D0%B0%D0%BD%D1%82%D0%B1%D0%BE%D0%BB%D0%B5%D0%B5-%D0%B3%D1%80%D0%B0%D1%84%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B9">Первый вариант - более графический</h4><p>Первый вариант - вводим в терминале команду <code>nmtui</code> и видим вот такой псевдографический интерфейс, тут можно найти сеть, подколючиться к ней, отредактировать соединение, например, задать статический айпи, всё это будет само подключаться при перезагрузке.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2023/09/------------10.png" class="kg-image" alt loading="lazy" width="648" height="431" srcset="https://tech-research.ru/content/images/size/w600/2023/09/------------10.png 600w, https://tech-research.ru/content/images/2023/09/------------10.png 648w"></figure><p>Таким же методом можно и проводное подключение настроить, быстро и удобно...</p><h4 id="%D0%B2%D0%B0%D1%80%D0%B8%D0%B0%D0%BD%D1%82-2%D1%87%D0%B5%D1%80%D0%B5%D0%B7-%D0%BA%D0%BE%D0%BD%D1%81%D0%BE%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9-%D0%B8%D0%BD%D1%82%D0%B5%D1%80%D1%84%D0%B5%D0%B9%D1%81">Вариант 2 - через консольный интерфейс</h4><p>Второй вариант больше для сервисных вещей, допустим, роутер отвалился и вам нужно восстановить соединение, или в качестве резервного канала есть другой роутер с мобильной сетью...</p><p>Подробное описание есть <a href="https://habr.com/ru/companies/vdsina/articles/512282/?ref=tech-research.ru">на хабре</a> и еще тут <a href="https://networkmanager.dev/docs/api/latest/nm-settings-nmcli.html?ref=tech-research.ru">документация с параметрами тонкой настройки</a> в тонкой настройке можно задать время ожидания интерфейса, количество попыток переподключения и вроде как точный bsid вайфая, когда у вас бесшовная сеть или 5ггц+2.4ггц с одним именем, то тут можно явно потвикать качество соединения. </p><figure class="kg-card kg-code-card"><pre><code>sudo nmcli device wifi connect 'WiFINetworkName' ifname wlan0</code></pre><figcaption>подключение к сети</figcaption></figure><figure class="kg-card kg-code-card"><pre><code>sudo nmcli device wifi list</code></pre><figcaption>поиск сетей</figcaption></figure><figure class="kg-card kg-code-card"><pre><code>nmcli connection show</code></pre><figcaption>показать текущие соединения, их статус (зеленые активные) и названия</figcaption></figure><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2023/10/------------1.png" class="kg-image" alt loading="lazy" width="670" height="89" srcset="https://tech-research.ru/content/images/size/w600/2023/10/------------1.png 600w, https://tech-research.ru/content/images/2023/10/------------1.png 670w"></figure><figure class="kg-card kg-code-card"><pre><code>nmcli connection edit Pavlik-wifi</code></pre><figcaption>редактирование в интерактивном режиме тонких настроек</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2023/10/-----------.png" class="kg-image" alt loading="lazy" width="731" height="554" srcset="https://tech-research.ru/content/images/size/w600/2023/10/-----------.png 600w, https://tech-research.ru/content/images/2023/10/-----------.png 731w" sizes="(min-width: 720px) 720px"><figcaption>команда print выводит текущие настройки</figcaption></figure><p>Ну и если по какой-то причине соединение вдруг отвалилось, то есть команда подключения</p><pre><code>nmcli connection up Pavlik-wifi</code></pre><p>Иногда у меня такое возникало, когда выключал питание одноплатника простым выдергиванием питания, то при дальнейшем включении интернет не поднимался, написал такой скрипт, который ждет 15 секунд, отправляет один пинг на роутер и если он неудачный, то запускает подключение, а если пинг идет, то снова спит 15 секунд, данное решение на коленке за 3 секунды накидано, но пока работает</p><pre><code class="language-bash">#!/bin/bash
connection_name="Pavlik-wifi"
period=15


while sleep $period; do
/bin/ping 192.168.1.1 -c1 || nmcli connection up $connection_name
done</code></pre><p>Далее, этот скрипт нужно сделать исполняемым</p><pre><code>chmod +x имя файла</code></pre><p>И прописать в /etc/rc.local с амперсандом на конце, чтобы скрипт не стопорил дальнейший процесс и уходил в фон.</p><h2 id="%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0-%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B">Настройка системы</h2><p>У меня достаточно встроенное решение, когда один одноплатник крутит один jar файл с Java-приложением, поэтому захотелось оптимизировать систему, сильно заморачиваться с перепиливанием инициализации не хочу, но могу выпилить некоторые сервисы из автозапуска, которые замедляют время включения аппарата.</p><p>Для начала, нужно обновиться, т.к. образ системы собран не сегодня и наверно даже не неделю назад, то появилось много обновлений.</p><pre><code>sudo su

apt update &amp;&amp; apt upgrade</code></pre><p>В серверной убунте установлено из коробки всё подряд, даже докер, опенвпн и т.д... Мне это всё особо не нужно. В т.ч. встроенный конфигуратор и блютуз.</p><pre><code>apt purge openvpn docker-ce docker-ce-cli containerd.ioy vim-runtime gcc-12 gcc-11 cpp-12 g++-11 cpp-11 alsa-utils nfs-common dnsmasq bluetooth bluez bluez-tools

apt autoremove</code></pre><p></p><h2 id="%D0%B4%D0%BE%D0%BF%D0%BE%D0%BB%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE">Дополнительно</h2><ul><li><a href="http://www.orangepi.org/orangepiwiki/index.php/Orange_Pi_Zero_3?ref=tech-research.ru">http://www.orangepi.org/orangepiwiki/index.php/Orange_Pi_Zero_3</a> - мануал официальный</li></ul> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Опыт с Synology DS218 ]]></title>
        <link>https://tech-research.ru/synology-ds218/</link>
        <turbo:topic><![CDATA[ Опыт с Synology DS218 ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/synology-ds218/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2023-02-15T11:35:31 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Решил я поиграться с Synology, брать более дешевые устройства с 512мб оперативной памяти не хотел, однодисковые не сильно надежно, если уж сваливать все данные на хранилище, то нужно быть в нем уверенным, поэтому взял двухдисковое на 4тб, объединил в зеркальный рейд. Модели с плюсом тоже не особо вижу преимущество, ну будет там слабый и старый селерон, особо дата-центр не развернуть, лучше уж взять на ARM процессоре. Золотой серединой был DS218, у него 4х ядерный процессор, 2 гига оперативки, лотки для быстрой установки без винтов и разборки корпуса.</p><h2 id="%D0%BF%D0%B5%D1%80%D0%B2%D1%8B%D0%B9-%D0%BE%D0%BF%D1%8B%D1%82">Первый опыт</h2><h3 id="%D0%BF%D1%80%D0%BE%D1%81%D0%BC%D0%BE%D1%82%D1%80-%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE">Просмотр видео</h3><p>20 гиговое видео транскодирует достаточно хорошо, неподдерживаемый на моем телевизоре формат показывает без зависаний. На телевизоре установлено приложение DS Video </p><h3 id="%D1%81%D0%BA%D0%BE%D1%80%D0%BE%D1%81%D1%82%D1%8C-%D0%BA%D0%BE%D0%BF%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85">Скорость копирования данных</h3><p>По гигабитной сети скорость копирования информации около 112 мегабайт в сек, что соответствует 896 мегабитам (примерно предел для дешевого коммутатора) и примерно равно скорости одного диска, жесткие диски WD Red со скоростью вращения 5400 примерно 115-120 мегабайт в сек имеют скорость, не знаю зачем все требуют 2.5 или 10 гигабит, если только в рейд-0 с удвоением скорости. По wifi  жмет только 25 мегабайт в сек, это около 200 мегабит, но у меня на компе не самая лучшая антенна и сетевая карта (на прием 400, на отдачу 200-250).</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2023/02/------------2.png" class="kg-image" alt loading="lazy" width="492" height="297"></figure><h3 id="%D1%81%D0%BE%D1%84%D1%82">Софт</h3><p>По софту тут хоть и не всё идеально, но лучше конкурентов, всё стабильно, куча приложений для мобильных устройств, куча пакетов в базовом репозитории + есть репозиторий community, для его подключения нужно в веб-интерфейсе зайти в центр пакетов - источники пакетов, нажать добавить и вписать адрес <strong>http://packages.synocommunity.com/</strong> </p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2023/02/------------3.png" class="kg-image" alt loading="lazy" width="1062" height="470" srcset="https://tech-research.ru/content/images/size/w600/2023/02/------------3.png 600w, https://tech-research.ru/content/images/size/w1000/2023/02/------------3.png 1000w, https://tech-research.ru/content/images/2023/02/------------3.png 1062w" sizes="(min-width: 720px) 720px"></figure><p>Сама операционная система ставится на диски и оперативно обновляется.</p><h3 id="%D0%BF%D0%BE%D0%BB%D0%B5%D0%B7%D0%BD%D1%8B%D0%B5-%D0%BF%D0%B0%D0%BA%D0%B5%D1%82%D1%8B-%D0%B8%D0%B7-%D1%80%D0%B5%D0%BF%D0%BE%D0%B7%D0%B8%D1%82%D0%BE%D1%80%D0%B8%D1%8F-community">Полезные пакеты из репозитория community</h3><p><strong>SynoCli Monitor tools</strong> добавит такие вещи как watch, iperf и другие</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2023/02/------------6.png" class="kg-image" alt loading="lazy" width="802" height="436" srcset="https://tech-research.ru/content/images/size/w600/2023/02/------------6.png 600w, https://tech-research.ru/content/images/2023/02/------------6.png 802w" sizes="(min-width: 720px) 720px"></figure><p><strong>SynoCli File tools </strong>добавит множество полезных программ и утилит, среди которых удобный редактор nano</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2023/02/------------7.png" class="kg-image" alt loading="lazy" width="786" height="337" srcset="https://tech-research.ru/content/images/size/w600/2023/02/------------7.png 600w, https://tech-research.ru/content/images/2023/02/------------7.png 786w" sizes="(min-width: 720px) 720px"></figure><h2 id="%D0%B1%D0%BE%D1%80%D1%8C%D0%B1%D0%B0-%D1%81-%D1%88%D1%83%D0%BC%D0%BE%D0%BC">Борьба с шумом</h2><p>В первую очередь, гудение самих дисков, стоит приподнять устройство в руках - звук уменьшается и практически не слышен, только шум вентилятора, поэтому, можно подложить мягкий материал и станет значительно тише, поверхностью под устройством не будет жужжать.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2023/02/-----------.png" class="kg-image" alt loading="lazy" width="2000" height="1500" srcset="https://tech-research.ru/content/images/size/w600/2023/02/-----------.png 600w, https://tech-research.ru/content/images/size/w1000/2023/02/-----------.png 1000w, https://tech-research.ru/content/images/size/w1600/2023/02/-----------.png 1600w, https://tech-research.ru/content/images/size/w2400/2023/02/-----------.png 2400w" sizes="(min-width: 720px) 720px"></figure><p>Если хранилище используется редко, например раз в неделю зайти с телефона резервную копию сделать, то можно настроить гибернацию дисков</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2023/02/------------4.png" class="kg-image" alt loading="lazy" width="1014" height="412" srcset="https://tech-research.ru/content/images/size/w600/2023/02/------------4.png 600w, https://tech-research.ru/content/images/size/w1000/2023/02/------------4.png 1000w, https://tech-research.ru/content/images/2023/02/------------4.png 1014w" sizes="(min-width: 720px) 720px"></figure><p>Только слишком частую наверно лучше не делать, частые остановки и раскрутки дисков не очень полезны.</p><p>Отдельная проблема - сам вентилятор, тут установлен вентилятор на 92мм, очень шумный, его слышно даже на слабых оборотах, как его усмирить будет далее...</p><p>Для регулировки профиля вентилятора нужно открыть файлик <code>/usr/syno/etc.defaults/scemd.xml</code></p><pre><code class="language-xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;scemd&gt;
&lt;fan_config hibernation_speed="UNKNOWN" type="DUAL_MODE_HIGH" threshold="6" period="20"&gt;
.......
&lt;/fan_config&gt;

&lt;!--
это для тихого профиля 
hibernation_speed="STOP" - остановка вентилятора при остановке дисков  
--&gt;
&lt;fan_config hibernation_speed="STOP" type="DUAL_MODE_LOW" threshold="6" period="20"&gt;
  &lt;!--
	0 градусов - 10% скорость
    46 градусов - 15% скорость
    ....
    при 61 градусах аварийное выключение
  --&gt;
  &lt;disk_temperature action="NONE" fan_speed="10%40hz"&gt;0&lt;/disk_temperature&gt;
  &lt;disk_temperature action="NONE" fan_speed="15%40hz"&gt;46&lt;/disk_temperature&gt;
  &lt;disk_temperature action="NONE" fan_speed="35%40hz"&gt;52&lt;/disk_temperature&gt;
  &lt;disk_temperature action="NONE" fan_speed="60%40hz"&gt;55&lt;/disk_temperature&gt;
  &lt;disk_temperature action="NONE" fan_speed="99%40hz"&gt;58&lt;/disk_temperature&gt;
  &lt;disk_temperature action="SHUTDOWN" fan_speed="99%40hz"&gt;61&lt;/disk_temperature&gt;
  &lt;!--аналогично для температуры процессора--&gt;
  &lt;cpu_temperature action="NONE" fan_speed="10%40hz"&gt;0&lt;/cpu_temperature&gt;
  &lt;cpu_temperature action="NONE" fan_speed="35%40hz"&gt;70&lt;/cpu_temperature&gt;
  &lt;cpu_temperature action="NONE" fan_speed="99%40hz"&gt;80&lt;/cpu_temperature&gt;
  &lt;cpu_temperature action="SHUTDOWN" fan_speed="99%40hz"&gt;105&lt;/cpu_temperature&gt;
&lt;/fan_config&gt;
        
.... дальше не интересно</code></pre><p>После изменения конфига нужно перезагрузиться командой <code>reboot</code></p><p>В веб-интерфейсе странный баг, всегда показывает ровно 40 градусов</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2023/02/------------5.png" class="kg-image" alt loading="lazy" width="518" height="229"></figure><p>Не совсем уверен, но похоже настоящая температура определяется вот так</p><pre><code>cat /sys/class/hwmon/hwmon0/temp1_input

43522</code></pre><p>И судя по всему, у меня 43.5 градусов</p><p>Узнать температуру дисков можно так, строчка <strong>Temperature_Celsius</strong></p><pre><code> smartctl -A -d sat  /dev/sda
 smartctl -A -d sat  /dev/sdb</code></pre><p>На всякий случай, нагрузить процессор можно выполнив несколько раз</p><pre><code>dd if=/dev/urandom | bzip2 -9 &gt; /dev/null &amp;</code></pre> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ WakeOnLan Linux ]]></title>
        <link>https://tech-research.ru/wakeonlan-linux/</link>
        <turbo:topic><![CDATA[ WakeOnLan Linux ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/wakeonlan-linux/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2023-01-29T14:51:26 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Иногда возникает необходимость дистанционно включать компьютер, в моем случае, это сервер для бэкапов, в нем много дисков и они шумят, но круглыми сутками он не нужен, только по расписанию</p><h2 id="%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0-wakeonlan-%D0%B2-bios">Настройка WakeOnLan в BIOS</h2><p>Первым делом, нужно включить поддержку WOL в биосе, иногда эта настройка находится в настройках питания и так и называется, но вот на материнских платах ASUS нужно зайти в пункт APM Configuration и там включить Power In by PCI-E</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2023/01/-----------.png" class="kg-image" alt loading="lazy" width="500" height="375"></figure><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2023/01/------------1.png" class="kg-image" alt loading="lazy" width="500" height="375"></figure><p></p><h2 id="%D0%B2%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-%D0%BF%D0%BE%D0%B4%D0%B4%D0%B5%D1%80%D0%B6%D0%BA%D0%B8-wol-%D0%BD%D0%B0-debian">Включение поддержки WOL на Debian</h2><p>Открываем <code>/etc/network/interfaces</code> и прописываем там опцию <code>ethernet-wol g</code></p><pre><code class="language-bash"># The primary network interface
allow-hotplug enp3s0
iface enp3s0 inet static
        address 192.168.0.8/24
        gateway 192.168.0.1
        dns-nameservers 192.168.0.1
        ethernet-wol g</code></pre><p>Далее перезагружаем и выключаем сервер </p><pre><code>reboot
...
shutdown -h now</code></pre><p>А с другого компа выполняем команду <code>wakeonlan</code> с указанием mac-адреса</p><pre><code> wakeonlan 05:43:1b:98:4b:60</code></pre><h2 id="%D0%BE%D1%81%D0%BE%D0%B1%D0%B5%D0%BD%D0%BD%D0%BE%D1%81%D1%82%D0%B8-%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%8B-wol">Особенности работы WOL</h2><p>Функция wakeonlan может не работать если вы выключите из розетки и снова включите компьютер, т.е. он должен быть предварительно выключен из операционной системы в определенный режим ожидания. Поэтому, лучшим решением будет настройка включения после потери питания.</p><p>Если электроэнергия мигнет, то сервер включится, выключить его можно по ssh, а включить по wakeonlan.</p><p></p><h2 id="bash-%D1%81%D0%BA%D1%80%D0%B8%D0%BF%D1%82-%D0%B4%D0%BB%D1%8F-%D0%B2%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F-%D0%B8-%D0%BE%D0%B6%D0%B8%D0%B4%D0%B0%D0%BD%D0%B8%D1%8F">Bash скрипт для включения и ожидания</h2><p>Удобно не запоминать mac-адреса включаемых машин и не запускать руками пинг в ожидании готовности.</p><pre><code class="language-bash">#!/bin/bash
case $1 in

bigbro)
targ_mac="04:42:1a:97:4b:66";
targ_ip="192.168.0.33"
;;

synology)
targ_mac="05:44:1b:93:4b:65";
targ_ip="192.168.0.66"
;;

*)
cat &lt;&lt; EOF
Fignya params!!!
Use: wol bigbro | wol synology

EOF

exit;
;;

esac


wait_ip(){
i=0;
while [ $i -lt 40 ];
do
i=$((i+1))
ping -q -c1 ${targ_ip} &amp;&gt;/dev/null &amp;&amp; echo "host is enabled!!!" &amp;&amp; break || echo host ${targ_ip} is disabled, waiting ${i}/40...
sleep 3
echo "wait enable host"
done
}


wakeonlan ${targ_mac} &amp;&amp; wait_ip</code></pre><p>Данный скрипт накатан на коленке, поэтому не особо хорош, но свои задачи выполняет, в моей сети постоянно работает только экономичный мини-пк потребляющий около 5 ватт, я подключаюсь к нему и с него стартую команду типа <code>wol bigbro</code> которая отправляет сигнал включения на комп и ждет пока он включится, далее пишет что комп готов и я могу подключиться к компу.</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Почему объем диска с системе меньше? ]]></title>
        <link>https://tech-research.ru/pochiemu-obiem-diska-s-sistiemie-mienshie/</link>
        <turbo:topic><![CDATA[ Почему объем диска с системе меньше? ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/pochiemu-obiem-diska-s-sistiemie-mienshie/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2022-10-09T10:23:00 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Многие неопытные люди удивляются тому, что в системе в свойствах объем диска отличается от того, что написано на корпусе диска, попробуем разобраться в этом феномене.</p><p>Вчера в отзывах к одному жесткому диску увидел в поле недостатков момент что у диска на 12Тб по факту только 10.9 в системе.</p><p>Издавна, в жестких дисках указывались не такие байты, которым нас учили на информатике. Нас учили что в одном килобайте 1024 байт, в одном мегабайте 1024 килобайт, в одном гигабайте 1024 мегабайт и в одном террабайте 1024 гигабайт.</p><p>Но производители дисков искользуют систему си, поэтому приставка тера для них это 12 нулей или *10^12, точнее это не тарабайт, а тебибайт.</p><p>12000000000000/1024/1024/1024/1024 = 10.91 терабайт</p><p>упрощенно вот так</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/10/------------3.png" class="kg-image" alt loading="lazy" width="459" height="119"></figure><p>Получим примерно такую таблицу дисков</p><!--kg-card-begin: markdown--><table>
<thead>
<tr>
<th>На диске</th>
<th style="text-align:center">В системе</th>
</tr>
</thead>
<tbody>
<tr>
<td>1TB</td>
<td style="text-align:center">909Мб</td>
</tr>
<tr>
<td>3TB</td>
<td style="text-align:center">2.72</td>
</tr>
<tr>
<td>4TB</td>
<td style="text-align:center">3.63</td>
</tr>
<tr>
<td>6TB</td>
<td style="text-align:center">5.45</td>
</tr>
<tr>
<td>8TB</td>
<td style="text-align:center">7.27</td>
</tr>
<tr>
<td>10TB</td>
<td style="text-align:center">9.09</td>
</tr>
<tr>
<td>12TB</td>
<td style="text-align:center">10.91</td>
</tr>
<tr>
<td>14TB</td>
<td style="text-align:center">12.73</td>
</tr>
<tr>
<td>16TB</td>
<td style="text-align:center">14.55</td>
</tr>
<tr>
<td>18TB</td>
<td style="text-align:center">16.37</td>
</tr>
<tr>
<td>20TB</td>
<td style="text-align:center">18.18</td>
</tr>
</tbody>
</table>
<!--kg-card-end: markdown--><p>На самом деле и эта цифра может отличаться, я уже писал раннее о зарезервированном пространстве в Linux, в Windows тоже иногда создаются дополнительные разделы.</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ mdadm - программный рейд Linux ]]></title>
        <link>https://tech-research.ru/mdadm-proghrammnyi-rieid-linux/</link>
        <turbo:topic><![CDATA[ mdadm - программный рейд Linux ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/mdadm-proghrammnyi-rieid-linux/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2022-10-08T16:30:24 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Любой слабенький комп на райзене, а уж тем более современные 8 ядерные процы с достаточным объемом оперативной памяти способны создать достаточно быстрый массив, который уделает бюджетные контроллеры и к тому же более предсказуем, переставляем диски на любой другой комп даже через usb-корзину и собираем Raid.</p><h2 id="%D1%81%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BC%D0%B0%D1%81%D1%81%D0%B8%D0%B2%D0%B0">Создание массива</h2><p>На всякий случай потрем суперблоки, чтобы не возникало ошибок после перезагрузки, на основе этих суперблоков при старте собираются массивы, я один раз совершил ошибку, расформировал Raid-1 и собрал Raid-0, а при перезагрузке получил совсем не тот массив что собирал с поломанными данными</p><blockquote>В данном примере рассматриваем создание массива из цельных дисков, если указывать номер раздела, то можно тоже самое делать с разделами, это удобно при зеркалировании дисков разных размеров, например есть диск на 10 террабайт и на 5, можно на двух дисках создать разделы по 5 террабайт и зазеркалить и еще 5 террабайт будут без зеркала или подключены в другой массив...</blockquote><pre><code>mdadm --zero-superblock /dev/sdx
mdadm --zero-superblock /dev/sdy</code></pre><p>Если выдает ошибку, значит суперблоков нет, всё ок.</p><p>Затрем метаданные на дисках</p><pre><code>wipefs --all --force /dev/sdx
wipefs --all --force /dev/sdy</code></pre><p>Создаем устройство</p><ul><li>-l 0 - RAID-0</li><li>-n 2 - два диска в массиве</li></ul><pre><code>mdadm --create --verbose /dev/md8 -l 0 -n 2 /dev/sdd /dev/sda</code></pre><p>Создаем файловую систему на md устройстве</p><pre><code>mkfs.ext4 /dev/md8</code></pre><h2 id="%D1%80%D0%B0%D1%81%D1%84%D0%BE%D1%80%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BC%D0%B0%D1%81%D1%81%D0%B8%D0%B2%D0%B0">Расформирование массива</h2><p>Если вдруг захотели из Raid1 переделать в Raid0, то действия следующие</p><p>Отмонтируем диск</p><pre><code>umount /dev/md8</code></pre><p>Остановим массив</p><pre><code>mdadm -S /dev/md8</code></pre><p>Далее, чтобы при рестарте системы у нас не собрался непредсказуемый массив основанный на устаревших данных в дисках, нужно затереть суперблоки</p><pre><code>mdadm --zero-superblock /dev/sdx1
mdadm --zero-superblock /dev/sdy1</code></pre><h2 id="%D0%BE%D0%B1%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D0%BA%D0%BE%D0%BD%D1%84%D0%B8%D0%B3%D1%83%D1%80%D0%B0%D1%86%D0%B8%D0%B8">Обновление конфигурации</h2><p>Бывает такое что после удаления и вновь создания массивов возникают проблемы с нумерацией, когда вместо md1 создается md127, решается это примерно так</p><pre><code>mdadm --examine --scan &gt;&gt; /etc/mdadm/mdadm.conf</code></pre><p>Далее нужно открыть файл <code>/etc/mdadm/mdadm.conf</code> и удалить или закомментировать там дублирующие старые строчки, а потом обновить initramfs и перезагрузиться</p><pre><code>update-initramfs -u
reboot </code></pre><h2 id="%D0%B2%D1%8B%D0%B2%D0%BE%D0%B4-%D0%B8%D0%B7-%D1%80%D0%B5%D0%B6%D0%B8%D0%BC%D0%B0-read-only">Вывод из режима read-only</h2><p>Для raid5 может такое произойти что диск синхронизировался, вы не дождались полной синхронизации и перезагрузили компьютер</p><pre><code>md5 : active (auto-read-only) raid5 sdd[2] sda[1] sdc[4] sdf[0]
      52734587904 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/3] [UUU_]
      bitmap: 0/131 pages [0KB], 65536KB chunk</code></pre><p>Чтобы вывести диск из этого режима нужно выполнить команду</p><pre><code>mdadm -w /dev/md5</code></pre><p>Иногда рейд переходит в автоматический RO лишь по причине что раздел не примонтирован, стоит его смонтировать и всё будет как обычно.</p><h3 id="%D0%BE%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-%D1%81%D0%B8%D0%BD%D1%85%D1%80%D0%BE%D0%BD%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8">Остановка синхронизации</h3><p>Если вдруг ваши диски синхронизировались и вы перезагрузили компьютер, то синхронизация может остановиться и вы увидите <code>resync=PENDING</code></p><pre><code>echo idle &gt; /sys/block/md5/md/sync_action</code></pre><h2 id="%D1%83%D1%81%D0%BA%D0%BE%D1%80%D0%B5%D0%BD%D0%B8%D0%B5-%D1%81%D0%B8%D0%BD%D1%85%D1%80%D0%BE%D0%BD%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8">Ускорение синхронизации</h2><p>Если вы синхронизируете большой массив, например диски по 18Тб и скорость синхронизации показывает около 100 мегабайт в сек, сервер в данный момент ничем не занят и его можно загрузить фоновыми задачами, в промышленной эксплуатации такое не рекомендуется, но в момент начальной настройки можно ускорить процесс, можно сделать скорость синхронизации от 500 до 600</p><pre><code>echo 500000 &gt; /proc/sys/dev/raid/speed_limit_min
echo 600000 &gt; /proc/sys/dev/raid/speed_limit_max</code></pre><p>действует до первой перезагрузки потом будет от 10 до 200</p><h2 id="%D0%BE%D1%81%D0%BE%D0%B1%D1%8B%D0%B5-%D0%BF%D0%B0%D1%80%D0%B0%D0%BC%D0%B5%D1%82%D1%80%D1%8B-%D0%BF%D1%80%D0%B8-%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B8">Особые параметры при форматировании</h2><ul><li><strong>stride</strong> - шаг</li><li><strong>stripe-width</strong> - ширины полосы</li></ul><p>stribe = chunk_size / размер блока</p><p>stripe-width = количество_дисков * stribe</p><p>Размер блока задается при форматировании, он будет 4КиБ = 4096 байт</p><p>Chunk_size можно узнать командой</p><pre><code>mdadm --detail /dev/md10 | grep 'Chunk Size'
        Chunk Size : 512K</code></pre><p>На Raid10 при 4х дисках с данными только 2, вторые 2 его зеркальная копия, поэтому дисков будем считать 2, а не 4.</p><p><strong>stribe </strong>= 512/4 = <strong>128</strong></p><p><strong>stripe-width </strong>= 128*2 = <strong>256</strong></p><p>Итого команда форматирования будет выглядеть так</p><pre><code>mkfs.ext4 -v -m 0.01 -b 4096 -E stride=128,stripe-width=256 /dev/md0</code></pre><h2 id="%D0%BE%D0%BF%D1%86%D0%B8%D0%B8-%D0%BC%D0%BE%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F">Опции монтирования</h2><pre><code>/dev/md5 /mnt/data ext4 nodiratime,noatime,defaults,discard,commit=120 1 2</code></pre><p></p><p>Еще дополнительно откопал статью по доп возможностям рейда</p><ul><li><a href="https://linuxshare.ru/docs/admin/ud_sraid.html?ref=tech-research.ru">https://linuxshare.ru/docs/admin/ud_sraid.html</a></li></ul> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ В Linux df показывает меньше доступного чем размер диска ]]></title>
        <link>https://tech-research.ru/v-linux-df-pokazyvaiet-mienshie-dostupnogho-chiem-razmier-diska/</link>
        <turbo:topic><![CDATA[ В Linux df показывает меньше доступного чем размер диска ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/v-linux-df-pokazyvaiet-mienshie-dostupnogho-chiem-razmier-diska/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2022-10-02T14:36:10 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Решил я объединить парочку жестких по 4Тб в один рейд-0 на 8Тб и получил следующую картинку</p><p></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2022/10/-----------.png" class="kg-image" alt loading="lazy" width="692" height="198" srcset="https://tech-research.ru/content/images/size/w600/2022/10/-----------.png 600w, https://tech-research.ru/content/images/2022/10/-----------.png 692w"><figcaption>Размер 7.3Тб, а доступно только 6.9Тб</figcaption></figure><p>Получается что 400 гигабайт ушло непонятно куда? Это примерно 5+% емкости, но при объемах под 8 террабайт и больше объем может показаться внушительным.</p><p>Решается такой командой, действует на примонтированном устройстве</p><figure class="kg-card kg-code-card"><pre><code>tune2fs -m 1 /dev/md1</code></pre><figcaption>1%</figcaption></figure><p>Но при желании можно совсем не резервировать место, в моем случае это не системный диск, а "для хлама"</p><figure class="kg-card kg-code-card"><pre><code>tune2fs -m 0 /dev/md1</code></pre><figcaption>0% резерв</figcaption></figure><p>В итоге получим примерно такую картину</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/10/------------2.png" class="kg-image" alt loading="lazy" width="663" height="194" srcset="https://tech-research.ru/content/images/size/w600/2022/10/------------2.png 600w, https://tech-research.ru/content/images/2022/10/------------2.png 663w"></figure> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Samba - сетевая папка Linux для Windows ]]></title>
        <link>https://tech-research.ru/samba-sietievaia-papka-linux-dlia-windows/</link>
        <turbo:topic><![CDATA[ Samba - сетевая папка Linux для Windows ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/samba-sietievaia-papka-linux-dlia-windows/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2022-09-17T22:43:52 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>У нас под рукой сервер на Debian 11, первым делом, установим самбу</p><pre><code>apt install samba</code></pre><p>Далее, нам нужно определиться в какую папку будем складывать и под каким пользователем будем хранить данные, допустим, у меня есть рейд массив по пути <code>/mnt/disk1</code>, я создам там две папки - media и documents</p><pre><code>cd /mnt/disk1
mkdir media documents</code></pre><p>Структура примерно такая</p><pre><code>---------------
├──/mnt/disk1
│   ├── /media - всякие фотки
│   ├── /documents - всякие документы</code></pre><p>Узнаем имя нашего интерфейса</p><pre><code>ip addr | grep 192.168
    inet 192.168.0.7/24 brd 192.168.1.255 scope global enp42s0</code></pre><!--kg-card-begin: markdown--><table>
<thead>
<tr>
<th>Элемент</th>
<th>Значение</th>
</tr>
</thead>
<tbody>
<tr>
<td>Путь до первой папки</td>
<td>/mnt/disk1/media</td>
</tr>
<tr>
<td>Сетевое имя первой папки</td>
<td>Media</td>
</tr>
<tr>
<td>Путь до второй папки</td>
<td>/mnt/disk1/documents</td>
</tr>
<tr>
<td>Сетевое имя второй папки</td>
<td>Docs</td>
</tr>
<tr>
<td>Подсеть</td>
<td>192.168.0.0 (роутер на 192.168.0.1)</td>
</tr>
<tr>
<td>Интерфейс, смотрящий в локальную сеть</td>
<td>enp42s0</td>
</tr>
<tr>
<td>Пользователь сетевой папки</td>
<td>user01</td>
</tr>
<tr>
<td>Имя машины в сети</td>
<td>myservername</td>
</tr>
</tbody>
</table>
<!--kg-card-end: markdown--><p>Отредактируем файл <code>/etc/samba/smb.conf</code></p><pre><code>[global]
   bind interfaces only = yes
   deadtime = 15
   disable netbios = yes
   dns proxy = no
   domain master = yes
   encrypt passwords = true
   guest ok = no
   hosts allow = 192.168.0.0/255.255.255.0 127.0.0.1
   hosts deny = all
   interfaces = enp42s0
   invalid users = nobody root
   load printers = no
   max connections = 10
   netbios name = myservername
   preferred master = yes
   preserve case = yes
   printable = no
   server string = Samba Share
   socket options = TCP_NODELAY IPTOS_LOWDELAY SO_RCVBUF=131072 SO_SNDBUF=131072
   strict sync = no
   sync always = no
   syslog = 0
   workgroup = WORKGROUP
   log file = /dev/null
   log level = 0
   min protocol = SMB2


[Media]
   browseable = yes
   path = /mnt/disk1/media
   guest ok = no
   create mask = 0750
   writable = yes
   
[Docs]
   browseable = yes
   path = /mnt/disk1/documents
   guest ok = no
   create mask = 0750
   writable = yes</code></pre><p>Добавим нашего нового пользователя в samba, пароль желательно отличный от системного</p><pre><code>smbpasswd -a user01</code></pre><p>А потом перезапустим сервер samba</p><pre><code>service smbd restart</code></pre><p>Далее жмем <code>win+R</code> печатаем там адрес нашего сервера <code>\\192.168.0.7</code>, вводим логин и пароль и видим две наши папки</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/09/-----------.png" class="kg-image" alt loading="lazy" width="449" height="126"></figure><p>Можно кликнуть правой кнопкой и подключить как сетевой диск.</p><p>Важно дать доступ своему пользователю (user01) к этим папкам</p><pre><code>chown -R user01 /mnt/disk1/media
chown -R user01 /mnt/disk1/documents</code></pre> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ JAVA HTTPClient ]]></title>
        <link>https://tech-research.ru/java-httpclient/</link>
        <turbo:topic><![CDATA[ JAVA HTTPClient ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/java-httpclient/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2022-07-20T02:14:41 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Тестовый класс, прошу не пинать, так сказать заготовка HelloWorld</p><pre><code>import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;



public class Http3 {

    private static final String KEYSTOREPATH = "keystore.jks"; // or .p12
    private static final String TRUSTSTOREPATH = "truststore.jks"; // or .p12
    private static final String KEYSTOREPASS = "123123";
    private static final String KEYPASS = "123123";

    KeyStore readStore() throws Exception {
        try (FileInputStream trustKeyStoreFile = new FileInputStream(new File(KEYSTOREPATH))) {
            KeyStore keyStore = KeyStore.getInstance("JKS"); // or "PKCS12"
            keyStore.load(trustKeyStoreFile, KEYSTOREPASS.toCharArray());
            return keyStore;
        }

    }

    KeyStore readTrust() throws Exception {
        try (FileInputStream trustStoreStream2 = new FileInputStream(new File(TRUSTSTOREPATH))) {
            KeyStore trustStore = KeyStore.getInstance("JKS"); // or "PKCS12"
            trustStore.load(trustStoreStream2,KEYSTOREPASS.toCharArray());
            return trustStore;
        }
    }




    public void query() throws Exception {

        System.out.println(System.getProperty("user.dir"));
        System.out.println(KEYSTOREPATH);

        SSLContext sslContext = SSLContexts.custom()
                .loadTrustMaterial(readTrust(),null)
                //.loadTrustMaterial(null, new TrustSelfSignedStrategy())
                //.loadTrustMaterial(null, (x509CertChain, authType) -&gt; true) //вариант принимающий всё
                .loadKeyMaterial(readStore(), KEYPASS.toCharArray()) // use null as second param if you don't have a separate key password
                .build();


        HttpClient httpClient = HttpClients.custom().setSSLContext(sslContext).build();

        HttpPost query = new HttpPost("https://192.168.200.10/index.php?koko=1");
        query.setHeader("р1","yes"); //заголовок
        query.setEntity(new StringEntity("ratatatat")); //тело


        HttpResponse response = httpClient.execute(query);
        HttpEntity entity = response.getEntity();

        System.out.println("----------------------------------------");
        System.out.println(response.getStatusLine());
        String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
        System.out.println("Response body: " + responseBody);
        EntityUtils.consume(entity);
    }
}</code></pre> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Опыты с сертификатами №1 - генерация и подпись ]]></title>
        <link>https://tech-research.ru/podpis-sobstviennykh-siertifikatov/</link>
        <turbo:topic><![CDATA[ Опыты с сертификатами №1 - генерация и подпись ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/podpis-sobstviennykh-siertifikatov/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2022-07-17T21:43:00 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Сегодня немного попробуем поиграться с сертификатами</p><h2 id="%D0%BF%D0%BE%D0%B4%D0%B3%D0%BE%D1%82%D0%BE%D0%B2%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B5-%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B8">Подготовительные настройки</h2><pre><code>apt install openssl</code></pre><p>Создадим каталоги, т.к. файлы достаточно секретные, нам нужно хранить все исходники в укромном месте, например, в папке /root</p><pre><code>mkdir -p /root/certs/{ca,intermediate,clients,servers}/{certs,crl,newcerts,keys}</code></pre><pre><code>touch /root/certs/{ca,intermediate}/{index.txt,openssl.cnf}
echo 1000 &gt; /root/certs/ca/serial
echo 1000 &gt; /root/certs/intermediate/serial</code></pre><p></p><p>Создание корневого сертификата</p><pre><code>cd /root/certs/ca
nano openssl.cnf</code></pre><pre><code>[ ca ]
default_ca = CA_default

[ CA_default ]
# Directory and file locations.
dir               = /root/certs/ca
certs             = $dir/certs
crl_dir           = $dir/crl
new_certs_dir     = $dir/newcerts
database          = $dir/index.txt
serial            = $dir/serial
RANDFILE          = $dir/keys/.rand

# The root key and root certificate.  
 private_key       = $dir/keys/ca.key.pem  
 certificate       = $dir/certs/ca.cert.pem

# For certificate revocation lists.  
 crlnumber         = $dir/crlnumber  
 crl               = $dir/crl/ca.crl.pem  
 crl_extensions    = crl_ext  
 default_crl_days  = 30

# SHA-1 is deprecated, so use SHA-2 instead.  
 default_md        = sha256

name_opt          = ca_default  
 cert_opt          = ca_default  
 default_days      = 375  
 preserve          = no  
 policy            = policy_strict

[ policy_strict ]
# The root CA should only sign intermediate certificates that match.
# See the POLICY FORMAT section of man ca.
countryName             = match
stateOrProvinceName     = match
organizationName        = optional
organizationalUnitName  = optional
commonName              = optional
emailAddress            = optional


[ req ]
# Options for the `req` tool (`man req`).
default_bits        = 2048
distinguished_name  = req_distinguished_name
string_mask         = utf8only

# SHA-1 is deprecated, so use SHA-2 instead.  
default_md          = sha256

# Extension to add when the -x509 option is used.  
x509_extensions     = v3_ca

[ req_distinguished_name ]
# See https://en.wikipedia.org/wiki/Certificate_signing_request.
countryName                     = Country Name (2 letter code)
stateOrProvinceName             = State or Province Name
localityName                    = Locality Name
organizationName                = Organization Name
organizationalUnitName          = Organizational Unit Name
commonName                      = Common Name
emailAddress                    = Email Address

# Optionally, specify some defaults.  
countryName_default             = RU  
stateOrProvinceName_default     = Russia  
localityName_default            = Russia  
organizationName_default       = Tech-Research.RU  
#organizationalUnitName_default  =  
#emailAddress_default            =

[ v3_ca ]
# Extensions for a typical CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign


[ usr_cert ]
# Extensions for client certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection



[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth


[ crl_ext ]
# Extension for CRLs (`man x509v3_config`).
authorityKeyIdentifier=keyid:always

[ ocsp ]
# Extension for OCSP signing certificates (`man ocsp`).
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning
</code></pre><p>Генерим приватный ключ</p><pre><code>openssl genrsa -aes256 -out keys/ca.key.pem 4096
</code></pre><p>Создаем самоподписанный сертификат, корневой серт сам себя подписывает</p><pre><code>openssl req -config openssl.cnf \
-key keys/ca.key.pem \
-new -x509 -days 7300 -sha256 -extensions v3_ca \
-out certs/ca.cert.pem</code></pre><h2 id="%D0%BF%D1%80%D0%BE%D0%BC%D0%B5%D0%B6%D1%83%D1%82%D0%BE%D1%87%D0%BD%D1%8B%D0%B9-%D1%81%D0%B5%D1%80%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%82">Промежуточный сертификат</h2><p>Обычно используют промежуточный сертификат, точнее его секретную часть, чтобы подписывать серверные и клиентские сертификаты, корневой можно удалить и спрятать, а потом генерить себе сертификаты уже промежуточным</p><pre><code> cd /root/certs/intermediate/
 echo 1000 &gt; crlnumber
 mkdir csr
 nano openssl.cnf</code></pre><pre><code>[ ca ]
# `man ca`
default_ca = CA_default

[ CA_default ]
# Directory and file locations.
dir               = /root/ca/intermediate
certs             = $dir/certs
crl_dir           = $dir/crl
new_certs_dir     = $dir/newcerts
database          = $dir/index.txt
serial            = $dir/serial
RANDFILE          = $dir/private/.rand

# The root key and root certificate.
private_key       = $dir/private/intermediate.key.pem
certificate       = $dir/certs/intermediate.cert.pem

# For certificate revocation lists.
crlnumber         = $dir/crlnumber
crl               = $dir/crl/intermediate.crl.pem
crl_extensions    = crl_ext
default_crl_days  = 30

# SHA-1 is deprecated, so use SHA-2 instead.
default_md        = sha256

name_opt          = ca_default
cert_opt          = ca_default
default_days      = 375
preserve          = no
policy            = policy_loose

[ policy_strict ]
# The root CA should only sign intermediate certificates that match.
# See the POLICY FORMAT section of `man ca`.
countryName             = match
stateOrProvinceName     = match
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ policy_loose ]
# Allow the intermediate CA to sign a more diverse range of certificates.
# See the POLICY FORMAT section of the `ca` man page.
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ req ]
# Options for the `req` tool (`man req`).
default_bits        = 2048
distinguished_name  = req_distinguished_name
string_mask         = utf8only

# SHA-1 is deprecated, so use SHA-2 instead.
default_md          = sha256

# Extension to add when the -x509 option is used.
x509_extensions     = v3_ca

[ req_distinguished_name ]
# See &lt;https://en.wikipedia.org/wiki/Certificate_signing_request&gt;.
countryName                     = Country Name (2 letter code)
stateOrProvinceName             = State or Province Name
localityName                    = Locality Name
0.organizationName              = Organization Name
organizationalUnitName          = Organizational Unit Name
commonName                      = Common Name
emailAddress                    = Email Address

# Optionally, specify some defaults.  
countryName_default             = RU  
stateOrProvinceName_default     = Russia  
localityName_default            = Russia  
organizationName_default       = Tech-Research.RU  
#organizationalUnitName_default  =  
#emailAddress_default            =

[ v3_ca ]
# Extensions for a typical CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

[ usr_cert ]
# Extensions for client certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection

[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth

[ crl_ext ]
# Extension for CRLs (`man x509v3_config`).
authorityKeyIdentifier=keyid:always

[ ocsp ]
# Extension for OCSP signing certificates (`man ocsp`).
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning
</code></pre><p>Генерим приватный ключ</p><pre><code>openssl genrsa -aes256 \
-out keys/intermediate.key.pem 4096</code></pre><p>Создаем запрос на генерацию подписанного ключа</p><pre><code>openssl req -config openssl.cnf -new -sha256 \
-key keys/intermediate.key.pem \
-out csr/intermediate.csr.pem</code></pre><p>Подписываем</p><pre><code>openssl ca -config ../ca/openssl.cnf -extensions v3_intermediate_ca \
-days 3650 -notext -md sha256 \
-in csr/intermediate.csr.pem \
-out certs/intermediate.cert.pem</code></pre><p>Следующей командой можно сверить доверие от корневого к промежуточному сертификату</p><pre><code>openssl verify -CAfile ../ca/certs/ca.cert.pem certs/intermediate.cert.pem</code></pre><h2 id="%D0%B3%D0%B5%D0%BD%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D1%8F-%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%BD%D0%BE%D0%B3%D0%BE-%D1%81%D0%B5%D1%80%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%82%D0%B0">Генерация серверного сертификата</h2><p>Если убрать опцию <code>-aes256</code> то ключ будет без пароля и будет меньше заморочек с веб-сервером</p><pre><code>openssl genrsa -aes256 -out keys/192.168.200.10.key.pem 2048</code></pre><pre><code>openssl req -config openssl.cnf \
-key keys/192.168.200.10.key.pem \
-new -sha256 -out csr/192.168.200.10.csr.pem</code></pre><pre><code>openssl ca -config openssl.cnf \
-extensions server_cert -days 375 -notext -md sha256 \
-in csr/192.168.200.10.csr.pem \
-out certs/192.168.200.10.cert.pem</code></pre><blockquote>Тоже самое можно повторить, указав вместо server_cert usr_cert</blockquote><h2 id="%D0%B3%D0%B5%D0%BD%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D1%8F-%D0%BA%D0%BB%D0%B8%D0%B5%D0%BD%D1%82%D1%81%D0%BA%D0%B8%D1%85-%D1%81%D0%B5%D1%80%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%82%D0%BE%D0%B2">Генерация клиентских сертификатов</h2><p>Мы сгенерируем сразу два сертификата <strong>client1 </strong>и <strong>client2</strong></p><pre><code>  openssl genrsa -out keys/client1.key.pem 2048
  openssl genrsa -out keys/client2.key.pem 2048
  
  
  openssl req -config openssl.cnf -key keys/client1.key.pem -new -sha256 -out csr/client1.csr.pem
  openssl req -config openssl.cnf -key keys/client2.key.pem -new -sha256 -out csr/client2.csr.pem
  
  openssl ca -config openssl.cnf -extensions usr_cert -days 375 -notext -md sha256 -in csr/client1.csr.pem -out certs/client1.cert.pem
  openssl ca -config openssl.cnf -extensions usr_cert -days 375 -notext -md sha256 -in csr/client2.csr.pem -out certs/client2.cert.pem</code></pre><h3 id="%D1%83%D0%BF%D0%B0%D0%BA%D0%BE%D0%B2%D0%BA%D0%B0-%D0%BA%D0%BB%D0%B8%D0%B5%D0%BD%D1%82%D1%81%D0%BA%D0%B8%D1%85-%D1%81%D0%B5%D1%80%D1%82%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%82%D0%BE%D0%B2">Упаковка клиентских сертификатов</h3><p>Для начала создадим цепочку из нашего промежуточного и корневого CA</p><pre><code>cat /root/certs/intermediate/certs/intermediate.cert.pem /root/certs/ca/certs/ca.cert.pem &gt; /root/certs/intermediate/ca_keychain.crt</code></pre><pre><code>openssl pkcs12 -export -in certs/client1.cert.pem -inkey keys/client1.key.pem -certfile ca_keychain.crt -out client1.p12 -passout pass:123321</code></pre><pre><code>openssl pkcs12 -export -in certs/client2.cert.pem -inkey keys/client2.key.pem -certfile ca_keychain.crt -out client2.p12 -passout pass:123321</code></pre> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Опыты на досуге #1 - делаем авторизацию с клиентским сертификатом на nginx ]]></title>
        <link>https://tech-research.ru/opyty-na-dosughie-1-dielaiem-avtorizatsiiu-s-kliientskim-siertifikatom-na-nginx/</link>
        <turbo:topic><![CDATA[ Опыты на досуге #1 - делаем авторизацию с клиентским сертификатом на nginx ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/opyty-na-dosughie-1-dielaiem-avtorizatsiiu-s-kliientskim-siertifikatom-na-nginx/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2022-07-17T15:02:00 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Мне потребовалось сделать тестовый сервер, принимающий POST запросы с аутентификацией по клиентскому сертификату. Пока не буду рассказывать для чего это, просто изучаю Java и нужно отлаживать отправку запросов с mtls. Статья достаточно подробная и "сырая", всё как есть, чтобы не забыть все действия и переиспользовать их в дальнейшем.</p><h2 id="%D0%B2%D0%B2%D0%BE%D0%B4%D0%BD%D1%8B%D0%B5-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D0%B5">Вводные данные</h2><p>Итак, что у нас есть:</p><ul><li>Некая машина для опытов с виртуализацией: <strong>Windows 10</strong> (можно использовать и Linux и Mac по вкусу)</li><li>Виртуализатор, я буду использовать <strong>Hyper-V</strong></li><li>Клиентское ПО для проброса запросов</li><li>Софт для подключения по ssh - можно использовать обычный PowerShell, можно Windows Terminal</li></ul><blockquote>В данных экспериментах мы не будем использовать "правильные" сертификаты, такие как LetsEncrypt, наша цель вообще разобраться как их выпускать, подписывать и т.д.</blockquote><h2 id="%D1%81%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5-%D0%B8-%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0-%D0%B2%D0%B8%D1%80%D1%82%D1%83%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B9-%D0%BC%D0%B0%D1%88%D0%B8%D0%BD%D1%8B-%D0%BD%D0%B0-hyper-v">Создание и настройка виртуальной машины на Hyper-V</h2><p>Заходим в приложения, там справа будет пункт "Программы и компоненты"</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/07/------------1.png" class="kg-image" alt loading="lazy" width="840" height="377" srcset="https://tech-research.ru/content/images/size/w600/2022/07/------------1.png 600w, https://tech-research.ru/content/images/2022/07/------------1.png 840w" sizes="(min-width: 720px) 720px"></figure><p>Далее выбираем пункт "включение или отключение компонентов"</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/07/------------2.png" class="kg-image" alt loading="lazy" width="210" height="158"></figure><p>Теперь нужно активировать Hyper-V в компонентах, нажать ОК и перезагрузиться</p><blockquote>Будьте внимательны, при активации Hyper-V вы не сможете запускать другие варианты виртуализаторов, такие как VirtualBox, Vmware Player и др., если у вас используется другая система виртуализации, то лучше используйте ее и пропустите этот раздел</blockquote><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/07/------------3.png" class="kg-image" alt loading="lazy" width="412" height="366"></figure><p>После перезагрузки запускаем Диспетчер Hyper-V и создаем наш первый виртуальный коммутатор</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/07/------------4.png" class="kg-image" alt loading="lazy" width="719" height="692" srcset="https://tech-research.ru/content/images/size/w600/2022/07/------------4.png 600w, https://tech-research.ru/content/images/2022/07/------------4.png 719w"></figure><blockquote>Мы сделали коммутатор с внутреней сетью, который имеет доступ к нашей машине и другим виртуалкам в этом коммутаторе, будет использовать NAT</blockquote><p>Далее нужно зайти в свойства сетей и прописать для нашего адаптера ip адрес, когда то можно было использовать Default Switch для этих целей, но с последними обновлениями он стал самостоятельно переопределять адреса.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/07/------------5.png" class="kg-image" alt loading="lazy" width="334" height="275"></figure><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/07/------------6.png" class="kg-image" alt loading="lazy" width="360" height="469"></figure><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/07/------------7.png" class="kg-image" alt loading="lazy" width="394" height="457"></figure><p>Подсеть специально создана 192.168.200.0/24 чтобы не пересекаться с моей внутренней локалкой 192.168.0.0/24, а шлюз не указан с той целью, чтобы не портить существующих маршрутов на хост-машине.</p><p>Теперь остается добавить NAT (SNAT) чтобы наши машины из 200 сети подменялись айпишником хост-машины и ответы прилетали обратно из внешней сети.</p><p>Открываем PowerShell с правами администратора</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/07/------------8.png" class="kg-image" alt loading="lazy" width="403" height="375"></figure><p>Вводим команду </p><pre><code>New-NetNat -Name nat1 -InternalIPInterfaceAddressPrefix 192.168.200.0/24</code></pre><p> Подробнее об DNAT (пробросе портов) можно почитать тут <a href="https://tech-research.ru/nastroika-sieti-v-hyper-v-chieriez-nat-probros-portov/">https://tech-research.ru/nastroika-sieti-v-hyper-v-chieriez-nat-probros-portov/</a></p><p>На этом этапе считаем что наш виртуализатор готов к использованию сети по NAT...</p><h2 id="%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-linux-debian">Установка Linux (Debian)</h2><p>Качаем iso-образ Debian net install с официального сайта</p><p>Далее создаем новую виртуальную машину</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/07/------------9.png" class="kg-image" alt loading="lazy" width="1027" height="331" srcset="https://tech-research.ru/content/images/size/w600/2022/07/------------9.png 600w, https://tech-research.ru/content/images/size/w1000/2022/07/------------9.png 1000w, https://tech-research.ru/content/images/2022/07/------------9.png 1027w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2022/07/------------10.png" class="kg-image" alt loading="lazy" width="707" height="559" srcset="https://tech-research.ru/content/images/size/w600/2022/07/------------10.png 600w, https://tech-research.ru/content/images/2022/07/------------10.png 707w"><figcaption>указываем имя машины по вкусу</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2022/07/------------11.png" class="kg-image" alt loading="lazy" width="708" height="559" srcset="https://tech-research.ru/content/images/size/w600/2022/07/------------11.png 600w, https://tech-research.ru/content/images/2022/07/------------11.png 708w"><figcaption>указываем поколение</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2022/07/------------12.png" class="kg-image" alt loading="lazy" width="708" height="557" srcset="https://tech-research.ru/content/images/size/w600/2022/07/------------12.png 600w, https://tech-research.ru/content/images/2022/07/------------12.png 708w"><figcaption>указываем размер памяти, у меня много оперативки, поэтому могу и 10 гиг выделить</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2022/07/------------13.png" class="kg-image" alt loading="lazy" width="710" height="558" srcset="https://tech-research.ru/content/images/size/w600/2022/07/------------13.png 600w, https://tech-research.ru/content/images/2022/07/------------13.png 710w"><figcaption>укажем для машины созданный нами коммутатор</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2022/07/------------14.png" class="kg-image" alt loading="lazy" width="709" height="560" srcset="https://tech-research.ru/content/images/size/w600/2022/07/------------14.png 600w, https://tech-research.ru/content/images/2022/07/------------14.png 709w"><figcaption>тут все хватит и так, а можно и меньше</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2022/07/------------15.png" class="kg-image" alt loading="lazy" width="706" height="559" srcset="https://tech-research.ru/content/images/size/w600/2022/07/------------15.png 600w, https://tech-research.ru/content/images/2022/07/------------15.png 706w"><figcaption>укажем наш iso из которого будем ставить систему</figcaption></figure><p>После создания системы нужно правой кнопкой по ней кликнуть и кое-что подкрутить</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2022/07/------------16.png" class="kg-image" alt loading="lazy" width="720" height="295" srcset="https://tech-research.ru/content/images/size/w600/2022/07/------------16.png 600w, https://tech-research.ru/content/images/2022/07/------------16.png 720w" sizes="(min-width: 720px) 720px"><figcaption>в разделе безопасность отлючим безопасную загрузку</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2022/07/------------17.png" class="kg-image" alt loading="lazy" width="718" height="687" srcset="https://tech-research.ru/content/images/size/w600/2022/07/------------17.png 600w, https://tech-research.ru/content/images/2022/07/------------17.png 718w"><figcaption>отключим автоматические контрольные точки, если потребуется, будем сами их создавать</figcaption></figure><p>Далее стартуем и ставим систему, выбираем просто Install</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/07/------------18.png" class="kg-image" alt loading="lazy" width="1024" height="849" srcset="https://tech-research.ru/content/images/size/w600/2022/07/------------18.png 600w, https://tech-research.ru/content/images/size/w1000/2022/07/------------18.png 1000w, https://tech-research.ru/content/images/2022/07/------------18.png 1024w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2022/07/------------19.png" class="kg-image" alt loading="lazy" width="989" height="728" srcset="https://tech-research.ru/content/images/size/w600/2022/07/------------19.png 600w, https://tech-research.ru/content/images/2022/07/------------19.png 989w" sizes="(min-width: 720px) 720px"><figcaption>тут всё стандартно</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2022/07/------------20.png" class="kg-image" alt loading="lazy" width="1007" height="353" srcset="https://tech-research.ru/content/images/size/w600/2022/07/------------20.png 600w, https://tech-research.ru/content/images/size/w1000/2022/07/------------20.png 1000w, https://tech-research.ru/content/images/2022/07/------------20.png 1007w" sizes="(min-width: 720px) 720px"><figcaption>тут сразу можно нажать отмену и настроить сеть вручную</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2022/07/------------21.png" class="kg-image" alt loading="lazy" width="670" height="327" srcset="https://tech-research.ru/content/images/size/w600/2022/07/------------21.png 600w, https://tech-research.ru/content/images/2022/07/------------21.png 670w"><figcaption>тут настроим наш айпи из той же подсети, что выделили новому адаптеру</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2022/07/------------22.png" class="kg-image" alt loading="lazy" width="769" height="261" srcset="https://tech-research.ru/content/images/size/w600/2022/07/------------22.png 600w, https://tech-research.ru/content/images/2022/07/------------22.png 769w" sizes="(min-width: 720px) 720px"><figcaption>всё оставляем как есть</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2022/07/------------24.png" class="kg-image" alt loading="lazy" width="1000" height="326" srcset="https://tech-research.ru/content/images/size/w600/2022/07/------------24.png 600w, https://tech-research.ru/content/images/2022/07/------------24.png 1000w" sizes="(min-width: 720px) 720px"><figcaption>тоже аналогично</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2022/07/------------25.png" class="kg-image" alt loading="lazy" width="998" height="292" srcset="https://tech-research.ru/content/images/size/w600/2022/07/------------25.png 600w, https://tech-research.ru/content/images/2022/07/------------25.png 998w" sizes="(min-width: 720px) 720px"><figcaption>а вот dns укажем или наш wifi роутер или провайдерский</figcaption></figure><p>Далее несколько шагов, там всё по своему усмотрению</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2022/07/------------26.png" class="kg-image" alt loading="lazy" width="988" height="299" srcset="https://tech-research.ru/content/images/size/w600/2022/07/------------26.png 600w, https://tech-research.ru/content/images/2022/07/------------26.png 988w" sizes="(min-width: 720px) 720px"><figcaption>на тестовых машинах я обычно ставлю всё на один раздел, но для прома можно заморочиться и посчитать</figcaption></figure><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/07/------------27.png" class="kg-image" alt loading="lazy" width="976" height="298" srcset="https://tech-research.ru/content/images/size/w600/2022/07/------------27.png 600w, https://tech-research.ru/content/images/2022/07/------------27.png 976w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/07/------------28.png" class="kg-image" alt loading="lazy" width="1006" height="166" srcset="https://tech-research.ru/content/images/size/w600/2022/07/------------28.png 600w, https://tech-research.ru/content/images/size/w1000/2022/07/------------28.png 1000w, https://tech-research.ru/content/images/2022/07/------------28.png 1006w" sizes="(min-width: 720px) 720px"></figure><p></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2022/07/------------29.png" class="kg-image" alt loading="lazy" width="989" height="371" srcset="https://tech-research.ru/content/images/size/w600/2022/07/------------29.png 600w, https://tech-research.ru/content/images/2022/07/------------29.png 989w" sizes="(min-width: 720px) 720px"><figcaption>пробелом снимаем все галочки, добавим только ssh и стандартные утилиты</figcaption></figure><p>Через несколько секунд система предложит нам извлечь сидиром и перезагрузиться....</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/07/------------30.png" class="kg-image" alt loading="lazy" width="1022" height="872" srcset="https://tech-research.ru/content/images/size/w600/2022/07/------------30.png 600w, https://tech-research.ru/content/images/size/w1000/2022/07/------------30.png 1000w, https://tech-research.ru/content/images/2022/07/------------30.png 1022w" sizes="(min-width: 720px) 720px"></figure><h2 id="%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-%D1%81%D0%BE%D1%84%D1%82%D0%B0">Установка софта</h2><p>Изначально можно залогиниться под root прямо из окошка Hyper-V, а можно зайти по ssh под пользователем и набрать команду su</p><blockquote>Все действия выполняем от суперпользователя, иначе нужно установить sudo и добавлять перед каждой командой sudo</blockquote><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/07/------------31.png" class="kg-image" alt loading="lazy" width="1026" height="276" srcset="https://tech-research.ru/content/images/size/w600/2022/07/------------31.png 600w, https://tech-research.ru/content/images/size/w1000/2022/07/------------31.png 1000w, https://tech-research.ru/content/images/2022/07/------------31.png 1026w" sizes="(min-width: 720px) 720px"></figure><p>Первое, что нужно в новой системе, это навести порядок в репозиториях</p><pre><code>nano /etc/apt/sources.list</code></pre><p>По умолчанию у нас что-то типа такого</p><pre><code>deb http://deb.debian.org/debian/ bullseye main
deb-src http://deb.debian.org/debian/ bullseye main

deb http://security.debian.org/debian-security bullseye-security main
deb-src http://security.debian.org/debian-security bullseye-security main

deb http://deb.debian.org/debian/ bullseye-updates main
deb-src http://deb.debian.org/debian/ bullseye-updates main
</code></pre><p>У нас подключены только ветки main, но нет contrib и non-free, поэтому список пакетов ограничен, добавим их</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/07/------------32.png" class="kg-image" alt loading="lazy" width="1110" height="628" srcset="https://tech-research.ru/content/images/size/w600/2022/07/------------32.png 600w, https://tech-research.ru/content/images/size/w1000/2022/07/------------32.png 1000w, https://tech-research.ru/content/images/2022/07/------------32.png 1110w" sizes="(min-width: 720px) 720px"></figure><p>Далее сохраняем файл в нано через <code>ctrl+w</code>, выходим <code>ctrl+x</code></p><p>Теперь обновим репозиторий и систему</p><pre><code>apt update &amp;&amp; apt upgrade</code></pre><p>Далее поставим самое необходимое</p><pre><code>apt install nginx php-fpm</code></pre><h3 id="%D0%BA%D0%BE%D0%BD%D1%84%D0%B8%D0%B3%D1%83%D1%80%D0%B0%D1%86%D0%B8%D1%8F-nginx-fpm">Конфигурация NGINX + FPM</h3><blockquote>Данная конфигурация похожа больше на Hello World, в проме требуются более тщательные тонкие настройки, тут у нас нет деления по доменным именам, только один хост, к которому привязан некий простейший обработчик на PHP</blockquote><pre><code>server {
        listen 80 default_server;
        listen [::]:80 default_server;

        # SSL configuration
        #
        listen 443 ssl default_server;
        ssl_certificate /opt/ssl/server.crt;
        ssl_certificate_key /opt/ssl/server.key;
        #mtls
        ssl_client_certificate /opt/ssl/trust.crt;
        ssl_trusted_certificate /opt/ssl/client1.crt;
        ssl_verify_client optional;

        root /www;

        index index.php index.html index.htm index.nginx-debian.html;

        server_name _;

        location / {
                try_files $uri $uri/ /index.php?$args;
        }


        location  ~ \.php$ {
                include snippets/fastcgi-php.conf;

                fastcgi_pass unix:/run/php/php7.4-fpm.sock;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

                fastcgi_param           X-SSL-CERT        $ssl_client_cert;
                fastcgi_param           X-SSL-VERIFIED    $ssl_client_verify;
                fastcgi_param           X-SSL-CLIENT-DN   $ssl_client_s_dn;
                fastcgi_param           X-SSL-ISSUER-DN   $ssl_client_i_dn;
                fastcgi_param           HTTP_PROXY      "";
                fastcgi_param SSL_CLIENT_SERIAL $ssl_client_serial;
        }
}</code></pre><pre><code class="language-php">&lt;pre&gt;
&lt;?php print_r($_SERVER); ?&gt;
POST=
&lt;?php print_r($_POST)?&gt;
GET=
&lt;?php print_r($_GET)?&gt;
RAW=
&lt;?=file_get_contents('php://input')?&gt;
&lt;/pre&gt;</code></pre> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Code-server ]]></title>
        <link>https://tech-research.ru/code-server/</link>
        <turbo:topic><![CDATA[ Code-server ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/code-server/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2022-05-21T13:03:00 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Итак, задача - иногда нужно внести небольшие правки в код своего инди-проекта пока едешь в трамвае после работы. Уже несколько лет я привык кодить на сервере, т.е. вся среда развернута на маленьком бесшумном компьютере на подобии Intel NUC, на своем компе я просто устанавливаю VSCode, подключаюсь по ssh и правлю код, тут же в браузере или терминале стартую и проверяю. Клиентские устройства я меняю достаточно часто, то макбуком поиграюсь, то виндобуком, то решу стационарный комп собрать с кучей мониторов, то большой ящик захочу поменять на маленькую сборочку.</p><blockquote>Конечно, можно просто в докере разворачивать то что нужно или в виртуалке, но в случае с переездом с x86 на m1 не всё и сразу было доступно, виртуалбокс так вроде и не завезли, базы данных типа mysql поздно завезли, в общем, программировать на настроеном сервере достаточно удобно, к тому же - можно еще и на ресурсах локального ноутбука экономить, обойтись устройством с 4 гигами оперативки... Но сегодня задался вопросом - а можно ли кодить со смартфона или планшета? </blockquote><p>В каком то виде можно, есть облачная код-платформа на основе VSCode, которая работает в обычных браузерах</p><p>Первым делом залогинимся </p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Ryzen зависает в простое - черный экран или картинка замирает ]]></title>
        <link>https://tech-research.ru/ryzen-zavisaiet-v-prostoie-chiernyi-ekran-ili-kartinka-zamiraiet/</link>
        <turbo:topic><![CDATA[ Ryzen зависает в простое - черный экран или картинка замирает ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/ryzen-zavisaiet-v-prostoie-chiernyi-ekran-ili-kartinka-zamiraiet/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2022-03-29T21:40:39 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Недавно я собрал себе комп взамен проданного макбука, хотел добавить и купить макбук помощнее, но не судьба, цены выросли, единственным вариантом было собирать стационарный комп, ну и AMD Ryzen относительно бюджетное решение получить 6-8 ядер с хорошей частотой, встроенной графикой и малым TPD.</p><p>Собрал я комп, первые дни просто гонял стресс-тесты, ставил драйвера и после всех манипуляций выключал комп, проблем не было даже при долговременных нагрузках.</p><h3 id="%D0%BF%D0%B5%D1%80%D0%B2%D1%8B%D0%B9-%D0%B7%D0%B2%D0%BE%D0%BD%D0%BE%D1%87%D0%B5%D0%BA">Первый звоночек</h3><p>Включил с утра комп, пока собирался на работу - отходил в душ, поставил видео на паузу, пришел и включил воспроизведение, видео начало дергаться рывками и вообще всё застыло - часы не тикают, мышка не двигается, клавиатура не работает, на мониторе застыла картинка, помогла только перезагрузка. Никаких синих экранов, просто зависает.</p><h3 id="%D0%B2%D1%82%D0%BE%D1%80%D0%BE%D0%B9-%D1%81%D0%BB%D1%83%D1%87%D0%B0%D0%B9">Второй случай</h3><p>Комп остался включеным, а я ушел на работу, прихожу вечером, монитор выключен, пошевелил мышкой - монитор включился, но на мониторе просто <strong>черный экран.</strong></p><p>Сильно расстроился, начал читать интернет, там и про брак материнских плат и про дефектные процессоры начитался, но в одной из статей наткнулся на совет - включить максимальную производительность, но сразу так не стал делать, сперва залез в свой <strong><u>сбалансированный план электропитания</u></strong></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2022/03/------------2.png" class="kg-image" alt loading="lazy" width="395" height="441"><figcaption>сбалансированная схема - 0%</figcaption></figure><p>Обратите внимание, минимальное состояние процессора стоит 0%, я максимум что видел за всю жизнь даже в режимах экономии - 5%</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2022/03/------------3.png" class="kg-image" alt loading="lazy" width="403" height="438"><figcaption>экономия энергии - 5%</figcaption></figure><p>После я поставил и в сбалансированной схеме минмалку, но не на 5%, а сразу с запасом на 15%, чтоб совсем уж не экономилось, но при этом и на 100% всегда не шпарило.</p><p>Прошел день - вечером пришел, шевельнул мышкой и он проснулся, при этом проснулся достаточно быстро, видимо, помогло!</p><h2 id="%D0%B2%D1%8B%D0%B2%D0%BE%D0%B4%D1%8B">Выводы</h2><p>Из всего этого я так понял что процессор в простое снижает настолкьо низко температуры, что не может справиться с элементарными базовыми задачами и зависает намертво на них.</p><h2 id="%D1%87%D1%82%D0%BE-%D0%B5%D1%89%D0%B5-%D0%BC%D0%BE%D0%B6%D0%B5%D1%82-%D0%BF%D0%BE%D0%BC%D0%BE%D1%87%D1%8C">Что еще может помочь?</h2><h3 id="%D0%B4%D1%80%D0%B0%D0%B9%D0%B2%D0%B5%D1%80%D0%B0-%D0%BD%D0%B0-%D1%87%D0%B8%D0%BF%D1%81%D0%B5%D1%82">Драйвера на чипсет</h3><p>Заходим на сайт АМД и качаем драйвер на свой чипсет, у меня это B550, на сайте асуса крайние драйвера были старее чем на сайте АМД</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/03/------------4.png" class="kg-image" alt loading="lazy" width="2000" height="791" srcset="https://tech-research.ru/content/images/size/w600/2022/03/------------4.png 600w, https://tech-research.ru/content/images/size/w1000/2022/03/------------4.png 1000w, https://tech-research.ru/content/images/size/w1600/2022/03/------------4.png 1600w, https://tech-research.ru/content/images/2022/03/------------4.png 2222w" sizes="(min-width: 720px) 720px"></figure><h3 id="%D0%BE%D1%82%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-%D0%B1%D1%8B%D1%81%D1%82%D1%80%D0%BE%D0%B9-%D0%B7%D0%B0%D0%B3%D1%80%D1%83%D0%B7%D0%BA%D0%B8">Отключение быстрой загрузки</h3><p>Этот параметр иногда и к синим экранам может приводить</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/03/------------5.png" class="kg-image" alt loading="lazy" width="1128" height="627" srcset="https://tech-research.ru/content/images/size/w600/2022/03/------------5.png 600w, https://tech-research.ru/content/images/size/w1000/2022/03/------------5.png 1000w, https://tech-research.ru/content/images/2022/03/------------5.png 1128w" sizes="(min-width: 720px) 720px"></figure><h3 id="%D1%80%D0%B0%D0%B7%D0%B3%D0%BE%D0%BD-%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D0%B9-%D0%BF%D0%B0%D0%BC%D1%8F%D1%82%D0%B8">Разгон оперативной памяти</h3><p>Если вы крутил настройки в биосе, то иногда это может приводить к проблемам, лучше сбросить всё на стандартные настройки и понаблюдать.</p><h3 id="%D0%BE%D0%B1%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D0%B1%D0%B8%D0%BE%D1%81%D0%B0">Обновление биоса</h3><p>Желательно ставить самый свежий биос, особенно для 4000-5000 серий, многие материнские платы не поддерживают их, да даже если и поддерживают то криво, плюсом еще недавно обнаружилась проблема когда райзены зависают из-за кривой работы программного TPM модуля, тут еще и Windows желательно обновить.</p><h3 id="%D0%BE%D1%85%D0%BB%D0%B0%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5">Охлаждение</h3><p>У моей материнки чипсет B550 достаточно горячий, температура растет примерно по градусу в минуту, когда я просто добавил снизу на передней панели вентилятор на вдув - температура снизилась до 40 и на такой отметке держится, до этого разогревалось до 66-70 даже без нагрузок, если у вас можно на переднюю панель поставить два вентилятора, то и наверх тоже будет полезно, планки памяти тоже достаточно горячие, особенно при разгонах, хороший продув материнской платы никогда не помешает, даже m2 накопители на материнке скажут спасибо за более низкие температуры.</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Wiki.js - структурированная документация ]]></title>
        <link>https://tech-research.ru/wiki-js-strukturirovannaia-dokumientatsiia/</link>
        <turbo:topic><![CDATA[ Wiki.js - структурированная документация ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/wiki-js-strukturirovannaia-dokumientatsiia/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2022-02-11T15:22:00 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Как вы знаете, я пилю на досуге собственную блог-платформу и фреймворк, даже для меня самого требуется наличие какой-то документации на проект, иногда залезаю спустя полгода в свой же код и совершенно забыл какие методы какую логику преследуют, приходится залезать в другой код и там снова вникать, ну это долго, да и последователям нужно что-то оставить, чтобы взяв мой код с GitHub могли быстро проникнуться за полчаса и накатать свое...</p><p>Конечно, я могу за выходные свою wiki-систему запилить и свою блог-систему, но тут можно упереться в такую ситуацию "решил сделать блог о программировании, но сперва нужно написать свою блог систему", в общем, если есть готовые решения, то запускаем их да и всё, мой блог на Ghost (хотя к нему много вопросов), а вот Wiki будет на wiki.js</p><h1 id="%D0%BF%D0%BE%D1%87%D0%B5%D0%BC%D1%83-%D0%BD%D0%B5-docuwiki">Почему не DocuWiki?</h1><p>Раннее я всегда использовал обычные docuwiki, их достоинство - просто скопировал папку, запустил php и работает, можно локально использовать, можно на домашнем сервере запустить, не требует никаких баз данных, есть и пить не просит, с учетом того что в документацию заходишь раз в полгода то и скорости какой то и хайлоада не требуется.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2022/02/-----------.png" class="kg-image" alt loading="lazy" width="2000" height="1816" srcset="https://tech-research.ru/content/images/size/w600/2022/02/-----------.png 600w, https://tech-research.ru/content/images/size/w1000/2022/02/-----------.png 1000w, https://tech-research.ru/content/images/size/w1600/2022/02/-----------.png 1600w, https://tech-research.ru/content/images/2022/02/-----------.png 2092w" sizes="(min-width: 720px) 720px"><figcaption>пример странички на DocuWiki</figcaption></figure><p>Есть еще MediaWiki, та самая, на которой википедия работает, для этих вики есть куча плагинов и оформлений, но что-то в этих системах уже определенно устарело и сам синтаксис не нравится.</p><h2 id="%D1%87%D1%82%D0%BE-%D1%82%D0%B0%D0%BA%D0%BE%D0%B5-wikijs">Что такое Wiki.js</h2><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/02/------------1.png" class="kg-image" alt loading="lazy" width="2000" height="1111" srcset="https://tech-research.ru/content/images/size/w600/2022/02/------------1.png 600w, https://tech-research.ru/content/images/size/w1000/2022/02/------------1.png 1000w, https://tech-research.ru/content/images/size/w1600/2022/02/------------1.png 1600w, https://tech-research.ru/content/images/2022/02/------------1.png 2340w" sizes="(min-width: 720px) 720px"></figure><p>Wiki.JS это вики-система на Node.js, версия 2.5 пока не особо развита, но функционала достаточно. Редактор страниц как обычный визивиг, так и наш любимый MarkDown, даже в текущей блог системе Ghost я привык все списки и заголовки и блоки с кодом набирать на MarkDown</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/02/------------3.png" class="kg-image" alt loading="lazy" width="2000" height="1274" srcset="https://tech-research.ru/content/images/size/w600/2022/02/------------3.png 600w, https://tech-research.ru/content/images/size/w1000/2022/02/------------3.png 1000w, https://tech-research.ru/content/images/size/w1600/2022/02/------------3.png 1600w, https://tech-research.ru/content/images/2022/02/------------3.png 2166w" sizes="(min-width: 720px) 720px"></figure><p>Базовая структура этой системки вполне заточена под создание последовательных структурированных документаций с содержанием, с листингами кода, можно вставлять картинки в целом, всё что нужно...</p><p>Но у этой системы чувствуется недоделка, хочется конечно редактор как на Ghost, хочется вставка картинок из буфера обмена прямо в редакторе, тут это можно делать даже в MarkDown режиме, кнопочку слева нажал и ctrl+v </p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/02/------------4.png" class="kg-image" alt loading="lazy" width="2000" height="1240" srcset="https://tech-research.ru/content/images/size/w600/2022/02/------------4.png 600w, https://tech-research.ru/content/images/size/w1000/2022/02/------------4.png 1000w, https://tech-research.ru/content/images/size/w1600/2022/02/------------4.png 1600w, https://tech-research.ru/content/images/2022/02/------------4.png 2206w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/02/------------5.png" class="kg-image" alt loading="lazy" width="2000" height="1025" srcset="https://tech-research.ru/content/images/size/w600/2022/02/------------5.png 600w, https://tech-research.ru/content/images/size/w1000/2022/02/------------5.png 1000w, https://tech-research.ru/content/images/size/w1600/2022/02/------------5.png 1600w, https://tech-research.ru/content/images/size/w2400/2022/02/------------5.png 2400w" sizes="(min-width: 720px) 720px"></figure><h2 id="%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-wikijs-%D0%B7%D0%B0-5-%D1%81%D0%B5%D0%BA%D1%83%D0%BD%D0%B4">Установка Wiki.js за 5 секунд</h2><p>В наше время не требуется много сил на развертывание, как это было в моей "молодости", Docker творит чудеса и не особо важно какой у вас линукс, главное чтобы там докер был.</p><p>Вариантов с развертыванием PostgreSQL, Mysql и другого не буду рассматривать, меня интересует минималичная документашка под маленький проект и встраиваемая sqlite вполне подойдет</p><p>Сперва создадим директорию под наш проект, пусть это будет <code>/www/wiki.js/</code></p><pre><code>mkdir -p /www/wiki.js

#переходим в папку
cd /www/wiki.js

#создаем пустую базу
sqlite3 database.sqlite "VACUUM;"</code></pre><p>Далее создадим минимальный конфиг <code>nano  config.yml</code></p><pre><code class="language-yml">port: 3000
db:
  type: sqlite
  storage: /wiki/database.sqlite

#ssl:
#  enabled: false
#  port: 3443

bindIP: 0.0.0.0
logLevel: info
offline: false
ha: false

# ---------------------------------------------------------------------
# Data Path
# ---------------------------------------------------------------------
# Writeable data path used for cache and temporary user uploads.
dataPath: /wiki/data</code></pre><p></p><p>Запускаем первый вариант - отладочный, консоль заблокируется, но можно уже в браузеер открыть <code>https://192.168.0.2:8080</code> и провести инсталляцию</p><blockquote>вместо 192.168.0.2 ваш ip, вероятно это будет просто localhost если на текущем пк</blockquote><pre><code class="language-bash">docker run \
  --rm \
  --publish 8080:3000 \
  --name wiki.js \
  --volume $PWD/database.sqlite:/wiki/database.sqlite \
  --volume $PWD/config.yml:/wiki/config.yml \
  requarks/wiki:2</code></pre><p>Если всё ок - жмем `ctrl+c` в консольке и стартуем докер в режиме автозапускаемого фонового сервиса</p><pre><code>docker run \
  -d \
  --restart=always \
  --publish 8080:3000 \
  --name wiki.js \
  --volume $PWD/database.sqlite:/wiki/database.sqlite \
  --volume $PWD/config.yml:/wiki/config.yml \
  requarks/wiki:2</code></pre><p>В целом всё! Дальше можно настроить проксирование через nginx, добавить https через certbot на nginx, а вместо <code>8080:3000</code> в порте можно указать <code>127.0.0.1:8080:3000</code> чтобы сразу закрыть прямое обращение минуя nginx.</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Мониторинг оборудования на Linux-сервере ]]></title>
        <link>https://tech-research.ru/monitoringh-oborudovaniia-na-linux-siervierie/</link>
        <turbo:topic><![CDATA[ Мониторинг оборудования на Linux-сервере ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/monitoringh-oborudovaniia-na-linux-siervierie/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2022-01-29T21:03:00 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/01/------------12.png" class="kg-image" alt loading="lazy" width="1280" height="960" srcset="https://tech-research.ru/content/images/size/w600/2022/01/------------12.png 600w, https://tech-research.ru/content/images/size/w1000/2022/01/------------12.png 1000w, https://tech-research.ru/content/images/2022/01/------------12.png 1280w" sizes="(min-width: 720px) 720px"></figure><blockquote>В тот момент, когда убираешь на дальнюю полочку свой сервер и теперь ему там работать без выключений несколько лет, задумываешься как бы мониторить его состояние. Сегодня мы рассмотрим самые простые методы без использования специализированных средств...</blockquote><p>Подопытным будет комп на PROXMOX, это по сути тот же Debian 11, только ядро немного свежее и подточенное для виртуализаций. </p><p>Первым делом определим перечень метрик, которые нам интересны</p><ul><li>Температурные показатели - нагрев дисков, нагрев процессора, скорость вентиляторов</li><li>Текущая частота процессора</li><li>Заполненность оперативной памяти</li><li>Заполненность жесткого диска</li><li>Износ диска, метрики smart</li></ul><p> </p><h2 id="%D0%BC%D0%BE%D0%BD%D0%B8%D1%82%D0%BE%D1%80%D0%B8%D0%BD%D0%B3-%D0%B4%D0%B0%D1%82%D1%87%D0%B8%D0%BA%D0%BE%D0%B2-lm-sensors">Мониторинг датчиков lm-sensors</h2><p>Самая полезная утилита в Linux, это lm-sensors, она снимает показания с датчиков, может отображать показания температур, напряжения на материнской плате и скорости вентиляторов.</p><pre><code>apt install lm-sensors</code></pre><p>Дальше нужно продетектить все сенсоры чтобы все нужные модули подгрузились</p><pre><code>sensors-detect</code></pre><p>На вопросы можно просто enter нажимать, обычно этого достаточно, но можно везде yes вводить</p><blockquote>На свежих процессорах Ryzen 5XXX нужно ядро от 5.15 и выше ставить, на 5.13 адекватно мониторинг не работает</blockquote><p>На x570 чипах помогает добавление</p><pre><code>GRUB_CMDLINE_LINUX_DEFAULT="acpi_enforce_resources=lax"</code></pre><p>Дальше выхлоп команды <code>sensors</code> такой</p><hr><pre><code>k10temp-pci-00c3
Adapter: PCI adapter
Tctl:         +36.5°C  

nvme-pci-0100
Adapter: PCI adapter
Composite:    +41.9°C  (low  = -273.1°C, high = +81.8°C)
                       (crit = +84.8°C)
Sensor 1:     +41.9°C  (low  = -273.1°C, high = +65261.8°C)
Sensor 2:     +43.9°C  (low  = -273.1°C, high = +65261.8°C)

amdgpu-pci-0300
Adapter: PCI adapter
vddgfx:      731.00 mV 
vddnb:         1.14 V  
edge:         +36.0°C  
power1:        2.00 mW 

nct6793-isa-0290
Adapter: ISA adapter
in0:                    56.00 mV (min =  +0.00 V, max =  +1.74 V)
in1:                     1.86 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in2:                     3.39 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in3:                     3.39 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in4:                   256.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM
in5:                   136.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM
in6:                   720.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM
in7:                     3.39 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in8:                     3.25 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in9:                     1.84 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in10:                  184.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM
in11:                  136.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM
in12:                    1.86 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in13:                    1.73 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in14:                  200.00 mV (min =  +0.00 V, max =  +0.00 V)  ALARM
fan1:                     0 RPM  (min =    0 RPM)
fan2:                   512 RPM  (min =    0 RPM)
fan3:                     0 RPM  (min =    0 RPM)
fan4:                     0 RPM  (min =    0 RPM)
fan5:                     0 RPM  (min =    0 RPM)
SYSTIN:                +115.0°C  (high =  +0.0°C, hyst =  +0.0°C)  sensor = thermistor
CPUTIN:                 +52.0°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor
AUXTIN0:                +42.0°C  (high =  +0.0°C, hyst =  +0.0°C)  ALARM  sensor = thermistor
AUXTIN1:               +108.0°C    sensor = thermistor
AUXTIN2:               +107.0°C    sensor = thermistor
AUXTIN3:               +105.0°C    sensor = thermistor
SMBUSMASTER 0:          +36.5°C  
PCH_CHIP_CPU_MAX_TEMP:   +0.0°C  
PCH_CHIP_TEMP:           +0.0°C  
PCH_CPU_TEMP:            +0.0°C  
intrusion0:            OK
intrusion1:            ALARM
beep_enable:           disabled</code></pre><hr><p> Из всего этого для меня полезно знать несколько не всё, поэтому, выхлоп команды <code>sensors</code> можно отфильтровать утилитой grep, а точнее можно использовать расширенную версию egrep для применения регулярок</p><pre><code>sensors | egrep "(Composite|fan2|CPUTIN)"</code></pre><p>Получим выхлоп типа такого</p><blockquote>root@srv1:~# sensors | egrep "(Composite|fan2|CPUTIN)"<br>Composite:    +41.9°C  (low  = -273.1°C, high = +81.8°C)<br>fan2:                   510 RPM  (min =    0 RPM)<br>CPUTIN:                 +52.0°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor</blockquote><p>Дальше можно применить утилиту sed для того, чтобы модифицировать текст, этакая русификация</p><pre><code>sensors | egrep "(Composite|fan2|CPUTIN)"| \
sed \
-e "s/Composite/Температура NVME/" \
-e "s/fan2/Скорость вентилятора/" \
-e "s/CPUTIN/Температура CPU/"</code></pre><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/01/------------14.png" class="kg-image" alt loading="lazy" width="2000" height="349" srcset="https://tech-research.ru/content/images/size/w600/2022/01/------------14.png 600w, https://tech-research.ru/content/images/size/w1000/2022/01/------------14.png 1000w, https://tech-research.ru/content/images/size/w1600/2022/01/------------14.png 1600w, https://tech-research.ru/content/images/2022/01/------------14.png 2168w" sizes="(min-width: 720px) 720px"></figure><p>То что в скобках и после них для нас не сильно интересно, добавим в sed еще одно преобразование</p><pre><code>-e "s/(.*).*//"</code></pre><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/01/------------15.png" class="kg-image" alt loading="lazy" width="1406" height="418" srcset="https://tech-research.ru/content/images/size/w600/2022/01/------------15.png 600w, https://tech-research.ru/content/images/size/w1000/2022/01/------------15.png 1000w, https://tech-research.ru/content/images/2022/01/------------15.png 1406w" sizes="(min-width: 720px) 720px"></figure><p>Вроде уже прекрасно, но после двоеточий слишком много пробелов, давайте их затрем тоже</p><pre><code>-e  "s/:\s*/: /"</code></pre><p>Получилось то что нужно</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/01/------------16.png" class="kg-image" alt loading="lazy" width="1294" height="462" srcset="https://tech-research.ru/content/images/size/w600/2022/01/------------16.png 600w, https://tech-research.ru/content/images/size/w1000/2022/01/------------16.png 1000w, https://tech-research.ru/content/images/2022/01/------------16.png 1294w" sizes="(min-width: 720px) 720px"></figure><p>Для удобства парсинга сторонними системами, лучше всего сделать key:val формат, поэтому, я сделаю что-то вроде </p><blockquote>Параметр (единица измерения): 0.00</blockquote><p>Написать одно преобразование у меня не удалось, регулярки в SED работают не так как я привык</p><p>Если бы не sed, то регулярка выглядела так</p><pre><code>(.*):[^0-9]*([0-9.]+)\s*(.*)</code></pre><p>Но в регулярках sed надо экранировать скобочки чтобы они были как регулярки и наоборот не экранировать если нужно найти именно символ скобки, еще надо экранировать плюсики, а вот квадратные скобки наоборот не нужно экранировать, вторым преобразованием я удаляю лишние пробелы перед закрывающей скобкой</p><pre><code>-e "s/\(.*\):[^0-9]*\([0-9.]\+\)\s*\(.*\)/\1(\3): \2/" \
-e "s/\s*)/)/"</code></pre><p>Получилось вот такая команда</p><pre><code class="language-bash">sensors |\
`#фильтруем строки` \
egrep "(Composite|fan2|CPUTIN)" |
sed \
`#переводим значения` \
-e "s/Composite/Температура NVME/"  \
-e "s/fan2/Скорость вентилятора/"  \
-e "s/CPUTIN/Температура CPU/"  \
`#убираем хлам в скобках и после` \
-e "s/(.*).*//" \
`#убираем пробелы после двоеточий` \
-e  "s/:\s*/: /"  \
`#форматируем выхлоп в key:val` \
-e "s/\(.*\):[^0-9]*\([0-9.]\+\)\s*\(.*\)/\1(\3): \2/" \
`#пробелы перед скобками` \
-e "s/\s*)/)/" </code></pre><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/01/------------18.png" class="kg-image" alt loading="lazy" width="1278" height="914" srcset="https://tech-research.ru/content/images/size/w600/2022/01/------------18.png 600w, https://tech-research.ru/content/images/size/w1000/2022/01/------------18.png 1000w, https://tech-research.ru/content/images/2022/01/------------18.png 1278w" sizes="(min-width: 720px) 720px"></figure><p></p><h2 id="%D0%BC%D0%BE%D0%BD%D0%B8%D1%82%D0%BE%D1%80%D0%B8%D0%BD%D0%B3-%D1%81%D0%BE%D1%81%D1%82%D0%BE%D1%8F%D0%BD%D0%B8%D1%8F-%D0%B4%D0%B8%D1%81%D0%BA%D0%BE%D0%B2">Мониторинг состояния дисков</h2><p>На моей практике был только один погибший SSD диск, но он отработал более 6 лет в режиме 24/7, на нем крутились десятки виртуальных машин, которые я регулярно удалял, создавал, пересоздавал, делал снепшоты, в общем он активно отработал и в один момент выключился когда я его гонял в неттопе, вероятно от перегрева, сейчас у меня в сервере чуток больше места и радиатор установлен (смотрите видео на канале).</p><p>Единственная наверно программа для мониторинга любых дисков - это smartctl</p><pre><code>apt install smartmontools</code></pre><p>Чтобы проверить состояние диска достаточно ввести</p><figure class="kg-card kg-code-card"><pre><code>smartctl -a /dev/nvme0</code></pre><figcaption>название устройства отличается на разных конфигурациях</figcaption></figure><p>Полезный выхлоп примерно такой</p><pre><code>=== START OF SMART DATA SECTION ===
SMART overall-health self-assessment test result: PASSED

SMART/Health Information (NVMe Log 0x02)
Critical Warning:                   0x00
Temperature:                        42 Celsius
Available Spare:                    100%
Available Spare Threshold:          10%
Percentage Used:                    0%
Data Units Read:                    3,343,688 [1.71 TB]
Data Units Written:                 4,315,804 [2.20 TB]
Host Read Commands:                 19,343,569
Host Write Commands:                32,330,671
Controller Busy Time:               43
Power Cycles:                       62
Power On Hours:                     21
Unsafe Shutdowns:                   35
Media and Data Integrity Errors:    0
Error Information Log Entries:      0
Warning  Comp. Temperature Time:    0
Critical Comp. Temperature Time:    0
Temperature Sensor 1:               42 Celsius
Temperature Sensor 2:               44 Celsius

Error Information (NVMe Log 0x01, 16 of 64 entries)
No Errors Logged
</code></pre><p>Но тут опять же нас будет интересовать несколько параметров, поэтому опять примеим что-то похожее на прошлый скрипт с применением egrep + sed</p><pre><code class="language-bash">smartctl -a /dev/nvme0 |\
`#фильтруем строки` \
egrep "(Percentage Used|Data Units Written)" |
sed \
`#переводим значения` \
-e "s/Percentage Used/Износ/"  \
-e "s/Data Units Written/Кол-во записей/"  \
`#убираем пробелы после двоеточий` \
-e  "s/:\s*/: /"  \
`#оставим только в квадратных скобках` \
-e  "s/\(.*\):.*\[\(.*\)\]/\1: \2 /"  \
`#форматируем выхлоп в key:val` \
-e "s/\(.*\):[^0-9]*\([0-9.]\+\)\s*\(.*\)/\1(\3): \2/" \
`#пробелы перед скобками` \
-e "s/\s*)/)/"</code></pre><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/01/------------19.png" class="kg-image" alt loading="lazy" width="1262" height="784" srcset="https://tech-research.ru/content/images/size/w600/2022/01/------------19.png 600w, https://tech-research.ru/content/images/size/w1000/2022/01/------------19.png 1000w, https://tech-research.ru/content/images/2022/01/------------19.png 1262w" sizes="(min-width: 720px) 720px"></figure><h2 id="%D1%80%D0%B0%D1%81%D1%85%D0%BE%D0%B4-%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%82%D0%B8%D0%B2%D0%BD%D0%BE%D0%B9-%D0%BF%D0%B0%D0%BC%D1%8F%D1%82%D0%B8">Расход оперативной памяти</h2><p>Команда <code>free -m</code> выдаст количество свободной памяти в процентах</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/01/------------20.png" class="kg-image" alt loading="lazy" width="1810" height="238" srcset="https://tech-research.ru/content/images/size/w600/2022/01/------------20.png 600w, https://tech-research.ru/content/images/size/w1000/2022/01/------------20.png 1000w, https://tech-research.ru/content/images/size/w1600/2022/01/------------20.png 1600w, https://tech-research.ru/content/images/2022/01/------------20.png 1810w" sizes="(min-width: 720px) 720px"></figure><p>Опять же, можем прогнать через grep и сократить количество строк</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/01/------------21.png" class="kg-image" alt loading="lazy" width="1844" height="324" srcset="https://tech-research.ru/content/images/size/w600/2022/01/------------21.png 600w, https://tech-research.ru/content/images/size/w1000/2022/01/------------21.png 1000w, https://tech-research.ru/content/images/size/w1600/2022/01/------------21.png 1600w, https://tech-research.ru/content/images/2022/01/------------21.png 1844w" sizes="(min-width: 720px) 720px"></figure><p>Теперь попробуем применить более тяжелую артиллерию - утилиту <em><strong>awk</strong></em></p><p>Вот так можно вывести 3й столбец, т.е. количество используемой</p><pre><code>free -m | grep "Mem:" | awk '{print $3}'</code></pre><p>А чтобы получить % занятости памяти - можно просто 3й столбец поделить на 2й и домножить на сто, т.е. количество занятой памяти делим на общее количество и умножаем на 100</p><pre><code>free -m | grep "Mem:" | awk '{print $3/$2*100}'</code></pre><p>далее можно пристыковать текстовые строки для красоты</p><pre><code>free -m | grep "Mem:" | awk '{print "RAM Usage(%): "$3/$2*100}'</code></pre><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/01/------------22.png" class="kg-image" alt loading="lazy" width="1694" height="142" srcset="https://tech-research.ru/content/images/size/w600/2022/01/------------22.png 600w, https://tech-research.ru/content/images/size/w1000/2022/01/------------22.png 1000w, https://tech-research.ru/content/images/size/w1600/2022/01/------------22.png 1600w, https://tech-research.ru/content/images/2022/01/------------22.png 1694w" sizes="(min-width: 720px) 720px"></figure><h2 id="%D0%B7%D0%B0%D0%BF%D0%BE%D0%BB%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5-%D0%B4%D0%B8%D1%81%D0%BA%D0%B0">Заполнение диска</h2><p>Обычно команда <code>df -h</code> отдает заполнение всех дисков в человекочитаемом виде.</p><p>А следующая команда отфильтрует ту позицию, которая примонтирована на корень</p><pre><code>df -h | egrep '/$'</code></pre><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/01/------------23.png" class="kg-image" alt loading="lazy" width="1050" height="144" srcset="https://tech-research.ru/content/images/size/w600/2022/01/------------23.png 600w, https://tech-research.ru/content/images/size/w1000/2022/01/------------23.png 1000w, https://tech-research.ru/content/images/2022/01/------------23.png 1050w" sizes="(min-width: 720px) 720px"></figure><p>используя прошлые знания, мы можем через awk отфильтровать только значение 15%</p><pre><code>df -h | egrep '/$' | awk '{print "Заполнение диска: "$5}'</code></pre><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/01/------------24.png" class="kg-image" alt loading="lazy" width="1550" height="144" srcset="https://tech-research.ru/content/images/size/w600/2022/01/------------24.png 600w, https://tech-research.ru/content/images/size/w1000/2022/01/------------24.png 1000w, https://tech-research.ru/content/images/2022/01/------------24.png 1550w" sizes="(min-width: 720px) 720px"></figure><p>Ну и добавив sed, можно причесать результат к общему формату</p><pre><code>df -h | egrep '/$' | awk '{print "Заполнение диска: "$5}' | sed -e "s/\(.*\):[^0-9]*\([0-9.]\+\)\s*\(.*\)/\1(\3): \2/"</code></pre><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/01/------------25.png" class="kg-image" alt loading="lazy" width="2000" height="174" srcset="https://tech-research.ru/content/images/size/w600/2022/01/------------25.png 600w, https://tech-research.ru/content/images/size/w1000/2022/01/------------25.png 1000w, https://tech-research.ru/content/images/size/w1600/2022/01/------------25.png 1600w, https://tech-research.ru/content/images/2022/01/------------25.png 2166w" sizes="(min-width: 720px) 720px"></figure><h2 id="%D1%82%D0%B5%D0%BA%D1%83%D1%89%D0%B0%D1%8F-%D1%87%D0%B0%D1%81%D1%82%D0%BE%D1%82%D0%B0-%D0%BF%D1%80%D0%BE%D1%86%D0%B5%D1%81%D1%81%D0%BE%D1%80%D0%B0">Текущая частота процессора</h2><p>Мониторить текущую частоту всех процессорных ядер можно например такой командой</p><pre><code>watch -n0.2 cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq</code></pre><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/01/------------26.png" class="kg-image" alt loading="lazy" width="2000" height="779" srcset="https://tech-research.ru/content/images/size/w600/2022/01/------------26.png 600w, https://tech-research.ru/content/images/size/w1000/2022/01/------------26.png 1000w, https://tech-research.ru/content/images/size/w1600/2022/01/------------26.png 1600w, https://tech-research.ru/content/images/2022/01/------------26.png 2172w" sizes="(min-width: 720px) 720px"></figure><p>Частоту самого быстрого ядра в гигагерцах можно выдать примерно так</p><pre><code>cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq |sort -r|awk '{print "Частота процессора(Ghz): "$1/1000000}'|head -1</code></pre><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/01/------------27.png" class="kg-image" alt loading="lazy" width="2000" height="170" srcset="https://tech-research.ru/content/images/size/w600/2022/01/------------27.png 600w, https://tech-research.ru/content/images/size/w1000/2022/01/------------27.png 1000w, https://tech-research.ru/content/images/size/w1600/2022/01/------------27.png 1600w, https://tech-research.ru/content/images/2022/01/------------27.png 2166w" sizes="(min-width: 720px) 720px"></figure><h2 id="%D0%B7%D0%B0%D0%B4%D0%B5%D1%80%D0%B6%D0%BA%D0%B8-%D1%81%D0%B5%D1%82%D0%B8">Задержки сети</h2><pre><code>ping -q -c1 8.8.8.8 | grep avg | sed -e "s/s*\([0-9.]\+\)\/.*/\1/" -e "s/[^=]*=\s*//"|xargs echo "Ping (ms): "$1</code></pre><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/01/------------28.png" class="kg-image" alt loading="lazy" width="2000" height="302" srcset="https://tech-research.ru/content/images/size/w600/2022/01/------------28.png 600w, https://tech-research.ru/content/images/size/w1000/2022/01/------------28.png 1000w, https://tech-research.ru/content/images/size/w1600/2022/01/------------28.png 1600w, https://tech-research.ru/content/images/2022/01/------------28.png 2170w" sizes="(min-width: 720px) 720px"></figure><p>А так самое наверно верное, показывает среднее</p><pre><code>ping -q -c3 192.168.0.1 | grep avg |awk -v FS="/" '{print "Ping(ms): "$5}'</code></pre><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/01/------------29.png" class="kg-image" alt loading="lazy" width="1980" height="134" srcset="https://tech-research.ru/content/images/size/w600/2022/01/------------29.png 600w, https://tech-research.ru/content/images/size/w1000/2022/01/------------29.png 1000w, https://tech-research.ru/content/images/size/w1600/2022/01/------------29.png 1600w, https://tech-research.ru/content/images/2022/01/------------29.png 1980w" sizes="(min-width: 720px) 720px"></figure><p>Результат вот такой</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2022/01/------------30.png" class="kg-image" alt loading="lazy" width="1138" height="580" srcset="https://tech-research.ru/content/images/size/w600/2022/01/------------30.png 600w, https://tech-research.ru/content/images/size/w1000/2022/01/------------30.png 1000w, https://tech-research.ru/content/images/2022/01/------------30.png 1138w" sizes="(min-width: 720px) 720px"><figcaption>пинг до гугла</figcaption></figure><p>Пример скрипта на <a href="https://github.com/TechResearchRu/LinuxScripts/blob/master/tr_srv_mon.sh?ref=tech-research.ru">github</a></p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Идеальная блог-платформа ]]></title>
        <link>https://tech-research.ru/idiealnaia-blogh-platforma/</link>
        <turbo:topic><![CDATA[ Идеальная блог-платформа ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/idiealnaia-blogh-platforma/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2022-01-21T10:24:06 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Когда ты программист, то все продукты кажутся с изъянами и прежде чем завести свой блог, очень хочется написать свою платформу. Попробуем поразмышлять что мне вообще нужно...</p><h2 id="%D0%BF%D0%B5%D1%80%D0%B2%D0%BE%D0%B5%D1%8F%D0%B7%D1%8B%D0%BA-%D0%BD%D0%B0-%D0%BA%D0%BE%D1%82%D0%BE%D1%80%D0%BE%D0%BC-%D0%BD%D0%B0%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%BE">Первое - язык на котором написано</h2><p>Желательно, чтобы это был знакомый вам язык, для меня это PHP. При этом, лучше максимально отказаться от готовых решений, вся эта гибкость и модульность хороша, но добавляет лишние мегабайты кода, но это уже вкусовщина, можете десять фреймворков и двадцать библиотек подключить. Но язык не важен, если продукт не придется дописывать.</p><h2 id="%D0%B2%D1%82%D0%BE%D1%80%D0%BE%D0%B5%D1%83%D0%B4%D0%BE%D0%B1%D0%BD%D1%8B%D0%B9-%D1%80%D0%B5%D0%B4%D0%B0%D0%BA%D1%82%D0%BE%D1%80">Второе - удобный редактор</h2><p>Редактор страниц должен поддерживать вставку изображений из буфера обмена, чтобы просто нажал ctrl+v и готово.</p><p>Еще редактор не должен создавать лишнего мусорного кода, только минимальная разметка - абзацы, заголовки, таблицы, списки, цитаты, блоки кода, встраиваемые картинки и видео.</p><p>Про код самое главное - нужно чтобы я мог</p><pre><code class="language-php">//писать код</code></pre><p>И желательно сделать так, чтобы подсветка этого кода была не только на внешнем разделе сайта, но и в редакторе было идентичным.</p><p>Вообще, нужно позаботиться и оформить CSS скрипт, который подключать и в админке, и в основной части сайта, чтобы написанный текст на выходе выглядел полностью идентично.</p><p>Еще хотелось бы не только поддержку листингов кода, встраивания видео и вставку картинок, но и draw.io, хочется рисовать диаграммы прямо на сайте, но для начала можно их рисовать на десктопном клиенте и потом встраивать.</p><p>Кстати да, еще одна полезная фича - вставка html кода или js в тело страницы, тогда можно и яндекс-карты и всякие интересные модули в страницу вставлять.</p><h2 id="%D1%82%D1%80%D0%B5%D1%82%D1%8C%D0%B5%D0%B0%D0%B2%D1%82%D0%BE%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5-%D0%B8-%D1%87%D0%B5%D1%80%D0%BD%D0%BE%D0%B2%D0%B8%D0%BA%D0%B8">Третье - автосохранение и черновики </h2><p>То что пишется - должно сохраняться автоматом в настраиваемый интервал, а то вдруг зависнет браузер и то что писал последний час пропадет. При падении связи с сервером нужно использовать локальное хранилище и показывать уведомление о недоступности некоторых функций (использующие серверные мощности).</p><p></p><h2 id="%D1%87%D0%B5%D1%82%D0%B2%D0%B5%D1%80%D1%82%D0%BE%D0%B5%D0%B4%D0%BE%D1%81%D1%82%D0%B0%D0%B2%D0%BA%D0%B0-%D0%BA%D0%BE%D0%BD%D1%82%D0%B5%D0%BD%D1%82%D0%B0">Четвертое - доставка контента</h2><p>Прошли те времена, когда человек бегает по сайтам и проверяет что там нового написали, сейчас все листают ленты в том же ВК и уже оттуда переходят на сайты. После каждой публикации - должна срабатывать интеграция с соцсетями, вероятно еще с группой в телеге. И еще надо предусмотреть турбостраницы для яндекса.</p><p>Еще важным моментом - красивое встраивание по ссылке в соцсети, нужно разметить shema.org разметкой заголовок статьи, краткий вступительный контент, обложку...</p><p>Отдельно можно сделать рассылку на почту, чтобы раз в месяц приходило письмо всем подписчикам с статьями из интересующих его тематик.</p><h2 id="%D1%80%D0%B0%D0%B7%D0%B4%D0%B5%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5-%D0%BD%D0%B0-%D1%82%D0%B5%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8">Разделение на тематики</h2><p>Нужно реализовать тегирование и разделы, чтобы пользователи читали только то, что им интересно.</p><h2 id="%D0%BA%D0%BE%D0%BC%D0%BC%D0%B5%D0%BD%D1%82%D0%B0%D1%80%D0%B8%D0%B8-%D1%81-%D0%BF%D1%80%D0%B5%D0%BC%D0%BE%D0%B4%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B5%D0%B9">Комментарии с премодерацией</h2><p>Не так хороша статья, как обсуждение ее, но рекламу чего-дибо лучше не публиковать, поэтому хотелось бы иметь премодерацию.</p><h2 id="%D0%BA%D0%BB%D0%B8%D0%BA%D0%B0%D0%B1%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B5-%D0%BA%D0%B0%D1%80%D1%82%D0%B8%D0%BD%D0%BA%D0%B8">Кликабельные картинки</h2><p>Хочется чтобы картинки автоматически подрезались на несколько размеров и по ним можно было кликать в том случае, если они большие.</p><h2 id="%D1%81%D0%B2%D0%B5%D1%80%D1%85%D0%BB%D0%B5%D0%B3%D0%BA%D0%BE%D1%81%D1%82%D1%8C">Сверхлегкость</h2><p>Платформа должна быть настолько легкой, что ее можно было бы разместить на самом дешевом хостинге, нужно оптимизировать не только серверную мощность, но и фронтенд, чтобы везде под соточку измерение скорости было.</p><h2 id="%D0%BE%D0%BF%D1%82%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F-%D0%BF%D0%BE%D0%B4-%D0%BC%D0%BE%D0%B1%D0%B8%D0%BB%D1%8C%D0%BD%D1%8B%D0%B5">Оптимизация под мобильные</h2><p>Чтобы писать статьи не только с компа, но и с телефона, вероятно еще можно сделать отправку контента на блог через телеграмм. Нужно и админку и внешнюю часть оптимизировать под мобильные устройства, ведь потребители сейчас особенные.</p><p>Большинство из этого я постараюсь релизовать в рамках проекта LE2-blog, следите за гитхабом</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ HP Driver MacOS 12.0 version ]]></title>
        <link>https://tech-research.ru/hp-driver-macos-12-0-version/</link>
        <turbo:topic><![CDATA[ HP Driver MacOS 12.0 version ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/hp-driver-macos-12-0-version/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2022-01-06T10:33:11 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Дело началось, когда я на новом макбуке решил установить драйвер для принтера HP, версия MacOS у меня 12.1, а драйвер для принтера HP хотел версию 12.0 или более ранней версии.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2022/01/------------1.png" class="kg-image" alt loading="lazy" width="1358" height="900" srcset="https://tech-research.ru/content/images/size/w600/2022/01/------------1.png 600w, https://tech-research.ru/content/images/size/w1000/2022/01/------------1.png 1000w, https://tech-research.ru/content/images/2022/01/------------1.png 1358w" sizes="(min-width: 720px) 720px"><figcaption>Вот такая ошибка</figcaption></figure><p>Сам драйвер скачивается например <a href="https://support.hp.com/ru-ru/drivers/selfservice/closure/hp-laserjet-pro-m1132-multifunction-printer-series/3965842/model/3965843?ssfFlag=true&sku=&ref=tech-research.ru">тут</a></p><p>А вот примерное решение нашел вот <a href="https://forums.macrumors.com/threads/monterrey-and-hp-printers.2319676/?ref=tech-research.ru">тут</a>  </p><p>Сперва скачал драйвер в формате dmg и примонтировал.</p><p>Потом открыл терминал и набрал</p><pre><code class="language-bash">cd ~/Downloads

pkgutil --expand /Volumes/HP_PrinterSupportManual/HewlettPackardPrinterDrivers.pkg ./hplip

</code></pre><p>Потом открыл папку hplip, которая появилась в папке загрузок, в ней открыл файл Distribution</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/01/------------2.png" class="kg-image" alt loading="lazy" width="896" height="168" srcset="https://tech-research.ru/content/images/size/w600/2022/01/------------2.png 600w, https://tech-research.ru/content/images/2022/01/------------2.png 896w" sizes="(min-width: 720px) 720px"></figure><p>И в этом файле заменил проверку версии 12.0 на 13.0</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2022/01/------------3.png" class="kg-image" alt loading="lazy" width="2000" height="797" srcset="https://tech-research.ru/content/images/size/w600/2022/01/------------3.png 600w, https://tech-research.ru/content/images/size/w1000/2022/01/------------3.png 1000w, https://tech-research.ru/content/images/size/w1600/2022/01/------------3.png 1600w, https://tech-research.ru/content/images/size/w2400/2022/01/------------3.png 2400w" sizes="(min-width: 720px) 720px"><figcaption>обратите внимание на 13.0, тут было 12.0</figcaption></figure><p>Дальше обратно запаковываем в пакет отредактированную папку</p><pre><code class="language-bash">pkgutil --flatten hplip ~/Downloads/HP_Drivers_12.pkg </code></pre><p>А потом можно запускать файл HP_Drivers_12</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/01/------------4.png" class="kg-image" alt loading="lazy" width="1364" height="900" srcset="https://tech-research.ru/content/images/size/w600/2022/01/------------4.png 600w, https://tech-research.ru/content/images/size/w1000/2022/01/------------4.png 1000w, https://tech-research.ru/content/images/2022/01/------------4.png 1364w" sizes="(min-width: 720px) 720px"></figure><p>Теперь мой принтер работает</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2022/01/------------5.png" class="kg-image" alt loading="lazy" width="1556" height="896" srcset="https://tech-research.ru/content/images/size/w600/2022/01/------------5.png 600w, https://tech-research.ru/content/images/size/w1000/2022/01/------------5.png 1000w, https://tech-research.ru/content/images/2022/01/------------5.png 1556w" sizes="(min-width: 720px) 720px"></figure> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Автозапуск на MacOS ]]></title>
        <link>https://tech-research.ru/avtozapusk-na-macos/</link>
        <turbo:topic><![CDATA[ Автозапуск на MacOS ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/avtozapusk-na-macos/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2021-09-08T13:45:49 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Самое простое из доступного простому пользователю - это объекты входа в настройках пользователя</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2021/09/------------1.png" class="kg-image" alt loading="lazy"></figure><p>Но иногда возникает ситуация, когда надоедливый софт стартует принудительно и никак не отключается, первое, с чем я столкнулся - это Office365, купил подписку, установил и как не включу ноутбук, так Microsoft AutoUpdate запускается, даже когда не пользуюсь офисом, эта обновлялка стартует даже если я вчера обновился, обновления приходят чаще чем я пользуюсь офисом. И эта программа проверки обновлений никак не отключается в настройках. Есть еще всякие программы, которые бы хотелось запускать только руками, они трей захламляют и уменьшают время автономной работы на ноутбуке... Со временем система может захламиьтся тонной хлама, который стартует в фоне, проверяет обновления и всё такое, хватит это терпеть.</p><p>Помимо простейших объектов входа, существуют еще "демоны" и "агенты", пользователи Linux знают о чем речь, "демоны" это аналог служб в Windows, т.е. фоновые сервисы. </p><p>А агенты это тоже запускаемые сервисы или просто приложения, но они запускаются уже только при входе пользователя.</p><p>Ну допустим есть Daemon который отвечает за веб-сервер, хоть пользователь зашел, хоть нет - сервер должен работать, а есть например сервис уведомлений о новой почте, он только в пользовательском окружении пригодится и должен для конкретного пользователя только его почту проверять. В этом отличие Daemon от Agent.</p><p>В MacOS есть два типа директорий - это LaunchDaemons для фоновых служб и LaunchAgents для пользовательских сервисов.</p><p>~/Library/LaunchAgents - агенты конкретного пользователя</p><p>/Library/LaunchAgents/ - агенты для всех пользователей от стороннего софта</p><p>/System/Library/LaunchAgents/ - агенты для всех пользователей из поставки системы</p><p>/Library/LaunchDaemons - службы стороннего софта</p><p>/System/Library/LaunchDaemons - службы из поставки системы</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Хостинг на VDS CookBook ]]></title>
        <link>https://tech-research.ru/khostingh-na-vds-cookbook/</link>
        <turbo:topic><![CDATA[ Хостинг на VDS CookBook ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/khostingh-na-vds-cookbook/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2021-08-07T18:40:00 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <blockquote>Ставить всё буду на <strong>Debian 10</strong>, первое, что я сделаю - это пересоберу ядро с минимальным набором модулей, сократив размер ядра с 200 до 14 мегабайт, второе - удалю все лишние локали, ну и в конце почищу кеши apt, но об этом будет отдельная статья...</blockquote><p>Чтобы хостить всякие разные сайты не всегда первой свежести потребуется использовать разные версии PHP, иногда нужно и nodejs или еще какие штуки, да еще и между разными контейнерами желательно разграничить пространство, поэтому самое оптимальное - это использовать докер для контейнеризации.</p><p>При этом база данных будет общая на всех и не будет контейнеризироваться, т.е. будет стоять  на самом хосте, может я что-то недопонял, но mysql в контейнере хоть немного но просаживается, VDS не такой уж мощный, поэтому не вижу ничего плохого что сервис предоставляющий БД будет на самом хосте.</p><p>Помимо всего нам нужно реализовать настройку почтового сервера, он будет сконфигурирован так, чтобы почта из контенеров пересылалась во внешнюю сеть, это для всяких уведомлений с сайтов.</p><p>И самым главным звеном всей этой кухни будет nginx, он будет все входящие запросы маршрутизировать по контейнерам.</p><h2 id="-">Настройка почтовика</h2><h3 id="-dns-ptr">Настройка DNS PTR</h3><p>Для того, чтобы от вашего сервера почтовики брали хоть какую-то почту - нужно обратиться в техподдержку хостера или откопать в кабинете такую опцию, прописать, нужно чтобы команда</p><pre><code>nslookup 1.2.3.4</code></pre><p>Возвращало домен к которому привязан этот айпи, допустим у нас домен </p><p><strong>srv1.mydomain.ru</strong>, помимо этого, нужно прописать и прямую зону A на этот поддомен...</p><p>Примерно так должно быть</p><figure class="kg-card kg-code-card"><pre><code>pavelbelaev@Mac-mini-Pavel ~ % nslookup 5.181.255.66

Non-authoritative answer:
66.255.181.5.in-addr.arpa	name = vm-2a9e742.na4u.ru.




pavelbelaev@Mac-mini-Pavel ~ % nslookup vm-2a9e742.na4u.ru

Non-authoritative answer:
Name:	vm-2a9e742.na4u.ru
Address: 5.181.255.66</code></pre><figcaption>ip ссылается на домен, а домен на айпи</figcaption></figure><p>После прописывания записей у регистратора домена и у хостера нужно подождать пару часов, пока всё применится, а то вдруг до гугла это сразу не дойдет и будет блочить.</p><h3 id="-postfix">Установка POSTFIX</h3><pre><code>apt install postfix</code></pre><p>При установке выбираем интернет-сайт, нам не надо получать входящую, только исходящую слать</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2021/08/-----------.png" class="kg-image" alt loading="lazy"></figure><p>Далее указать тот самый домен, на который прописана обратная зона к IP</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2021/08/------------1.png" class="kg-image" alt loading="lazy"><figcaption>srv1.mydomain.ru надо заменить на свое, несуществующий домен работать не будет</figcaption></figure><p>На этом пока всё, отдельно по настройке отправки из докеров можете почитать <a href="https://tech-research.ru/otpravka-php-pochty-iz-docker/">вот тут</a>, но мы к этому вернемся еще в нашей статье.</p><h2 id="-docker">Установка Docker</h2><p>По установке докера на дебиан написано на <a href="https://docs.docker.com/engine/install/debian/?ref=tech-research.ru">официальном сайте</a></p><p>Переходим под рутом и выполняем следующее</p><pre><code>apt update &amp;&amp; apt install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg \
    lsb-release;
    
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

echo \
  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list &gt; /dev/null
  
apt update &amp;&amp; apt install docker-ce docker-ce-cli containerd.io
</code></pre><h2 id="-nginx">Установка NGINX</h2><pre><code>apt install nginx</code></pre><p>Накидываем конфиг, примерно такой <code>etc/nginx/nginx.conf</code></p><pre><code>user www-data;
worker_processes 4;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
	worker_connections 768;
	# multi_accept on;
}

http {

	##
	# Basic Settings
	##

	sendfile on;
	tcp_nopush on;
	tcp_nodelay on;
	keepalive_timeout 65;
	types_hash_max_size 2048;
	# server_tokens off;

	# server_names_hash_bucket_size 64;
	# server_name_in_redirect off;

	include /etc/nginx/mime.types;
	default_type application/octet-stream;

	##
	# SSL Settings
	##

	ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
	ssl_prefer_server_ciphers on;

	##
	# Logging Settings
	##

	access_log /var/log/nginx/access.log;
	error_log /var/log/nginx/error.log;

	##
	# Gzip Settings
	##

	gzip on;

	gzip_vary on;
	gzip_proxied any;
	gzip_comp_level 6;
	gzip_buffers 32 8k;
	gzip_http_version 1.1;
	gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

	client_max_body_size 1000M;
	##
	# Virtual Host Configs
	##

	include /etc/nginx/conf.d/*.conf;
	include /etc/nginx/sites-enabled/*;
}</code></pre><h2 id="-certbot">Установка Certbot</h2><p>certbot необходим для раздачи беспалтных ssl для наших сайтов и их автоматического обновления...</p><pre><code>apt install certbot</code></pre><p>про настройку сертификатов будет ниже при конфигурировании первого сайта...</p><h2 id="-mariadb">Установка MariaDB</h2><p>Практика показала, что mysql8 значительно медленнее 7.5. mariadb 10.3 примерно равна mysql 7.5, а mariadb 10.6  даже слегка быстрее...</p><p>инструкция по установке</p><pre><code>apt-get install software-properties-common dirmngr apt-transport-https
apt-key adv --fetch-keys 'https://mariadb.org/mariadb_release_signing_key.asc'
add-apt-repository 'deb [arch=amd64,arm64,ppc64el] https://mirror.surf/mariadb/repo/10.6/debian buster main'

apt update &amp;&amp; apt install mariadb-server</code></pre><p>Дальше надо задать пароль</p><pre><code>mariadb-secure-installation </code></pre><p>А потом надо создать такого рута, который все может</p><pre><code>GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'password';
grant all privileges on *.* to 'root'@'%' with grant option;
flush privileges;</code></pre><h3 id="--1">Управление доступом</h3><p>По-умолчанию mysql пускает подключения только с локалхоста, это не подходит для контейнеризации </p><p>Сперва нам нужно узнать ip нашего моста с докер-контейнерами</p><pre><code>ip addr| grep docker0</code></pre><p>У меня это <code>172.17.0.1</code></p><p>отредактируем файлик <code>/etc/mysql/mariadb.conf.d/50-server.cnf</code></p><p>Разрешим прослушивание моста докеров, вместо локального интерфейса</p><pre><code>bind-address            = 172.17.0.1</code></pre><p>После этого доступ будет из докеров, но не будет извне... </p><p>Нужно только перезапустить mysql</p><pre><code>service mysql restart</code></pre><p>Из докеров PHP надо настраивать подключение тоже на адрес <code>172.17.0.1</code> вместо локалхоста...</p><p>Соответственно и пользователей mysql нужно создавать не <code>user@%</code>, а <code>user@172.17.%</code> контейнерам будут выдаваться динамические адреса, но все они будут в пределах подсети /16 (255.255.0.0)</p><blockquote>Тонким тюннингом mariaDB займемся позже, вероятно в конце этой статьи, а вероятно в отдельной статейке</blockquote><h2 id="--2">Создание первого хоста (сайта)</h2><p>Сперва создадим папку для нашего сайта, это /www/sitename/web</p><p>Всё что выше по уровню от папки web недоступно веб-серверу, там будут файлы для конкретного сайта - всякие временные файлы, конфиги, сессии.</p><p>Итак, допустим у меня сайт <code>example.ru</code></p><pre><code>sitename="example.ru"

mkdir -p /www/$sitename/web &amp;&amp; cd /www/$sitename</code></pre><p>Мы находимся в папке сайта, теперь будем его переносить с другого хостинга, вариант запаковывать, переносить и распаковывать архив не очень, т.к. размер около 40 гигабайт, а место на диске около 60, просто не хватит места чтобы распаковать архив, да и накладно это всё по ресурсам и времени, попробуем просто через rsync копирнуть. </p><p>Т.к. на источнике права заданы на пользователя отличного от тех, которые доступны для логина по ssh, то может просто прав не хватить, но на приемнике всё логично, тут пустая папка и пока я не прикрыл логин под рутом. Поэтому я просто залогинюсь на старый хостинг и буду с него засылать всё это...</p><pre><code>cd /www/example.ru/
rsync -vtrz . root@example.ru:/www/example.ru/</code></pre><p>Если на старом хостинге что-то поменяется, я могу еще раз перед финальным переходом сделать rsync и передадутся только измененные файлы.</p><p>У меня есть копии сайтов на личной машине, хоть и не самые актуальные, но там изменилось максимум 5%, во-первых домашний интернет у меня 250 мегабит и на VDS около гигабита, тогда как на старом колокейшн 100 мегабитный тарий, во-вторых не хочется забивать канал на рабочем продакте, поэтому я сперва сделаю rsync с личного пк, а потом повторю с прода, чтобы минимум его нагружать...</p><blockquote>Пока всё копируется, можно дальше продолжать настраивать целевую машину....</blockquote><blockquote>В итоге перенос 32 гигов с личного пк на сервер у меня занял около 27 минут. Раньше я запаковывал архив минут 15, минут 15 его распаковывал и еще минут 20 тратил на его скачивание. Дальше я за секунд 10 актуализировал с текущего продакта состояние файлов, там буквально штук 100 файликов обновилось... Отныне буду только через rsync заливку делать на виртуалки...</blockquote><h3 id="nginx-">Nginx - новый сайт</h3><p>Как мы помним, у нас в главном конфиге nginx прописан инклуд из папки <code>/etc/nginx/sites-enabled/</code>, поэтому создадим отдельный файлик для нашего хоста</p><pre><code>nano /etc/nginx/sites-enabled/example.ru</code></pre><p>Пример конфига пока не самый лучший, но можно <a href="https://github.com/TechResearchRu/LE_PHP_Docker?ref=tech-research.ru#nginx-example">примерно такое </a>использовать...</p><h3 id="--3">Развертывание базы данных для сайта</h3><p>Сперва создадим нашего пользователя, помните раздел выше про mariadb? там мы определяли IP</p><pre><code>CREATE USER 'user'@'172.17.%' IDENTIFIED BY 'passw***';
GRANT USAGE ON *.* TO 'user'@'172.17.%' REQUIRE NONE WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0; </code></pre><p>Дальше создадим базу и предоставим привелегии уровня бд</p><pre><code>CREATE DATABASE `base1`;
GRANT ALL PRIVILEGES ON `base1`.* TO 'user'@'172.17.%' WITH GRANT OPTION;
 
flush privileges;
 
quit</code></pre><p>Теперь создадим дамп нашей БД и зальем</p><p>Сперва на сервере источника</p><pre><code>mysqldump mybase -uroot -p &gt; base1.sql</code></pre><p>Потом на новом сервере (опцию -p можно пропустить, если по сокету локально авторизация без пароля)</p><pre><code>mysql base1 -uroot -p &lt; /www/base1.sql</code></pre><p>ну и в конфиге сайта пропишем</p><pre><code class="language-php">/*DB CONFIGURATION*/
SYSCONF::$DB['db_name'] = 'base1';
SYSCONF::$DB['user'] = 'user';
SYSCONF::$DB['pass'] = '*******';
SYSCONF::$DB['host'] = '172.17.0.1';</code></pre><h2 id="docker">Docker</h2><p>Как вы поняли, мои сайты используют PHP и у меня немного подточенный <a href="https://github.com/TechResearchRu/LE_PHP_Docker?ref=tech-research.ru#%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0">контейнер</a> с пропатчеными локалями, с предустановленными необходимыми модулями типа поддержки RabbitMQ. Там почти все есть почти для любого проекта и работает на php-fpm, в моем контейнере даже есть почтовый транспорт.</p><p>Сперва соберем контейнер из докерфайла</p><pre><code>mkdir php_le_docker;
cd php_le_docker;
wget https://raw.githubusercontent.com/TechResearchRu/LE_PHP_Docker/main/Dockerfile
docker build -t php-le .</code></pre><h3 id="-docker-1">Настройка почты из Docker</h3><p>Как я уже говорил, мой контейнер поддерживает работу с почтой, но нам потребуется немножко подкрутить наш Postfix и создать конфиг...</p><p>Опять вспомним IP нашего докера и еще вспомним какой домен мы прописали в PTR на этапе установки и настройки Postfix, если забыли, возвращаемся выше и вспоминаем о чем тут речь... </p><p>Создадим файлик <code>/etc/postfix/sender_canonical_maps</code></p><pre><code>/.+/    postmaster@srv.mydomain.ru</code></pre><p>Далее пропишем в <code>nano /etc/postfix/main.cf</code></p><pre><code>#тут хак для подмены отправителя из докеров
sender_canonical_classes = envelope_sender
sender_canonical_maps =  regexp:/etc/postfix/sender_canonical_maps</code></pre><p>И еще там же не забудем дописать нашу подсеть из докеров, тут перечислены все сети от которых будет без авторизации почта браться и пересылаться во внешний мир</p><pre><code>mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 172.17.0.0/16</code></pre><p>Почти всё, остается создать конфиг транспорта для контейнера</p><p><code>nano /www/ssmtp.conf</code></p><pre><code>#see ptr
rewriteDomain=srv.mydomain.ru
FromLineOverride=YES
#host ip, see "ip addr|grep docker0"
mailhub=172.17.0.1
UseTLS=YES
UseSTARTTLS=YES</code></pre><p>А дальше запустим</p><pre><code>docker run -d \
--restart=always \
--name default-fpm \
-p 127.0.0.1:9000:9000 \
-v /www/ssmtp.conf:/etc/ssmtp/ssmtp.conf \
-v /www:/www \
-v /mp:/mp \
php-le</code></pre><p>В этом примере я всю папку /www прокинул в контейнер, но можно прокидывать по одному сайту, таким образом изолировать файловую систему отдельного сайта от других, я так делаю на всяких джумлах, особенно слегка устаревших, но там и версия php другая...</p><p>Обратите внимание, я указал 127.0.0.1 при пробросе порта, дальше локалхоста никто не сможет забраться в мой контейнер, nginx на локальном компе, ему это всё доступно будет, а большего нам не нужно.</p><p></p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Отправка PHP почты из Docker ]]></title>
        <link>https://tech-research.ru/otpravka-php-pochty-iz-docker/</link>
        <turbo:topic><![CDATA[ Отправка PHP почты из Docker ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/otpravka-php-pochty-iz-docker/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2021-08-01T18:39:17 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Не так давно начал мигрировать на Docker, слепил себе контейнер для php-fpm, но основное с чем возникли сложности - это отправка почты.</p><p>Если использовать почту в домене и авторизовываться в ящике, то можно прикрутить какой-нибудь PHPMailer, но я хотел обычный почтовик настроить, чтобы от любого емейла слать уведомления с сайта и не пользоваться услугами почтовых сервисов для этого.</p><p>Изначально пишем примерно такой скрипт</p><pre><code class="language-php">&lt;?php

$to      = 'mymail@gmail.com';
$subject = 'the subject';
$message = 'hello4';
$headers = 'From: admin2@site.ru' . "\r\n" .
    'X-Mailer: PHP/' . phpversion();

mail($to, $subject, $message, $headers);</code></pre><h2 id="-">Настройка хоста</h2><p>На самом хосте ставим Postfix, настраиваем его <code>nano /etc/postfix/main.cf</code></p><pre><code class="language-bash">#обязательно указать PTR на ваш айпи равный этому
myorigin = web.mydomain.ru

smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
biff = no
append_dot_mydomain = no
readme_directory = no
compatibility_level = 2

# TLS parameters
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

# See /usr/share/doc/postfix/TLS_README.gz in the postfix-doc package for
# information on enabling SSL in the smtp client.

#тут хак для подмены отправителя из докеров
sender_canonical_classes = envelope_sender
sender_canonical_maps =  regexp:/etc/postfix/sender_canonical_maps


smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated defer_unauth_destination
mydomain = $myhostname 
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
mydestination = localhost

#указать, если нужно слать через почтарь хостера
relayhost = 

#последним подсеть докеров - допустимые доверительные подсети
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 172.17.0.0/24
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
inet_protocols = ipv4
smtp_tls_security_level = may</code></pre><p></p><p>Далее создадим файлик <code>nano /etc/postfix/sender_canonical_maps</code></p><pre><code>/.+/    postmaster@web.mydomain.ru</code></pre><h2 id="--1">Настройки в докере</h2><pre><code>apk add ssmtp</code></pre><p>И конфиг <code>/etc/ssmtp/ssmtp.conf</code></p><pre><code>rewriteDomain=web.mydomain.ru
FromLineOverride=YES
mailhub=172.17.0.1
#hostname=web.mydomain.ru
UseTLS=YES
UseSTARTTLS=YES</code></pre><h2 id="--2">В чем был подвох?</h2><p>ssmtp это минималистичный мейлер из докера, в нем прописан адрес нашего хоста 172.17.0.1 и прописан домен, которым он должен прикидываться, в postfix вся подсеть из докера в доверенной зоне. </p><p>Если на этом остановиться, то почта по идее ходила, но она была от имени root, т.е. From не работал, после того, как я прописал <code>FromLineOverride=YES</code> - у меня адекватно заработал From и отправитель отображался корректно, но <strong>при этом почта попадала в спам</strong> на gmail. Но при этом с самого хоста почта работала хорошо и досылалась и в спам не попадала.</p><p>Оказывается в smtp есть сам заголовок в теле письма и есть еще заголовки при общении почтарей, это smtp.from, утилита ssmtp подменяла всё и сразу из заголовка From, а гугл проверял домен @... и говорил что ваш сервер не имеет права от него слать и письмо в спам улетало.</p><p>Вот тут и помогла подмена отправителя следующей конструкцией</p><pre><code>sender_canonical_classes = envelope_sender
sender_canonical_maps =  regexp:/etc/postfix/sender_canonical_maps</code></pre><blockquote>Обратите внимание! nslookup &lt;ip&gt; должен возвращать тот домен, который везде фигурирует, в моем примере это web.mydomain.ru</blockquote> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ CkEditor5 приготовление ]]></title>
        <link>https://tech-research.ru/ckeditor5-prighotovlieniie/</link>
        <turbo:topic><![CDATA[ CkEditor5 приготовление ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/ckeditor5-prighotovlieniie/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2021-05-19T00:15:18 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <h2 id="-">Загрузка картинок</h2><p>Загрузка картинок в CKeditor5 производится путем простого <code>ctrl+v</code> или вставки ссылки на картинку, но по ссылке оно так и останется, а вот кнопка на панели инструментов с выбором локального файла или вставка из буфера обмена требует загрузки файла на ваш сервер и возврата ссылки на него, например <code>/pub_data/kokoko/2678493.jpg</code> </p><p>Как собрать редактор со своими модулями, чтобы все это работало, мы рассматривали в видео</p><figure class="kg-card kg-embed-card"><iframe width="200" height="113" src="https://www.youtube.com/embed/76-sUB6cnQc?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></figure><p>Нужно включить модуль <strong><a href="https://ckeditor.com/docs/ckeditor5/latest/features/image-upload/simple-upload-adapter.html?ref=tech-research.ru">Simple upload adapter</a></strong></p><p>Для загрузки достаточно указать в конфиге url где это будет обрабатываться</p><pre><code class="language-JavaScript">simpleUpload: {uploadUrl: '/admin/blog'}</code></pre><p>При желании можно указать GET параметры</p><pre><code>simpleUpload: {uploadUrl: '/admin/blog?param=addimg'}</code></pre><p>Но как быть, если архитектура нашего приложения берет POST поля?</p><p>Нужно открыть исходник (пусть и минифицированный) и поискать там <code>o.append("upload</code> </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2021/05/------------1.png" class="kg-image" alt loading="lazy"><figcaption>Поиск по минифицированному файлу</figcaption></figure><p>Если рассмотреть эту функцию без минификации, то будет вот такое</p><pre><code>_sendRequest(t) {
                const e = this.options.headers || {};
                const n = this.options.withCredentials || false;
                for (const t of Object.keys(e)) {
                    this.xhr.setRequestHeader(t, e[t])
                }
                this.xhr.withCredentials = n;
                const o = new FormData;
                o.append("upload", t);
                this.xhr.send(o)
            }</code></pre><p>Нужно дописать после после поля upload например такое</p><pre><code>o.append("ajax","yes");
o.append("mod","add_img");</code></pre><p>По поводу вставки видео с ютуб, чтобы было не <code>&lt;oembed&gt;</code>, а <code>&lt;iframe&gt;</code> есть тоже видео</p><figure class="kg-card kg-embed-card"><iframe width="200" height="113" src="https://www.youtube.com/embed/Dn5oViFUVF8?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></figure><p>Про все дальнейшие манимпуляции и приготовления смотрите на нашем канале на ютубе, там целый плейлист, в котором мы создаем с нуля фреймворк и дальше делаем на нем блог, а далее будем делать магазин и другие подобные типовые вещи.</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ MarkDown редактор ]]></title>
        <link>https://tech-research.ru/markdown-riedaktor/</link>
        <turbo:topic><![CDATA[ MarkDown редактор ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/markdown-riedaktor/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2021-05-04T01:56:17 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Поработав некоторое время на CMS Ghost, я сильно полюбил разметку MarkDown за чистейшую разметку кода, но столкнувшись с ограничениями самого Ghost, захотел сделать свою блог-систему...</p><p>И вот захотелось мне найти JS-редактор хотя бы приближенный к Ghost (CkEditor и TinyMCE не очень удобны на блоге о программировании), мне понравилось два проекта <a href="https://pandao.github.io/editor.md/en.html?ref=tech-research.ru">EditorMD</a> и <a href="https://github.com/nhn/tui.editor?ref=tech-research.ru">ToastUI Editor</a>, такое ощущение, что это одно и тоже, но ToastUI мне показался более развитым, шустрее грузится, последняя версия пару недель назад вышла, тогда как EditorMD не обновлялся уже лет 6. </p><p>На просторах интернета достаточно много разных обсуждений про этот редактор, а выглядит он примерно вот так</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2021/05/-----------.png" class="kg-image" alt loading="lazy"></figure><p>Подключается достаточно просто, сперва в Head добавляются стили и зависимости</p><pre><code> &lt;!-- Editor's Dependecy Style --&gt;
  &lt;link
    rel="stylesheet"
    href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.4/codemirror.min.css"
  /&gt;
  &lt;!-- Editor's Style --&gt;
  &lt;link rel="stylesheet" href="https://uicdn.toast.com/editor/latest/toastui-editor.min.css" /&gt;
&lt;/head&gt;</code></pre><p>Далее создается блок для размерение редактора</p><pre><code>&lt;div id="editor"&gt;&lt;/div&gt;</code></pre><p>А далее, что важно, внутри тега body, а не в head прописываются скрипты</p><pre><code>&lt;script src="https://uicdn.toast.com/editor/latest/toastui-editor-all.min.js"&gt;&lt;/script&gt;

 &lt;script&gt;
 
    
      const editor = new toastui.Editor({
        el: document.querySelector('#editor'),
        previewStyle: 'vertical',
        height: '500px',
        initialValue: '### hello world \n```\n&lt;?="&lt;?"?&gt;php\n```'   
      });
 &lt;/script&gt;</code></pre><p>По идее у редактора есть своя подсветка, но она не очень распознает язык и мне больше по душе <code>highlight.js</code> </p><p>Поэтому в head подключил его </p><pre><code>&lt;link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/styles/default.min.css"&gt;
&lt;script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/highlight.min.js"&gt;&lt;/script&gt;</code></pre><p>Далее есть такой момент, когда редактируем в TUI-Editor код, то справа превью не обновляется, я прописал такое</p><pre><code>&lt;script&gt;
editor.on('change',function(e){
     /*hljs.highlightAll();*/
     document.querySelectorAll('div.te-preview pre').forEach(block =&gt; {
        // then highlight each
        hljs.highlightBlock(block);
        });
     
     });   

&lt;/script&gt;</code></pre><p>Остается еще приготовить загрузку картинок и вставку из буфера обмена и можно слепить свой легковесный бложек на PHP</p><h3></h3><h3 id="upload-images-on-toastui-editor-on-php">Upload Images on ToastUI Editor on PHP</h3><p>Загрузка картинок происходит или просто из буфера обмена или из локального файла, суть в том, что наш хук перехватывает это событие, отправляет файл на сервер, обратно получает ссылку и вставляет код в редактор с указанием этой ссылки</p><pre><code>    const editor = new toastui.Editor({
        el: document.querySelector('#editor'),
        previewStyle: 'vertical',
        height: '500px',
        initialValue: '### hello world \n```\n&lt;?="&lt;?"?&gt;php\n```',
        //этот кусок кода отвечает за загрузка
        hooks: 
        {
            addImageBlobHook:function(blob, callback)
            {
                let formData = new FormData();

                formData.append("upl_img", blob, blob.name);
                formData.append("opt", 'upload_img');
                formData.append("clear", 'yes');

                // /ui_test это ссылка где обработается наш POST
                fetch('/ui_test', {method: 'POST',body: formData
                }).then(resp =&gt; resp.json()).then(resp=&gt;{
                   if (!resp.success) 
                   {
                   throw new Error('Validation error');
                   }
                   
                   callback(resp.data.url, 'alt text');
                });
            }  
        }
    });</code></pre><p>Далее пример кода на PHP</p><pre><code>if (isset($_FILES['upl_img']))
{
    $uploaddir = WEBDIR.'pub_data/upload/img/';
    $f_name=basename($_FILES['upl_img']['name']);
    $uploadfile = $uploaddir . basename($_FILES['upl_img']['name']);
    if (move_uploaded_file($_FILES['upl_img']['tmp_name'], $uploadfile)) 
    {
        $out = ['success'=&gt;1];
        $out['data'] = ['url'=&gt;'/pub_data/upload/img/'.$f_name];
        $mod_out = json_encode($out);
    }
}</code></pre><p>Данный кусок чисто как пример, по хорошему нужно проверять файл, подрезать его размер, делать копию поменьше и побольше и хорошо бы обертывать в конечной версии этот файл лайтбоксом чтобы к примеру /img/ менялось на /img_big/, но это пока идея, если не смотрите мой ютуб, то загляните туда, я на досуге разрабатываю свой легковесный фреймворк пригодный и для сайтов и для консольных скриптов и фоновых служб на php, кажды этап разъясняю...</p><figure class="kg-card kg-embed-card"><iframe width="200" height="113" src="https://www.youtube.com/embed/hEfP0tYnmd4?list=PL0WBDVO8h9xcHuyw19JnOVjbxS-p6X3VF" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></figure> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ VSCode тонкие настройки ]]></title>
        <link>https://tech-research.ru/vscode/</link>
        <turbo:topic><![CDATA[ VSCode тонкие настройки ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/vscode/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2021-04-25T14:52:00 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <h3 id="-">Автозакрытие скобок и кавычек</h3><blockquote>Есть такие вещи, когда за долгую жизнь привык сразу два раза кавычки вставлять, а далее стрелочкой на клавиатуре между ними курсор сдвигать и начинать писать...  "|"</blockquote><p>VsCode по-умолчанию закрывает кавычки, управляется это через настройки, там в поиске вбиваем quotes, есть параметр auto close quotes</p><!--kg-card-begin: markdown--><pre><code>&quot;editor.autoClosingQuotes&quot;: &quot;never&quot;
</code></pre>
<!--kg-card-end: markdown--><p>Аналогично есть не для кавычек, а для скобок автозакрытие, со скобками вообще отдельная история, иногда хочу блок кода обозначить, на первой строке вставляю { и хочу через несколько строчек вставить }, а у меня сразу {}, в общем, я привык ручками все вводить без самодеятельности от редактора...</p><pre><code>"editor.autoClosingBrackets": "never"</code></pre><p></p><h3 id="--1">Автоматический отступ</h3><p>Иногда текущая строка сознательно с таким отступом, ставишь энтер, а тебе вдруг придумывает отступ, я оставляю отступ только для скобок и с сохранением отступа текущей строки</p><pre><code>"editor.autoIndent": "brackets"</code></pre><p></p><h3 id="--2">Перенос строки</h3><p>Часто открываешь совершенно разнообразный код (иногда просто выхлоп каких-то логов) и самое неприятное в нем - это горизонтальная прокрутка, для многих будет удобно, когда длинные строки будут пеерноситься в зависимости от ширины окна, при этом, в редакторе четко видно сто это одна строк</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2021/04/-----------.png" class="kg-image" alt loading="lazy"></figure><pre><code>"editor.wordWrap": "on"</code></pre><p></p><h3 id="--3">Карта кода</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2021/04/------------1.png" class="kg-image" alt loading="lazy"><figcaption>Справа около полосы прокрутки часто есть такая штука</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2021/04/------------2.png" class="kg-image" alt loading="lazy"><figcaption>более крупно</figcaption></figure><p>Иногда это удобно, а иногда кодить приходится на ноутбуке, у меня есть ноутбук, у которого высота примерно как и ширина, т.е. почти квадратный экран, и ширины не очень хватает для подобных кейсов, когда слева дерево файлов, справа карта кода, лишний расход пространства</p><figure class="kg-card kg-code-card"><pre><code>"editor.minimap.enabled": false</code></pre><figcaption>так отключаем карту</figcaption></figure><p>... продолжение следует ...</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Износ SSD на новых Mac M1 ]]></title>
        <link>https://tech-research.ru/iznos-ssd-na-novykh-mac-m1/</link>
        <turbo:topic><![CDATA[ Износ SSD на новых Mac M1 ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/iznos-ssd-na-novykh-mac-m1/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2021-03-05T11:57:00 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Начнем с того, что люди рассказывают об износе диска на 2% за 2 месяца, а это получается 100/2/12=4+ года... У других людей за 2 месяца только на 1% износ, а это вообще 8 лет. </p><blockquote>По своему опыту скажу что для обычных (не серверных) SSD ресурс около 4 лет, при эксплуатации в режиме 24/7. У меня один диск уже умер на сервере, правда, это не относится к Mac, стоял у меня SSD от Intel на компе, где крутилось 5 виртуальных машин со всякими базами данных, я хранил на нем и систему и данные, много раз переустанавливал, ну и на 4й год он просто умер (через 4 года аналогичные диски подешевели почти в 4 раза и стали быстрее в 1.5 раза). Умер он не от износа, а просто контроллер отказал, а я при этом постоянно мониторил показания диска, поэтому, даже если у вас на 4й год эксплуатации будет показывать 0% износа, то сильно не радуйтесь, не забывайте о бекапах.</blockquote><p>Но все же мы попытаемся понять что там такого может писаться в таких объемах?</p><ol><li>Заходим в лаунчер, открываем мониторинг системы</li><li>Переходим на вкладку диск</li></ol><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2021/03/-----------.png" class="kg-image" alt loading="lazy"><figcaption>не выключал на ночь комп, просто заблокировал экран</figcaption></figure><p>На картинке выше видно что Firefox за вечер и ночь успел записать 4 гига на диск, видимо это кеш, как с ним бороться - разберемся позже, но 4 гига это не очень много...</p><p>Чтобы узнать примерный статус вашего SSD, нужно установить homebrew, smartmontools и выполнить команду smartctl</p><pre><code>/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

brew install smartmontools
sudo smartctl –all /dev/disk0</code></pre><p>На Linux примерно так</p><pre><code>sudo smartctl -l devstat /dev/sda</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2021/03/------------1.png" class="kg-image" alt loading="lazy"><figcaption>выхлоп smartctl macos</figcaption></figure><p>Из выхлопа smart мне кажется что показывает он совсем неадекватные значения, судя по полю Power On Hours, диск отработал 10 часов, но я комп как минимум часов 15 назад включил, и вообще его вторую неделю мучаю.</p><p>Чтобы убедиться, я запустил uptime</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2021/03/------------2.png" class="kg-image" alt loading="lazy"><figcaption>судя по выводу, мой комп включен более 15 часов</figcaption></figure><p>Первое, что приходит в голову - это или smart неправильные показания дает, или комп вырубает диск...</p><p>Второй момент - MacOS работает слегка со сбоями, у меня была ситуация когда в процессах висело много экземпляров CrashReporter, оказалось что один из подпроцессов айтюнса вылетал циклично и система пыталась сформировать отчет, это вызывало запись на диск собранных отчетов и еще одно ядро процессора было занято на сотку.</p><p></p><p>А третий момент - в первое время действительно будет много записи</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2021/03/------------3.png" class="kg-image" alt loading="lazy"></figure><p>я трижды обнулял весь диск, переустанавливал систему, еще экспериментировал с бета-версиями, заливал видосы для тестового монтажа, разворачивал бекапы на сотни гигабайт. Мне кажется что те пользователи, которые отписались про износ дисков тоже достаточно много игрались и тестировали новые процессоры, вероятно монтировали 4к видео и все такое, но в любом случае SMART отображает некорректные данные, скорей всего эти SSD нет в базе smart и вскоре все скорректируют. </p><p>Что делать и как укротить бесполезную запись на диск - разберемся позже, для этого нужно примерно такое: </p><ul><li>слегка подрезать своп (оперативная память на диске)</li><li>вырубить сбор и отправку аналитики (достаточно много логов по всем программам и процессам собрается и постоянно шлется)</li><li>вырубить по максимуму индексирование диска (индексы тоже постоянно дописываются если у вас много файлов залетает на комп)</li><li>в FF в оперативку делать запись кеша, а не на диск, а то насмотришься видосов и перероешь кучу сайтов, насобираешь за день десяток гигабайт кеша</li><li>желательно вырубить проверку и загрузку обновлений, делать это на выходных, это не только ресурсы компа сэкономит, но и избавит от неожиданных поломок, когда что-то перестало работать после обновлений.</li></ul><p>Если у вас есть советы по уменьшению износа SSD, то пишите в комментариях...</p><p>UPD: судя по данным дисковой утилиты у меня вообще  smart не поддерживается...</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ MacOS, M1, MacMini - проблемы ]]></title>
        <link>https://tech-research.ru/macos-m1-macmini-probliemy/</link>
        <turbo:topic><![CDATA[ MacOS, M1, MacMini - проблемы ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/macos-m1-macmini-probliemy/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2021-02-23T23:17:44 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Прошло вот уже около 5 лет, как я избавился от всех яблок и зарекся больше ими не пользоваться, но тут вышел процессор Apple M1, было много обзоров какой он быстрый, а мне по сути стационарный ПК нужен только ради всяких монтажных работ и если этот Мак Мини может все так отлично рендерить, при этом не нагреваться и не шуметь, то почему бы не попробовать.</p><h2 id="-macos-11-2-1-bigsur-mac-mini-m1-lg-49wl95c">Итак, начинаем, MacOS 11.2.1 BigSur, Mac Mini M1 и монитор LG 49WL95c</h2><p>Статья, вероятно будет пополняться, если будут какие-то продвижения, буду дописывать.</p><h3 id="-">День первый</h3><ol><li>Привезли комп, подключил монитор по type-c, а он <strong>не включает родное разрешение</strong>, у меня 5120*1440, но максимальное возможное было 3840*1080, зажал кнопку ALT, нажал еще раз на пункт масштабирование и появилось мое разрешение (типа не родное). Не помню, но мне показалось что звук монитора регулировался...</li><li>Обновил систему до 11.2.1, теперь мое разрешение монитора 5120*1440 стало по-умолчанию, <strong>но звук не регулируется</strong>, в Windows я например на мониторе ставил громкость 30%, а в системе регулировал от 0 до 100 кнопками клавиатуры, тут получается никак не изменить громкость в системе, нужно тянуться к кнопкам монитора.</li><li>Еще на моменте первичной настройки у меня были <strong>розовые пиксели</strong>, а в системе я столкнулся с тем, что <strong>картинка</strong> какая-то не такая, она <strong>тусклая</strong>, на мониторе стоит яркость 100%, но изображение темное, такое ощущение, что система сама выкрутила яркость, возомнив себя макбуком...</li><li>Помимо низкой яркости, еще и <strong>цвета какие-то странные</strong>, такое ощущение, что серые буквы стали почти черными, а черный стал ну очень черным, точнее даже не так, мне кажется что мой 8 битный монитор стал 6 битным, все цвета странные. Я прееключал цветовые профили, даже из драйверов для windows вытащил профиль icm, это совсем немного меняет картинку, но все равно она остается странной.</li></ol><blockquote>Помимо всего прочего остались старые болезни, когда подключаешь мышку Logitech, а не Apple, то ускорение скрола становится странным, если крутить плавно, то страница двигается медленно, а если крутить быстрее, то он летит по несколько экранов за раз. Еще хотелось бы масштаб больше, все какое-то мелкое, а если уменьшить разрешение то размытое, в винде можно масштабировать интерфейс отдельно от разрешения, жаль что в макоси за 5 лет ничего не сделали.</blockquote><p><strong>Что по софту?</strong></p><ul><li><a href="https://code.visualstudio.com/insiders?ref=tech-research.ru">VSCode</a> есть под M1, версия на M1 хоть и бета, но стартует раз в 5-7 быстрее чем через Rosetta (там есть подпунктик Apple Silicon)</li></ul><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2021/02/image.png" class="kg-image" alt loading="lazy"></figure><ul><li><a href="https://www.blackmagicdesign.com/ru/support/download/c3265687f738416dacfc822e6e30c9e8/Mac%20OS%20X?ref=tech-research.ru">Davinci Resolve 17.1 beta 9</a> поддерживает M1, по первым впечатлениям, работает вполне годно</li></ul><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2021/02/image-1.png" class="kg-image" alt loading="lazy"></figure><ul><li>ShiftIt - работает хоть и на Intel, но без всяких проблем и тормозов...</li><li>HomeBrew - работает, но то что я оттуда установил (ShiftIt) сделано под Intel, вероятно можно скомпилироваться из исходников, но я пока не пробовал...</li></ul><p>В целом можно пользоваться, за время всяких установок, просмотра видео и т.д. компьютер остался холодным и сохранил уровень шума на уровне совсем неслышного, с софтом почти нет проблем, никаких зависаний не поймал, но с монитором полная беда, не могу на такое смотреть, нельзя регулировать громкость с клавиатуры</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2021/02/image-2.png" class="kg-image" alt loading="lazy"></figure><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2021/02/image-3.png" class="kg-image" alt loading="lazy"></figure><blockquote>UPD: Как выяснилось, макось не умеет микшировать цифровой звук по DisplayPort или HDMI, пускает его как есть без модификации, поэтому придется лезть за монитор каждый раз чтобы прибавить или убавить громкость, ну или использовать встроенные регуляторы во всяких плеерах, на сайтах типа яндекс-музыки и т.д. </blockquote><p>Есть несколько обходных моментов, когда устанавливается виртуальная звуковая карта, она микшируется нормально, и транслирует звук в HDMI/DP, но там драйвера и софт которые еще не адаптированы под М1.</p><h3 id="-macos-hdmi-dp-">Как регулировать звук в MacOS на мониторе (HDMI/DP)?</h3><p>UPD: В homebrew можно поставить утилиту eqMac, она позволяет не только регулировать громкость на мониторах подключенных по HDMI и DP, но и работает как эквалайзер</p><pre><code>brew install --cask eqmac</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2021/03/image.png" class="kg-image" alt loading="lazy"><figcaption>Выбираем в eqmac нужный выход, а в меню громкости выбираем eqMac, я лично эквалайзер выключил, без модификации звук запускаю</figcaption></figure><p> С монитором еще осталась одна беда, он не просыпается после сна, т.е. MacOS не умеет его включать...</p><blockquote>С клавиатурой Logitech K380 есть такой момент, чтобы работал запуск лаунчера через F4, нужно установить софт с сайта, а если вы не хотите чтобы start и alt менялись местами на маке, нужно зажать fn+P на 3 секунды, обратно в режим MacOS fn+I</blockquote><p></p><h2 id="-macos">Медленная мышка в MacOS</h2><p>Выкрутил скорость мышки на максимум, но курсор движется медленно, при том, что я купил оригинальную Magic Mouse 2, для пользователей MacOS это может и норма, но мне после винды сильно не нравилось, плюсом у меня монитор шириной как два 27 дюймовых, приходилось по коврику летать в несколько итераций чтобы половину экрана пройти, помогло следующее</p><figure class="kg-card kg-code-card"><pre><code>defaults write -g com.apple.mouse.scaling 12.0</code></pre><figcaption>дефолтное значение 3.0, можете поставить не 12, а например 10, если слишком быстро</figcaption></figure><p>После выполнения данной команды в терминале, нужно выйти из сеанса и снова войти...</p><p>Аналогично можно и трекпад подкрутить (пока не проверял, но там стоит значение по-умолчанию 1, а при максимуме 3), но мне максимума для трекпада достаточно</p><pre><code>defaults write -g com.apple.trackpad.scaling</code></pre><h2 id="-apple-magic-keyboard-2">Косая кавычка и тильда на русской Apple Magic Keyboard 2</h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2021/03/------------4.png" class="kg-image" alt loading="lazy"><figcaption>под кнопкой ESC совсем не то что ожидается</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2021/03/------------5.png" class="kg-image" alt loading="lazy"><figcaption>а вот что на клавиатуре версии США</figcaption></figure><p>По поводу кастомизации раскладок, есть утилита  <a href="https://software.sil.org/ukelele/?ref=tech-research.ru">Ukelele</a></p><p>А пример использования + другие тонкости в моем видео</p><figure class="kg-card kg-embed-card"><iframe width="200" height="113" src="https://www.youtube.com/embed/jONwalo3t9k?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></figure><p></p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ SSH консоль на Windows 10 ]]></title>
        <link>https://tech-research.ru/ssh_client_on_win10/</link>
        <turbo:topic><![CDATA[ SSH консоль на Windows 10 ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/ssh_client_on_win10/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2021-02-22T15:51:00 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Статья больше актуальна для Windows 10, ведь это самая прекрасная операционная система для десктопа.. Но без Linux наш мир не обойдется, поэтому многим людям приходится подключаться по ssh к своим серверам, будь они на отдельном компе или на запущенной виртуальной машине, различное окружение для разработки, атс на Asterisk и просто роутер или файлопомойка, все это обычно на Линуксе, он легкий, гибкий и может быть запущен на любом одноплатнике.</p><p>Ни для кого не секрет, что в Windows 10 есть терминал со вкладками и ssh, для этого даже не требуется устанавливать WSL, в простом PowerShell можно набрать ssh user@host и работать по ssh</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2021/02/------------1.png" class="kg-image" alt loading="lazy"><figcaption>windows terminal</figcaption></figure><p>Для того, чтобы не вводить каждый раз пароль, нам нужно сгенерировать ключ ssh</p><pre><code>ssh-keygen
//дальше просто энтер жмем и все</code></pre><p>А дальше прокинуть ключ на сервер</p><figure class="kg-card kg-code-card"><pre><code>cat ~/.ssh/id_rsa.pub | ssh user@192.168.200.100 "mkdir -p ~/.ssh &amp;&amp; cat &gt;&gt; ~/.ssh/authorized_keys"</code></pre><figcaption>это тоже в обычном терминале</figcaption></figure><p>Но остается один момент, лень вводить имя пользователя для подключения по SSH, если имя локального пользователя отличается от удаленного</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2021/02/------------2.png" class="kg-image" alt loading="lazy"><figcaption>Локальный пользователь user123, но такого нет на сервере и не авторизует</figcaption></figure><p>Для этого заходим в папку <code>C:\Users\Username\.ssh</code>, в ней открываем или создаем файл config и пишем или дописываем такое</p><pre><code>Host 192.168.0.2
  HostName 192.168.0.2
  User username111</code></pre><p>Тепеоб просто можем вводить <code>ssh 192.168.0.2</code> и заходить на нужный сервер, у меня в локальной сети несколько таких серверов и еще виртуалками развернуто несколько.</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ PHP Windows 10 utf-8 setlocale ]]></title>
        <link>https://tech-research.ru/php-windows-10-utf-8/</link>
        <turbo:topic><![CDATA[ PHP Windows 10 utf-8 setlocale ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/php-windows-10-utf-8/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2021-01-14T21:51:31 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Сегодня столкнулся с тем, что мое приложение на PHP корректно не отрабатывает под Windows 10 тот функционал, который требует задания локали.</p><p>например у меня было</p><pre><code>&lt;?php
setlocale(LC_ALL,'ru_RU.UTF-8');</code></pre><p>Такая локаль есть к примеру в Linux, но в Windows нет.</p><p>Открываем <a href="https://docs.microsoft.com/en-us/windows/win32/intl/code-page-identifiers?ref=tech-research.ru">эту </a>документацию и видим что 65001 равно utf-8</p><p>В PHP прописываем</p><pre><code>&lt;?php
$locale = setlocale(LC_ALL, 'Russian_Russia.65001');

echo $locale."\n";

echo strftime("%A %d %B %Y", mktime(0, 0, 0, 12, 22, 1978)); </code></pre><p>Запускаем в терминале, видим результат</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2021/01/------------5.png" class="kg-image" alt loading="lazy"></figure><p>Ну и чтобы 2.5+3 получалось 5.5 а не 5,5</p><pre><code>&lt;?php
setlocale(LC_NUMERIC, 'C');</code></pre> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Docker - дистрибуция приложений ]]></title>
        <link>https://tech-research.ru/docker-start/</link>
        <turbo:topic><![CDATA[ Docker - дистрибуция приложений ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/docker-start/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2020-09-11T02:00:00 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/09/------------18.png" class="kg-image" alt loading="lazy"></figure><p>Часто бывает такое, что нужен к примеру самый новый PHP или другой софт на сервере, плюсом требуется некоторая кастомизация системы и вы хотите чтобы ваше приложение заработало на другом сервере, у другого человека, чтобы он просто развернул контейнер и всё. Иногда нужны пропатченные библиотеки, а на другом компе это может поломать другие приложения.</p><p>Уже давно очень популярна контейнеризация на основе Docker, т.к. она решает все эти вопросы, каждое приложение запускается в своей виртуальной системе со своим окружением - системные библиотеки, дополнительный софт, настройки самой системы и многое другое.</p><p>Сегодня попробуем немного поэкспериментировать в Docker!</p><p>Все опыты будут выполняться на Debian 10, актуально и для убунты и для всего остального...</p><p>Для начала установим докер</p><pre><code>apt install docker</code></pre><p>В докере есть образы, а есть контейнеры, контейнер это так сказать экземпляр системы из образа, т.е. контейнер использует образ.</p><p>Если нужного для контейнера образа нет в системе, то он сам скачается...</p><p>Для большинства задач достаточно стандартных образов, этот блог на таком же и развернут, была <a href="https://tech-research.ru/blog-ghost/">статья </a>раннее.</p><p>Но иногда нужно что-то особенное, для этого я решил углубить свои познания.</p><p>Самый минимальный образ это <a href="https://hub.docker.com/_/alpine?ref=tech-research.ru">alpine</a>. Но иногда стабильнее будет работать к примеру Debian или Ubuntu, т.к. в Alpine нет glibc.</p><p>Скачать образ можно так</p><pre><code>docker pull ubuntu</code></pre><p>А посмотреть список образов в системе вот так</p><pre><code>docker images</code></pre><p>Удалить образ можно так</p><pre><code>docker rmi ubuntu</code></pre><p>Создадим контейнер, в который сразу провалимся, команда run создает контейнер и выполняет </p><pre><code>docker run -it ubuntu bash</code></pre><p>По умолчанию у нас внутри нет ни nano, ни vim и даже apt install не работает, нужно выполнить например <code>apt-get update</code> но только в докере такая ситуация, как только вы выйдите из консоли и по новой запустите контейнер, все пропадет...</p><p>Чтобы хоть что-то сохранять, нужно или образ свой лепить на основе этого со своими модификациями, или пробрасывать свою папку внутрь контейнера, то что будет писаться в виртуальной среде будет и в папке...</p><p><code>docker ps</code> - выводит запущенные контейнеры, а <code>docker ps --all</code> все, в том числе и остановленные</p><p>Если мы в команде <code>run</code> не указали никаких параметров, то докер сам придумывает имена контейнерам, я пару раз запустил баш в убунте и у меня два контейнера </p><pre><code>root@debian-testing:~# docker ps --all
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
f877b8cfec0d        ubuntu              "bash"              5 minutes ago       Exited (0) 4 minutes ago                       frost
y_engelbart
543a77036c96        ubuntu              "bash"              9 minutes ago       Exited (0) 5 minutes ago                       nosta
lgic_shannon</code></pre><p>Попробуем не создавать теперь, а просто снова запустить созданный контейнер</p><p>Если бы там был демон, то можно было сделать например</p><p> <code>docker start f877b8cfec0d</code></p><p>Но у нас там баш, остается наверно только снести контейнеры с пустым башем</p><pre><code>docker rm f877b8cfec0d 543a77036c96</code></pre><p>Если нам нужно выполнить команду в определенном образе, но не хранить этот контейнер, он у нас не демон, то можно вот так, на пример php-cli</p><pre><code>docker run -it --rm --name my-running-script -v "$PWD":/usr/src/myapp -w /usr/src/myapp php:7.4-cli php your-script.php</code></pre><p><code>-v</code>  - это прокинуть текущую папку в виртуальную внутрь контейнера /usr/src/myapp</p><p><code>-w</code> - сразу перейти в эту директорию</p><p>Мне захотелось слепить свой образ, который будет компактным, ничего лишнего и с моими настройками, php.ini, еще чтобы там изначально были некоторые библиотеки, как например клиент для RabbinMQ, небольшие патчи локализации и некоторые вещи, которые я настраиваю в приложении, хотелось бы настроить в php.ini... Плюсом ко всему, приложение будет заперто от всех контейнеров. Хочу сделать сразу cli версию для фоновых обработчиков и fpm, а на хостовом компе будет nginx все это проксировать.</p><p>Попробуем создать свой образ, для начала возьмем то что есть в <a href="https://github.com/docker-library/php/tree/master/7.4/alpine3.12/fpm?ref=tech-research.ru">официальном образе</a>, немного перелопатим и попробуем...</p><figure class="kg-card kg-code-card"><pre><code>FROM alpine:3.12
RUN apk add --no-cache ca-certificates curl tar xz openssl

RUN set -eux; addgroup -g 82 -S www-data; adduser -u 82 -D -S -G www-data www-data
ENV PHP_INI_DIR /usr/local/etc/php

#создаем все папки для работы php
RUN set -eux; mkdir -p "$PHP_INI_DIR/conf.d"; \
[ ! -d /var/www/html ]; mkdir -p /var/www/html; \
chown www-data:www-data /var/www/html; chmod 777 /var/www/html

#создаем папку, качаем в нее файл
ENV PHP_URL="https://www.php.net/distributions/php-7.4.10.tar.xz"
RUN mkdir -p /usr/src/php; cd /usr/src; \
curl -fsSL -o php.tar.xz "$PHP_URL";
#распакуем
RUN tar -Jxvf /usr/src/php.tar.xz -C /usr/src/php --strip-components=1

#временно устанавливаем все необходимое для компиляции
RUN set -eux; apk add --no-cache --virtual .build-deps \
autoconf dpkg-dev dpkg file g++ gcc libc-dev make \
pkgconf re2c argon2-dev coreutils curl-dev \
libedit-dev libsodium-dev libxml2-dev linux-headers \
oniguruma-dev openssl-dev sqlite-dev

#компилируем
ENV PHP_CFLAGS="-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
ENV PHP_CPPFLAGS="$PHP_CFLAGS"
ENV PHP_LDFLAGS="-Wl,-O1 -pie"

RUN export CFLAGS="$PHP_CFLAGS" CPPFLAGS="$PHP_CPPFLAGS" \
LDFLAGS="$PHP_LDFLAGS"; \
cd /usr/src/php; \
gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \
./configure \
--build="$gnuArch" \
--with-config-file-path="$PHP_INI_DIR" \
--with-config-file-scan-dir="$PHP_INI_DIR/conf.d" \
--enable-option-checking=fatal \
--with-mhash --enable-ftp --enable-mbstring --enable-mysqlnd \
--with-password-argon2 --with-pdo-sqlite=/usr \
--with-sqlite3=/usr \
--with-curl --with-libedit --with-openssl --with-zlib \
--with-pear --enable-fpm --with-fpm-user=www-data \
--with-fpm-group=www-data \
--disable-cgi; \
make -j 4; \
find -type f -name '*.a' -delete; \
make install; \
find /usr/local/bin /usr/local/sbin -type f -perm +0111 -exec strip --strip-all '{}' + || true; \
make clean; \
cp -v php.ini-* "$PHP_INI_DIR/"

RUN	cd /; \
runDeps="$( \
scanelf --needed --nobanner --format '%n#p' --recursive /usr/local | tr ',' '\n' | sort -u \
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }')"; \
	apk add --no-cache $runDeps; \
	\
	apk del --no-network .build-deps; \
	\
	pecl update-channels; \
	rm -rf /tmp/pear ~/.pearrc /usr/src/php;

RUN set -eux; \
cd /usr/local/etc; \
cp php-fpm.conf.default php-fpm.conf; \
cp php-fpm.d/www.conf.default php-fpm.d/www.conf; \
sed -i 's!=NONE/!=!g' php-fpm.conf;\
{ \
		echo '[global]'; \
		echo 'error_log = /proc/self/fd/2'; \
		echo 'log_limit = 8192'; \
		echo '[www]'; \
		echo 'access.log = /proc/self/fd/2'; \
		echo 'clear_env = no'; \
		echo 'catch_workers_output = yes'; \
		echo 'decorate_workers_output = no'; \
	} | tee php-fpm.d/docker.conf; \
	{ \
		echo '[global]'; \
		echo 'daemonize = no'; \
		echo '[www]'; \
		echo 'listen = 9000'; \
	} | tee php-fpm.d/zz-docker.conf

STOPSIGNAL SIGQUIT

EXPOSE 9000
CMD ["php-fpm"]</code></pre><figcaption>Dockerfile</figcaption></figure><p>Желательно создавать из пустой папки, положить в нее только Dockerfile</p><p>собираем образ php-mp (со своим префиксом, чтобы не пересекаться с официальными образами)</p><pre><code>docker build -t php-mp .</code></pre><p>Всё собралось, для php-fpm нет понятия document-root, он просто запускает тот файл, который передан из nginx, минимально тестово можно сделать так</p><pre><code>...
root /var/www/html
location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass localhost:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
...</code></pre><p>И запустить, предварительно положив в /var/www/html <code>index.php</code> с содержимым типа <code>&lt;?php phpinfo();</code> </p><pre><code> docker run -d -p 9000:9000 -v /var/www/html:/var/www/html -w /var/www/html php-mp</code></pre><p>Всё получилось...</p><p>А теперь самое интересное, посмотрим список образов</p><pre><code># docker images
REPOSITORY     TAG       IMAGE ID       CREATED             SIZE
php-mp       latest    5b8c7cf24f1e   58 minutes ago        477MB
php          7.4-cli   285d825479be4  7 days ago            405MB
ubuntu       latest    46e2eef94cd6b  3 weeks ago           73.9MB
alpine       3.12      a24bb4013296   3 months ago          5.57MB</code></pre><p>Интересная картинка, я собирал на основе alpine, который 5 мегабайт, но у меня получился образ на 477 мегабайт, официальный php образ тоже не маленький, 405 мегабайт... В чем же дело?</p><p>Попробуем посмотреть историю изменения нашего образа</p><pre><code># docker history php-mp
IMAGE              CREATED BY                                      SIZE               
4b8c7cf24f1e           /bin/sh -c #(nop)  CMD ["php-fpm"]              0B
322041d76f21         /bin/sh -c #(nop)  EXPOSE 9000                  0B
1a6ac1349fb4         /bin/sh -c #(nop)  STOPSIGNAL SIGQUIT           0B
afc59ced57ba         /bin/sh -c set -eux; cd /usr/local/etc; cp p…   25.4kB
d4ba7843c37a       /bin/sh -c cd /; runDeps="$( scanelf --neede…   51.6kB
6786fe77ed30        /bin/sh -c export CFLAGS="$PHP_CFLAGS" CPPFL…   78.6MB
1104663835d0       /bin/sh -c #(nop)  ENV PHP_LDFLAGS=-Wl,-O1 -…   0B
7267e5e725a3       /bin/sh -c #(nop)  ENV PHP_CPPFLAGS=-fstack-…   0B
78e9c4a80b2a       /bin/sh -c #(nop)  ENV PHP_CFLAGS=-fstack-pr…   0B
3c59c17a324b       /bin/sh -c set -eux; apk add --no-cache --vi…   266MB
7a0e31d9f804        /bin/sh -c tar -Jxvf /usr/src/php.tar.xz -C …   114MB
d7cb999958ae       /bin/sh -c mkdir -p /usr/src/php; cd /usr/sr…   10.3MB
7d8970c4f4fe        /bin/sh -c #(nop)  ENV PHP_URL=https://www.p…   0B
9240b0b75cb6        /bin/sh -c set -eux; mkdir -p "$PHP_INI_DIR/…   0B
663500a7b308        /bin/sh -c #(nop)  ENV PHP_INI_DIR=/usr/loca…   0B
0396dfa3d284        /bin/sh -c set -eux; addgroup -g 82 -S www-d…   4.68kB
1a21cc439955       /bin/sh -c apk add --no-cache ca-certificate…   2.75MB
a24bb4013296        /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B
&lt;missing&gt;           /bin/sh -c #(nop) ADD file:c92c248239f8c7b9b…   5.57MB</code></pre><p>Получается так, что если скачать архив в одной команде <code>RUN</code> то это сохранится в один слой, если в слудующей команде компиляция, то это еще в один слой, если потом в следующем <code>RUN</code> подчищаем все, то по факту размер образа не уменьшается. </p><h3 id="-">Какие могут быть решения для уменьшения размера образа?</h3><ul><li>Собирать с опцией <code>--squash</code>  в экспериментальном режиме, где все слои должно склеить, но у меня это отработало не совсем корректно и образ не особо уменьшило, видимо повторно этот же докерфайл собирает слишком поверхностно и надо сперва удалить раннее собранный, не стал копаться тут...</li><li>Можно весь скрипт в один RUN, там где скачал и распаковал файлы, в этой же команде RUN и чистить следы, удалять лишние пакеты требуемые для сборки...</li><li>Воспользоваться крутой утилитой <a href="https://github.com/docker-slim/docker-slim?ref=tech-research.ru">Docker-slim</a></li></ul><h3 id="docker-slim-docker">Docker-slim цменьшаем размер образа Docker</h3><p>Попробуем уменьшить размер образа</p><pre><code> wget https://downloads.dockerslim.com/releases/1.32.0/dist_linux.tar.gz
 tar -zxvf dist_linux.tar.gz
 cd dist_linux/
 ./docker-slim</code></pre><p>Набираем команду в утилите</p><pre><code>build --target php-mp</code></pre><p>В итоге в списке образов появится такой же, но с префиксом <code>.slim</code></p><p>Было 477 мегабайт, стало 25, круто ведь, проверил, все работает корректно.</p><p>Теперь о том, как выгрузить этот образ, ведь он будет для наших кастомных задачек, публиковать на докер-хабе не собираюсь.</p><pre><code>docker save php-mp.slim &gt; myphp.tar</code></pre><p>А на другом сервере</p><pre><code>docker load --input myphp.tar</code></pre><p>Получается мы можем забилдить контейнеры со своими конфигами, своими опциями сборки и модулями, скопировать на все сервера 25 мегабайтный архив, развернуть, запустить и все будет работать, никаких десятков пакетов в <code>apt-get install</code>, никаких монотонных правок php.ini и my.cnf, просто распаковать в докер, запустить и оно работает везде одинаково, везде с одним окружением... Магия!</p><p>Эта статья больше ознакомительная и шпаргалка для себя на будущее, скопировать готовый докер и запустить особо ума не надо, моя дальнейшая цель поработать с опциями, кое-что включить, а кое-что выключить, скачать сторонние библиотеки и собрать, больше не будет у меня такого что на новом сервере ставлю другую версию ПО на другой версии системы и потом спустя время ловлю что то тут то там забыл что-то настроить или установить, докер это круто.</p><h3 id="--1">Предварительная подготовка докерфайла</h3><p>У любого человека при виде такого массивного Dockerfile возникнет вопрос - как же это вообще создать, чтобы не было ошибок, все просто, сперва запускаем консоль, предварительно сразу прокинув нужный порт, например 9000</p><pre><code> docker run -it --rm -p 9000:9000 -v /var/www/html:/var/www/html alpine:3.12 sh</code></pre><p>Начинаем в нем выполнять команды типа <code>apk add</code>, <code>apk del</code>, <code>make</code> и все такое, в конце запускаем например php-fpm и тестируем из браузера, nginx ведь уже настроен, только остановите предварительно прошлый контейнер, который использует 9000 порт...</p><p><strong>Немного про apline...</strong></p><p>Устанавливать пакеты через <code>apk add</code>, удалять <code>apk del</code> </p><p>Если использовать параметр --no-cache, то кеш не будет создаваться и заполнять место, параметр --virtual это вообще интеерсная штука, после параметра virtual можно указать некое имя и потом по этому имени всё это снести что этой командой ставилось, например</p><pre><code>apk add --no-cache --virtual kokoko nano glib zip ...
adk del kokoko</code></pre><p>Это очень удобно, можно снести все что ставилось для компиляции и больше не требуется.</p><p>В ходе кастомной сборки у вас наверняка будут возникать моменты, когда какой-то библиотеки нет в системе, вы будете доустанавливать пакеты, поэтому во втором окне рядом откройте блокнот и актуализируйте команду установки, добавляя туда новые пакеты...</p><p>Когда все получилось, все действия в блокнотике отмечены, все команды и параметры, составляем наш докер-файл, и билдим, с первого раза может не получиться, например в одном RUN команды через <code>;</code>, а все переносы экранируются <code>\</code>, когда многотекстовый документ надо заполнить, то так не получится:</p><pre><code>echo 'f
fff
fff
gggg' &gt; file.txt</code></pre><p>Докер не понимает открытой строки, можно делать так как в примере выше было</p><figure class="kg-card kg-code-card"><pre><code>{\
echo "f";\
echo "fff";\
echo "ggg";\
} | tee file.txt</code></pre><figcaption>обратите внимание на обратный слеш около переносов строк</figcaption></figure><p>Дальше все зависит от вашей фантазии, помните, эксперименты и опыты наше всё!</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ База данных Oracle дома ]]></title>
        <link>https://tech-research.ru/baza-dannykh-oracle-doma/</link>
        <turbo:topic><![CDATA[ База данных Oracle дома ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/baza-dannykh-oracle-doma/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2020-09-05T17:47:00 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>На новой работе мне требуются знания БД Oracle, для того, чтобы немного изучить как это вообще работает, я поставил на домашний сервер Oracle XE, это тот же самый Oracle, только бесплатный и с ограничениями - только 2 ядра процессора, 2 гига оперативы, и база до 12 гиг, но мне этого хватит.</p><p>Ставить буду на Debian 10.</p><p>Скачать актуальную версию можно <a href="https://www.oracle.com/database/technologies/xe-downloads.html?ref=tech-research.ru">тут</a></p><p>Все действия под рутом!</p><p>Копируем ссылку на сайте, качаем, конвертируем, устанавливаем...</p><pre><code>apt-get install libaio* alien
wget https://download.oracle.com/otn-pub/otn_software/db-express/oracle-database-xe-18c-1.0-1.x86_64.rpm
mv ./oracle-database-xe-* ./oracle_db.rpm
alien  --scripts ./oracle_db.rpm
dpkg -i ./oracle*.deb</code></pre><p>Сперва нужно проверить актуальность своего айпи в файле /etc/hosts</p><p>Вероятнее всего нам выдаст ошибку</p><p><strong>[FATAL] [DBT-50000] Unable to check for available memory.</strong></p><p>Нужно отредактировать файлик /etc/init.d/</p><pre><code>nano /etc/init.d/oracle-xe-18c</code></pre><p>Находим там строчку Configuring Oracle Database</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/09/---------05-09-2020-155627.jpg" class="kg-image" alt loading="lazy"></figure><p>Ниже в строчке <code>$SU -s /bin/bash</code> найдем <code>$EM_EXPRESS_PORT</code> и после вставим, добавив пробелы до и после </p><pre><code>-J-Doracle.assistants.dbca.validate.ConfigurationParams=false</code></pre><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/09/------------9.png" class="kg-image" alt loading="lazy"></figure><p>Теперь запустим конфигуратор</p><pre><code>/etc/init.d/oracle-xe-18c configure</code></pre><p>У нас спросит пароль для системных юзеров базы данных, придумайте пароль, только не забудьте!</p><p>База запускается так, только после конфигуратора она должна сама запуститься</p><pre><code>/etc/init.d/oracle-xe-18c start</code></pre><p>Устанавливаем системные переменные вот так</p><pre><code>export ORACLE_SID=XE
export ORAENV_ASK=NO
. /opt/oracle/product/18c/dbhomeXE/bin/oraenv</code></pre><p>Проверить что все ок можно так</p><pre><code>lsnrctl status</code></pre><p>У Оракла есть веб-админка, но по-умолчанию она доступна только с локалхоста, можно расшарить и с других компов</p><pre><code>sqlplus system</code></pre><p>Вводим пароль, который устанавливали выше, дальше вводим команду</p><pre><code>EXEC DBMS_XDB.SETLISTENERLOCALACCESS(FALSE);</code></pre><p>и выходим командой <code>quit</code></p><p>Теперь пробуем открыть (меняем на свой айпи) <a href="https://192.168.0.3:5500/?ref=tech-research.ru">https://192.168.10.3:5500</a></p><p>Вводим там логин SYSTEM и свой пароль, видим примерно такое</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/09/------------10.png" class="kg-image" alt loading="lazy"></figure><p>Забавно, но админка требует флеш-плеер, такие дела, но пока мы не особо разбираемся, это пригодится.</p><p>Оригинальная инструкция <a href="https://docs.oracle.com/en/database/oracle/oracle-database/18/xeinl/installation-guide.html?ref=tech-research.ru#GUID-31891F22-B1FA-4489-A1C5-195E6B3D89C8">тут </a></p><p>Пока можете потренироваться с запросами в sqlplus, чтобы кодировка нормально отображалась и был русский язык, если у вас локаль UTF</p><pre><code>export NLS_LANG=RUSSIAN_CIS.UTF8</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2020/09/------------11.png" class="kg-image" alt loading="lazy"><figcaption>поддержка кирилицы в Oracle</figcaption></figure><p>По дефолту создается схема XE для юзера system, но мы попробуем создать свою схему, для этого</p><pre><code>sqlplus /nolog
SQL&gt; connect sys as sysdba
*** вводим пароль ***
SQL&gt; alter session set "_ORACLE_SCRIPT"=true
SQL&gt; create user Pavlik identified by Pass123;
SQL&gt; GRANT CREATE SESSION, CONNECT, RESOURCE, DBA TO Pavlik;
**это похоже делает вообще все привелегии**
SQL&gt; GRANT ALL PRIVILEGES TO myschema;</code></pre><p>Теперь попробуем зацепиться через <a href="https://www.oracle.com/ru/tools/downloads/sqldev-v192-downloads.html?ref=tech-research.ru">SQL Developer</a> с десктопа...</p><p>Сам SQL Developer портативный, просто распаковал и запускай</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/09/------------12.png" class="kg-image" alt loading="lazy"></figure><p>Кстати, наш порт нам показывало при конфигурировании на этапе выше...</p><p>Попробуем подключиться не к системному, а к новому пользователю, всё ок</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/09/------------13.png" class="kg-image" alt loading="lazy"></figure><p>Теперь можно и таблички создавать...</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/09/------------14.png" class="kg-image" alt loading="lazy"></figure><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/09/------------15.png" class="kg-image" alt loading="lazy"></figure><p>Если переключиться на вкладку DDL, то можно увидеть как это делается на SQL запросах</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/09/---------05-09-2020-191617.jpg" class="kg-image" alt loading="lazy"></figure><p>Дальше сами разбирайтесь, гуглите, читайте, для старта все есть.</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Десктопное PHP-приложение Windows ]]></title>
        <link>https://tech-research.ru/diesktopnoie-php-prilozhieniie/</link>
        <turbo:topic><![CDATA[ Десктопное PHP-приложение Windows ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/diesktopnoie-php-prilozhieniie/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2020-09-05T11:38:00 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <blockquote>Статья написана для Windows, но актуальна и для Linux, достаточно установить PHP, выполнить в терминале команду из папки приложения и всё будет работать, для Windows достаточно кликнуть один ярлык.</blockquote><blockquote>Вы сразу спросите почему PHP, почему не Electron или Python, да все потому что нет времени изобретать что-то новое, если логика уже реализована в админке сайта например, или же уже сформирована достаточная кодовая база на PHP, если нужно разработать новое приложение, тогда да, можно его писать на чем-то с нуля, но тут просто скопировал, вставил, запаковал в архив и пользуйся.</blockquote><p>Графическим интерфейсом для проекта будет тот же веб-сервер, достаточно в bat-скрипте после запуска сервера вписать открытие например localhost:10000 и готово. В идеале можно взять портативный браузер, сконфигурировать его правильным образом и запускать с правильными параметрами, чтобы не было никаких панелей, только окно сайта, но об этом позже вероятно расскажу.</p><p>В качестве веб-сервера будет использоваться тот, что встроен в PHP, ради однопользовательского приложения можно не ставить Apache или Nginx.</p><p>В качестве хранилища данных можно использовать файлы или SQLite, это по сути тот же MySQL, только чуть проще и не нужно отдельный сервер запускать, приложение просто дергает файл и оперирует данными из него.</p><p>Итак, начнем, создаем папку, например, <strong>WebTool</strong>, в этой папке создадим папку BIN и положим туда распакованный <a href="https://www.php.net/downloads.php?ref=tech-research.ru">PHP</a> для Windows,  в моем случае это 7.4.10</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/09/-----------.png" class="kg-image" alt loading="lazy"></figure><p>Внутри WebTool, рядом с BIN создадим APP, там будет наше веб-приложение..</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/09/------------1.png" class="kg-image" alt loading="lazy"></figure><p></p><p>Но внутрь BIN мы положим еще один файлик, хоть он и php, но будет этаким роутером, вместо .htaccess и веб-сервера.</p><p>Назовем его server.php и положим в папку BIN</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/09/------------2.png" class="kg-image" alt loading="lazy"></figure><figure class="kg-card kg-code-card"><pre><code>&lt;?php
//echo $_SERVER['REMOTE_ADDR']; exit();
//if($_SERVER['REMOTE_ADDR']!='::1') exit("ONLY LOCAL");

$path = parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
$ext = pathinfo($path, PATHINFO_EXTENSION);
$__DOC = $_SERVER["DOCUMENT_ROOT"]; 

$__full = realpath($__DOC . $path);
$path = rtrim($path,"/");


// все php и несуществующие пути обрабатываем приложением
if ((!is_file($__full) || $ext=='php')|| empty($path))
    include $__DOC.'/run.php';
//остальное, типа картинок отдаем пользователю напрямую
else
    return false;</code></pre><figcaption>BIN/server.php</figcaption></figure><p>А в папку APP положим пока просто файл run.php c текстом типа </p><p><code>&lt;?php phpinfo();</code></p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/09/------------3.png" class="kg-image" alt loading="lazy"></figure><p>Теперь первый тестовый запуск, в папку WebTool создадим файл <code>start.bat</code></p><p>С таким содержимым важно путь до PHP правильный</p><figure class="kg-card kg-code-card"><pre><code>start /MIN "WebTool" BIN\php-7.4.10-x64\php.exe -S localhost:10000 -t APP\ BIN\server.php
start "" http://localhost:10000</code></pre><figcaption>start.bat - запускает сервер и открывает страницу с браузере по-умолчанию</figcaption></figure><p>Достаточно будет кликнуть по start.bat и у нас откроется наше веб-приложение в браузере, а перед этим запустится сервер, тут нужно будет доработать, чтобы он дважды не запускался, но это потом... Дважды он итак не запускается, при втором запуске строчка с php не выполняется, выдает ошибку, а строчка с открытием странички в браузере срабатывает...</p><p>Чтобы остановить сервер - нужно закрыть свернутый терминал с сервером!</p><p>Если все правильно, то в браузере увидим примерно такую старничку</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/09/------------4.png" class="kg-image" alt loading="lazy"></figure><p>Дальше нам нужно привести в порядок php.ini, копируем внутри папки <code>BIN/php-xxxx/</code> файл <code>php.ini-development</code> переименовываем копию в <code>php.ini</code></p><p>Наводим порядки в файле, можно удалить всё лишнее, все равно это можно достать из оригинального файла из которого скопировали, у меня получилось типа такого:</p><figure class="kg-card kg-code-card"><pre><code>[PHP]
engine = On
short_open_tag = On
precision = 14
output_buffering = 4096
;output_handler =
zlib.output_compression = Off
implicit_flush = Off
unserialize_callback_func =
serialize_precision = -1
disable_functions =
disable_classes =
zend.enable_gc = On
zend.exception_ignore_args = Off
expose_php = On
max_execution_time = 120
max_input_time = 60
memory_limit = 1280M
error_reporting = E_ALL
display_errors = On
display_startup_errors = On
log_errors = On
log_errors_max_len = 1024
ignore_repeated_errors = Off
ignore_repeated_source = Off
report_memleaks = On
variables_order = "GPCS"
request_order = "GP"
register_argc_argv = Off
auto_globals_jit = On
post_max_size = 800M
auto_prepend_file =
auto_append_file =
default_mimetype = "text/html"
default_charset = "UTF-8"
doc_root =
user_dir =
extension_dir = "ext"
enable_dl = Off
file_uploads = On
;upload_tmp_dir =
upload_max_filesize = 800M
max_file_uploads = 20
allow_url_fopen = On
allow_url_include = Off
default_socket_timeout = 60

extension=bz2
extension=curl
extension=ftp
extension=fileinfo
extension=gd2
extension=intl
extension=imap
extension=mbstring     
extension=mysqli
extension=oci8_12c  
;extension=odbc
extension=openssl
;extension=pdo_firebird
;extension=pdo_mysql
extension=pdo_oci
;extension=pdo_odbc
;extension=pdo_pgsql
extension=pdo_sqlite
;extension=pgsql
extension=sockets
extension=sqlite3



[CLI Server]
cli_server.color = On

[Date]
date.timezone = UTC

[bcmath]
bcmath.scale = 0

[Session]
session.save_handler = files
session.use_strict_mode = 0
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.cookie_samesite =
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.referer_check =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.sid_length = 26
session.trans_sid_tags = "a=href,area=href,frame=src,form="
session.sid_bits_per_character = 5


[mbstring]
mbstring.language = Russian
mbstring.internal_encoding = UTF-8

[Tidy]
tidy.clean_output = Off

[soap]
soap.wsdl_cache_enabled=1
soap.wsdl_cache_dir="/tmp"
soap.wsdl_cache_ttl=86400
soap.wsdl_cache_limit = 5

[sysvshm]
; A default size of the shared memory segment
;sysvshm.init_mem = 10000

[opcache]
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=256
opcache.max_accelerated_files=100000
opcache.validate_timestamps=1
opcache.revalidate_freq=5
opcache.save_comments=0</code></pre><figcaption>php.ini</figcaption></figure><p>Перезапускаем сервер, дальше делаем этакое приложение, сразу скажу, у меня с прошлой работы очень много наработок завалялось, из этого начнем лепить приложение, итак, что нам нужно? <br></p><p>1.  Парсер URL для подгрузки нужных модулей</p><p>2. Система работы с модулями, систему контроля доступа можно упустить.</p><p>3. Базовая библиотека с обертками для выполнения типовых операций и работы системы.</p><p>4. Простенький шаблонизатор, чтоб не мешать логику и представление.</p><p>5. Контроллер для модулей.</p><p>6. UI-библиотека, состоящая из php+css+js, чтобы в пару строчек слепить форму...</p><p>7. Всякие классы типа для работы с БД...</p><p>Можно по идее взять готовый фреймворк, но я обойдусь несколькими файлами.</p><p>Если вам тема интересна - заходите в мою группу в вк, подписывайтесь, пишите в личку, на почту. </p><p>Сверху есть ссылка поддержать проект, если вдруг захотите.</p><p></p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ PoweShell превращение xml в sql ]]></title>
        <link>https://tech-research.ru/poweshell-prievrashchieniie/</link>
        <turbo:topic><![CDATA[ PoweShell превращение xml в sql ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/poweshell-prievrashchieniie/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2020-07-10T21:06:47 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <ol><li>Добавить код в Notepad++</li></ol><pre><code>Write-Host 'Вставляйте XML строчки, важно, без пустых строк, когда всё закончилось - жмете Enter в последней строке';
$xml_arr = @()
$inp = $null
While($inp -ne "") 
{
    If ($inp -ne $null) {$xml_arr += $inp.Trim()}
    $inp = Read-Host
}

Write-Host  "______RESULT________`n`n`n`n";


for ($i = 0; $i -le ($xml_arr.length - 1); $i += 1)
{ 
    $str = $xml_arr[$i];
    [xml]$str_xml = $xml_arr[$i];
    $it = $str_xml.FirstChild;
    $tbl=$it.Name;
    $fields = 

    Write-Host "-- SELECT * FROM $($tbl) WHERE ...."

    $select_arr = @()
    $insert_f = @()
    $insert_v = @()
    $upd_arr = @()


    foreach ($field in $it.Attributes )
    {
        $f = $field.Name
        $v = $field.Value

        $select_arr += "'$v' $f"
        $insert_f += $f
        $insert_v += "B.$f"
        $upd_arr += "A.$f = B.$f"

        
    }

    Write-Host "MERGE INTO $tbl A USING
    (SELECT
    $($select_arr -join ", ")
    FROM DUAL) B
ON ($($upd_arr -join " AND "))
WHEN NOT MATCHED THEN
    INSERT ($($insert_f -join ", "))
    VALUES ($($insert_v -join ", "))
WHEN MATCHED THEN
    UPDATE SET $($upd_arr -join ", ");";

}

Write-Host  "---------эту строку не копировать-----`n`nPress any key to continue...";
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown');</code></pre><p>2. Сохранить в кодировке cp1251 c расширением ps1</p><p>3. Правой кнопкой выполнить в PowerShell</p><p>3. Вставляем xml в формате </p><pre><code>&lt;table1 field1="val1" field2="val2"/&gt;
&lt;table1 field1="val1" field2="val2"/&gt;</code></pre><p>Получаем мерджи для оракла</p><p></p><p>P.S. но в такой заготовке в блок ON и UPDATE одинаковая последовательность пишется, нужно пройтись руками удалить поля, оставить в ON только ключи, а в UPDATE остальные...<br>В выходные еще немного заморочился, сделал интерактивный алгоритм, который спрашивает пользователя какие поля ключевые, по ним идет поиск, а остальные идут для UPDATE...<br></p><pre><code>Write-Host 'Вставляйте XML строчки, важно, без пустых строк, когда всё закончилось - жмете Enter в последней строке';
#read multi string
$xml_arr = [ordered]@{}
$inp = $null
$i=0;
While($inp -ne "") 
{
    If ($inp -ne $null) 
    {
        [xml]$str_xml = $inp.Trim();
        $it = $str_xml.FirstChild;
        $tbl=$it.Name;
        #if (!$xml_arr.ContainsKey($tbl))
        if (!$xml_arr.$tbl)
        {
            $xml_arr.add($tbl,@());
        }

        $xml_arr[$tbl]+=$it;

    }
    $inp = Read-Host
}


$out =  "______RESULT________`n`n`n`n";


foreach ($tbl in $xml_arr.keys)
{
    $tbl_arr= $xml_arr[$tbl];
    $table_keys = [ordered]@{};
    $table_fields = [ordered]@{};
    Write-Host "`nНужно определить ключи таблицы $tbl,`nвпишите номера строк через пробел"
    $i=0
    foreach ($field in $tbl_arr[0].Attributes )
    {
        $i+=1;
        Write-Host "[$i] - $($field.Name)";
        $table_fields.add("f_$i",($field.Name));        
    }

    $inp = Read-Host
    $k_nums = $inp -split " ";

    foreach ($k in $k_nums )
    {
          $k = "f_$k";
          if (($k -eq "") -or (!$table_fields.$k))
          {
              continue
          }
    
          $table_keys.add(($table_fields.$k),1);
    }

    $out+= "-- SELECT * FROM $($tbl) WHERE ....`n"
    

    foreach ($it in $tbl_arr)
    {
        $on_arr = $insert_v =$insert_f = $upd_arr = $select_arr = @()
        #attr iteration
        foreach ($field in $it.Attributes )
        {
            $f = $field.Name
            $v = $field.Value

            
            $select_arr += "'$v' $f"
            $insert_f += $f
            $insert_v += "B.$f"
            if ($table_keys.$f)
            {
                $on_arr += "A.$f = B.$f"  
            }  
             else
            {            
                $upd_arr += "A.$f = B.$f"
            }   
        }

    $out+= "MERGE INTO $tbl A USING
    (SELECT
    $($select_arr -join ", ")
    FROM DUAL) B
ON ($($on_arr -join " AND "))
WHEN NOT MATCHED THEN
    INSERT ($($insert_f -join ", "))
    VALUES ($($insert_v -join ", "))
WHEN MATCHED THEN
    UPDATE SET $($upd_arr -join ", ");`n";
    }

}


Write-Host  $out"`n---------эту строку не копировать-----`n`nPress any key to continue...";
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown');</code></pre> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Sublime Text Minify es6 error ]]></title>
        <link>https://tech-research.ru/sublime-text-uglify-es6/</link>
        <turbo:topic><![CDATA[ Sublime Text Minify es6 error ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/sublime-text-uglify-es6/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2020-05-03T23:02:37 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Такие дела, потихоньку начал использовать let и стрелочные функции в JS, у меня в SublimeText при сохранении создается сразу копия минифицированная .min.js и сам движок в prod режиме пути перенаправляет, можно и в nginx настроить все алиасы, но пока не об этом, история о том, что у меня не минифицирует и ругается когда пытаюсь сохранить файл с let</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/05/------------1.png" class="kg-image" alt loading="lazy"></figure><p> Немного погуглив, нашел<a href="https://www.npmjs.com/package/uglify-es?ref=tech-research.ru"> uglify-es</a></p><p>Открываем PowerShell или любую другую консоль...</p><pre><code>npm install uglify-es -g</code></pre><p>Этот пакет запускается такой же командой uglifyjs, поэтому, даже ничего не придется менять...</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Для входа введите CTRL+ALT+DEL ]]></title>
        <link>https://tech-research.ru/vvieditie/</link>
        <turbo:topic><![CDATA[ Для входа введите CTRL+ALT+DEL ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/vvieditie/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2020-05-02T00:04:39 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Как исправить эту фигню? Всё на фото</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/05/-----------.png" class="kg-image" alt loading="lazy"></figure> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Работа с дисками в Linux ]]></title>
        <link>https://tech-research.ru/rabota-s-diskami-v-linux/</link>
        <turbo:topic><![CDATA[ Работа с дисками в Linux ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/rabota-s-diskami-v-linux/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2020-04-29T03:37:00 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Допустим, изначально мы подключили новый диск, на нем нет разделов, разделы, это типа логические диски, даже если диск не разбит на несколько, на нем должен хотя бы один быть раздел...</p><h3 id="-linux">Определение имени диска в Linux</h3><p>Первым делом смотрим все диски в системе</p><pre><code>fdisk -l</code></pre><p>В результате увидим несколько дисков и один из них нужный нам</p><pre><code>Disk /dev/sdb: 100 GiB, 107374182400 bytes, 209715200 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0x8b972816

Device     Boot Start       End   Sectors  Size Id Type
/dev/sdb1        2048 209715199 209713152  100G 83 Linux




Disk /dev/sdc: 20 GiB, 21474836480 bytes, 41943040 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes</code></pre><p>В данном листинге видно то что /dev/sdb на 100 гигов и на нем есть раздел, нет, это не наш, а вот в самом низу /dev/sdc, на нем ни одного раздела, значит это наш диск...</p><h3 id="-linux-1">Создание раздела на диске в Linux</h3><p>Далее, нам нужно создать раздел на диске <strong>/dev/sdc</strong></p><pre><code>fdisk /dev/sdc</code></pre><p>Жмем <strong>m</strong>, если хотим увидеть все команды...</p><blockquote>По-умолчанию, вероятно, у вас будет создана таблица doc(mbr), в которой разделы не больше 2Тб, чтобы переключиться на GPT - нужно ввести команду <strong>g </strong></blockquote><p>Чтобы создать раздел, нужно ввести команду <strong>n     </strong></p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/04/------------2.png" class="kg-image" alt loading="lazy"></figure><p>Дальше нас спрашивает основной или расширенный раздел, выбираем основной <strong>p,</strong> с этого момента и дальше можно просто нажимать enter, выберется все так, чтобы на диске был один раздел...</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/04/------------3.png" class="kg-image" alt loading="lazy"></figure><p>В самом конце нужно записать изменения и выйти, для этого команда w</p><p>Теперь у нас есть не только диск <strong>/dev/sdc</strong>, но и раздел на нем <strong>/dev/sdc1</strong></p><h3 id="-linux-2">Форматирование диска в Linux</h3><p>После того, как диск создан, нужно на нем создать файловую систему, будем форматировать в ext4, многие думают что форматирование это стирание, но на самом деле, форматирование это создание файловой системы на диске.</p><p>На этом и всех других этапах не копируем слепо, а перепечатываем команду под ваш диск, т.е. меняя имя диска</p><pre><code> mkfs.ext4 /dev/sdc1</code></pre><p>Вроде всё, наш раздел содан, файловая система на нем, но это еще не всё...</p><h3 id="-linux-3">Монтирование диска в Linux</h3><p>Если в том же Windows для монтирования нужно указать букву диска, то тут нужно указать папку, куда этот диск примонтируется, корень общий, а дальше в подпапки в любое место можно монтировать диски, я буду монтировать в корень, в папку /databases, сперва эту папку нужно создать</p><pre><code>mkdir /databases</code></pre><p>Для того, чтобы примонтировать идеально раздел, нужно знать его uuid, на обычном компе можно и просто писать /dev/sdc1, но на той же виртуалке при всяких обновлениях Hyper-V у меня диски местами менялись, они и на обычном компе наверно могут поменяться, если шлейфы местами поменять, хотя у меня такого вроде не было, в общем, лучше указывать уникальный uuid раздела, чтобы его узнать, нужно ввести в командной строке</p><pre><code>blkid /dev/sdc1


/dev/sdc1: UUID="5228272d-9a5a-4150-9ef0-4f0fde7f6482" TYPE="ext4" PARTUUID="1c54c7c7-01"</code></pre><p>Дальше открываем файлик /etc/fstab, предварительно скопируем наш UUID</p><pre><code>nano /etc/fstab</code></pre><p>Дописываем последней строчкой (диск папка фс параметры...)</p><pre><code>UUID="5228272d-9a5a-4150-9ef0-4f0fde7f6482" /databases ext4 defaults 0 0</code></pre><p></p><p>Теперь проверим, примонтируем всё, что прописано в /etc/fstab и еще не примонтировано</p><pre><code>mount -a</code></pre><p>И после проверим</p><pre><code>mount -l |grep /dev/sdc1</code></pre><p>Результат должен быть примерно такой</p><pre><code>mount -l | grep /dev/sdc1
/dev/sdc1 on /databases type ext4 (rw,relatime,data=ordered)</code></pre><p>Это означает что всё примонтировано...</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Ckeditor 4.14+ Upload image ]]></title>
        <link>https://tech-research.ru/ckeditor/</link>
        <turbo:topic><![CDATA[ Ckeditor 4.14+ Upload image ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/ckeditor/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2020-04-22T20:18:09 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Сегодня обновил ckeditor, добавил YouTube в редактор, потребовалось интегрировать видосики...</p><p>Да вот только старый механизм подгрузки сломался, раньше была загрузка при которой в GET передавалась функция и в результате она выполнялась с параметрами нужными, а теперь нужно стало возвращать JSON код....</p><p>В <strong><u>config.js</u></strong> нужно прописать такое</p><pre><code class="language-js">config.filebrowserUploadUrl = '/upload_ck.php';</code></pre><p>А в файле <strong><u>upload_ck.php</u></strong></p><pre><code>&lt;?php
//тут нужно проверить имеет ли данный запрос право выполняться, 
//если нет, то выкинуть 503 и послать нафиг

$path = $_SERVER['DOCUMENT_ROOT'].DIRECTORY_SEPARATOR."media";

if (isset($_FILES['upload']) &amp;&amp; isset($_FILES['upload']['name'])) 
{
   
    if (!is_dir($path)) mkdir($path);

    //ваша функция генерации имен файлов
    $name = GEN_FNAME($_FILES['upload']['name'],$path);

    $url = $path.DIRECTORY_SEPARATOR.$name;


    //if move file - exit
    if (!move_uploaded_file($_FILES['upload']['tmp_name'], $url))
        exit('{"uploaded": 0,"error": {"message": "Fail"}');
    


    //resize function
    //MPIMG::resize ($url,$url,1700,1700);

    echo json_encode(['uploaded'=&gt;1,'fileName'=&gt;$name,'url'=&gt;$url]);

}
else
    $message = 'No file has been sent';</code></pre><p>В данном листинге используются собственные функции генерации имен и контроля максимального размера, загрузка происходит в папку media, ни в коем случае не рекомендую использовать данный код в таком виде, как минимум, тут еще нужно проверять авторизацию пользователя.</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ CSS transparent не работает в Safari ]]></title>
        <link>https://tech-research.ru/transparent-nie-rabotaiet-v-safari/</link>
        <turbo:topic><![CDATA[ CSS transparent не работает в Safari ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/transparent-nie-rabotaiet-v-safari/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2020-04-19T15:51:10 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Если указать в стилях например прозрачный фон или градиент из какого-то цвета в прозрачность, то в safari не будет такое работать, там просто в какой-то серый цвет переливается такой градиент.</p><p>Как такое починить? Да всё просто, вспоминаем про альфа-канал и заменяем слово transparent на #ffffff00</p><p>Всем спасибо за просмотр, счастья, здоровья.</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Неточность при работе с дробными числами ]]></title>
        <link>https://tech-research.ru/float_opearations/</link>
        <turbo:topic><![CDATA[ Неточность при работе с дробными числами ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/float_opearations/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2020-04-10T05:51:43 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Впервые столкнувшись с программированием, хоть на бэкэнде (php), хоть на фронтенде (JavaScript), я столкнулся с проблемой неточности, когда например вместо 2.0 получаешь 1.99999999 или 2.0000001.</p><p>Возникает это из-за того, что числа с плавающей точкой не имеют  бесконечной точности и где-то там на сороковм знаке после запятой будет или на единичку больше, или на единичку меньше, например, вы делаете</p><pre><code>$a=2.4;</code></pre><p>А в памяти сохраняется</p><p>2.400000000000000000000000000000000001</p><p>или наоборот где то на единичку поменьше...</p><p>2.399999999999999999999999999999999999999</p><p>Если вы, например, округляете копейки в большую сторону, то во втором случае получите 2.40, а в первом 2.41, т.е. клиенту посчитали цену на количество, он на калькуляторе пересчитал, ровно 2.40 посчитал, а тут выводит 2.41, это вызовет негодование, можно и на штрафы нарваться за такое дело...</p><p>Самое лучшее решение, которое мной используется уже несколько лет - изначально округлять по математическим законам на один разряд больше нужного, а потом делитьна 10 и округлять до целых в большую сторону...<br><br>Например, нам нужно перевести рубли в копейки:</p><p><strong>один </strong>рубль равен <strong>100 </strong>копейкам<br><strong>21.5</strong> рубль равен <strong>2150 </strong>копейкам </p><p>Теперь о наших "ущербных" числах, нужно получить до 2х знаков после запятой</p><p>2.40000000000001</p><p><em>домножаем на 1000</em><br>2400.00000000001</p><p><em>округлим по математическим законам, справа ноль, округлится до</em><br>2400</p><p><em>Теперь, делим на 10 и округляем в большую сторону</em><br>240</p><p>На php такая округлялка будет выглядеть вот так</p><pre><code>function float2int2($n,$m):int 
{
    $n*=pow(10,($m+1));
    $n = round($n);
    return Ceil($n/10);
}</code></pre><p>или так</p><pre><code>function float2int2($n,$m):int 
  {
    $n*=pow(10,($m+1));
    return Ceil(round($n)/10);
  }</code></pre><p>Нужно все входные количества дробные округлять и цены, вести все операции с целыми числами, а в самом конце можно выводить деленное на 100 форматированное число из копеек в рубли.</p><p>В базе данных лучше использовать такие типы как DECIMAL, там с ограниченной точностью, по сути как целое хранится, только сдвигается запятая на определенное количество знаков.</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Debian 10 command not found и другие новшества ]]></title>
        <link>https://tech-research.ru/debian-10-command-not-found/</link>
        <turbo:topic><![CDATA[ Debian 10 command not found и другие новшества ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/debian-10-command-not-found/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2020-03-29T18:15:39 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Недавно установил Debian 9 и столкнулся со странной ситуацией, когда при переключении на root командой su в PATH не добавляется /usr/sbin.</p><p>И выдает что-то типа command not found или команда не найдена.</p><p>Вот например</p><pre><code>root@homelab2:# shutdown
bash: shutdown: команда не найдена
bash: shutdown: command not found
root@homelab2:# reboot
bash: reboot: команда не найдена
bash: reboot: command not found
root@homelab2:# a2enmod
bash: a2enmod: команда не найдена
bash: a2enmod: command not found</code></pre><p>При этом, все утилиты установлены, дело просто в PATH</p><h3 id="-">Решений тут несколько</h3><ol><li>Вместо <code>su</code> писать <code>su -</code></li><li>Вписать в <code>/root/.bashrc</code> в конец строчку</li></ol><pre><code>export PATH=$PATH:/usr/sbin</code></pre><p>3. В <code>/etc/bash.bashrc</code> вписать алиас (в конец файла)</p><pre><code>alias su='su -'</code></pre><p>4. В файле <code>/etc/login.defs</code> дописать</p><pre><code>ALWAYS_SET_PATH yes</code></pre><p>После этого нужно полностью выйти из системы, даже из ограниченного пользователя...</p><p>Последний способ наверно самый адекватный...</p><p></p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Osmo Action c объективом Pixaero видеоинструкция ]]></title>
        <link>https://tech-research.ru/osmo-action-c-obiektivom-pixaero-vidieoinstruktsiia/</link>
        <turbo:topic><![CDATA[ Osmo Action c объективом Pixaero видеоинструкция ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/osmo-action-c-obiektivom-pixaero-vidieoinstruktsiia/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2020-03-12T18:13:17 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Сегодня сделал видео о том, как менять объектив экшн-камеры Osmo Action на Pixaero, установив этот объектив получил три вещи</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/03/------------2.png" class="kg-image" alt loading="lazy"></figure><ol><li>Нет бочки, не нужно напрягать процессор камеры на коррекцию (даже в видоискателе)</li><li>На широкоугольном объективе есть искажения перспективы</li></ol><p>Вот посмотрите, сверху если, то монитор узкий, а если слева то ооочень широкий.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/03/-----------.png" class="kg-image" alt loading="lazy"></figure><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/03/------------1.png" class="kg-image" alt loading="lazy"></figure><p>3. Можно снимать с коротких дистанций, хоть на поверхности линзы можно сфокусироваться.</p><p>4. Можно смазывать задний фон.</p><p>Почти зеркальный фотоаппарат, жаль матрица как на смартфоне стоит, но при хорошем свете можно получить достаточно хорошую картинку.</p><p>Единственное,что меня сильно смущает это шумодав, он портит картинку.</p><figure class="kg-card kg-embed-card"><iframe width="480" height="270" src="https://www.youtube.com/embed/4LecgINgOt8?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></figure><p>Не забываем подписать на нашу <a href="https://vk.com/tech_research?w=wall-180760993_54&ref=tech-research.ru">группу в вк</a>.</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Nginx - изменение размера картинок на примере GHOST ]]></title>
        <link>https://tech-research.ru/ghost-i-razmiery-izobrazhienii-v-postakh/</link>
        <turbo:topic><![CDATA[ Nginx - изменение размера картинок на примере GHOST ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/ghost-i-razmiery-izobrazhienii-v-postakh/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2020-02-29T11:41:00 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Поставил Ghost, особо не замечал, но тут стал замечать что при большом количестве картинок они очень уж туго подгружаются в браузере, боялся что с сервером что-то не так, а оказалось беда в Ghost, он прямо в оригинальном размере в статьях картинки размещает. Раньше я мало картинок вставлял и не замечал, а тут заметил...</p><p>Как же быть? Вспоминаем то что у нас всё идет через NGINX</p><p>Проверим что наш nginx собран с нужным модулем, для этого в консоли</p><pre><code>nginx -V</code></pre><p> Там должен быть параметр сборки </p><pre><code> --with-http_image_filter_module</code></pre><p>За это можно особо не париться, в свежих дистрибутивах с этим всё хорошо</p><p>Но вот в том же Debian выдаст ошибку</p><pre><code>nginx: [emerg] unknown directive "image_filter"</code></pre><p>Потомучто нужно установить пакет</p><pre><code>apt install libnginx-mod-http-image-filter</code></pre><p>А если такой пакет уже утсноавлен, то нужно в самом верху /etc/nginx/nginx.conf прописать</p><pre><code>load_module modules/ngx_http_image_filter_module.so;</code></pre><p></p><p>Открываем конфиг nginx, где прописан наш сайт</p><p>У нас там есть что-то типа такого</p><pre><code>        location /
        {
        access_log off;
        proxy_pass http://127.0.0.1:3001;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header Nginx-Https "on";
        proxy_connect_timeout 2s;
        }</code></pre><p></p><p>Перед этим еще один раздел location создадим для картинок (обратите  внимание на порт и на адрес для прокси)</p><p>Но у нас сервис находится на локальном сервере, поэтому для картинок не будем ничего проксировать, а сразу прокинем папку локальную</p><pre><code>  location ~* ^/content/images/(.+\.(?:gif|jpe?g|png))$                      
        {                                                                    
        set $width "-";                                                      
        set $height "-";                                                     
        set $quality "95";                                                   
        if ($arg_w != '')                                                    
        {                                                                    
         set $width $arg_w;                                                  
        }                                                                    
        if ($arg_h != '')                                                    
        {                                                                    
         set $height $arg_h;                                                 
        }                                                                    
        if ($arg_q != '')                                                    
        {                                                                    
         set $quality $arg_q;                                                
        }                                                                    
        #proxy_pass http://localhost:2368;                                   
        #proxy_set_header X-Forwarded-Proto https;                           
                                                                             
        alias /var/www/mysite/content/images/$1;                   
        access_log off;                                                      
        expires 10d;                                                         
        image_filter resize $width $height;                                  
        image_filter_jpeg_quality $quality;                                  
 }                                                                           </code></pre><p>Перезагрузим nginx</p><p>Тепепь, если открыть любую картинку и добавить к адресу например ?w=100, то увидим что она сразу меньше стала!!!</p><p>Если выдает ошибку <strong>415 Unsupported Media Type</strong>, значит ваша картинка ну очень огромная, я с таким сталкивался, нужно прописать </p><pre><code>image_filter_buffer 6M;</code></pre><p>Но тут будет конечно не супер, можете всю оперативку скушать на сервере с такими размерами...</p><p>Дальше нужно модифицировать SRC в шаблонах...</p><p>Вот тут я запнулся, пришел к выводу, что Ghost нужно или конкретно патчить, или же переходить на альтернативный продукт, жаль что я не имею опыта в NodeJS, но придется его получить! Когда время будет - вернусь к этому вопросу.</p><p></p><p></p><p></p><p></p><p>Линки</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://docs.nginx.com/nginx/admin-guide/dynamic-modules/image-filter/?ref=tech-research.ru"><div class="kg-bookmark-content"><div class="kg-bookmark-title">NGINX Docs | Image-Filter</div><div class="kg-bookmark-description">Crop, resize, rotate, and perform other transformations on GIF, JPEG, and PNG images, with the Image-Filter dynamic module supported by NGINX, Inc.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://docs.nginx.com/_static/favicon-64x46.ico" alt=""><span class="kg-bookmark-author">NGINX Documentation</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://docs.nginx.com/_static/images/nginx-documentation-500x300.png" alt=""></div></a></figure> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Мой первый в жизни ЛУТ ]]></title>
        <link>https://tech-research.ru/moi-piervyi-v-zhizni-lut/</link>
        <turbo:topic><![CDATA[ Мой первый в жизни ЛУТ ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/moi-piervyi-v-zhizni-lut/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2020-02-04T11:56:44 +0500</pubDate>
        <media:content url="https://tech-research.ru/content/images/2020/02/---------29-02-2020-130931-2.png" medium="image"/>
        <turbo:content><![CDATA[ <p>Многим радиолюбителям интересен процесс изготовления печатных плат в домашних условиях, да, сейчас можно заказать у китайцев от 5 штук, да, фоторезист рулит, но ЛУТ (лазерно-утюжная технология) самая дешевая, быстрая и простая технология, правда, требует железных нервов на старте...</p><p>Моя первая в жизни плата получилась вот такой, это не устройство и вообще никуда не пригодится, тут я просто отлаживал техпроцесс...</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/02/------------25.png" class="kg-image" alt loading="lazy"></figure><p>Вероятно, чуть позже смогу достичь еще более лучших результатов... Но даже такое я смог достичь с 15го раза, да, для начала придется на 1 листе сразу по 4 шаблона выводить, печатать 3 таких листа, разрезать и утюжить, смывать, чистить, снова утюжить, главное не бросайте это дело, пробуйте, пробуйте, если устали, отложите на завтра. Меняйте параметры - время, силу нажима, температуру (мой утюг аж помял плату на максималке).</p><p>Пришел к выводу что стеклотекстолит толщиной 1мм вполне пойдет, фольгу тоже лучше брать 18мкм, а не 35, иначе травить будете ровно в 2 раза больше, но даже не в 2, а в 3, т.к. чем дольше травите, тем раствор холоднее и тем медленнее процесс, зависимость нелинейная...</p><p>Я залез на Авито и купил 10 отрезков текстоллита по 30 рублей, состояние может и не супер, но пройдя нождачкой получаем идеальную почти поверхность...</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/02/------------26.png" class="kg-image" alt loading="lazy"></figure><p>Нождачка по опыту в Оби очень хорошая, брать нужно примерно на 600-800, на 1200 можно для совсем таких работ типа стирания тонера без растворителя. Но на 1200 плохо липнет тонер, в общем он на глянец хуже липнет чем на слегка матовый, но главное царапины не должны быть глубокими, на фото выше я вообще начал очень крупной шкуркой...</p><p>Шкурить лучше с жидким мылом или фейри, так более гладкая поверхность получается и шкурка не стирается и не засоряется медью...</p><p>Когда плату зашкурили, нужно тщательно спиртом или ацетоном пройтись и больше не прикасаться к поверхности, если у вас новый дорогой текстолит, то там шкурить не надо, там говорят идеально тонер ложится на поверхность...</p><p>Далее печатаем шаблон в Sprint Layout, советую сразу зайти в копии и натыкать там по вертикали и горизонтали максимум копий, чтобы на лист сразу влезло много шаблонов, потом их разрезать, кстати к шаблонам тоже лучше не прикасайтесь, тонер не трогать на шаблоне, может помешать идеальному прилипанию...</p><h3 id="-">Выбор бумаги для ЛУТ</h3><p>Бумагу для печати ЛУТом я выбрал<strong> Lomond 0102145 (</strong>глянцевая, 85г/м<sup>2</sup>, 100листов <strong>), </strong>и кто там говорит что дорого?</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/02/------------2.png" class="kg-image" alt loading="lazy"></figure><p>Менее 4 рублей за один снимок. Да, не пугайтесь что это бумага для струйной печати, а печатать будем на лазерном принтере, у нас вообще редкостное извращение, кто-то на листах журнала печатает, кто то на подложке от самоклейки, кто-то вообще фольгу приклеивает к обычному листу бумаги, с фольгой мы еще попробуем, автор этой статьи вообще впервые в жизни плату делает, пока техпроцесс налаживается...</p><p>Если скажете что любая глянцевая пойдет, то нет, у меня валялась фотобумага непонятного производителя, на фото она слева...</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/02/------------3.png" class="kg-image" alt loading="lazy"></figure><p>Как видно, пятачки не пропечатались</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/02/------------4.png" class="kg-image" alt loading="lazy"></figure><p>А вот на ломонде вполне годно и полигоны тоже заливает четко</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/02/------------5.png" class="kg-image" alt loading="lazy"></figure><p>Да, есть мелкая крошка, но она на результат не влияет...</p><p>Как говорил, печатать лучше сразу много, я на один лист выводил по 4 штуки</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/02/------------27.png" class="kg-image" alt loading="lazy"></figure><p></p><h3 id="--1">Выбор утюга для ЛУТ</h3><p>Утюг лучше поискать в кладовке старый советский, скоблить по фольге не очень для нежных современных, у которых нано-покрытия для деликатных тканей и еще желательно утюг без отверстий для отпаривания, так контакт будет равномерным... Если такого нет - поищите на Авито, на крайняк можно пройтись по всяким галамартам и фикспрайсам, поискать утюг без пара и рельефа на подошве...</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/02/------------28.png" class="kg-image" alt loading="lazy"></figure><p></p><h3 id="--2">Подбор поверхности для ЛУТ</h3><p>Поверхность тоже имеет важную роль, у меня было две разделочные дощечки, тонкая и толстая...</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/02/------------29.png" class="kg-image" alt loading="lazy"></figure><p></p><p>Тонкая имеет явные перекосы, если мы на такое положим плату и утюг, то некоторые места не прогреет!</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/02/------------30.png" class="kg-image" alt loading="lazy"></figure><p>А вот толстая доска, которая стоит кстати рублей 50 в фикспрайсе, вполне сгодится</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/02/------------31.png" class="kg-image" alt loading="lazy"></figure><p>Обратите внимание, на обеих дощечках нет ни лака ничего, чтоб ничего не поплавилось, доска потолще еще и убережет лучше поверхность, я к примеру утюжил на стиральной машине, на 1см от поверхности уже стиралка защищена лучше, хотя я на нее еще сверху стелил полотенце и газету.</p><h3 id="--3">Лазерно-утюжная технология</h3><p><strong>1.Подготовка текстолита, нагрев утюга</strong></p><p>В общем, процесс такой, обезжиренный текстолит кладем на доску, разогреваем утюг, хоть и советуют на 100%, но мне хватило 80%, чтобы ничего не плыло, переносилось идеально и чтобы текстолит не корежило при нагреве... </p><p><strong>2. Первитчный прогрев заготовки</strong></p><p>Сперва нужно подогреть сам текстолит, тут главное не перегреть, если разогреть его очень сильно, то будет сложно прицелиться, при первом прикосновении половина рисунка сразу прилепится  и его двигать не получится, но у вас много шаблонов, можете экспериментировать, запаситесь ацетоном, 646 растворителем или на край совсем мелкой нождачкой или кометом/содой + чистой губкой для посуды, будете 20 раз смывать и снова утюжить пока не получится, главное не сцарапать всё покрытие, оно тонкое, поэтому <strong>смывать или сцарапывать нужно максимально нежно!</strong></p><p>Первичный прогрев нужен для того, чтобы металл не так расширялся относительно бумаги, дорожки не рвутся не смазываются, полигоны не так сильно рвутся... Бумага наоборот дает усадку небольшую, мой экземпляр на заготовке 10*15см не особо усаживался, не заметил сдвига дорожек, вот доказательство - рамка не сдвинулась!</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/02/------------32.png" class="kg-image" alt loading="lazy"></figure><p>3. Прикладываем заготовку, бумага полупрозрачная, целиться удобно, далее начинаем утюжить, сперва с одного края приклеиваем, потом с другого, далее можно разглаживать, качество разглажки видно сквозь бумагу, тонер начинает просвечивать.</p><p>4. Берем или мягкий шпатель или бочонок, я взял маленький скотч (рулончик) и им вдоль и поперек прогладил пока не остыло, потом еще раз утюгом и еще раз прогладил...</p><p>5. Чуть ждем чтобы остыло, совсем немного и под воду, я под горячую, чтобы не было перепада температур, бумага почти как писчая, размокает быстро, дальше нежно щеточкой проходим, главное не соскрести тонер, но если всё правильно, то его сцарапать достаточно сложно, дальше сушим, идем за стол под лампу, разглядываем, очень нежно убираем лишнее между дорожками. Но если на этом этапе сразу видны лютые косяки, а первые 10-15 раз это будет, поверьте, то всё нафиг смываем и по-новой утюжим, утюг не выключаем, стопку шаблонов не убираем далеко...</p><p>Первые разы у меня получалось вот такое (не прилипало)</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/02/------------33.png" class="kg-image" alt loading="lazy"></figure><p>Или вот такое (всё поплыло, контакты слиплись, формы дорожек нарушены)</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/02/------------34.png" class="kg-image" alt loading="lazy"></figure><p>Но на 15й раз получилось вот так, почти идеально, но руку еще надо набить, дорожки 0.1 почти годно, но порвалось, а вот от 0.2 идеально!!!</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/02/------------15.png" class="kg-image" alt loading="lazy"></figure><p>Кстати про кусочки бумаги между контактами, дорожками (см. на разъем слева внизу)...</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/02/------------16.png" class="kg-image" alt loading="lazy"></figure><p>Где-то выскреб, где-то для теста оставил, оно протравилось, за это вообще не парьтесь сильно, бумага промокает и сквозь нее травится, химия агрессивная, если передержать то и тонер разъедает, а бумагу вообще за 5 минут разлагает.</p><h3 id="--4">Травление</h3><p>Берем Аммония персульфат, насыпаем в отношении 1 к 2 в горячую воду, в холодной будет вяло протекать...</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/02/------------17.png" class="kg-image" alt loading="lazy"></figure><p>Опускаем в емкость плату...</p><p>Процесс выглядит так</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/02/------------18.png" class="kg-image" alt loading="lazy"></figure><p>Через 10-15 минут у нас вот такое (остались только дорожки)</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/02/------------19.png" class="kg-image" alt loading="lazy"></figure><p>Отмываем тоннер растворителем или еще чем, я содой сцарапал, не было под рукой растворителя...</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/02/------------20.png" class="kg-image" alt loading="lazy"></figure><p>Результат пока не очень идеальный, но это моя первая плата, дальше технологию еще набью...</p><p>Далее нужно лудить, я просто намазал дорожки тагсом и прошел паяльником, потом с мылом тщательно промыл платы и протиер спиртом, но получилось не очень, мелкие дорожки отвалились, потом я убавил температуру до 230 и переставли отваливаться, но тут лучше сплав розе или что-то такое, тут тоже руку набью еще.</p><p>Видео про лазерно утюжную технологию (ЛУТ) ниже.</p><figure class="kg-card kg-embed-card"><iframe width="480" height="270" src="https://www.youtube.com/embed/gD0eWuuHuDs?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></figure><p></p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Импульсные блоки питания ]]></title>
        <link>https://tech-research.ru/impulsnyie-bloki-pitaniia/</link>
        <turbo:topic><![CDATA[ Импульсные блоки питания ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/impulsnyie-bloki-pitaniia/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-12-26T16:53:00 +0500</pubDate>
        <media:content url="https://tech-research.ru/content/images/2020/02/ep5-smd_220x0_34e.png" medium="image"/>
        <turbo:content><![CDATA[ <p>Статья больше ознакомительная, если захотите сделать импульсный источник питания, то вам придется пару месяцев смотреть всякие разные видео на ютубе, читать статьи на всяких сайтах. И везде будет какая-то недосказанность, остальное придется доискивать.</p><p>Я пока только в теории прикинул на чем буду собирать блок питания и каких он будет размеров. Ну примерно для 170-200 и даже в теории до 500 ватт хватит ферритового колечка на 29мм...  Т.е. блок питания будет достаточно компактным, пока практики с намоткой нет, я соберу инвертор и буду на нем эксперментировать с разными колечками, разными диаметрами, но это в будущем.</p><p>Для всех рассчетов сгодятся программы от человека с псевдонимом Старичок. У него их много и для дросселей тоже....</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/12/------------7.png" class="kg-image" alt loading="lazy"></figure><p>Теперь попробую структурировать всё, что удалось накопать за последнее время, по мере появления дополнительной информации - статья будет пополняться.</p><h3 id="-">Чем отличается импульсный источник питания (блок питания)?</h3><p>Помните блок питания от приставки Sega? Он такой тяжелый что розетку выламывал из стены и посмотрите на миниатюрный зарядник от вашего смартфона, быстрые зарядники не в счет, они чуть крепнее, у них мощность больше. Но у сеги адаптер примерно на 10 ватт и ваш зарядник к смартфону 5в 1А тоже на 10 ватт, а быстрые зарядки по 20-30 ватт и даже они меньше адаптера от сеги.</p><p>Если бы блок питания для компьютера на 700-800 ватт был обычным, то он бы весил килограмм 20 и был размером с весь ваш системник, сейчас пришла эпоха <strong>импульсных блоков питания</strong>! Они при большей мощности в сто раз компектнее, нужно меньше килограмм меди на производство, получается всё дешевле, но есть свои заморочки с ними, их нужно уметь готовить...</p><h3 id="--1">Почему импульсные блоки питания мощнее и компактнее?</h3><p>Точной формулы вам не покажу, но если кратко, то одной из составляющей, от которой пропорционально растет КПД трансформатора - частота тока. Обычный переменный ток в розетке 50-60герц, а для импульсных источников питания применяется около 50 килогерц, что в 1000 раз больше. Чем выше частота, тем лучше показатели, но сильно высоко задрать не позволят характеристки сердечника, скорость силовых ключей и много других параметров, если ниже сделать, то попадем в звуковой диапазон и будут лишние помехи да еще и сам трансформатор будет раза в 2-3 больше.</p><h3 id="--2">На чем мотать импульсный трансформатор?</h3><p>Для высокочастотных транформаторов уже не сгодится обычная трансформаторная сталь, сердечник ставят из феррита. Лично не проверял, но люди, которые делают блоки питания, говорят что торроид (круглое колечко) компактнее и мощнее, чем Ш-образные сердечники.</p><p>Только лишь формой не обойтись, материал тоже у всех разный, есть отечественные кольца типа M1000, M2000, M6000, можно задействовать их, а есть всякие Epcos, самое главное - магнитная пронгицаемость, чем выше, тем меньше витков надо наматывать и еще верхние пределы нужно смотреть по частотам, к примеру Epcos до 150 килогерц написано что держит, а M6000H указан предел в 30 килогерц, для нашего трансформатора 50 килогерцного уже не сгодится. </p><p>Можно в том же чипдипе поизучать ассортимент, почитать описания и позабивать в рассчетную программу разные сердечники, попробовать слепить максимально миниатюрный и мощный блок питания в теории, на практике могут быть конечно отклонения и габаритная мощность колечка не соответсовать реальной...</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2019/12/------------8.png" class="kg-image" alt loading="lazy"><figcaption>Не реклама, просто пример</figcaption></figure><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/12/------------9.png" class="kg-image" alt loading="lazy"></figure><p>В общем, чем больше колечко, тем меньше на него мотать и тем мощнее может получиться трансформатор, програмка от Старичка поможет сориентироваться и прикинуть что и как...</p><h3 id="--3">Чем мотать импульсный трансформатор?</h3><p>Мотать можно и витой парой и проводом МГТФ, но лучше сгодится эмалированная медь, рублей за 200 можно купить катушку на 100 метров, должно хватить.</p><p>Самое главное - импульсные трансформаторы не получится мотать как обычные, толстенными жилами по 2мм, тут есть свои ограничения, и чем толще жилка провода, тем меньше частоту можно будет взять!</p><p>Таблица примерно такая, взято <a href="http://soundbarrel.ru/pitanie/IR2153_03.html?ref=tech-research.ru">тут</a></p><!--kg-card-begin: markdown--><table>
<thead>
<tr>
<th>Максимальная частота (кГц)</th>
<th>Диаметр не более (мм)</th>
</tr>
</thead>
<tbody>
<tr>
<td>50</td>
<td>0.6</td>
</tr>
<tr>
<td>70</td>
<td>0.5</td>
</tr>
<tr>
<td>90</td>
<td>0.4</td>
</tr>
</tbody>
</table>
<!--kg-card-end: markdown--><p>Ну а как же нам достичь нужного тока для обмотки? Просто берется жгут из нескольких тонких проводков, он выглядит как плоский шлейф, им наматывают и на выходе все проводочки спаивают...</p><p>Чтобы посчитать площадь сечения - нужна формула Пи*R<sup>2</sup></p><p>R - это радиус, половина диаметра, который получаем со штангенциркуля, не забываем убавить толщину лаковой изоляции.  На один квадратный мм сечения закладывается 3-4 Ампера тока.</p><p>Первичная обмотка должна осилить все вторичные, а вторичные должны быть достаточной суммарной площади, чтобы ток отдать нужный и не сплавиться.</p><h3 id="--4">Драйвер или инвертор импульсного трансформатора</h3><p>Драйвера собираются на IR2153 или на SG3525, первая микросхема позволяет буквально из нескольких деталек собрать драйвер, вторая чуть сложнее и уже умнее в плане стабилизации выходного напряжения.</p><p>Общая упрощенная схема выглядит так - сперва 220 вольт проходит через диодный мост, там в постоянное 310 превращается, т.к. из переменного мы верха срезаем синуса, то напряжение пульсирует, чтобы такого не было на вход ставят электролиты примерно по 1мкф на 1 ватт и напряжением 400 вольт чтоб не пробило, дальше микросхемой управляется парочка силовых транзисторов на 600 вольт, которые попеременно включаются и создают переменный ток с частотой под 40-50 килогерц и больше, дальше это на трансформатор и на выходе выпрямляется.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/12/------------11.png" class="kg-image" alt loading="lazy"></figure><p>Обратная связь лепится через оптопару, с выхода трансформатора снимается напряжение, контроллер понижает или повышает частоту, управляя тем самым КПД трансформатора и подправляя тонко выходным напряжением, когда оно просаживается под нагрузкой, то на вход меняется частота. Но тут нужно быть аккуратным, если выходных катушек несколько, то нагруженную обмотку контролируемую повысит контроллер, а остальные обмотки выходные задираются. И к примеру в компе в китайских блоках бывает 12 вольт проседает до 11.5, контроллер до 12 задирает, а 5 вольт при это до 5.6 поднимается, так можно жесткие диски или юсб-устройства убить.</p><p>Тут на ум приходит такое - либо на каждую линию свой трансформатор со своим контролем, либо на выходе стабилизаторы импульсные или линейные, при большой нагрузке линейные превратят блок в печку. </p><p>Оптопара представляет из себя светодиод и светочуствительный элемент типа фототранзистора, который проводит ток сильнее, если светодиод светится сильнее, так происходит линейная зависимость тока на выходе и ругулятора на входе в трансформатор.</p><h3 id="--5">Без защиты никак</h3><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/12/------------13.png" class="kg-image" alt loading="lazy"></figure><ol><li><strong>Плавный пуск (soft start)</strong></li></ol><p>Чем мощнее блок питания, тем больше электролит на входе, и чем больше электролит на входе, тем сильнее выброс энергии в сеть при включении прибора в розетку. Искрящая вилка при включении, мигающий свет, сейчас даже у пылесосов есть плавный пуск, чтобы не шатать электросеть.</p><p>В простейших и маломощных блоках просто ставится термистор, принцип действия такой - сперва сопротивление больше, на термисторе рассеивается тепло, он разогревается и сопротивление уменьшается, при этом плавненько, схема выходит на полную мощность. Есть недостаток - если выдернуть и вставить быстро вилку из розетки, то термистор горячий и плавного пуска не будет, ну хоть такое и то лучше чем ничего.</p><p>Более продвинутая схема плавного старта сперва через резистор заряжает плавно конденсатор, потом включает на полную мощность и параллельно драйвер с его нагрузкой подключает, вместо резистора иногда ставят транзистор, он плавно увеличивает ток, там буквально пару секунд, а потом замыкается релешкой, тут всё от фантазии зависит.</p><p><strong>2. Защита от перенапряжения</strong></p><p>Ходят рассказы про обрыв нуля и что в квартиру может прилететь 380 вольт, в этом случае в схему в самом начале, после предохранителя ставится варистор, при определенном напряжении он вдруг коротит схему, сам взрывается, но успевает сжечь предохранитель, и блок питания, и весь прибор остаются живыми.</p><p><strong>3. Входной сетевой фильтр</strong></p><p>Сетевой фильтр выполняется из конденсаторов и дросселей, гасит как приходящие помехи, так сеть защищает от себя, дросселей два типа ставят сразу или один, один с одной обмоткой, другой с двумя - это синфазный. Но я пока в этой теме не вник, но фильтр не помешает в финальном устройстве, без него сеть загадится. </p><p><strong>4. Защита от КЗ и перенапряжения</strong></p><p>В некоторых случаях и транзисторы и диоды может разорвать, в другом случае если прибор где-то коротнет, то блок питания выжгет весь прибор, а так он уйдет в защиту и ничего особо не произойдет. Защита делается токовым трансформатором, 2-3 витка толстенным проводов на первичку и побольше витков на вторичку, когда ток протекает по проводнику большой, то на вторичку ток какой-то поступает, который к примеру транзистором усиливается и при определенном значении размыкает схему, блокирует шим-контроллер, тут как токовые клещи, почитайте про токовые трансформаторы, если любопытно.</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Как я выбирал камеру для YouTube-канала ]]></title>
        <link>https://tech-research.ru/kak-ia-vybiral-kamieru-dlia-youtube-kanala/</link>
        <turbo:topic><![CDATA[ Как я выбирал камеру для YouTube-канала ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/kak-ia-vybiral-kamieru-dlia-youtube-kanala/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-12-21T09:17:05 +0500</pubDate>
        <media:content url="https://tech-research.ru/content/images/2020/02/104686.jpeg" medium="image"/>
        <turbo:content><![CDATA[ <p>Очень сложно начинающему видео-блогеру, обзавестись всем необходимым, писать тексты с фотографиями гораздо проще, чем фиксировать весь процесс на видео.</p><h3 id="-">О новой рубрике</h3><p>Сегодня я хочу поделиться своим опытом, вероятно, не совсем удачным и правильным, но отрицательный опыт тоже имеет пользу.</p><p>С 2006 года я веду разные блоги, сперва это был ЖЖ, потом blog.ru, с 2010 по 2019 сидел на гугловском блоггер.ком, несколько раз в год пишу статьи на хабр. В моей жизни часто происходит такое, что может пригодиться не только другим людям, но и мне самому спустя много лет. Да, я часто заглядываю в блог, ищу статью 10 летней давности, чтобы вспомнить как там это делалось, ибо с некоторыми вещами сталкиваюсь один раз в 10 лет.</p><p>Сегодня на сайте Tech-Research я запускаю рубрику "Летопись", это будет что-то похожее на стену во вконтакте или твиттер, тут не будет строгих обучающих статей на конкретную тему, тут будет просто передача опыта. Мой опыт ни в коем случае не нужно считать авторитетным, но сложив десятки таких "опытов" можно приблизиться к некому подобию истины.</p><h3 id="--1">Как выглядит видеоблогинг изнутри</h3><p>Ладно, не будем отвлекаться, в общем, история началась еще несколько месяцев назад, я решил снимать видеоблог на смартфон, у меня тут происходит всякий DIY, в основном, электронника, пайка. Многочасовой процесс фиксируется на камеру (в этот момент желательно не отвлекаться на камеру), далее на Пост-продакшн вырезаются моменты всякие где я долго не могу отковырять край скотча, где жду нагрева паяльника, где роюсь в ящике в поиске нужной детальки. Далее нудные и долгие моменты ускоряются, ключевые моменты озвучиваются, где нужно - добавляется инфографика, текстовые вставки, подсказки... Процесс очень долгий и нудный, на выходе получаем 5-10 минутный ролик, который снимается 1.5 часа и монтируется часа 4 в несколько этапов, на каждом этапе весь ролик просматривается целиком, находятся недочеты, к примеру обрезал фрагмент неровно и в него влезло то, чего не должно быть.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/12/------------6.png" class="kg-image" alt loading="lazy"></figure><p>Дак вот, самое главное в этом процессе - камера, про "свет для нищих" расскажу позже, про это, вероятно, даже видео сниму. В качестве "камеры для нищих" смартфон не сгодился...</p><h3 id="--2">Почему смартфон не годится для влога? </h3><p>Смартфон не подходит для видеоблога, конкретно для моего - совсем!</p><p>Если вы немного знакомы с фотографией, то должны знать что такое глубина резкости, в общем, когда вы фотографируете человека, а задний фон мутный, то это дает особый акцент на нужном объекте, если пролетела муха, то она тоже не попадет в кадр, т.к. ближе чем объект, если глубина резкости больше, то в кадр попадет не только человек, но и задний фон, на котором он фотографируется или другой объект. </p><p>Глубина резкости целиком контролируется диафрагмой, чем сильнее открыта диафрагма, тем меньше глубина и больше смажется ближе или дальше от фокуса. И наоборот, чем сильнее закрыта диафрагма, тем больше попадает в фокус. Т.е. при ручном фокусе нужно отрегулировать так диафрагму, чтобы к примеру в пределах рабочей области всё попадало в фокус, чтобы при движении рук они не смазывались. </p><p>Автофокус, каким бы он не был прекрасным - не годится для всякого DIY, посмотрите многих видеоблогеров, которые постоянно ладошку подкладывают под винтик, чтобы показать его, вместо винтика в фокус попадает столешница или еще что. Если вы снимаете свое лицо и бьюти-блоггер, то эта статья не для вас, если вы ходите с камерой и снимаете репортажи, то тоже можете в видоискателе контролировать всё и фокус подстраивать. Но когда вы ставите камеру на штатив, фиксируете ее над столом и несколько часов занимаетесь своим любимым делом и отвлекаться на камеру не хотите, то у вас аналогичная ситуация.</p><p>Я не особо разглядывал смартфоны, но подавляющее большинство из них не умеет регулировать диафрагму, она фиксированная, в характеристиках так и пишут f2.3, а не f2.3-8.2, чем меньше цифра после F, тем меньше глубина резкости, больше открыта диафрагма, сильнее мажет задний фон (что круто для портретной фотографии), и при этом, чем сильнее открыта диафрагма, тем светосильнее объектив, т.е. при слабом свете фото будет четче, меньше смазываться, но нам наоборот нужно закрытую темную диафрагму, темноту мы скомпенсируем освещением рабочего места.</p><p>Отсюда <strong>вывод </strong>- нам нужна <strong>оптика с ручными настройками</strong> и желательно сменная оптика, чтобы подобрать специфичный объектив.</p><p>Да даже камеры для видеоблогов не всегда сильно справляются, вот скрин с канала Мурка, не в обиду, я тут не про канал, а вообще про эти все камеры и сложности съемки.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/12/------------2.png" class="kg-image" alt loading="lazy"></figure><p></p><p></p><h3 id="--3">Что есть на рынке из недорогого?</h3><p>Выбор достаточно прост, если вы располагаете суммой около 60, 70, а то и 100 тысяч на камеру (не забывайте еще про свет, звук, компик для монтажа, вероятно вложения на дизайн, логотипы, анимации, рекламу, камера это только часть расходов), но если на камеру у вас есть буквально 20-30 тысяч, то вы столкнетесь с тем же вопросом, что и я.</p><p>Дополнительно поставил задачу 1080р и 50-60 кадров для видео, хочется плавности. Компактные камеры не рассматриваем, там при такой маленькой матрице вообще с закрытой диафрагмой ничего не разглядеть, да и видео они пишут от 10 до 30 кадров.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/12/-----------.png" class="kg-image" alt loading="lazy"></figure><p>Такие камеры только детям как игрушка пойдут ну или для съемки нетребовательных видео...</p><p>Чего-то адекватного можно добиться на ЭкшнКамерах, но там картинка будет как в дверном глазке, некоторые из них умеют выпрямлять ее и подрезать ровно края, но там это не всё идеально, есть еще объективы от Пиксаэро и всякие с АлиЭкспресс с меньшим углом, но это всё равно игрушки, света потребуется еще больше для таких камер, да и диафрагма опять фиксированная, не сильно лучше телефона.</p><p>Дальше идет нечто адекватное типа кэнон или фуджик, но это уже уходит за предел и не совсем то что надо, дальше поясню... </p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/12/------------1.png" class="kg-image" alt loading="lazy"></figure><p>После долгих поисков я наткнулся на всякие Sony типа NEX-5, особенно последняя модель 5t вроде годная, но чуть дальше есть Sony a5100, этот фотик прямо самый крайний из бюджетных, почти как 6000 или 6500, его можно купить за 12 тысяч на авито и в достаточно годном качестве + объектив тысячи за 4. Если нет без объектива, то берите с объективом примерно за 16-17, там часто за эти 17 еще много плюшек продают типа 2-3 дополнительных аккумулятора, сумка, чехол, светофильтры, в общем, люди часто или забивают на всю эту фотографию, т.к. когда нужно нет с собой фотика, а в кармане есть смартфон или же покупают себе альфа 7 или вообще на кэноны/панасоники уходят, в общем, продают обычно и аккумуляторы и всякие дополнительные аксессуары. </p><p>Многие хотят много за свои фотики, NEX5t дороже 10-11 с объективом не покупайте, а5100 дороже 16-17 с объективом не покупайте, лучше добавить и уже a6000 взять, объективы sel1650 тоже не берите дороже 4000, расширяйте поиск по всей стране, делайте по всем категориям, иногда не туда размещают объявление, торгуйтесь.</p><h3 id="--4">Перегрев беззеркальных камер</h3><p>Но со всеми этими беззеркалками есть одна большая проблема - перегрев, в столь тонком корпусе разместить массивное охлаждение сложно и все эти NEX, a5000, a5100, a6000, a6500 греются, меньше или больше, но греются, отснять непрерывно 1.5 часа на них нереально, частичное решение этого вопроса и обзор устройства охлаждения этих фотоаппаратов я записал на видео, смотрите, если интересно.</p><figure class="kg-card kg-embed-card"><iframe width="480" height="270" src="https://www.youtube.com/embed/l2_X8EaAIRw?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe></figure><p> Я прилеплял даже внешний радиатор, ограничение кстати тоже снял на 30 минут, но камера перегревалась, можно в ней между процессором и теплораспределительной крышкой медную пластину прилепить, а далее внешнюю крышку перфорированную выпилить и к ней радиатор уже прилепить, но весь фотоаппарат превратится в нечто колхозное и потеряет мобильность и компактность, еще непонятно что в этом фотоаппарате еще будет перегреваться, может сама матрица тоже перегрузки испытывает при съемке видео, лучше рассмотреть именно видеокамеру, предназначенную для видео... Еще на фотоаппаратах часто нет выхода под внешний микрофон и встроенный тоже не супер.</p><h3 id="--5">Выбор ВИДЕОкамеры вместо фотоаппарата.</h3><p>Долго думать не пришлось, примерно в то же время, что и NEX - выпускались видеокамеры в той же линейке - VG20 и VG30</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/12/------------4.png" class="kg-image" alt loading="lazy"></figure><p> Видеокамера 2012 года, но снимает не в 5 раз хуже, чтобы переплачивать в 5 раз больше за новинки. Сразу скажу, ищите предложения на авито без объектива, комплектный объектив 18-200 стоит как сама камера, нам не надо вероятно снимать на больших расстояниях, а вот угол наоборот понадобится чуть пошире, минимальное фокусное от 16мм, поэтому, берем объектив mount-e от наших Нексов и 5000/6000/a7 и прикручиваем на нашу камеру.</p><p>Сама камера VG30 на авито стоит около 25 тысяч без всяких косяков типа сломанной шторки, но таких предложений часто 2-3 на всю страну, другие хотят 30 тысяч за VG20 со сломанной шторкой, убитой батарейкой, торгуйтесь, мониторьте и вас ждет успех.</p><p>С небольшим объективом-блинчиком selp16 камера будет вот такой</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/12/------------5.png" class="kg-image" alt loading="lazy"></figure><p>Камера пишет аж 5 канальный звук, имеет вход под внешний микрофон, аккумулятора хватает часа на полтора-два, есть какие-то увеличенные, кучу обвеса на али можно найти.</p><p></p><p></p><p>PS: Как не пытался подружиться с VG30, так и не смог!</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/02/bNK82etj21M.jpg" class="kg-image" alt loading="lazy"></figure><p>Камера имеет низкий битрейт, если мой смартфон жмет около 80 мегабит при 1080р/60fps, то у этой камеры около 28, и что самое главное, при увеличении фреймрейта с 30 до 50 кадров, битрейт не особо поднимается, а качество еще сильнее страдает. </p><p>В общем, камера на видео такие лютые артефакты давала в виде искажения цветом, смазывания мелких деталек, я едва ее продал за полцены от купленного, сейчас у меня примерно такое происходит...</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/02/------------22.png" class="kg-image" alt loading="lazy"></figure><p>В общем, фиксирую до сих пор всё смартфоном, сейчас думаю, либо мне снимать процесс пайки мелкотни на микроскоп (который тоже придется выбирать), либо экшн-камеру сверху направить на весь стол, чтобы в 4к снимала и потом увеличивать до 1080, кадрировать нужные участки, а с рук кадры крупные уже телефоном, ну не накопил я еще на годную камеру современную, фотоаппараты не умеют снимать  долго, главное наверно содержимое, а не супер-картинка...</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Разгон компа е5-1660v4 + Patriot 2133Mhz ]]></title>
        <link>https://tech-research.ru/razghon-kompa-ie5-1660v4-patriot-2133mhz/</link>
        <turbo:topic><![CDATA[ Разгон компа е5-1660v4 + Patriot 2133Mhz ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/razghon-kompa-ie5-1660v4-patriot-2133mhz/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-11-17T12:49:47 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Сегодня, вдохновившись разгонами всяких Huanan, решил попробовать погнать мой около топовый комп на геймерской материнке MSI x99 raider.</p><p>Самое главное, что меня беспокоило - моя оперативка, затарился еще лет 5 назад 2133 оперативкой, сперва она на старом процессоре вообще работала на 1866, потом проц проапгрейдил до 1660v4 и она стала работать на 2133Mhz, но вот при всяких быстрых вычислениях полезно иметь быструю память, у меня 8 планок по 16 гиг, если их все продавать дешево и покупать чуть дороже новую, то тут как минимум 16 тысяч будет потеря...</p><p>Итак, вооружился AIDA64, первый замер такой (на штатных)</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/11/-----------.png" class="kg-image" alt loading="lazy"></figure><blockquote>Эксперимент 1 - попробуем в биосе просто поменять частоту памяти с 2133 на 2400</blockquote><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/11/------------1.png" class="kg-image" alt loading="lazy"></figure><blockquote>Эксперимент 2 - поднимем частоту шины с 100 до 100.4, а тайминги с 17 до 16...</blockquote><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/11/------------2.png" class="kg-image" alt loading="lazy"></figure><blockquote>Эксперимент 3 - сделаем тайминги вообще 15-15-15</blockquote><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/11/------------3.png" class="kg-image" alt loading="lazy"></figure><p>Как видим, латентность памяти еще снизилась на 2 наносекунды</p><p>При такой частоте шины тайминги меньше 15 никак не заводились, поэтому, я еще немного поднял частоту шины</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/11/------------4.png" class="kg-image" alt loading="lazy"></figure><p>Теперь, латентность памяти еще слегка уменьшилась</p><p>Т.е. память Patriot Memory PSD416G21332 16gb 2133Mhz легко работает на частоте 2429Mhz с таймингом 15-15-15-40, латентность памяти снижена с 82.8 до 76.8, это задержка уменьшилась на 7%... Примерно на это же число увеличилась скорость чтения и записи.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/11/------------5.png" class="kg-image" alt loading="lazy"></figure> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Как пользоваться Штангенциркулем ]]></title>
        <link>https://tech-research.ru/kak-polzovatsia-shtanghientsirkuliem/</link>
        <turbo:topic><![CDATA[ Как пользоваться Штангенциркулем ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/kak-polzovatsia-shtanghientsirkuliem/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-10-26T16:10:25 +0500</pubDate>
        <media:content url="https://tech-research.ru/content/images/2019/10/NKAdbrd-gbo.jpg" medium="image"/>
        <turbo:content><![CDATA[ <p>Сегодня поговорим о таком сверхточном приборе, как штангенциркуль, если будете делать чертежи для станков ЧПУ или 3д-принтера при изготовлении точных корпусов под ваши самоделки, подбирать диаметры болтиков, то он вам сильно пригодится.</p><h3 id="-">Как пользоваться штангенциркулем?</h3><p>Как же пользоваться этим шайтан-прибором? Лет 18 назад нас учили в школе как работать с таким прибором, а сейчас могут и упустить из программы.</p><p>Для начала нужно узнать цену деления вашего экземпляра, это может быть и 0.1 мм и 0.05 и даже 0.001 мм, но полагаться на точность таких приборов особо не нужно, самые точные штангенциркули стоят раз в 20 дороже, но дома такое и не пригодится многим.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2019/10/------------1.png" class="kg-image" alt loading="lazy"><figcaption>В моем экземпляре цена деления 0.02мм, от этого будет отталкиваться дальше</figcaption></figure><p>Попробуем измерить гайку для ключа на 10...</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/10/------------2.png" class="kg-image" alt loading="lazy"></figure><ol><li>Сопоставим нолик на нижней шкале с верхней шкале</li></ol><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/10/----------1.jpg" class="kg-image" alt loading="lazy"></figure><p>На верхней шкале сантиметры и милимметры, видим что у нас почти 1 см или 10 мм, но целых делений будет только 9, значит у нас не 10, а 9мм, это первый этап, понимаем что у нас 9 с чем то мм, почти 1 сантиметр, а вот сколько точно - поймем дальше.</p><p>2. Теперь смотрим какое деление на нижней шкале совпадет точно с любым делением на верхней шкале...</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/10/----------2.jpg" class="kg-image" alt loading="lazy"></figure><p>Начнем с того, что на нижней шкале каждые 5 делений равняется 1 и пронумерованы 1, 2, 3, ... Если умножить 5 на цену деления 0.02, то получим 0.1, значит тут для удобства каждые 0.1мм пронумерованы.</p><p>Ищем какая риска снизу точно совпадет с риской сверху, у нас это одно деление после 8, если бы было точно на 8, то было было 0.8, но у нас еще одна риска правее, как помним, у нас цена деления 0.02, значит к 0.8 прибавляем 0.02 и получаем 0.82!</p><p>Если бы на нижней шкале вообще не было цифр, то нужно было бы посчитать сколько делений от 0 до совпавшей риски, у нас это 41 деление, 41*0.02=0.82мм. На менее точных штангенциркулях делений снизу может быть не 50 как тут (10 по 5), а только 10.</p><p>3. Конечный результат</p><p>В итоге мы посчитали по верхней шкале что у нас 9 целых делений = 9мм, а по нижней посчитали что еще 0.82, складываем, и получаем 9.82 мм, до 1 см не хватает 0.18 мм, видимо припуск чтобы ключик легко надевался, а может просто китайские гайки + китайский штангенциркуль.</p><h3 id="--1">Где купить недорогой и качественный штангенциркуль</h3><p>Мне приехал с Aliexpress штангенциркуль, выглядит достаточно хорошо, нули совпадают, есть царапинки очень слабые, видимо хранили кучей, а потом разложили по чехлам и отправили. Стоит такой прибор около 700 руб со всеми доставками, доставили буквально за 2 недели. Упаковано качественно, в комплекте прочный дермантиновый чехол, с таким чехлом удобнее хранить, а то можно поцарапать его о другие инструменты.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/10/-----------.png" class="kg-image" alt loading="lazy"></figure><p> Можно найти и дешевле и электронный пластиковый, но больше половины этих товаров отвратительного качества, неровные губки, не совпадают нули и т.д., но этот штангенциркуль можно считать лучшим из бюджетных для домашнего использования. </p><p><a href="https://letyshops.com/r/aliexpress-5tmb73hvqb4sw0?ref=tech-research.ru"><strong>Ссылочка на товар</strong></a>, лично проверенный, если не верите - почитайте отзывы других людей.</p><p>Чуть позже может и электронный возьму, но с ними всё сложнее, на многих цифры скачут как дикие, половина из них пластиковые, болтаются да и штангенциркуль это такой прибор, который лежит годами, вдруг понадобилось что-то замерить, достал и какая будет досада, когда батарейка сядет.</p><figure class="kg-card kg-embed-card kg-card-hascaption"><iframe width="480" height="270" src="https://www.youtube.com/embed/wSodMItfjHY?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><figcaption>Для тех, кому удобнее, есть видео!</figcaption></figure> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Перенос профиля Firefox ]]></title>
        <link>https://tech-research.ru/pierienos-profilia-firefox/</link>
        <turbo:topic><![CDATA[ Перенос профиля Firefox ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/pierienos-profilia-firefox/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-09-24T00:05:47 +0500</pubDate>
        <media:content url="https://tech-research.ru/content/images/2020/02/1200px-Firefox_Logo-_2017.svg.png" medium="image"/>
        <turbo:content><![CDATA[ <p>К примеру при переустановке системы (полной) и тем более при смене жесткого диска будет полезным перенести профиль Firefox, там и активные сеансы и закладки и сохраненные пароли и многое другое, годами нажитое, в общем, если хотите чтобы при переходе на новую систему вы открыли браузер и не надо было по новой везде заходить в вк и в другие места, то эта статья для вас.</p><h3 id="-firefox">Резервная копия профиля Firefox</h3><p>Первым делом на еще рабочей старой системе до переустановки и др. нужно сделать резервную копию, открываем вкладку about:profiles</p><p>Видим где находится текущий профиль, жмем открыть папку</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------41.png" class="kg-image" alt loading="lazy"></figure><p>Переходим на уровень выше, папку profiles и копируем всю нашу папку...</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------42.png" class="kg-image" alt loading="lazy"></figure><h3 id="-firefox-1">Восстановление зарезервированного профиля Firefox</h3><p>Аналогичным образом перехожу в папку с профилями и перемещаю туда свой старый профиль</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------43.png" class="kg-image" alt loading="lazy"></figure><p>Теперь в about:profiles делаю следующее</p><ol><li>Создать новый профиль</li><li>Пишем имя, любое, хоть вася и указываем папку</li></ol><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------44.png" class="kg-image" alt loading="lazy"></figure><p>Укажем нашу папку, кстати ее можно было разместить не в profiles, а хоть где в корне диска к примеру или на другом диске</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------45.png" class="kg-image" alt loading="lazy"></figure><p>Далее жмем в списке профилей Запустить еще один браузер с этим профилем (новый профиль должен появиться внизу)</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------46.png" class="kg-image" alt loading="lazy"></figure><p>Теперь важно следующее, взять и закрыть окно со старым профилем, а потом только с новым, если последовательность не соблюдена, то нужно через win+r выполнять firefox.exe -p для запуска нужного профиля.</p><p>Немного потренировавшись, можно за пару секунд перетаскивать профиль старый на новый комп или новую систему, очень актуально когда старый комп накрылся, ты с него диск подключаешь для переноса файлов и сразу профиль, все дополнения и настройки, всё будет как раньше</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Настройка сети в Hyper-V через NAT (проброс портов) ]]></title>
        <link>https://tech-research.ru/nastroika-sieti-v-hyper-v-chieriez-nat-probros-portov/</link>
        <turbo:topic><![CDATA[ Настройка сети в Hyper-V через NAT (проброс портов) ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/nastroika-sieti-v-hyper-v-chieriez-nat-probros-portov/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-09-23T23:45:10 +0500</pubDate>
        <media:content url="https://tech-research.ru/content/images/2019/09/1531042004_microsoft-hyper-v.png" medium="image"/>
        <turbo:content><![CDATA[ <p>Сегодня поговорим о сети в Hyper-V, особенно о таких случаях, когда компьютер подключен по wifi, что в домашних условиях бывает часто...</p><p>В таких продуктах, как Vmware Player и Virtualbox изначально идет заточка под десктоп и там легко заводится тип подключения мост на wifi адаптер, когда ip адреса прокидываются в вашу беспроводную сеть... Но Hyper-V заточен больше под серверное применение, можете попробовать установить Linux на virtualbox или vmware (тут не говорю про серверный аналог, только десктопный продукт) и пингануть сеть, то пинги будут слегка больше иметь задержки, чем на Hyper-V, к тому же, Hyper-V еще имеет автозапуск в фоне независимо от того зашел пользователь в систему или нет.</p><p>Всё это и многое другое, к примеру скорость дисковой подсистемы, определяет выбор в пользу Hyper-V для домашнего Linux-сервера на Windows машине.</p><p>Но вот в Hyper-V нет никаких специальных сетевых драйверов-прослоек, которые бы позволяли его использовать по wifi в режиме моста (внешняя сеть), при таком использовании начнутся проблемы с обрывами между машинами и самым правильным решением будет использовать внутреннюю сеть или NAT.</p><h3 id="-hyper-v-windows-10">Установка Hyper-V на Windows 10</h3><p>Hyper-V работает только на редакциях Windows 10 pro, для его активации нужно запустить настройки - приложения -программы и компоненты</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------34.png" class="kg-image" alt loading="lazy"></figure><p>Далее нужно зайти в "включени и отключение компонентов"</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------35.png" class="kg-image" alt loading="lazy"></figure><p></p><p>И тут отметить галочкой Hyper-V, после перезагрузки в пуске появится Диспетчер Hyper-V</p><h3 id="-hyper-v">Создание внутренней сети в Hyper-V</h3><p>Первым делом нужно создать виртуальный коммутатор, использовать Default Switch с недавнего времени стало невероятно, т.к. при каждой перезагрузке он сбрасывает ip на свой автоматический.</p><p>Для создания виртуального коммутатора, нужно зайти в диспетчер виртуальных коммутаторов</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------31.png" class="kg-image" alt loading="lazy"></figure><p>А дальше создать виртуальный сетевой коммутатор, выбрав для него режим внутренняя сеть</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------32.png" class="kg-image" alt loading="lazy"></figure><p>Назовем его к примеру VirtMachines</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------33.png" class="kg-image" alt loading="lazy"></figure><h3 id="-nat-windows-10-powershell-hyper-v-">Настройка NAT на Windows 10 в PowerShell для Hyper-v (и не только)</h3><p>Допустим, все виртуальные машины у нас будут в подсети 192.168.200.0, а шлюз у них будет 192.168.200.1, для этого этот айпи укажем у адаптера для virtmachines</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------36.png" class="kg-image" alt loading="lazy"></figure><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------37.png" class="kg-image" alt loading="lazy"></figure><p>А далее открываем PowerShell от имени администратора (правый клик по кнопке пуск)</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------38.png" class="kg-image" alt loading="lazy"></figure><p>И начинаем колдовать...</p><p>Первым делом нам нужно настроить сам nat, это snat или прямой нат или подмена источника... Он же маскарадинг. Дело в том, что если во внешнюю сеть улетит ip источника 192.168.200.100, то ответа никак не получит эта машина, для этого всю внутреннюю подсеть нужно скрывать за своим внешним или почти внешним айпи</p><pre><code>New-NetNat -Name nat1 -InternalIPInterfaceAddressPrefix 192.168.200.0/24</code></pre><p>Теперь в обратную сторону, то что приходит на физическую машину на 80 порт отправим на виртуальную машину с айпи 192.168.200.100</p><pre><code>Add-NetNatStaticMapping -NatName nat1 -Protocol TCP -ExternalIPAddress 0.0.0.0 -InternalIPAddress 192.168.200.100 -InternalPort 80 -ExternalPort 80</code></pre><p>Обратите внимание, что в прямом и обратном NAT применяется один NatName...</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Коротко о клавиатуре Microsoft All in One keyboard. ]]></title>
        <link>https://tech-research.ru/korotko-o-microsoft-all-in-one/</link>
        <turbo:topic><![CDATA[ Коротко о клавиатуре Microsoft All in One keyboard. ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/korotko-o-microsoft-all-in-one/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-09-22T14:00:41 +0500</pubDate>
        <media:content url="https://tech-research.ru/content/images/2019/09/5905bd9e-10d6-4377-9ede-f3e6c9a188df.jpg" medium="image"/>
        <turbo:content><![CDATA[ <p>Здравствуйте, уважаемые читатели, сегодня хотел бы поделиться личным опытом эксплуатации клавиатуры Microsoft All in one. Клавиатура конечно больше заточена к тому, чтобы быть на коленях и эксплуатироваться сидя на диване перед телевизором, но у меня роль телевизора выполняет компьютер, поэтому решил испытать ее в роли основной на компьютере...</p><p>После клавиатуры от logitech (mk240), которая при наборе текста звучит как печатная машинка, сами кнопки на ней может и бесшумные, но дно клавиатуры пластиковое и корпус пустой и тонкий и звучит как барабан. Клавиатура от Microsoft же, очень тихая, кнопки ходят очень мягко и тихо, и корпус достаточно почный, увесистый, в общем она почти не издает звуков.</p><p>Первым вопросом у меня было - а как вообще тут скриншот сделать??? Нет ведь кнопки print Screen... У этой клавиатуры много сочетаний клавишь вшитых.</p><p>Начнем с того, что есть инверсия функциональных кнопок, например, если вам важнее кнопки f1-f12, чем всякие мультимедийные, то можно сделать инверсию, т.е. функциональные кнопки нажимать без Fn, а мультимедийные с Fn. <strong>Для включения инверсии Fn (Fn Lock) нужно нажать Fn+Caps.</strong></p><ul><li>Домой: Fn + левая стрелочка.</li><li>End: Fn+ правая стрелочка</li><li>Page Up/Page Down: Fn+вверх/вниз</li><li>PrintScreen: Fn+Пробел</li></ul><p>Если что-то вдруг не работает, то попробуйте установить <a href="https://www.microsoft.com/accessories/ru-ru/products/keyboards/all-in-one-media-keyboard/n9z-00018?ref=tech-research.ru#techspecs-connect">драйвера</a>.</p><p>Через полгода отпишусь вероятно как мне эта клавиатура зашла, мне кажется что кнопки стали шумнее через несколько часов активной печати.</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Краткое введение в 1С-Битрикс управление сайтом ]]></title>
        <link>https://tech-research.ru/kratkoie-vviedieniie-v-1s-bitriks-upravlieniie-saitom/</link>
        <turbo:topic><![CDATA[ Краткое введение в 1С-Битрикс управление сайтом ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/kratkoie-vviedieniie-v-1s-bitriks-upravlieniie-saitom/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-09-20T14:44:00 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>В текущий момент один из интернет-магазинов захотел перебраться на 1С-Битрикс, как он себя поведет в деле - покажет время, а пока идет этап знакомства с этим продуктом, хочу поделиться с вами той информацией, которую накопал за последние дни.</p><p>Сразу хочу сказать что после самописного движка или даже после какого-нибудь минималистичного OpenCart, Битрикс покажется невероятно сложной системой - 10 разделов меню, в них куча подразделов, дальше еще куча подразделов, создаю товар, понимаю что в этом товаре надо прописать характеристики, которых раннее не указано нигде, приходится закрывать редактор, переходить в другой раздел, там еще создавать. Опять создаю товар, до этого все товары были в штуках и метрах погонных, теперь в квадратных, опять всё закрываю и иду создавать единицу измерения, потом опять куча кликов чтобы вернуться назад и всё в таком духе. Да, не исключаю что я просто слишком глуп и чего-то недопонимаю. Еще в самом товаре есть куча вкладок с кучей полей, а потом там еще товарные предложения в товаре и в них тоже много вкладок, еще неочевидный момент что когда сохранил товарное предложение, то сам товар то не сохранил и он не появится...</p><p>Мне для изменения какого-либо функционала часто проще по базе поискать или в конфигах грепнуть, чем найти это в меню, но на второй день знакомства уже всё проще, всё прийдет с опытом, вероятно, и я хочу поделиться с вами своим небольшим опытом...</p><h3 id="-">Редакции Битрикса</h3><p>В Битриксе есть около 4х редакций: <strong>Старт </strong>- где даже фотогалерей нет, в общем ничем не лучше джумлы, только +5.4тыс отдать, далее <strong>стандарт </strong>- там добавляются форумы, блоги, фотогалерея... Далее идет редакция <strong>Малый бизнес </strong>за 35.9 тыс, а дальше <strong>Бизнес </strong>за 72.9тыс...</p><p><strong>Малый бизнес</strong> и <strong>Бизнес </strong>- это так раз те редакции, которые могут заинтересовать большинство, т.к. в них есть модуль Интернет-магазин, в более младших этого нет... Малый бизнес - имеет обрезанную версию магазина без остатков по складам, мультиколоночного прайса, ну в общем сравните сами, если хватит обрезанной версии - пользуйтесь ей, если нет, то придется выложить в 2 раза больше. Если не ошибаюсь, то подобные траты можно компенсировать налогами, спросите у вашего бухгалтера, если это так, то сумма может многих не волновать.</p><h3 id="--1">Первоначальная установка Битрикс</h3><p>Достаточно скачать zip файл, распаковать его в папку www на хостинге или локальном сервере, при установке скажет какие настройки php.ini нужно исправить - мне пришлось подкрутить параметры opcache и mbstring, а еще прописать часовой пояс по-умолчанию. При установке можно указать логин и пароль пользователя mysql и бд сама создаст все и развернет, далее логин и пароль администратора сайта, этот этап у меня не вызвал лишних сложностей.</p><p>Если для ознакомления нужно запустить, то на официальном сайте битрикса вообще есть готовые образы для виртуалок, у меня просто окружение уже развернуто и мне было так проще. Но если вы не желаете устанавливать Linux, Apache, MySQL. </p><h3 id="--2">Первоначальная настройка битрикс</h3><ol><li>Заходим в админку /bitrix/admin/ или же если вы авторизованы, то просто сверху вкладка "Администрирование", а потом слева в меню выбираете <strong>Магазин</strong></li></ol><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/-----------.png" class="kg-image" alt loading="lazy"></figure><p>2. <strong>Настройка единиц измерения</strong> - заходим в магазин - настройки - единицы измерения (не путать с настройками каталога)</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------1.png" class="kg-image" alt loading="lazy"></figure><p>Добавляем там свои единицы измерения, например рулон, упаковка, банка, коробка... Сразу продумайте все единицы измерения, т.к. в процессе создания товаров можете запнуться что нет нужной и нужно возвращаться к этому этапу</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------2.png" class="kg-image" alt loading="lazy"></figure><p>3. Название каталога - по-умолчанию у нас прописано "Одежда", но у вас это может быть Бытовая техника или Напольные покрытия или Автотовары или просто <strong>каталог</strong>... Я назову каталог, так понятнее.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------3.png" class="kg-image" alt loading="lazy"></figure><p>Сразу после сохранения у нас раздел каталога назван каталогом а не одеждой...</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------5.png" class="kg-image" alt loading="lazy"></figure><p>4. <strong>Создание товаров и категорий в 1С:Битрикс</strong></p><p>Товары создаются и редактируются в разделах (Каталог - Разделы), там создаются еще и категории (разделы)...</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------6.png" class="kg-image" alt loading="lazy"></figure><p>Тут у нас есть справа вверху синяя кнопка "Создать товар", не совсем очевидно, что при наведении на треугольник у создания товара сожно создать не только товар, но и категорию (раздел), долго думал как создать категорию, пока не стал создавать сами товары...</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------7.png" class="kg-image" alt loading="lazy"></figure><blockquote>В будущем конечно вся эта выгрузка и обновление каталога будет автоматически из собственной товароучетной системы, но у меня цель вообще оценить стандартные возможности Битрикса, поиграться с настройками и характеристиками товаров...</blockquote><p>Попробуем создать категорию Линолеум, перейдем в разделы (главный) и создадим категорию Линолеум</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------8.png" class="kg-image" alt loading="lazy"></figure><p>Линолеум, как и всякие футболки должен группироваться, если в футболках будет для одного товара несколько цветов и размеров, то для Линолеума будут разные ширины и каждая ширина по своей цене, для Обуви тоже будут одни туфли разного размера и, например, разных цветов. В общем, по факту ты покупаешь конкретный товар с конкретными параметрами, но в каталоге несколько отличающихся товаров объединяются в один с несколькими предложениями, это позволяет меньше путать посетителей, выводить меньше товаров в категориях, исключать дубли похожих товаров. В 1С:Битрикс такая группировка называется "Товар с торговыми предложениями".</p><p>Но прежде чем создавать такой товар с торговыми предложениями - подумаем чем они будут отличаться и предварительно пропишем свойства торговых предложений...</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------10.png" class="kg-image" alt loading="lazy"></figure><p>Я создал два свойства: Ширина и Тип продажи для нашего линолеума...</p><p>Далее возвращаюсь опять в Каталог - Разделы - Линолеум и выбираю пункт "Создать товар с торговыми предложениями".</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------9.png" class="kg-image" alt loading="lazy"></figure><p>Пропишем название Товара, пока обощенное без уникальных свойств, например, "Линолеум Tarkett хороший", не будем вдаваться в конкретику, у нас просто тестовые данные.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------11.png" class="kg-image" alt loading="lazy"></figure><p>Ниже можно выбрать бренд, но мы его не прописали зараннее, так что не будем ничего выбирать, потом укажем...</p><p>На вкладках анонс и подробно можно залить картинки и описания, я так понял что анонс это то что выводится в категории в списке, а подробное описание и картинка будут уже при открытии товара.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------12.png" class="kg-image" alt loading="lazy"></figure><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------13.png" class="kg-image" alt loading="lazy"></figure><p>Раздел СЕО нам пока не интересен, потом в это вникнем, там по-умолчанию генерируются мета-теги по шаблону, но можно вписать индивидуальные, у меня на самописном движке такое уже есть и тут есть, это хорошо.</p><p>Переходим во вкладку Торговые предложения, тут нужно насоздавать конкретные предложения этого товара, у нас они будут различаться по типу продажи (опт или розница) и по ширине.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------14.png" class="kg-image" alt loading="lazy"></figure><p>Жмем добавить, у нас откроется еще одно окно, тут название изначально вписывается от товара к предложению, но вот при попытке выбрать тип продажи опять запнулся на том, что нельзя сразу тут вписать Тип продажи или ширину, у меня в движке так можно, у Битрикс такого нет, поэтому сохраняем как есть и идем создавать значения свойств.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------15.png" class="kg-image" alt loading="lazy"></figure><p>Даже не знаю к чему этот XML_ID, наверно пригодится при синхронизации с товароучетной системой.</p><p>Кстати на заметку, тут в списках во всех есть такая кнопка, я думал что это сортировка, а это изменение, имейте ввиду</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------16.png" class="kg-image" alt loading="lazy"></figure><p>Венемся опять к нашим торговым предложениям, создадим линолеум опт 3м</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------17.png" class="kg-image" alt loading="lazy"></figure><p>И укажем значения характеристик</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2019/09/------------18.png" class="kg-image" alt loading="lazy"><figcaption>Понятия не имею, почему у нас опять одежда в заголовке, ведь мы переименовали, вернемся к этому позже</figcaption></figure><p>Нам не даст сохранить товар без указания цены, переходим во вкладку торговый каталог и прописываем цену. Там еще куча вкладок во вкладках, копаться и копаться... Было бы тут логично, если бы цена продажи и название были на главной вкладке, ибо фигня какая-то, очень сложно.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------19.png" class="kg-image" alt loading="lazy"></figure><p></p><p>После этого создадим еще "4м опт",  "3м розница" и "5м розница" по аналогии...</p><p>Будьте внимательны, галочка активность это публикация на сайте, а не учет дат которые для активности...</p><p>У нас получается вот такое</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------21.png" class="kg-image" alt loading="lazy"></figure><p>Пробуем сохранить сам товар, снизу кнопка сохранить, иначе все предложения не сохранятся (наверно)...</p><p>Но на сайте у нас показывает до сих пор какие-то не наши характеристики для выбора товара, понять не могу почему</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------22.png" class="kg-image" alt loading="lazy"></figure><p>Итак, ползал несколько минут по админке, искал какие где галочки и вот что...</p><ol><li>У одного из предложений я оставил цвет и размер, поэтому у меня тут в списке вывелось лишнее...</li><li>Там, где мы создавали свойство - нужно в самом низу поставить галочку "используется для выбора торговых предложений"</li></ol><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------23.png" class="kg-image" alt loading="lazy"></figure><p>И вот результат</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------24.png" class="kg-image" alt loading="lazy"></figure><p>И в категории</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------25.png" class="kg-image" alt loading="lazy"></figure><p>Остается сделать товар чтобы он был в наличии... Заходим в 3м опт и прописываем <strong>доступное количество = 1</strong> во вкладке торговый каталог - параметры</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------26.png" class="kg-image" alt loading="lazy"></figure><p>Теперь товар выглядит вот так</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------27.png" class="kg-image" alt loading="lazy"></figure><p>Укажем у всех то что оно есть в наличии и вот результат</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------28.png" class="kg-image" alt loading="lazy"></figure><p>Обратите внимание, оно нам не даст выбрать комбинацию свойств, которых нет, вот к примеру для 3м есть опт и розн, а для 4м только опт</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------29.png" class="kg-image" alt loading="lazy"></figure><p>А для 5м только розница</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/09/------------30.png" class="kg-image" alt loading="lazy"></figure><p>Если в том же месте, где указывали количество на остатке выключить количественный учет и разрешить покупать при отсутсвии, то у нас не будет ничего перечеркивать, актуально для тех, у кого нет своего склада, а есть только свежие остатки от поставщика, они как-бы не точные, т.к. поставщик уже десять раз всем продал, но хотя бы есть вероятность что этот товар не сняли с продаж и он не пропал на складах...</p><p><em><strong>Продолжение следует...</strong></em></p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Windows 10 - первичная настройка на ноутбуке ]]></title>
        <link>https://tech-research.ru/windows-10-piervichnaia-nastroika-na-noutbukie/</link>
        <turbo:topic><![CDATA[ Windows 10 - первичная настройка на ноутбуке ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/windows-10-piervichnaia-nastroika-na-noutbukie/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-08-21T22:10:49 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Данная статья предназначена больше для людей, которые в теме, для людей, у которых обычно нет антивируса, а вместо него собственная голова... В общем, все советы и рекомендации на свой страх и риск, автор просто свое мнение выражает и личный опыт.</p><h3 id="-">Почему ноутбук?</h3><p>Почему статья акцентирована на ноутбук? А потому что ноутбук это чаще ультрапортативное устройство с относительно слабой начинкой и не очень большой батарейкой. Если же батарейка очень большая и еще в ноутбук можно добавить много памяти, то это чаще всего не ноутбук, а рабочая станция весом 2 кг. Есть еще ноутбуки с крутыми характеристиками и очень тонкие и легкие, но они часто стоят как автомобиль... Данная статья не только для ноутбуков, но и вообще для компьютеров, которые не блещут избытком ресурсов... Но на ноутбуке в первую очередь нужна максимальная оптимизация, т.к. нужно максимально долго прожить от батарейки и часто у вас только 2-4 гигабайта оперативной памяти, а не 16 и более, как на стационарном компьютере, еще на ноутбуках процессоры экономичные и относительно слабенькие, а не 8 ядерные монстры типа i9.</p><h3 id="windows-10-">Windows 10 очень даже хороша...</h3><p>Не нужно ругать Windows 10 и стремиться поставить Windows 7, во-первых у вас это может не получиться, т.к. современные ноутбуки только на UEFI, на них ничего более раннее не запустится (исключение Win 8), во-вторых сегодня в моде экраны высокой плотности где на 13 дюймов может быть почти 4к разрешение, в более ранних версиях (в т.ч. и в 8) будет всё или слишком мелко или размыто. Только Windows 10 и начиная только с последних выпусков адекватно работает масштабирование... Поэтому выбора особо нет, только десятку и всё. </p><blockquote>Да, вы сразу скажете что есть же Linux, который на 200 мегабайт меньше тратит оперативной памяти и такой облегченный и гибкий, но статья не о нем, против линукса ничего не имею, отличная система, но если не повезет, то потребление будет гораздо больше чем в Windows, еще и сканер отпечатков может не заработать и тачпад может не так четко работать... Да и вопрос экономии на системе не столь актуален, когда тот же браузер кушает несколько гигабайт из оперативной памяти. </blockquote><h3 id="-windows-10-">Чистая переустановка Windows 10 на компьютере/ноутбуке</h3><p>Первым делом советую при покупке нового ноутбука сделать установочную флешку Windows 10 через официальную утилиту <a href="https://www.microsoft.com/ru-ru/software-download/windows10?ref=tech-research.ru">Media Creation Tool</a>.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/08/------------3.png" class="kg-image" alt loading="lazy"></figure><p><strong>Попробую объяснить, почему это очень полезно.</strong></p><ol><li>Скорей всего при покупке ноутбука у вас будет предустановлен предыдущий выпуск, например сейчас актуален 1903, а у вас стоит 1809 или 1803, вы запустите обновление системы, у вас будут долго-долго скачиваться все обновления, система обновлений Windows устроена таким образом, что при каждом накатывании новой версии компонента сохраняется его предыдущая версия для возможности отката и как-бы мы не пытались почистить диск, все равно размер системы не будет таким же, как и был при первой установке...</li><li>С завода на ноутбуке часто предустановлено ну очень много всяких утилит, которые только тратят ресурсы, там еще и пробные версии антивирусов и много всего другого, это удалять только время лишнее тратить.</li><li>С завода часто диск размечен так, что у нас еще и скрытый раздел для восстановления системы (переустановки), это только отнимает место на диске...</li></ol><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/08/------------4.png" class="kg-image" alt loading="lazy"></figure><p>Взгляните на это фото, у меня мало того что разбит системный диск на два - Windows и Data, что не совсем удобно, т.к. иногда на Data может не хватить немного, а иногда и на системном, когда много софта поставишь, лишние заморочки... Еще у меня 0.5 гиг на winpe, 14gb на onekey, 1gb на WinRE, не знаю зачем это, мне оно не пригодится, но это 15.5 гигабайт пространства просто скушано под какие то восстановительные утилиты заводские.</p><p>Думаю теперь я убедил вас в полезности чистой переустановки с полной переразметкой диска (удалить все разделы и нажать установить на неразмеченную область).</p><p>Перед тем, как устанавливать систему, советую <a href="https://tech-research.ru/rieziervnoie-kopirovaniie-draivierov-windows-10/">сделать резервную копию всех установленных драйверов</a>, вдруг не найдете их на сайте производителя, некоторые китайские ноутбуки с отвратительной поддержкой и драйвера для них будете потом искать на всяких форумах...</p><p>Создаем установочную флешку через средство создания носителя (скачиваем на сайте Microsoft), устанавливаем систему, дальше устанавливаем все драйвера, если у производителя на сайте есть раздел загрузок, то скачиваем там последние версии, если там есть обновление биоса, то и его можно поставить, часто это решает серьезные проблемы типа залипания тачпада, неправильного энергосбережения, синих экранов и другого.</p><p>При первой загрузке новой системы отказываемся от всего, от чего только можно отказаться - отправка диагностических данных, улучшение определения местоположения и всё такое... Обычно я не захожу в учетную запись Microsoft, выбираю автономную.</p><h3 id="-windows-10">Первичная настройка/оптимизация Windows 10</h3><ol><li>Советую избавиться от Windows Defender, он любит дико сканировать всю систему и проверять все выполняемые процессы, что иногда загружает процессор на все 100% и потребляет много памяти, для этого сперва выключаем в нем защиту в реальном времени, потом создаем файл .reg с таким содержимым и вставляем в него код (либо руками правим реестр)</li></ol><pre><code>Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender]
"DisableAntiSpyware"=dword:00000001
"ServiceKeepAlive"=dword:00000000

[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender\Signature Updates]
"ForceUpdateFromMU"=dword:00000000
"UpdateOnStartUp"=dword:00000000</code></pre><p>2. Если у вас есть сканер отпечатков, то после DWS может отвалиться сканер отпечатков, нужно сперва в службах включить биометрическую службу, а потом в реестре HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Biometrics поставить 1 у ключа Enabled, но лучше DWS не использовать, он устарел и достаточно много других проблем дает.</p><p>3. Советую выключить службу Windows Search, любит она шариться в нескончаемых объемах моего многотеррабайтного файлохранилища, а после этого выключить индексацию...</p><p>4. Советую выключить восстановление системы (защита системы)</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/08/------------5.png" class="kg-image" alt loading="lazy"></figure><p>Практика показывает, что при серьезных сбоях ничего в итоге не восстанавливает, но это тратит лишнее место на диске и на фоне делает снимки системы, что тоже кушает ресурсы...</p><p>Чтобы зайти в это окно - правой кнопкой по меню пуск, там система, там справа сведения о системе, там дополнительные параметры и вкладка защита, дальше настроить и выключить там...</p><p>5. В предыдущем же диалоге кликаем на вкладку дополнительно и там заходим в быстродействие, я там обычно оставляю только сглаживание шрифтов, чтобы лесенок не было и тени окон оставляю, ибо они иногда сливаются.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/08/------------6.png" class="kg-image" alt loading="lazy"></figure><p>6. Автоматическое обновление автономных карт</p><p>Параметры-приложения-автономные карты, там стоит галочка обновлять автоматически, а зачем нам такое счастье</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/08/------------7.png" class="kg-image" alt loading="lazy"></figure><p>7. Синхронизация параметров - еще одна штука, рано или поздно вы все равно наверно зайдете в свою учетную запись и тут начнется...</p><p>Заходим в параметры - учетные записи - синхронизация ваших параметров, убираем все галочки, меня вот наоборот раздражает, на стационарном компьюетере я одни обои ставлю, на ноутбуке другие, а тут всё синхронизировалось и применилось везде одинаковое, да и вообще слив данных в облако не очень хорошо.</p><p>8. Меню пуск - рекомендуемы и последние...</p><p>Заходим в параметры - персонализация - пуск, тут я обычно выключаю "<strong>показывать недавно добавленные</strong>", чтобы не портить порядок приложений в пуске и не дублировать позиции и еще один пуктик важный "<strong>показывать иногда предложения</strong>", ибо не надо мне тут советовать и мониторить что у меня установлено, а еще один пуктик "<strong>показывать последние открытые элементы</strong>", ибо тоже нафиг что-то журналировать что последнее а что нет, что открывал и когда открывал...</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/08/------------8.png" class="kg-image" alt loading="lazy"></figure><p>9. Экран блокировки ползает лишний раз в интернет...</p><p>В персонализации выбираем экран блокировки, там фон выбираем просто "фото", а не "Windows-интересное" или "слайд-шоу", и чуть ниже выключаем забавные факты и шутки, мы тут работаем а не шутки смотрим.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/08/------------9.png" class="kg-image" alt loading="lazy"></figure><p>10. Фон рабочего стола</p><p>В фоне рабочего стола тоже ставил просто фиксированное фото, а не слайд-шоу всякие...</p><p>11. Временная шкала, это когда жмешь win+tab, а там помимо открытых окон показывает еще. Заходим в параметры - система - многозадачность, выключаем временную шкалу.</p><p>12. Локальный пользовательский словарь - штука которая собирает всё что вы печатаете и какой-то ваш словарь составляет, непонятно что оно туда насобирает, какую полезную информацию смогут вытащить вирусы из хранилища на диске, да и вообще лучше не делать лишнего, поэтому заходим в параметры - конфиденциальность - персонализация рукописного ввода, снимаем там галочку.</p><p>13. Журнал действий, еще один пункт в разделе конфиденциальность, тоже его там выключаем и очистить жмем внизу.</p><p>14. Фоновые приложения, вот тут то от души можно поработать, в разделе настроек конфиденциальность выбираем фоновые приложения, снимаем там галочки почти со всего, что не требует пуш-уведомлений, например можно оставить для почты, чтобы уведомления о новых письмах всплывали... Чаще там такие приложения, которые вечно ползают в интернет, проверяют наличие обновлений и всё такое, при подключении на мобильном интернете это еще и сэкономит нам трафик...</p><p>Пока тут всё, если у вас есть другие советы - пишите в комментарии, добавлю в статью.</p><h3 id="-windows-10-1">Автоматическое обновление системы Windows 10</h3><p>Многие люди ломают голову как же выключить автоматическое обновление Windows 10, ведь это очень и очень ужасный функционал, на ноутбуке он начинает ставить обновления когда я включаю или выключаю его, отнимая у меня минуты моего времени, у меня человек на телефоне ждет, я говорю сейчас ноут достану, мой ноут включается за 2-3 сек, но вот обновления могут ставить несколько минут, на стационарном компьютере система сама перезагружается ночами и сервера, работающие в фоне на Hyper-V, вырубаются, а на них может в это время идти резервное копирование, обновления нужны, но я ставлю их сам когда плановые работы идут. </p><p>Пользователи Windows 10 pro могут покрутить в групповых политиках</p><p>конфигурация компьютера -&gt; компоненты windows -&gt; центр обновления системы</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/03/------------3.png" class="kg-image" alt loading="lazy"></figure><p>Пользователям домашней версии, особенно на ноутбуке поможет включение лимитного подключения на wifi, это убережет от лишних трат трафика при подключении по мобильному интернету</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/03/------------4.png" class="kg-image" alt loading="lazy"></figure><h3 id="--1">Остановка и запуск приложений</h3><p>В Windows 10 есть такая неприятная особенность, когда выключаешь компьютер, то оно еще задает вопросы типа завершить эти приложения или нет, в итоге жмешь завершить, но иногда опять же жмешь завершить работу, закрываешь крышку и убегаешь, а ноутбук плавит твою сумку, не раз такое бывало еще на Windows XP. </p><p><strong>Как же убрать вопрос при завершении работы и сделать автоматическое завершение всех приложений?</strong></p><p>Заходим в реестр, HKEY_CURRENT_USER/Control Panel/Desktop</p><p>Создаем строковый параметр AutoEndTasks со значением 1, перезагружаемся и при следующем выключении или перезагрузке не будет задавать лишние вопросы, но это для опытных пользователей, которые всё сохраняют, а потом только завершение запускают...</p><p>Второй момент, который меня беспокоил и это только на Win 10 появилось - автоматический запуск приложений, выглядит это так, вы перезагружаетесь или выключаетесь, начинаете работать, а у вас вдруг запускается ворд, эксель, консоль, пара браузеров, текстовый редактор и всё что было до выключения, очень раздражало меня, вроде перезагружаюсь ради того, чтобы очистить память от хлама, а у меня снова куча запущенных приложений. Еси это выключить, то ночами перезагруженный компьютер не вернет все программы на место, поэтому либо вы сохраняетесь и выключаетесь в конце работы, либо с обновлениями у вас наведен порядок...</p><p>Заходим в настройки, учетные записи, варианты входа, там снимаем самую последнюю галочку, которая помимо всего еще и перезапускает все приложения при перезагрузке...</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/03/------------6.png" class="kg-image" alt loading="lazy"></figure> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Windows 10 - проверка аккумулятора на ноутбуке ]]></title>
        <link>https://tech-research.ru/windows-10-provierka-akkumuliatora-na-noutbukie/</link>
        <turbo:topic><![CDATA[ Windows 10 - проверка аккумулятора на ноутбуке ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/windows-10-provierka-akkumuliatora-na-noutbukie/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-08-08T15:07:10 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>История началась с того, что я купил ноутбук с витрины, который там отработал 4200 часов. Меня сразу насторожило то, что ноутбук разряжается за час по 20% (что очень быстро для него), хотя я просто оставил его и настроил чтобы экран не выключался... </p><p>Мой Acer Swift 1 должен жить от батарейки даже в средней нагрузке больше 6 часов, а без нее вообще часов 12-13, но он разряжался примерно за 5 часов. </p><p>Итак, после того, как я засек сколько работает мой ноутбук и сколько тратится зарядки за час, сразу озадачился вопросом Как сделать диагностику аккумулятора на ноутбуке? Как узнать износ батарейки? Ведь производитель очень размыто дает ресурс аккумулятора, и любой сервис вам в ответ сразу скажет что очень зависит от сценария использования и ничего доказать не сможете.</p><h3 id="-1-aida64">Способ 1 - Aida64</h3><p>При помощи Aida64, даже пробной версии вы сможете посмотреть ресурс батарейки, просто запускаем программу, заходим в раздел Компьютер -&gt; Электропитание, а там ищем износ аккумулятора</p><p>В результате я увидел примерно такое (извините за качество, на телефон щелкнул, некогда было скриншотить, кидать на флешку, сохранять...)</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/08/-----------.png" class="kg-image" alt loading="lazy"></figure><p>По картинке видем то что паспортная емкость аккумулятора 53939, при этом контроллер смог зафиксировать максимальную залитую зарядку в него 35886, из этого вывод что износ с аккумулятора 33%...</p><p>После того, как я поменял ноут на новый в магазине и снова проверил, то уже вот такая картинка (степень износа 0%)</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/08/------------1.png" class="kg-image" alt loading="lazy"></figure><p></p><h3 id="-2-windows-10">Способ 2 - стандартными средствами Windows 10</h3><p>Когда перед вами ноутбук с витрины или б/у из комиссионки или с барахолки, то вам тоже будет полезно его протестировать, берем открываем powershell от имени администратора (правой кнопкой по пуску), дальше вводим такую строку</p><pre><code>powercfg energy</code></pre><p>После этого нам напишет что отчет сохранен по такому то адресу, копируем этот адрес, вставляет в строку в браузере и крутим открытый файл до сведений о батарее.</p><p>Ищем там расчетную емкость и последнюю полную зарядку, делим меньшее на большее, умножаем на сто, получаем оставшийся ресурс...</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/08/------------2.png" class="kg-image" alt loading="lazy"></figure><p></p><p>Еще одним из показателей (но не совсем точным) является smart накопителя, запустим crystal disk info, там покажет общее время наработки, для витринных экспонатов это показатель, для б/у могут поменять накопитель...</p><p></p><p>Еще есть такой момент, как калибровка контроллера, иногда идет расхождение показаний, нужно хотя бы разок до 0 разрядить и зарядить до 100, новые ноутбуки пару раз полностью зарядить надо до тех пор пока они нормально начнут показывать, так что не спешите идти и менять ноутбук.</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Windows 10 - резервное копирование драйверов ]]></title>
        <link>https://tech-research.ru/win10-driver-backup/</link>
        <turbo:topic><![CDATA[ Windows 10 - резервное копирование драйверов ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/win10-driver-backup/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-08-02T17:36:24 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Сегодня расскажу как сделать резервное копирование всех драйверов встроенными средствами Windows 10.</p><ol><li>Создаем на диске <strong>C</strong>: папку <strong>DriversBackup</strong></li><li>Открываем терминал от имени администратора (или PowerShell)</li><li>Вводим такую конструкцию</li></ol><pre><code>dism /online /export-driver /destination:C:\DriversBackup</code></pre><p>3. Ждем окончания, теперь папку C:\DriversBackup на флешку сохраняем..</p><p>4. После переустановки системы просто делаем поиск по этой папке...</p><p></p><p>Очень удобно, когда например надо на ноуте систему поставить на другой диск или на новом ноутбуке чистую систему без лишних утилит заводских поставить, еще удобно например сразу поставить 1903, чем обновлять 1803 или 1809, т.к. потом с обновлениями папку Windows раздует, проще самую свежую сборку установить по чистому...</p><hr><p>Windows 10 drivers backup in powershell | tech-research</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Посимвольная обработка строки ]]></title>
        <link>https://tech-research.ru/posimvolnaia-obrabotka-stroki/</link>
        <turbo:topic><![CDATA[ Посимвольная обработка строки ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/posimvolnaia-obrabotka-stroki/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-06-04T17:51:02 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Иногда возникает такая задачка - понять почему две одинаковые строки кажутся для программы разными, а для нас одинаковыми.</p><p>Если в случае с буквой с и c (латинская и кириллическая) и а/a можно методом ctrl+c, ctrl+f вычислить злосчастное слово, то с такими вещами, как обычный пробел и неразрывный пробел может быть дикое замешательство, что sublime text, что firefox нормально находил первую подстроку во второй, а вот php так не считал...</p><p>Для своих исследований я написал вот такую функцию на PHP</p><pre><code>define('BR','&lt;br&gt;');

function str_pars($str)
{
	$len = mb_strlen($str);
	echo BR.$str.' (length='.$len.')'.BR;
	for ($i=0;$i&lt;$len;$i++)
	{
		$char = mb_substr($str,$i,1);
		echo 'ch="'.$char.'"('.mb_ord($char).')'.BR;

	}

}</code></pre><p>Это выведет посимвольно всю строку и для каждого символа покажет его код UTF, далее можете заглянуть вот <a href="https://www.utf8-chartable.de/unicode-utf8-table.pl?ref=tech-research.ru">сюда</a>.</p><p>У меня во всех строках был пробел с кодом 32, а в одной из них 160.</p><p>Предварительно код нужно перевести в 16 ричную систему, т.е. 160 = A0, значит по первой колонке ищем U+00A0</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/06/image.png" class="kg-image" alt loading="lazy"></figure><p>Есть и более интересные варианты, когда Й выражается через И и сдвинутую надстрочную галочку ̆, (й) в UTF достаточно много интересных символов. И буква ё и много другого во входных данных может казаться схожим внешне, но разными символами.</p><p>Скопируйте символ й в блокнот, попробуйте удалить букву и получите удаление надстрочного....</p><p>На хабре есть <a href="https://habr.com/ru/post/262679/?ref=tech-research.ru">статья </a>по этой теме </p><p>Чтобы нормализовать пробелы и заменить двойные пробелы на одинарные, я использую вот такую конструкцию</p><pre><code>$str = preg_replace('/\s{1,}/u', " ", $str);</code></pre> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Закончилось место на диске, хотя оно есть (Linux/Debian) ]]></title>
        <link>https://tech-research.ru/zakonchilos-miesto-na-diskie-khotia-ono-iest-linux-debian/</link>
        <turbo:topic><![CDATA[ Закончилось место на диске, хотя оно есть (Linux/Debian) ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/zakonchilos-miesto-na-diskie-khotia-ono-iest-linux-debian/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-05-14T21:41:48 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Сегодня произошла такая ситуация, знакомый попросил проверить его сервер, в итоге любая операция выводит сообщение что на диске закончилось место...</p><p>Вот тут видно что место есть</p><pre><code> df -h |grep /sda1
/dev/sda1          120G          78G   37G           68% /</code></pre><p>А если сделать вот так, то увидим что его нет</p><pre><code>df -i /
Файловая система  Iнодов IИспользовано IСвободно IИспользовано% Cмонтировано в
/dev/sda1        7987200       7987200      0              100% /</code></pre><p>Как такое получается, ну видимо так зарезервировали свободное место на диске...</p><p>На веб-сервере чаще всего проблема в сессиях, но удалить их так просто не получится, нужно сделать примерно вот так (предварительно зайдя в папку с сессиями или указав путь до нее вместо точки)</p><pre><code>find . -name "sess*" -delete -print</code></pre><p>Теперь сидим и смотрим как чистятся сессии... Но нет, оно зависает через несколько сотен тысяч файлов, rsync пустой папки тоже не очень, прочитал на хабре, оказывается лучше</p><pre><code>rm -r /path/</code></pre><p>т.е. не так ./*, а просто до папки...</p><p>Дальше выяснилось, что не только сессиями заполнен диск, нужно искать дальше, на помощь приходит примерно такой скрипт</p><pre><code>du -s --inodes * 2&gt;/dev/null |sort -g</code></pre><p>Перейдем в корень и попробуем выяснить где тут много файлов...</p><p>Можно конкретно указывать где смотреть...</p><pre><code>du -s --inodes /var/* 2&gt;/dev/null |sort -g</code></pre><p>или</p><pre><code>du -s --inodes /var 2&gt;/dev/null |sort -g</code></pre><p>ну к этому позже, теперь о том, как чистить устаревшие сессии в кастомных директориях, когда каждый сайт определяет свою папку с сессиями, ну примерно вот так</p><pre><code>find /path/to/sess -name "sess_*" -mmin +43200 -delete </code></pre><p>Это чистит куки, у которых время изменения больше 43200 минут, т.е. более месяца... Добавим это в кронтаб раз в 15 минут и можем жить спокойно... За месяц примерно 343278 сессий, при посещаемости 200 человек в сутки должно быть 6000 сессий в месяц, это значит что слишком много кто получает страницы не используя куки, т.е. каждая страница как новый посетитель, это скорей всего, всякие поисковые роботы, парсеры конкурентов...</p><blockquote>Нужно будет придумать такой механизм хранения сессий, когда изначально куки выдаются на 30 минут, но если повторно обратишься в течение этих 30 минут, например, товар в корзину добавил или просто перешел с одной страницы на другую, то уже выдавать +10 минут, потом +20, чем активнее пользователь, тем дольше у него куки. К этому вопросу я еще вернусь позже... </blockquote> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Уменьшение размера картинок на сайте ]]></title>
        <link>https://tech-research.ru/umienshieniie-razmiera-kartinok/</link>
        <turbo:topic><![CDATA[ Уменьшение размера картинок на сайте ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/umienshieniie-razmiera-kartinok/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-05-01T18:51:00 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Самым тяжелым местом, как правило, на сайте являются картинки, их очень много, сайт загружается дольше, на сеть нагрузка выше, в конечном итоге не только страдает конкретный единичный клиент, но и все остальные, если их много, т.к. нагрузка на трафик возрастает, трафик забивается и сервер в целом затыкается передачей статики...</p><h3 id="pngquant-80-28k-">PNGQuant (80к -&gt;28k)</h3><p>Я решил поиздеваться над сайтом одного магазина и попробовать оптимизировать картинку, не важно какой сайт, главвное нужен пример PNG и как он будет выглядеть. В примере будет только часть картинки без названия бренда, чтобы это не было рекламой...</p><p>Изначально картинка вот такая (80 килобайт, 16 бит RGBA, non-interlaced)</p><pre><code>ls -sh logo2.png &amp;&amp; file logo2.png
80K logo2.png
logo2.png: PNG image data, 281 x 56, 16-bit/color RGBA, non-interlaced</code></pre><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/05/image-3.png" class="kg-image" alt loading="lazy"></figure><p>Многие выступают против JQuery, т.к. он целую сотню килобайт отъедает ресурсов, а тут один логотип маленький... Просто верстка, очевидно, была торопясь и шаблон просто резался быстро со всеми установками по-умолчанию из фотошопа...</p><ol><li>Попробуем прогнать через pngquant</li></ol><pre><code>pngquant --speed 1 -f -v --ext .png --quality 60-80  logo2.png</code></pre><p>Получилось вот так, в 3 раза меньше размер, 8 битный цвет и индексированная карта цветов...</p><pre><code>28K logo2.png
logo2.png: PNG image data, 281 x 56, 8-bit colormap, non-interlaced</code></pre><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/05/image-2.png" class="kg-image" alt loading="lazy"></figure><p>2. Попробуем откатить результат на оригинал и прогнать немного иначе, до этого программа pngquant выдала нам то что сохранила картинку в 256 цветах... </p><pre><code>pngquant --speed 1 -f -v --ext .png 128   logo2.png</code></pre><pre><code>24K logo2.png
logo2.png: PNG image data, 281 x 56, 8-bit colormap, non-interlaced</code></pre><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/05/image-4.png" class="kg-image" alt loading="lazy"></figure><p>Изменение цветов с 256 на 128 не дало ощутимого прямо 2х кратного падения размера, внешне это тоже не совсем отобразилось.</p><p>Попробуем совсем радикальное решение - 16 цветов</p><pre><code>pngquant --speed 1 -f -v --ext .png 16   logo2.png </code></pre><pre><code>20K logo2.png
logo2.png: PNG image data, 281 x 56, 4-bit colormap, non-interlaced</code></pre><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/05/image-5.png" class="kg-image" alt loading="lazy"></figure><p>Дальше картинка жутко деградирует по цветам, а мы выигрываем какие-то жалкие 30%, из чего следует, что перегон в индексированную 8 битную палитру из 16 битной RGBA дает 3х кратное урезание картинки, тогда как дальнейшее уменьшение цветности результата совсем не дает, а только портит изображение...</p><p>Я бы отнес эту утилиту к хорошему решению для уменьшению картинок в 3 раза без потери качества...</p><p>OptiPNG</p><pre><code>optipng -o7 -strip all logo2.png

56K logo2.png
logo2.png: PNG image data, 281 x 56, 16-bit/color RGB, non-interlaced</code></pre><p>OptiPng совсем толком не помолгла, но смотрите что я сделаю дальше, а дальше я снова повторю то что делал раньше....</p><pre><code>pngquant --speed 1 -f -v --ext .png    logo2.png

12K logo2.png
logo2.png: PNG image data, 281 x 56, 8-bit colormap, non-interlaced</code></pre><p>Всего 12 килобайт и вот результат, примерно как при 24 килобайтах...</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/05/image-6.png" class="kg-image" alt loading="lazy"></figure><p>Исследовав дальше, я понял, что в pngquant тоже есть опция, но у меня стоит старая версия...</p><p></p><p>Дальше я обратил внимание вот на такие картинки!</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2019/05/image-7.png" class="kg-image" alt loading="lazy"><figcaption>jpeg 10кб</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2019/05/image-9.png" class="kg-image" alt loading="lazy"><figcaption>PNG 2kb</figcaption></figure><p>Всего 2 килобайта и нет размытия, а всё потому, что у нас двухцветное изображение, есть таких много изображений на сайте без градиентов и переливов, которые могут в формате PNG быть компактнее JPEG, после прогона через pngquant примерно такой командой (если картинка не 2х цветная, то часто достаточно 64-256 цветов). Утилита optipng, в данном случае, используется для срезания всех мета-данных, но в новой версии pngquant эта опция присутствует и можно обходиться только этой утилитой...</p><pre><code>pngquant --speed 1 -f -v --ext .png  2  logo2.png</code></pre><pre><code>file banner_bg1.png 
banner_bg1.png: PNG image data, 180 x 179, 1-bit colormap, non-interlaced</code></pre><p></p><p>Некоторые объекты на сайте типа крестиков, стрелочек, кружков можно вообще сделать через SVG, об этом постараюсь написать статью чуть позже...</p><p></p><h3 id="-">ИТОГ</h3><p>После двух дней опытов на двух своих проектиках я пришел к выводу, что PNG очень компактный и крутой формат, и если делать примерно вот так</p><pre><code>optipng -o7 -strip all logo2.png
</code></pre><p>А потом вот так</p><pre><code>pngquant --speed 1 -f -v --ext .png  2  logo2.png</code></pre><p>То сперва из файла вырежется всё лишнее и он сам оптимизируется, а потом еще через pngquant будет создана палитра цветов, которые присутствуют в файле и по ним будет сверхкомпактная картинка, я картиночки некоторые с 12 килобайт до 670 байт упростил, без появления размытия и потери качества, просто там нет градиентов, есть только двухцветная картинка... С JPEG я еще разберсь позже, но он вроде изначально вполне хорошо жмется, только мета-информация и теги при использовании с камеры, но протой ресайз средствами PHP очень хорошо вырежет всё лишнее.</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ PHP Warning:  Error while sending QUERY packet. ]]></title>
        <link>https://tech-research.ru/php-warning-error-while-sending-query-packet/</link>
        <turbo:topic><![CDATA[ PHP Warning:  Error while sending QUERY packet. ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/php-warning-error-while-sending-query-packet/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-04-11T18:25:48 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Ошибка PHP Warning:  Error while sending QUERY packet, с таким я столкнулся, когда написал демона на PHP, который в самом начале подключается к базе, а потом ждет задачки из RabbitMQ и выполняет их на базе MariaDB.</p><p>Если у вас умирающий скрипт, который некоторое время подумает, а потом снова к базе обращается и может произойти отключение в этот момент, то нужно в my.cnf прибавить таймаут, например, сделать его пару минут</p><pre><code>wait_timeout = 120</code></pre><p>Но у меня таймаут может быть хоть триста дней, для этого я решил наоборот его убавить, чтобы отловить этот момент и да, если выполняю запросы к базе, то все отлично, отсчитываю 10 сек, снова выполняю и скрипт вылетает, т.к. соединение с базой уже отвалилось. Нужно тут уже сам скрипт подпиливать.</p><p>У меня свой класс для работы базы на mysqli, конечно, первым делом подумал о том, что можно проверку соединения делать в момент запроса, но не добавит ли нам это лишних затрат по времени, когда например надо 5 миллионов записей в базу залить, там даже индексы и те добавляют некоторую задержку и я сперва забивал базу данными, потом индексировал поля.</p><p>Лучшим решением будет проверка соединения в момент запуска функции, а функция моя чаще выполняет 2-3 запроса и делает это за доли секунды.</p><p>Итак, скрипт висит на фоне, висит так пару суток, тут к нему прилетает запрос от Rabbit, он запускает функцию обработки, которая некоторые данные цепляет из базы и тут перед выполнением наших запросиков надо бы проверить соединение и переподключиться...</p><pre><code>class DB {
	public $l, 
			$db_name, 
			$last_res, 
			$cnt = 0, 
			$debug=0, 
			$last_rows;
	private $c = []; //connect config

	public function connect(&amp;$c)
	{
		if (isset($c['socket']) &amp;&amp; !empty($c['socket'])) 
			@$this-&gt;l = new mysqli(NULL, $c['user'], $c['pass'], $c['db_name'], NULL, $c['socket']);
		 else 
			@$this-&gt;l = new mysqli($c['host'], $c['user'], $c['pass'], $c['db_name']);

		if ($this-&gt;l-&gt;connect_errno) 
		{
			http_response_code(503);
			exit("ERROR CONNECT DB");
		}
	}

	function __construct(&amp;$c) {
		$this-&gt;connect($c);
		$this-&gt;c = &amp;$c;
	}


	public function check_conn () 
	{
		if ($this-&gt;l-&gt;ping()===false) 
		{
			//проверим еще раз не переподключился ли он автоматом
		    if ($this-&gt;l-&gt;ping()===false)
		    	$this-&gt;connect($this-&gt;c);
		} 	
	}

//тут еще дофига методов, но я их не покажу
}</code></pre><p><code>$l</code> - это у нас переменная <code>$mysqli</code></p><p>Я дважды проверил через <code>$mysql-&gt;ping</code>, т.к. в некоторых ситуациях в момент выполнения этой функции происходит автоматический реконнект, по умолчанию оно отключено, и даже если включено, то mysqlnd игнорит...</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Паттерны проектирования ]]></title>
        <link>https://tech-research.ru/pattiern-proiektirovaniia/</link>
        <turbo:topic><![CDATA[ Паттерны проектирования ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/pattiern-proiektirovaniia/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-04-10T16:04:59 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Недавно я начал читать книжку по паттернам проектирования, это такие общеприняттые и проверенные временем архитектуры проектирования программ или их частей. Был немного удивлен тем, что я некоторое из этого уже давно использую, не догадываясь что у меня какой-то паттерн, просто на практике много раз код переписывал, придумывал как разделить логику, как лучше организовать гибкость и повторное использование кода.</p><p>Пока я читаю книгу, данная статья будет пополняться, не знаю на сколько долго я буду в этом разбираться, но даже для самого себя полезно как краткий конспект. </p><p>Книга называется Паттерны проектирования, автор Эрик Фримен, примеры там на JAVA, но мне они показались очень понятными, хоть я и веб-разработчик на PHP, но имел дело с Pascal, Delphi, C, LUA, Python и иногда внести правку в код программы на незнакомом языке достаточно просто, т.к. основы то везде одинаковые - условия, переменные, циклы, функции, ввод и вывод...</p><p>Шаблоны (паттерны) проектирования - это всего-лишь примеры лучших практик для решения каких-либо задачек, но нельзя описать оптимальное решение для всего абсолютно, ваш проект будет чем то смежным между несколькими паттернами в разных местах и добавлением своих хитростей. </p><hr><h3 id="-">Наблюдатель</h3><p>Такой паттерн примерно использовался в моей прошлой статье, когда я подписывался на очередь из RabbitMQ, я просто передавал ссылку на свою функцию в класс AMQP и когда сообщение приходило, то тот класс дергал мою функцию.</p><p>Главный класс, который управляет ситуацией, например курсы валют через него обновляются. И есть классы наблюдающие, например, у нас входные цены в баксах, а надо в рублях цену обновлять каждый день. И есть несколько таких классов, один в товарах обновляет, другой в XML выгружает. Классы наблюдатели сообщают "главному" классу что когда валюта поменяется - дерни меня, передавая ему например ссылку на свой метод. </p><p>Когда наблюдающие классы регистрируются в классе курса валют, то он их в некий массив складывает, потом, когда мы вызываем метод задания курса валюты, то этот класс по событию изменения курса по массиву обходит и дергает все классы, которые в нем зарегистрировались, т.е. подписались на событие изменение курса...  </p><hr><h3 id="--1">Декоратор</h3><p>Это какой-то замудренный паттерн, но я видел его применение во многих кодах на PHP, например в том же PHPExcel. И я тоже такое делаю иногда, просто не знал как это назвать.</p><p>Суть заключается в том, что один из классов передается в другой и тот использует его методы, потом этот еще дальше передается в новый класс, тот его использует методы, а методы второго используют из первого класса при этом, каждый раз вызывается функция, которая задействует метод родителя с таким же именем, это какая-то лютая рекурсия. Но в конечном итоге, результат формируется прохождением через цепочку методов, наверно так сложно понять, я попытался изобразить на PHP то что в книге на Java расписывалось.</p><pre><code>&lt;?php

//кофе
class Coffee
{
	public $parent_method;

	function __construct(&amp;$m=false)
	{
		$this-&gt;method = $m;
	}

	//у кофе есть цена
	public function calc()
	{
		return 100;
	}

	public function descr()
	{
		return "Кофеек";	
	}
}

//сахар
class Sugar
{
	public $parent_method;

	function __construct(&amp;$m=false)
	{
		$this-&gt;parent_method = $m;
	}

	//цена сахара + цена класса выше
	public function calc()
	{
		return 10+$this-&gt;parent_method-&gt;calc();
	}

	public function descr()
	{
		return $this-&gt;parent_method-&gt;descr().", Сахарок";	
	}
}

//молоко
class Milk
{
	public $parent_method;

	function __construct(&amp;$m=false)
	{
		$this-&gt;parent_method = $m;
	}

	//цена молока + цена класса выше

	public function calc()
	{
		return 20+$this-&gt;parent_method-&gt;calc();
		
	}


	public function descr()
	{
		return $this-&gt;parent_method-&gt;descr().", Молоко";	
	}
}


$napitok = new Coffee(); //создаем напиток кофе
$napitok = new Sugar($napitok); //добавляем в него сахар
$napitok = new Milk($napitok); //добавляем молоко

echo $napitok-&gt;descr().PHP_EOL; //выводим название получившейся смеси
echo "Цена напитка: ".$napitok-&gt;calc().PHP_EOL; //выводим цену</code></pre><p>Суть в том, что мы создали класс кофе, потом сахар и запихнули в него класс кофе, а потом это еще раз отправили в класс молоко, а потом из последнего класса вызвали функцию генерации описания и подсчета цены и у нас по цепочке вложенности всё выполнилось, результат вот такой (выполняю код в консольке)</p><pre><code>~ php decorator.php 
Кофеек, Сахарок, Молоко
Цена напитка: 130</code></pre><p>Прикол в том, что можно исключить строчку сахар</p><pre><code>//$napitok = new Sugar($napitok); //добавляем в него сахар</code></pre><p>И получим вот такой результат</p><pre><code>~ php decorator.php 
Кофеек, Молоко
Цена напитка: 120</code></pre><p></p><p>Этот пример достаточно абстрактный приведен, чтобы показать как можно перезадуйствовать в одном классе другой. Можно привести пример что вместо первого класса у нас будет класс для работы с базой, а второй для работы с данными и в такой цепочке можно первый класс не mysql, а mongodb подключить и следующий класс для работы с данными просто будет стандартные методы выполнять и не знать что у нас там за база, ну это тоже абстрактно очень, главное, чтобы вам было понятен такой фокус.</p><blockquote>Если бы мне предложили считать кофе в таком элементарном коде и сделать это методом декоратор, то я бы сделал вообще вот так! </blockquote><pre><code>&lt;?php


class Napitok
{
	public $parent_method,$description,$price;

	//конструктор, то что передается при создании класса
	function __construct(&amp;$m=false,$d,$p)
	{
		$this-&gt;parent_method = $m;
		$this-&gt;description = $d;
		$this-&gt;price = $p;
	}

	public function calc()
	{
		if ($this-&gt;parent_method===false) 
			return $this-&gt;price;
		else
			return $this-&gt;price+$this-&gt;parent_method-&gt;calc();
	}

	public function descr()
	{
		if ($this-&gt;parent_method===false) 
			return $this-&gt;description;
		else
			return $this-&gt;parent_method-&gt;descr().', '.$this-&gt;description;	
	}
}





$start = false; //переменная с экземпляром по ссылке передается, в первом классе нет родителя
$napitok = new Napitok($start,'Кофе',100);
$napitok = new Napitok($napitok,'Молоко',20);
$napitok = new Napitok($napitok,'Сахар',10);


echo $napitok-&gt;descr().PHP_EOL;
echo "Цена напитка: ".$napitok-&gt;calc().PHP_EOL;</code></pre><p>Я тут просто три класса создал с разными параметрами в конструторе и передал их также по цепочке один в другой...</p><hr><h3 id="--2">Фабрика и простая фабрика</h3><p>Многие путают простую фабрику с фабрикой, в этом мы попробуем сегодня разобраться...</p><p><strong>Простая фабрика</strong> выглядит примерно так</p><ol><li>Сперва некая простая фабрика</li></ol><pre><code>class SimpleFabrica 
{
	public function create_class($type)
	{
		if ($type===1) return new Class1;
		if ($type===2) return new Class1;
		...
	}


}</code></pre><p>2. Потом класс, который ее использует</p><pre><code>class Myclass
{
	protected $fabrica;

	function __construct($fabrica)
	{
		$this-&gt;fabrica = $fabrica;
	}


	public function prepare($type)
	{
		$newclass = $this-&gt;fabrica-&gt;create_class($type);
		$newclass-&gt;get();
		$newclass-&gt;prepare();
		return $newclass-&gt;get_result();
	}
}</code></pre><p>А потом попробуем всё это задействовать</p><pre><code>$fabrica = new SimpleFabrica;
$creator = new MyClass($fabrica);
$result = $creator-&gt;prepare(1);</code></pre><p>В общем суть этого подхода в том, что есть отдельный класс - фабрика (простая), который в зависимости от типа объекта (переменная <code>$type</code>) создает подходящий класс, а дальше выполняет с ним определенную последовательность. Допустим, нам надо получить страницу или файл, мы передаем типа ftp или http или webdav, у нас создается нужный класс для работы с этим делом и над ним проводятся манипуляции - получить, обработать, вернуть результат...</p><p>Но это всё "простая фабрика", это не является полноценной фабрикой, это лишь подход к созданию объектов, он очень часто используется и является помощником паттернов...</p><hr><h3 id="--3">Паттерн фабрика</h3><p>Паттерну фабрика отведено 60 страниц в книге "Паттерны проектирования" серии Head First, чтобы вникнуть в это более глубоко, советую всё же прочитать книгу, это одно из фундаментальных знаний...</p><p>Насколько я понял, паттерн фабрика позволяет метод создания экземпляра класса вытащить в подклассы, для начала сделаем вот так</p><pre><code>abstract class Myclass
{

	public function prepare($type)
	{
		$newclass = $this-&gt;create_class($type);
		$newclass-&gt;get();
		$newclass-&gt;prepare();
		return $newclass-&gt;get_result();
	}

	protected function create_class($type)
	{
		//это будет в субклассах
	}
}</code></pre><p>Вообще, изначально в базовом абстрактном классе мы не должны раскрывать create_class, а вот в субклассах определяем логику создания классов.</p><pre><code>class Subclass extends Myclass
{
      protected function create_class($type)
      {
        if ($type===1) return new Class1;
        if ($type===2) return new Class1;
        ...
      }
}</code></pre><p>Короче фабрика печет пирожки, где для каждого разного пирожка создается специальный повар, а вот какого именно повара привлечь к созданию - сам субкласс определит, создав экземпляр.</p><hr><h3 id="--4">Паттерн одиночка</h3><p>Этот паттерн создает экземпляр в единственном числе, если экземпляр объекта уже создан, то возвращается он, а не его копия, реализация данного механизма усложняется в многопоточном программировании, когда один поток создает, а второй обратился или оба обратились в один момент и для двоих создались разные экземпляры, в многопоточности для каждого языка программирования есть свои методы синхронизации событий. И поэтому, простая проверка на создание экземпляра превращается в некий отдельный механизм, который гарантирует 100% предотвращение дублирования. </p><p>Где нельзя дублировать? Ну есть такие вещи, типа монопольный доступ к файлу, контроль очередей или процессов, если к этому будет два разных объекта свою политику вести несогласованную не зная друг о друге, то будут лютые конфликты. </p><hr><h3 id="--5">Патерн команда</h3><p>В простом понимании - основной класс имеет метод execute(), запускающий определенное действие, а дочерние классы этот метод переопределяют, выполняя свои дела.</p><p>В более усложенной форме есть массив с командами, есть метод для задания на определенную команду определенного метода, при вызове нужной команды выполняется нужное действие. </p><p>Конкретной реализации не стану приводить, скажу что у вас есть массив команд с их названиями и в значениях массива вызов конкретного метода, будь то из этого же класса или же из другого или вообще анонимная функция.</p><hr><h3 id="--6">Паттерн Адаптер и декоратор</h3><p>Описывать подробную реализацию данных паттернов не буду, всё будет понятно и так... Представьте такой момент, когда вы провели массовый рефакторинг, выпилили кучу методов, добавили новые, переименовали другие методы более логично, ваш функционал оказался несовместимым с большей частью кода. Или, например, у вас была библиотека PHPExcel для чтения и генерации Excel-файлов, а потом разработчики решили закопать библиотеку и создали новую PhpSpreadsheet, но у вас так много импортеров из прайс-листов Excel и всяких генераторов Excel файлов с отчетами, накладными, товарными чеками и других документов, предположим, что новая библиотека имеет совсем другие методы для чтения и записи, для работы с оформлением ячеек, конечно, можем пройтись поиском по файлам, найти сотни или тысячи вызовов методов и переименовать их, более того, если в новых методах вместо передачи нескольких переменных нужно уже передавать одним массивом или порядок параметров функций поменялся, то это создает очень большую нагрузку на голову. А представьте что вам нужно в вашей системе поддерживать обратную совместимость со старыми модулями сторонних разработчиков. Тут и идет на помощь паттерн адаптер или фасад, создаем некое подобие старой библиотеки с методами и классами, но в этих методах ничего не делаем, просто вызываем методы новой библиотеки. </p><p>В книге написано так - декоратор преобразует один интерфейс к другому, а адаптер не меняет интерфейс, добавляет новые обязанности... К этому вопросу я еще вернусь.</p><h3 id="--7">Паттерн Фасад</h3><p>Этот паттерн помогает делать рутинные действия с другими методами, т.е. методы этого класса будут запускать сразу целую пачку методов другого класса.</p><h3 id="--8">Шаблонный метод</h3><p>В шаблонном методе идет схожий порядок действий, только некоторые из них переопределяются в конкретной реализации, например приготавливая чай и кофе мы наливаем кипяток, добавляем пакетик чая или ложечку кофе, дальше сахар, а дальше в кофе молоко, а в чай лимон, т.е. некоторые стадии в этом порядке меняются, но весь алгоритм очень похож. Поэтому, создается некий шаблон и определяются специфические действия в конкретной реализации.</p><p></p><p></p><p></p><p></p><p></p><p></p><p>Если у вас есть что добавить по паттерну фабрика - пишите в комментариях.</p><p></p><p>Статья будет пополняться, сперва я хотел писать статью под каждый паттерн отдельно, это было бы лучшим решением, т.к. больше страниц просмотрят, больше рекламы, но лучше собрать больше для себя конспект структурированный по всему, чем писать нелепый бред.</p><p></p><p></p><p> </p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Поиск по тексту в MySQL ]]></title>
        <link>https://tech-research.ru/optimizatsiia-poiska-po-slovu-v-mysql/</link>
        <turbo:topic><![CDATA[ Поиск по тексту в MySQL ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/optimizatsiia-poiska-po-slovu-v-mysql/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-04-10T13:44:49 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Недавно начались некоторые опыты с морфологией, чтобы их произвести и обкатать некоторые алгоритмы, пришлось воспользоваться словарем от OpenCorpora. В исходном виде табличка со словарем включает около 405 тысяч строк, в каждой из них информация по формам слова, его лемме, род, время, падеж, одушевленное или нет, всё это занимает около 489 мегабайт.</p><p>Мне понадобилось вытаскивать по конкретному слову его данные, для этого составил табличку такого типа</p><!--kg-card-begin: markdown--><table>
<thead>
<tr>
<th>id</th>
<th>lemma_id</th>
<th>word</th>
<th>gram</th>
<th>gram_descr</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>1</td>
<td>клавиатура</td>
<td>...</td>
<td>...</td>
</tr>
</tbody>
</table>
<!--kg-card-end: markdown--><p>В поле gram прописываются некие теги по данному слову, а gram_descr - описание этих тегов (это пока для тестирования и анализа первая штука).</p><p>Например вот так</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/04/image-46.png" class="kg-image" alt loading="lazy"></figure><p>Можно прибегнуть к системам полнотекстового поиска, может так и сделаю, но меня первым делом смущает работа по http некоторых таких систем, если надо будет 1000 запросов в секунду кидать, ну я их еще проверю, еще планирую потестировать всякие MongoDB.</p><p>У меня получилась таблица с более чем 2.2 миллионов строк, попробуем поискать по ней слово "клавиатура", для того, чтобы гарантированно без всяких кешей получать время запроса, будем добавлять после <strong>SELECT </strong>параметр <code>SQL_NO_CACHE</code>. Выполняю несколько раз и получаю минимальный результат...</p><p>Итак, поехали, попробуем получить клавиатура... Как видим, 2.4 сек, иногда до 3.4 доходило, это очень ужасно.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/04/image-47.png" class="kg-image" alt loading="lazy"></figure><p></p><p>Теперь попробуем по точному совпадению key=&gt;val. Ситуация особо не меняется, странно, но даже дольше выполняется, несколько раз перезапускал и оно только вот так, 2.5 сек, такой результат еще более ужасный.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/04/image-48.png" class="kg-image" alt loading="lazy"></figure><p>Теперь попробуем такую мощную штуку, как полнотекстовый поиск, для этого нужно добавить полнотекстовый индекс к полю word...</p><pre><code>ALTER TABLE `morph` ADD FULLTEXT(`word`);</code></pre><p>К слову, у меня этот индекс был уже изначально на момент тестирования, выполняем запрос</p><pre><code>SELECT SQL_NO_CACHE *  FROM `morph` WHERE MATCH(word) AGAINST('клавиатура')</code></pre><p>И о чудо, 0.0004 сек, вот такой результат более чем приличный</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/04/image-49.png" class="kg-image" alt loading="lazy"></figure><p>Но если мы будем искать всякие местоимения, частицы, союзы и другое в стиле - "за", "с", "а", "мы", "я"... И еще такие слова как ёж, уж, Ра.</p><p>В конфигурации my.cnf есть такой параметр, если нет, то по умолчанию стоит 4, все что короче - игнорнируется.</p><pre><code>ft_min_word_len = 4</code></pre><p> Тут видно, что предлог "за" есть в таблице..</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/04/image-50.png" class="kg-image" alt loading="lazy"></figure><p>Но так не сможет его найти, т.к. есть ограничение</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/04/image-52.png" class="kg-image" alt loading="lazy"></figure><p>Давайте попробуем снять это ограничение, пропишем в конфиг <code>[mysqld]</code></p><pre><code>ft_min_word_len = 1</code></pre><p>Ничего не выходит, наверно нельзя по одной или двум буквам искать, значит нам это не совсем подходит... Но мы можем например выделить все слова до 3х символов в отдельную таблицу и там будет искать их быстро обычными методами...</p><p>В любом случае, этот метод будет достаточно хорош для поиска по текстам на сайте, например по описаниям товаров, если особенно на обычном хостинге, где нет Sphinx, ElasticSearch и другого такого.</p><p>Определим сколько у нас максимальное по длине слово</p><pre><code>SELECT SQL_NO_CACHE *, char_length(word) as `l`  FROM `morph` ORDER BY `l` DESC</code></pre><p> Получим 35, слова такие конечно редкие, но мы должны предусмотреть максимальную базу данных</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/04/image-53.png" class="kg-image" alt loading="lazy"></figure><p>Попробуем тип поля сделать не text, а varchar 50, а потом поискать стандартным способом через like, ничего не поменялось...</p><p>Попробуем сравнение изменить на <code>utf8_bin</code></p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/04/image-54.png" class="kg-image" alt loading="lazy"></figure><p>С Like ситуация не поменялась, с полным WHERE тоже, но теперь появилась возможность сделать простой индекс не полнотекстовый для поля word</p><pre><code>ALTER TABLE `morph` ADD INDEX(`word`);</code></pre><p>После добавления индекса к полю, у меня стало искать за доли секунды</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/04/image-56.png" class="kg-image" alt loading="lazy"></figure><p>При таком раскладе, скорость получения данных по словам будет 2500 слов в секунду, не плохо... Правда сравнение utf8_bin накладывает некоторые ограничения, например нет регистронезависимого поиска, нужно при выборке и хранении понижать регистр, хотя тут вроде итак всё в нижнем регистре.</p><p>Попробуем поменять сравнение в поле на utf8_unicode_ci, и снова перестроить индекс может там не сильно будет потеря, да, MariaDB вполне справляется, то что пишут на форумах про ускорение в сравнении bin наверно уже устарело.</p><p>Теперь попробую еще одну идею, добавить в таблицу поле length и записать в него длину, сделаем его INT(2), ну максимум у нас все равно слово может быть 50 букв, хотя это там даже не слово, а какие то длинные названия. И сделаем поле индексированным.</p><p>Сделаем такой запрос для его заполнения</p><pre><code>UPDATE morph
SET morph.length = CHAR_length(morph.word)
</code></pre><p>А теперь попробуем поискать вот так</p><pre><code>SELECT SQL_NO_CACHE * 
FROM(SELECT  *  FROM morph WHERE length=1) as t
WHERE word='б'</code></pre><p>Нет, это не дало результата должного, уже нет такого критичного времени, которое может оптимизироваться, но идея заключалась в том, чтобы выбрать по индексированному полю с длиной строки, а потом из этого уже по слову искать.</p><blockquote><strong>Выводы:</strong> если нужна выборка по текстовому полю, например ЧПУ страницы сайта, то надо использовать поле <strong>varchar</strong> фиксированного размера и добавлять к нему индекс, как видите, с миллионами записей справляется идеально... Если же нужен поиск по текстам описаний (text) с вхождением слов, то лучше использовать полнотекстовый поиск, он достаточно быстрый.</blockquote><p></p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ PhpMyAdmin - первый день недели понедельник ]]></title>
        <link>https://tech-research.ru/phpmyadmin-piervyi-dien-niedieli-poniedielnik/</link>
        <turbo:topic><![CDATA[ PhpMyAdmin - первый день недели понедельник ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/phpmyadmin-piervyi-dien-niedieli-poniedielnik/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-04-09T13:17:51 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Некоторые пользователи задаются вопросом - как же сделать в PhpMyAdmin адекватное отображение дней недели в "датапикере", привычное для России?</p><p></p><p>По-умолчанию вот так, первый день недели воскресенье</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/04/---------09-04-2019-130611.png" class="kg-image" alt loading="lazy"></figure><p>А хочется вот так, чтобы был понедельник первым днем</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/04/image-45.png" class="kg-image" alt loading="lazy"></figure><p>Интересно как это поправить?</p><p>Для этого заходим в папку с нашим phpmyadmin (у меня это /usr/share/phpmyadmin), находим файл <code>js/functions.js</code></p><p>Там ищем вот такой участок</p><pre><code> PMA_addDatepicker($(this), type, {
                showMillisec: showMillisec,
                showMicrosec: showMicrosec,
                timeFormat: timeFormat
            });</code></pre><p>И приводим его к такому виду (добавим запятую после timeFormat и строчку <code>firstDay:1</code>)</p><pre><code> PMA_addDatepicker($(this), type, {
                showMillisec: showMillisec,
                showMicrosec: showMicrosec,
                timeFormat: timeFormat,
                firstDay:1
            });</code></pre> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Механизмы обмена между клиентом и сервером ]]></title>
        <link>https://tech-research.ru/miekhanizmy-obmiena-miezhdu-kliientom-i-siervierom/</link>
        <turbo:topic><![CDATA[ Механизмы обмена между клиентом и сервером ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/miekhanizmy-obmiena-miezhdu-kliientom-i-siervierom/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-04-09T11:11:02 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Допустим, нам надо написать бота для Вконтакта или мобильное или десктопное приложение, или же бота для Телеграмм, любое приложение, которое должно получать уведомления с сервера об обновлениях (поставили лайк, хотят добавить в друзья, пришло новое сообщение, обновились цены).</p><p>Я лишь рассмотрю некоторые из них...</p><ol><li>Просто отправлять на сервер запросы раз в секунду или 20 раз в секунду, смотря как критичны задержки, например долбить аяксом на свой сервер и если он ответил что-то, то обновлять информацию в приложении (например фронтенд сайта на стороне браузера).</li><li>Открыть сокет и слушать данные, но это не везде реализуемо легко, зависит от типа приложения...</li><li><strong>Веб хуки</strong> или <strong>CallbackAPI</strong>, это больше при обмене сервер-сервер, когда ваш сервер тоже может принимать запросы от основного, и если там что-то происходит - он вам отправляет данные и вы их обрабатываете, тут лучше применять механизм очередей, складывать быстро и отвечать ок, а потом на фоне обрабатывать.</li><li>Long Pooling (Long Pool api) - вы отправляете запрос и ждете, как только данные появляются, вам приходит ответ, об этом способе хотел рассказать сегодня в этой статье.</li></ol><h3 id="long-pooling">Long Pooling</h3><p>Итак, что же это такое Long Pooling? Как он работает? Попробуем в этом разобраться. Представьте такой момент когда вы открываете сайт, но у вас висит белый экран пустой, крутится кружочек, думает, думает, вот проходит уже 15 секунд, а он всё думает, а потом загрузился с ответом что ничего нового, ждали например 30 секунд.</p><p>Если данные появились раньше чем через 30 секунд, то сервер отдаст ответ как только так сразу, например через 0.2 секунды.</p><p>Как только мы получили ответ от сервера - снова отправляем запрос и ждем.</p><p>Что мы от этого имеем? Мы получаем новые данные по мере их поступления сразу, если новых событий достаточно мало, а у нас задержки критичные не больше секунды, то при первом способе мы бы отправляли 60 запросов в минуту, а так достаточно например только 2х.</p><p>В отличии от веб-хуков (способ 3) - нам не требуется какой-то сервер разворачивать и слушать с него запросы, мы можем находиться на сером ip, внутри локальной сети, не открывать порты в локалку с роутера.</p><p>Но если вы делаете сервер с поддержкой long pooling, вам нужно конкретно продумать и настройку самого сервера и ваших скриптов, наверно лучше организовать очереди и молниеносно выбрасывать список сообщений, а не долбить базу, не выполнять сложные обработки.</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ RabbitMQ установка и использование (Debian, Web, Php) ]]></title>
        <link>https://tech-research.ru/rabbitmq-php/</link>
        <turbo:topic><![CDATA[ RabbitMQ установка и использование (Debian, Web, Php) ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/rabbitmq-php/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-04-07T10:47:47 +0500</pubDate>
        <media:content url="https://tech-research.ru/content/images/2020/02/rabbitmq_logo.png" medium="image"/>
        <turbo:content><![CDATA[ <p>Сегодня мне понадобилось связать два скриптика на php-cli между собой.</p><p>Раньше я делал на том, что всегда знаю, т.е. использовал RAM-таблицы mysql для обмена между несколькими скриптами, но там слишком большая нагрузка начиналась, когда запрос несколько раз в секунду в базу кидал для получения новых сообщений, да и последнее время решил не использовать то что давно знаю, а постоянно что-то новое осваивать, что и вам советую.</p><p>Один скрипт работает и просит периодами второй что-то там обработать и тот ему отвечает, этот получает информацию... Очень удобно...</p><p>Ну стратегия использования у каждого будет своя, можно даже сверхбыстро входящие данные примнимать с сайта и потихоньку их разгребать отложенно из очереди. Некоторые люди используют RabbitMQ, чтобы статистику собирать с тысяч серверов своих, а другим скриптом в фоне тихонечко это раскладывать по полочкам, в итоге сервера при отправке статистики не ждут пока скрипт ее обработает, а просто кидают и не ждут пока эту информацию обработают и примут...</p><h3 id="-rabbitmq">Установка сервера RabbitMQ</h3><p>Первым делом ставим сам сервер, он у нас может находиться как на локальной машине, так и на общей машине в сети. Удобно если использовать единую точку обмена информацией между кучей серверов, где каждый может не ждать ответа, а просто кидать сообщения куда надо и заниматься дальше своими делами, периодами проверяя не ответил ли ему кто-то.</p><p>Установка RabbitMQ на сервер под Debian 9 происходит вот так</p><pre><code>apt-get install rabbitmq-server</code></pre><h3 id="-rabbitmq-1">Веб-интерфейс RabbitMQ</h3><p>Если вы желаете потренироваться, помониторить и посмотреть наглядно что у вас происходит на сервере, в RabbitMQ есть плагин, который предоставляет веб-интерфейс, очень крутая фича.</p><p>Веб-интерфейс в RabbitMQ включается следующим образом:</p><pre><code>rabbitmq-plugins enable rabbitmq_management</code></pre><p>После этого, можете зайти на свой сервер по порту 15672</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/04/image-43.png" class="kg-image" alt loading="lazy"></figure><h3 id="-rabbitmq-2">Создание пользователя в RabbitMQ</h3><p>Но, чтобы работать дальше с RabbitMQ, нам нужно создать пользователя, пусть он будет называться <code>userok</code> а пароль у него будет <code>pass123</code></p><p>Для добавления пользователя администратора, нам нужно ввести в консоли следующее</p><pre><code>rabbitmqctl add_user userok pass123
rabbitmqctl set_user_tags userok administrator
rabbitmqctl set_permissions -p / userok ".*" ".*" ".*"</code></pre><p>После этого можете заходить с этим логином и паролем в веб-интерфейс на порт <code>15672</code> тут можно и поиграться с очередями и посмотреть что получается в результате работы ваших приложений.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/04/image-44.png" class="kg-image" alt loading="lazy"></figure><p></p><h3 id="-">Работа с сообщениями</h3><p>На <a href="https://www.rabbitmq.com/devtools.html?ref=tech-research.ru">этой странице</a> вы найдете исчерпывающий список библиотек для реализации работы с RabbitMQ.</p><p>Нам же сегодня нужно придумать как применить это в проекте на php.</p><p>Cудя по описанию, <a href="http://pecl.php.net/package/amqp?ref=tech-research.ru">pecl amqp library</a> собрана на C-клиенте RabbitMQ</p><p>Исходники проекта и его описание с примерами использования <a href="https://github.com/pdezwart/php-amqp?ref=tech-research.ru">вот тут на гитхабе</a>.</p><p>Как я подумал, то что в репозитории Debian названо <code>php-amqp</code> - это оно и есть, попробуем его установить</p><pre><code>apt-get install php-amqp</code></pre><p></p><p>Дальше из официальных примеров можем составить примеры кода передающей и принимающей стороны, немного упрощаю... </p><p>Сохраним этот файл с именем <strong>send.php</strong></p><pre><code>&lt;?
//Establish connection to AMQP
$connection = new AMQPConnection();
$connection-&gt;setHost('127.0.0.1');
$connection-&gt;setLogin('userok');
$connection-&gt;setPassword('pass123');
$connection-&gt;connect();
//Create and declare channel
$channel = new AMQPChannel($connection);
//AMQPC Exchange is the publishing mechanism
$exchange = new AMQPExchange($channel);


//название цепочки
$routing_key = 'hello';


//это важно при отсутствии цепочки с именем hello
$queue = new AMQPQueue($channel);
$queue-&gt;setName($routing_key);
$queue-&gt;setFlags(AMQP_NOPARAM);
$queue-&gt;declareQueue();


//тут уже просто размещение сообщения
$message = 'test '.microtime();
$exchange-&gt;publish($message, $routing_key);

//а тут отключение
$connection-&gt;disconnect();
</code></pre><p>Тут нужно понимать, если мы по Long Pool будем данные собирать, то в цикле будет бесконечное получение обновлений c сервера  и раскидывание по цепочкам, клиент обновлений не будет тратить время на какой-то там анализ, он молниеносно раскидывает в цепочки и всё. Ну и логичным будет блок декларирования цепочки на всякий случай один раз в начале запускать, а дисконект где-то после цикла или его вообще тут не будет, т.к. скрипт сколько живет столько и будет общаться с RabbitMQ </p><blockquote>Long Pool - это что за зверь? Об этом будет отдельная статья...</blockquote><p></p><p>Дальше принимающий скрипт, примерно такой, создадим его с именем <strong>reseive.php</strong></p><pre><code>$connection = new AMQPConnection();
$connection-&gt;setHost('127.0.0.1');
$connection-&gt;setLogin('userok');
$connection-&gt;setPassword('pass123');
$connection-&gt;connect();
//Create and declare channel
$channel = new AMQPChannel($connection);
//AMQPC Exchange is the publishing mechanism
$exchange = new AMQPExchange($channel);
$callback_func = function(AMQPEnvelope $message, AMQPQueue $q) use (&amp;$max_consume) {
	echo PHP_EOL, "------------", PHP_EOL;
	echo " [x] Received ", $message-&gt;getBody(), PHP_EOL;
	echo PHP_EOL, "------------", PHP_EOL;
	$q-&gt;nack($message-&gt;getDeliveryTag());
	sleep(1);
	
};
try{
	$routing_key = 'hello';
	
	$queue = new AMQPQueue($channel);
	$queue-&gt;setName($routing_key);
	$queue-&gt;setFlags(AMQP_NOPARAM);
	$queue-&gt;declareQueue();
	echo ' [*] Waiting for messages. To exit press CTRL+C ', PHP_EOL;
	$queue-&gt;consume($callback_func);
}catch(AMQPQueueException $ex){
	print_r($ex);
}catch(Exception $ex){
	print_r($ex);
}
echo 'Close connection...', PHP_EOL;
$queue-&gt;cancel();
$connection-&gt;disconnect();</code></pre><p>Открываем два терминала, например по SSH на нашу виртуалку, на одном стартуем <code>php reseive.php</code>, он будет жить пока не нажмешь ctrl+c, теперь на втором будем запускать <code>php send.php</code> и смотреть на вывод первого, если всё работает, то сиесекундно при выполнении первого скрипта во втором будет сообщение, вот так работает доставка. Работает она быстро.</p><blockquote>Это всего лишь вводный курс, если вы захотите разобраться с этой технологией, то вам придется много экспериментировать, лучше если это будет на реальном проекте, желательно не на том, который по-работе, лучше по фану что-то делать.</blockquote><p>Вы можете почитать полную документацию на php.net, только она на данный момент кроме датского никакой язык не поддерживает, может быть руки дойдут, переведу, анализируя код, вот ссылка <a href="http://docs.php.net/manual/da/book.amqp.php?ref=tech-research.ru">http://docs.php.net/manual/da/book.amqp.php</a></p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Установка Samba на Debian ]]></title>
        <link>https://tech-research.ru/ustanovka-samba-na-debian/</link>
        <turbo:topic><![CDATA[ Установка Samba на Debian ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/ustanovka-samba-na-debian/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-04-05T12:36:51 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Samba - это сервер или клиент на линуксе, поддерживающий протокол SMB, проще говоря, сетевая папка Windows. Очень полезно для взаимодействия linux и windows. Например, в офисе стоит сервер с CRM и есть сетевой сканер, который результаты складывает в сетевую папку, логично эту сетевую папку разместить на сервере под управлением Linux, а не на клиентской машине, т.к. сервер включен всегда, а машины включаются/выключаются в зависимости от присутствия сотрудников. </p><p>Второй пример - у меня рабочий комп на Windows 10, но разработку я веду на Linux, который в виртуальной машине под Hyper-V, Debian из коробки подгружает модули Hyper-V, которые делают 10 гигабитную сеть между машинами и между хостом и гостевыми машинами, если расшарить сетевую папку из линукса в Windows, то можно работать через сетевую папку и отклик будет настолько быстрым, что скорость не будет отличаться от локальной папки, только вот приходится немного подкрутить параметры, чтобы достигнуть желаемого без всяких подтормаживаний...</p><ol><li>Ставим сервер Samba</li></ol><pre><code>apt-get install samba</code></pre><p>2. Создаем папку, которую будем шарить, например <code>project</code> создавать папку в корне - плохой тон, но мне пофиг, у меня временный сервак для всяких опытов и все файлы на одном разделе диска...</p><pre><code>mkdir /project</code></pre><p>3. Открываем наш конфиг </p><pre><code>nano /etc/samba/smb.conf</code></pre><p>И начинаем разбираться с параметрами, можно удалить всё содержимое и заменить вот таким, можно почитать описания, что то подправить....</p><pre><code>[global]
   interfaces = eth0
   bind interfaces only = yes
   deadtime = 15
   disable netbios = yes
   dns proxy = no
   domain master = yes
   encrypt passwords = true
   guest ok = no
   hosts allow = 192.168.200.0/255.255.255.0 127.0.0.1
   hosts deny = all
   invalid users = nobody root
   load printers = no
   max connections = 10
   netbios name = techresearch
   preferred master = yes
   preserve case = yes
   printable = no
   server string = Samba Share
   ; это невероятное шаманство, сильно ускоряет все операции
   socket options = TCP_NODELAY IPTOS_LOWDELAY SO_RCVBUF=131072 SO_SNDBUF=131072
   strict sync = no
   sync always = no
   syslog = 0
   workgroup = WORKGROUP
   log file = /dev/null
   log level = 0


[project]
   browseable = yes
   path = /project
   guest ok = no
   create mask = 0750
   writable = yes</code></pre><p>Обратите внимание на <strong>eth0</strong> - название интерфейса, это достаточно важный параметр, когда ваш сервер смотрит и в интернет и в локальную сеть, нужно разрешить только локальную сеть.</p><p>А второй параметр <strong>192.168.200.0</strong> - даже если у меня каким-то образом прокинется порт в локалку и запрос прилетит с маршрутизатора, то всё равно IP адрес не будет разрешенным.</p><p>4. Теперь надо добавить пользователя для подключения, прописать его пароль, обратите на параметр <code>-a</code>, он добавляет пользователя (локального) в samba и позволяет задать для него отличающийся от системного пароль</p><pre><code>smbpasswd -a user</code></pre><p>При изменении пароля делается всё тоже самое, только без параметра, если же захотите удалить пользователя, то флаг <code>-x</code>, для отключения <code>-d</code>, для обратного включения <code>-e</code>, узнать все параметры можно через <code>-h</code></p><p>Потом перезагрузим </p><pre><code>/etc/init.d/samba restart</code></pre><p>Дальше можно проверять, win+r, вводим ip машины</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/04/image-6.png" class="kg-image" alt loading="lazy"></figure><p>Вводим логин и пароль, если не хотите вводить пароль и логин, но сохранить пароль на папку - можно его в самбе сделать совпадающим с локальным на Windows, в ограниченных редакциях Windows не дает сохранить пароль, поэтому там только вот так решается</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/04/image-7.png" class="kg-image" alt loading="lazy"></figure><p>Как видим, всё работает</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/04/image-8.png" class="kg-image" alt loading="lazy"></figure><p>Не забудьте еще дать соответственные права на чтение/запись в папку, которую расшариваем...</p><blockquote>Хочу сказать, что алгоритм на других линуксах аналогичный, только там вместо apt-get будет yum или еще какой менеджер пакетов.</blockquote> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Склонение существительных после количества, или 101 товар / 2 товара / 8 товаров ]]></title>
        <link>https://tech-research.ru/sklonieniie/</link>
        <turbo:topic><![CDATA[ Склонение существительных после количества, или 101 товар / 2 товара / 8 товаров ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/sklonieniie/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-04-03T13:04:27 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Часто при создании интернет магазинов и в других местах, где нужно показать количество во множественном числе - нужно пойти на некоторые хитрости. Первое решение, самое простое, вывести слово перед числом и указать некую общую форму, например, <code>Товаров в корзине: 3</code>, или в скобках прописать <code>3 товара(ов)</code>, но мы то хотим сделать всё красиво, поэтому, разберемся в сути вопроса. Нам нужно понять как подставлять правильное окончание слов в зависимости от количества.</p><p>Статья несет больше образовательный характер, чтобы получить готовый алгоритм и не вдаваться в подробности - можете пролистать до конца. Если загуглить склонение существительных после поличества, то можно найти много готовых примеров кода на разных языках программирования - JavaScript, C, PHP, но если вникнуть в суть самого алгоритма, то вы его сможете написать на любом языке, хоть на паскале, поэтому, решил разобраться в этой теме...</p><p>Для начала попробуем просклонять несколько слов - Товар, Ящик, Зубочистка, Конфета</p><!--kg-card-begin: markdown--><table>
<thead>
<tr>
<th style="text-align:right">Количество\Слово</th>
<th style="text-align:left">Товар</th>
<th style="text-align:left">Ящик</th>
<th>Зубочистка</th>
<th>Конфета</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:right">0</td>
<td style="text-align:left">Товаров</td>
<td style="text-align:left">Ящиков</td>
<td>Зубочисток</td>
<td>Конфет</td>
</tr>
<tr>
<td style="text-align:right">1</td>
<td style="text-align:left">Товар</td>
<td style="text-align:left">Ящик</td>
<td>Зубочистка</td>
<td>Конфета</td>
</tr>
<tr>
<td style="text-align:right">2</td>
<td style="text-align:left">Товара</td>
<td style="text-align:left">Ящика</td>
<td>Зубочистки</td>
<td>Конфеты</td>
</tr>
<tr>
<td style="text-align:right">3</td>
<td style="text-align:left">Товара</td>
<td style="text-align:left">Ящика</td>
<td>Зубочистки</td>
<td>Конфеты</td>
</tr>
<tr>
<td style="text-align:right">4</td>
<td style="text-align:left">Товара</td>
<td style="text-align:left">Ящика</td>
<td>Зубочистки</td>
<td>Конфеты</td>
</tr>
<tr>
<td style="text-align:right">5</td>
<td style="text-align:left">Товаров</td>
<td style="text-align:left">Ящиков</td>
<td>Зубочисток</td>
<td>Конфет</td>
</tr>
<tr>
<td style="text-align:right">6</td>
<td style="text-align:left">Товаров</td>
<td style="text-align:left">Ящиков</td>
<td>Зубочисток</td>
<td>Конфет</td>
</tr>
<tr>
<td style="text-align:right">7</td>
<td style="text-align:left">Товаров</td>
<td style="text-align:left">Ящиков</td>
<td>Зубочисток</td>
<td>Конфет</td>
</tr>
<tr>
<td style="text-align:right">8</td>
<td style="text-align:left">Товаров</td>
<td style="text-align:left">Ящиков</td>
<td>Зубочисток</td>
<td>Конфет</td>
</tr>
<tr>
<td style="text-align:right">9</td>
<td style="text-align:left">Товаров</td>
<td style="text-align:left">Ящиков</td>
<td>Зубочисток</td>
<td>Конфет</td>
</tr>
<tr>
<td style="text-align:right">10</td>
<td style="text-align:left">Товаров</td>
<td style="text-align:left">Ящиков</td>
<td>Зубочисток</td>
<td>Конфет</td>
</tr>
</tbody>
</table>
<!--kg-card-end: markdown--><p>Попробуем упростить эту таблицу</p><!--kg-card-begin: markdown--><table>
<thead>
<tr>
<th style="text-align:right">Количество\Слово</th>
<th style="text-align:left">Товар</th>
<th style="text-align:left">Ящик</th>
<th>Зубочистка</th>
<th>Конфета</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:right">0, 5-10</td>
<td style="text-align:left">Товаров</td>
<td style="text-align:left">Ящиков</td>
<td>Зубочисток</td>
<td>Конфет</td>
</tr>
<tr>
<td style="text-align:right">1</td>
<td style="text-align:left">Товар</td>
<td style="text-align:left">Ящик</td>
<td>Зубочистка</td>
<td>Конфета</td>
</tr>
<tr>
<td style="text-align:right">2-4</td>
<td style="text-align:left">Товара</td>
<td style="text-align:left">Ящика</td>
<td>Зубочистки</td>
<td>Конфеты</td>
</tr>
</tbody>
</table>
<!--kg-card-end: markdown--><p>Т.е. мы имеем всего три формы слова, если в пределах от 0 до 9</p><ol><li>Для одного - именительный падеж (кто/что)</li><li>От 2х до 4х - родительный падеж (кого/чего)</li><li>От 5 до 9 и 0 - множественное число (много конфет, много ящиков, много товаров...)</li></ol><blockquote>но количество 0 нужно обратывать правильно, писать пусто или нет в корзине ничего или конфет сегодня не будет...</blockquote><p>Продолжим наше исследование на диапазоне от 11 до 30, теперь уже по одному слову...</p><!--kg-card-begin: markdown--><table>
<thead>
<tr>
<th>Число</th>
<th>Форма</th>
</tr>
</thead>
<tbody>
<tr>
<td>11</td>
<td>Товаров</td>
</tr>
<tr>
<td>12</td>
<td>Товаров</td>
</tr>
<tr>
<td>13</td>
<td>Товаров</td>
</tr>
<tr>
<td>14</td>
<td>Товаров</td>
</tr>
<tr>
<td>15</td>
<td>Товаров</td>
</tr>
<tr>
<td>16</td>
<td>Товаров</td>
</tr>
<tr>
<td>17</td>
<td>Товаров</td>
</tr>
<tr>
<td>18</td>
<td>Товаров</td>
</tr>
<tr>
<td>19</td>
<td>Товаров</td>
</tr>
<tr>
<td>20</td>
<td>Товаров</td>
</tr>
<tr>
<td>21</td>
<td>Товар</td>
</tr>
<tr>
<td>22</td>
<td>Товара</td>
</tr>
<tr>
<td>23</td>
<td>Товара</td>
</tr>
<tr>
<td>24</td>
<td>Товара</td>
</tr>
<tr>
<td>25</td>
<td>Товаров</td>
</tr>
<tr>
<td>26</td>
<td>Товаров</td>
</tr>
<tr>
<td>27</td>
<td>Товаров</td>
</tr>
<tr>
<td>28</td>
<td>Товаров</td>
</tr>
<tr>
<td>29</td>
<td>Товаров</td>
</tr>
<tr>
<td>30</td>
<td>Товаров</td>
</tr>
</tbody>
</table>
<!--kg-card-end: markdown--><p></p><p>С 11 до 19 ситуация не меняется, но вот если сравнить таблицу первую с 0 до 10 с таблицей от 20 до 30, то ситуация в точности повторяется, очень интересно!</p><p>А что за числа с 11 до 19, это числа с окончанием "надцать" (одинадцать, пятнадцать, девятнадцать).</p><p>Теперь можете перепроверить, но я уже проверил сам, с 0 до 100 ситуация повторяет в точности ситуацию с 0 до 10,  исключением из этого будет только  то, что заканчивается на "надцать". Я бы даже сказал что от 0 до 9, во всех числах берется последняя цифра и по ней решается какая форма слова будет.</p><p>А что дальше? Дальше подставляйте хоть 1000, хоть миллион, ситуация повторится, решающими будут две последние цифры, если число заканчивается на 11-19 и во всех остальных случаях одна последняя цифра.</p><p>Какой алгоритм получится в результате?</p><ol><li>Отсекаем две последние цифры от числа, проверяем не находится ли это в диапазоне от 11 до 19, если так, то отдаем множественное число (п3).</li><li>Отсекаем еще раз от этого одну последнюю цифру - если 1, то отдаем именительный падеж (п1)</li><li>Если это цифра от 2 до 4, то отдаем родительный падеж.</li><li>Во всех остальных случаях множественное число.</li></ol><p>В некоторых алгоритмах просят вводить три формы слова, где-то 1,3,5, а где-то 1,2,4 или 1,2,7, но это сути не меняет, мы будем входными параметрами в функции использовать количество 1 (яблоко),2 (яблока),5 (яблок).</p><p>Пример на моем любимом PHP</p><p>$n - количество</p><p>$f1 = яблоко</p><p>$f2 = яблока</p><p>$f5 = яблок</p><pre><code>public static function num_morph($n, $f1, $f2, $f5) 
	{
	    $n = (abs($n) % 100); //отсекаем две последние цифры от цисла
	    
		//если это от 11 до 19, вернем множ. число
	    if ($n&gt;=11 &amp;&amp; $n&lt;=19) return $f5; 

	    $n1= $n % 10; //отсекаем от этого последнюю цифру

        //единственное число                     
	    if ($n1==1) return $f1;
		
        //родительный падеж
	    if ($n1&gt;1 &amp;&amp; $n1&lt;5) return $f2;
        
        //во всех остальных случаях множественное число
	    return $f5;
	}</code></pre><p>Если остались вопросы - задавайте в комментариях...</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Локализация блога Ghost ]]></title>
        <link>https://tech-research.ru/lokalizatsiia-blogha-ghost/</link>
        <turbo:topic><![CDATA[ Локализация блога Ghost ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/lokalizatsiia-blogha-ghost/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-04-02T09:44:53 +0500</pubDate>
        <media:content url="https://tech-research.ru/content/images/2020/02/ghost.png" medium="image"/>
        <turbo:content><![CDATA[ <p>Локализация состоит из 3х частей</p><ol><li>Внешняя часть</li><li>Админка</li><li>Системная часть</li></ol><h3 id="-">Внешняя часть</h3><p>Внешняя его часть легко локализуется при помощи правки шаблона - сперва скачиваем в админке шаблон, потом переименовываем полученный zip, обратно загружаем, получаем новую папку в content/templates, правим шаблоны, перезагружаем блог, радуемся. Но некоторые части мне не удалось найти в шаблоне, видимо они подгружаются из системы.</p><h3 id="--1">Админка</h3><p>Мне лично не мешает то что все надписи на английском, всё интуитивно понятно, но вот не все ведут блоги единолично, кто-то является компанией, где куча редакторов, некоторые из которых не могут быстро адаптироваться в этом интерфейсе...</p><p>Сколько не грепал готовый сайт - не смог найти нигде в локализациях строчки из админки, они жестко забиты в js приложение админки, можно просто открыть js приложение</p><pre><code>nano /core/built/assets/ghost.min-*.js</code></pre><p>Искать нужные строчки из админки и заменять на свои.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/04/image-2.png" class="kg-image" alt loading="lazy"></figure><p>Делать это руками не по-админски, поэтому, напишем такой скриптик для начала</p><pre><code>#!/bin/bash
F=$1

re ()
{
sed -i -re "s|${1}|${2}|g" "${F}"
}

re "Title &amp; description" "Заголовок и описание"</code></pre><p>Сохраним его с именем <code>rus_admin.sh</code> сделаем на него флаг исполнения </p><pre><code>chmod +x rus_admin.sh</code></pre><p>Ну и попробуем выполнить (внимание, путь до вашего ghost уникальный, может не совпадать с моим, завивит от сборки, поэтому смотрите что там).</p><p><strong>Еще перед выполнением сделайте бекап файлика, вдруг чего поломается...</strong></p><pre><code>bash ./rus_admin.sh ghost.min-a8ab0ab912a793319197ba23bc890afd.js</code></pre><p>Потом я перезапустил ghost и увидел вот такое</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/04/image-3.png" class="kg-image" alt loading="lazy"></figure><p>Т.е. работает...</p><blockquote>Идем дальше, добавим замену строк на всю админку, только будьте аккуратны, если будем делать замену по словам delete или другим односложным строкам из одного слова, есть великая вероятность наткнуться на замену самого кода или переименовать саму функцию,  я руководствуюсь тем, что в названиях функций нет пробелов и заменяемые строки достаточно длинные (2-3 слова через пробел)</blockquote><p>У меня получился вот такой скрипт</p><pre><code>#!/bin/bash
F=$1

re ()
{
str='s|"'${1}'"|"'${2}'"|g'
echo $str
sed -i -re "${str}" "${F}"
}
resub ()
{
sed -i -re "s|${1}|${2}|g" "${F}"
}
re "View site" "Просмотр сайта"
re "Manage" "Управление"
re "Posts" "Публикации"
re "Pages" "Страницы"
re "Your posts" "Публикации"
re "Your pages" "Страницы"
re "Staff" "Пользователи"
re "All posts" "Все публикации"
re "All pages" "Все страницы"
re "Draft posts" "Черновики"
re "Published posts" "Опубликованные"
re "Published pages" "Опубликованные"
re "Scheduled posts" "Запланированные"
re "Scheduled pages" "Запланированные"
re "Featured posts" "Особые публикации"
re "Featured pages" "Особые страницы"
re "Search authors" "Поиск по авторам"
re "Search tags" "Поиск по тегам"
resub 'Sort by:' 'Сортировка:'
re "Newest" "Новее"
re "Oldest" "Старее"
re "Recently updated" "Недавние изменения"
re "All authors" "Все авторы"
re "All tags" "Все теги"
re "You haven[\]'t created any pages yet!" "У вас нет страниц."
re "Create a new page" "Создать страницу"
re "New page" "Новая страница"
re "New post" "Новая публикация"
re "Staff users" "Пользователи"
re "Invite people" "Пригласить"
re "Active users" "Активные"
re "Suspended users" "Отключенные"
#re "Owner" "Владелец"
#re "Author" "Автор"
re "Invite a New User" "Пригласить"
re "Save" "Сохранить"
re "Saved" "Сохранено"



re "Settings" "Настройки"
re "General" "Основные"
re "Design" "Дизайн"
re "Tags" "Теги"
re "Code injection" "Внедрение кода"
re "Save settings" "Сохранить настройки"
re "Title &amp; description" "Заголовок и описание"
re "The details used to identify your publication around the web" "Подробности, идентифицирующие ваши публикации в интернете"
re "The name of your site" "Название сайта"
re "Used in your theme, meta data and search results" "Описание, используется в вашей теме, мета-данных и результатах поиска"
re "Site timezone" "Часовой пояс сайта"
re "Set the time and date of your publication, used for all published posts" "Задает время и дату ваших публикаций"
re "Publication Language" "Язык публикаций"
re "Upload Image" "Загрузить картинку"
re "Publication icon" "Иконка публикаций"
re "Publication logo" "Логотип публикаций"
re "Publication cover" "Фон публикаций"
re "Expand" "Раскрыть"
re "Close" "Закрыть"
re "The local time here is currently " "Текущее локальное время "
re "Integrations" "Интеграции"
resub "Ghost allows you to inject code into the top and bottom of your theme files without editing them. This allows for quick modifications to insert useful things like tracking codes and meta tags." "Ghost поддерживает внедрение кода в раздел head и в нижнюю часть страницы. Это позволяет вставлять всякие счетчики, аналитики, скрипты и собственные мета-теги"</code></pre><p>Но в конце концов я понял такую вещь - не всё получится вот так просто локализовать, надо брать исходник админки с шаблонами из github и собирать самостоятельно... Малость удалось насобирать, но не всё... Ибо компилированный файл содержит структуру тегов в виде массивов с такой сложной вложенностью, а в исходниках файлов это всё более понятно...</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/04/image-4.png" class="kg-image" alt loading="lazy"></figure><p>Если кому-то нужна локализованная админка - напишите комментарий, я попробую пересобрать из исходников всё это дело...</p><p>Эта локализация действует и на приложение Ghost для компа</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/04/image-5.png" class="kg-image" alt loading="lazy"></figure><p></p><h2 id="-ghost-">Сборка Ghost из исходников для локализации админки и системной части.</h2><pre><code>sudo apt-get update &amp;&amp; sudo apt-get install yarn</code></pre><pre><code>yarn global add knex-migrator grunt-cli ember-cli bower</code></pre><pre><code>git clone --recurse-submodules https://github.com/TryGhost/Ghost.git
cd Ghost
</code></pre><p>Заходим в /core/client/app/templates, правим шаблончики</p><p>Потом компилим систему</p><pre><code>yarn setup</code></pre><p>Потом собираем prod версию</p><pre><code>grunt prod</code></pre><p>Теперь можно хватать js админки и закидывать в свой сайт...</p><p>Более подробно об этом написано на Github, если есть какие-либо вопросы - обращайтесь, разберемся вместе.</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Установка NodeJS на Debian 9 ]]></title>
        <link>https://tech-research.ru/ustanovka-nodejs-na-debian/</link>
        <turbo:topic><![CDATA[ Установка NodeJS на Debian 9 ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/ustanovka-nodejs-na-debian/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-04-02T02:51:52 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <pre><code>su</code></pre><pre><code>curl -sL https://deb.nodesource.com/setup_10.x | bash -</code></pre><pre><code>apt-get install nodejs
</code></pre><p>Теперь у нас есть npm и node, можно ставить всякие gulp, cleancss и другие полезности...</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Время жизни сессии phpmyadmin, как  увеличить? ]]></title>
        <link>https://tech-research.ru/vriemia-siessii-phpmyadmin/</link>
        <turbo:topic><![CDATA[ Время жизни сессии phpmyadmin, как  увеличить? ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/vriemia-siessii-phpmyadmin/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-03-28T00:59:39 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>На продакте лучше так не делать, да и вообще лучше там не делать phpmyadmin, а вот на dev-сервере часто, очень часто приходится залезать в phpmyadmin, то это, то другое исправить, да и доступен он только из локалки, иногда так раздражает, когда ушел покушать, вернулся опять к работе, или пока пилил код, а потом зашел и снова вводить пароль, это сильно уменьшает производительность при частых обращениях к базе mysql, когда скрипт пилишь и на втором экране смотришь какие там у тебя таблицы с какими полями, тестируешь запросики перед изменением в скриптах. Нам нужно изменить время сессии, увеличив некоторые значения по-умолчанию.</p><p>Вот, инструкция на этот случай!</p><ol><li>Заходим в папку с phpmyadmin, находим там файлик <code>config.sample.inc.php</code> копируем его в <code>config.inc.php</code>, открываем, находим строчку типа <code>$cfg['blowfish_secret']</code> и вставляем ниже нее</li></ol><pre><code>$cfg['blowfish_secret'] = 'fhkghgkgkjhgkgklas'; 
$cfg['LoginCookieValidity'] = 7*24*60*60;</code></pre><p>это определит время сессии на семь дней, вполне достаточно, чтобы каждый день не переавторизовываться...</p><p>Но тут не всё, сам php тоже имеет такой параметр в php.ini, как  <code>session.gc_maxlifetime</code> поставим его на 604800 (7 дней)</p><pre><code>; After this number of seconds, stored data will be seen as 'garbage' and
; cleaned up by the garbage collection process.
; http://php.net/session.gc-maxlifetime
session.gc_maxlifetime = 604800</code></pre><p>Перезапустим apache, если у нас модуль или fpm, там уже зависит от вашей конфигурации.</p><p>Вот и всё, спасибо за внимание. Если вам интересно как установить phpmyadmin не из пакета Debian, а самостоятельно, то кидайте свои вопросы в комментарии, напишу для вас инструкцию.</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ MySQL ошибка out of sync ]]></title>
        <link>https://tech-research.ru/mysql/</link>
        <turbo:topic><![CDATA[ MySQL ошибка out of sync ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/mysql/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-03-26T21:35:56 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <blockquote>Commands out of sync; you can't run this command now</blockquote><p>Вот такую ошибку я встретил сегодня в <code>mysql</code>, когда решил отключить буферизацию, в MYSQL и PHP есть такой механизм работы с базой данных</p><p><code>MYSQLI_STORE_RESULT</code> и <code>MYSQLI_STORE_RESULT</code></p><p>В первом варианте получает весь результат в некий буфер и дает с ним работать, во втором варианте получает как-то построчно без буфера, экономит память, но имеет ряд недостатков.</p><p>Во-первых, нельзя получить <code>SQl_CALC_FOUND_ROWS</code></p><p>Во-вторых, как сегодня выяснилось - пока все строки из результата не выгрузил, нельзя выполнять еще один запрос. Но как вариант, можно создать второй экземпляр mysqli и пока из первого проходим записи - вторым писать.</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ MySQL отключение кеширования ]]></title>
        <link>https://tech-research.ru/mysql-otkliuchieniie-kieshirovaniia/</link>
        <turbo:topic><![CDATA[ MySQL отключение кеширования ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/mysql-otkliuchieniie-kieshirovaniia/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-03-25T23:32:17 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>На DEV сервере часто занимаюсь оптимизацией запросов и меня не устраивает тот момент, что первый раз выполняю запрос и у меня например 90ms, а при повторе 50ms, потом может то быстрее то медленнее, в общем, у нас сервер MySQL кеширует запросы для ускорения повторных выборок.</p><p>Для решения этой ситуации, вводящей в заблуждение, я отключаю кеширование в mysql.</p><p>Чтобы проверить состояние текущих настроек - можно или в phpmyadmin зайти в раздел переменные и там через ctrl+f поискать нужное среди кучи вариантов, либо же ввести запрос</p><pre><code>SHOW VARIABLES LIKE "query_cache%"</code></pre><p>Поставим query_cache_size на 0 и query_cache_limit тоже</p><pre><code>SET GLOBAL query_cache_size=0;
SET GLOBAL query_cache_limit=0;</code></pre><p>Но после перезапуска сервера это вернется обратно, тут или вот так выключать каждый раз, ну а можно прописать эти параметры в <code>my.cnf</code></p><pre><code>query_cache_limit = 0
query_cache_size = 0</code></pre><p>Но в последних версиях, уже вроде бы в 5.7 кеш по умолчанию выключен, поэтому там еще и <code>query_cache_type=OFF</code> на рабочем сервере при достаточном объеме оперативки лучше включить данным методом... А вот на MariaDB кеширование включено, вероятно что в некоторых дистрибутивах mysql сервер будет со своими конфигами, поэтому выключение кеша актуально.</p><p>Еще один момент, если вам просто нужно обкатать некоторые запросы и оптимизировать их по времени, то можно просто добавить после SELECT <code>SQL_NO_CACHE</code>, но когда у вас движок и вы не вникая в запросы хотите посмотреть на каких страницах какое время генерации и только потом залезать в запросы, то выключение кеша через настройки БД будет лучшим решением, конечно, на продакшн такое не делайте...</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Sublime text 3 - минификация (сжатие) статики CSS и JS ]]></title>
        <link>https://tech-research.ru/sublime-text-3-minifikatsiia-statiki/</link>
        <turbo:topic><![CDATA[ Sublime text 3 - минификация (сжатие) статики CSS и JS ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/sublime-text-3-minifikatsiia-statiki/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-03-19T06:12:54 +0500</pubDate>
        <media:content url="" medium="image"/>
        <turbo:content><![CDATA[ <p>Хотелось бы редактировать сразу в локальной папке на сайте полные копии файлов CSS и javascript (JS), и при сохранении пересохранять их минифицированную версию в файле min.css или min.js, без всяких дополнительных сборщиков проектов? Тогда это для вас.</p><p>Итак, у нас есть sublime text, так уж повелось, мне проще вести разработку прямо в текстовом редакторе без всяких продвинутых средств разработки, иногда это конечно же вообще прямо по ssh делается на хостинге, когда в руках есть мобилка с ssh клиентом и вдруг обнаружилась недоработка в коде... Да и по цене sublime достаточно недорогой, я его приобрел еще до подорожания курса доллара, но сейчас речь не о том.</p><p>У нас SublimeText3 и Windows10,  первым делом ставим пакет, сперва устанавливаем Package Control (он нам еще пригодится), оригинальная инструкция вот тут <a href="https://packagecontrol.io/installation?ref=tech-research.ru">https://packagecontrol.io/installation</a> </p><ol><li>На клавиатуре <code>CTRL</code>+` </li><li>Вбиваем вот этот кусок и жмем энтер</li></ol><pre><code>import urllib.request,os,hashlib; h = '6f4c264a24d933ce70df5dedcf1dcaee' + 'ebe013ee18cced0ef93d5f746d80ef60'; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler()) ); by = urllib.request.urlopen( 'http://packagecontrol.io/' + pf.replace(' ', '%20')).read(); dh = hashlib.sha256(by).hexdigest(); print('Error validating download (got %s instead of %s), please try manual install' % (dh, h)) if dh != h else open(os.path.join( ipp, pf), 'wb' ).write(by) </code></pre><p>3. Жмем комбинацию на клавиатуре <code>ctrl+shift+P</code>  и там вбиваем Install, выбираем <code>Install package</code></p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/03/image-2.png" class="kg-image" alt loading="lazy"></figure><p>4. В открывшемся окне ищем <code>Minify</code></p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/03/image-3.png" class="kg-image" alt loading="lazy"></figure><p>5. После установки перед нами откроется документашка, в ней пример конфига и вообще описание установки недостающих инструментов из npm.</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/03/image-4.png" class="kg-image" alt loading="lazy"></figure><p>Документацию советую почитать, там написано что есть два режима - минификация и, так сказать, форматирование (Beautify) к красифому виду, чуть позже рассмотрим форматер и для PHP, удобная штука, которая расставит все отступы и весь код в читаемый вид превратит... Но это уже в следующей статье.</p><p>6. Теперь устанавливаем node.js, в которой куча инструментов для форматирования css, js, html... Зайдем на сайт <a href="https://nodejs.org/en/?ref=tech-research.ru">https://nodejs.org/en/</a> и скачаем последнюю версию nodejs</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/03/image-5.png" class="kg-image" alt loading="lazy"></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2019/03/image-6.png" class="kg-image" alt loading="lazy"><figcaption>процесс установки NodeJS</figcaption></figure><p>7. Теперь откроем терминал (можно PowerShell) и введем следующее</p><pre><code>npm install -g clean-css-cli uglifycss js-beautify html-minifier uglify-js minjson svgo</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2019/03/image-7.png" class="kg-image" alt loading="lazy"><figcaption>Установка пакетов NodeJS в NPM</figcaption></figure><p>8. Теперь остается настроить конфиг нашего плагина</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/03/image-8.png" class="kg-image" alt loading="lazy"></figure><p>заходим в меню <code>prefences</code> -&gt; <code>package settings</code> -&gt; <code>minify</code> -&gt; <code>Settings User</code></p><p>там вбиваем вот такой текст, полный дефольтный конфиг по тому же пути можно найти, только Default, оттуда только те элементы, которые переопределеяются копируем</p><pre><code>{
              "open_file": false,
              "auto_minify_on_save": true,
              "allowed_file_types": [
                  "css",
                  "js"
              ]
}
    
</code></pre><p>Можно еще добавить, например, JSON, но мне и так достаточно, я вообще оставил только css и js. </p><hr><blockquote>Но при попытке минифицировать файл вылетает ошибка! И css и json вылетает ошибка!!!</blockquote><blockquote><code>File AppData\Roaming\Sublime Text 3\Packages\Minify\Minify.py", line 65, in handle_resultsublime.error_message(' '.join(cmd) + '\r\n\r\n' + output.decode('utf-8'))UnicodeDecodeError: 'utf-8' codec can't decode byte 0xad in position 11: invalid start byte</code></blockquote><p>В общем,<strong> надо перезапустить саму программу SublimeText</strong>, я целый час дебажил эту фигню, пытался понять в чем дело, даже некоторые основы на питоне познал, а оказалось что просто переменные окружения не подгрузились для выполнения утилит...</p><p>P.S. кстати, форматтер этот, где beautify - может превращать минифицированный файл обратно в удобочитаемый, удобно, когда надо подправить чужой проектик, который уже собран и минифицирован, а исходных файлов нет.</p> ]]></turbo:content>
    </item>
    <item turbo="true">
        <title><![CDATA[ Блог на Ghost ]]></title>
        <link>https://tech-research.ru/blog-ghost/</link>
        <turbo:topic><![CDATA[ Блог на Ghost ]]></turbo:topic>
        <turbo:source>https://tech-research.ru/blog-ghost/</turbo:source>
        <author><![CDATA[  ]]></author>
        <pubDate>2019-03-17T23:25:50 +0500</pubDate>
        <media:content url="https://tech-research.ru/content/images/2019/03/---------17-03-2019-224731.png" medium="image"/>
        <turbo:content><![CDATA[ <p>Данная статья будет длиннопостом, решил не плодить кучу статей о Ghost, а в одну скидать всё, что потребуется...</p><h3 id="-">Как запустить?</h3><p>Чтобы завести свой блог на Ghost - первым делом понадобится хостинг, можно конечно и на их сайте прикрутить свой домен и платить абонентку, но иногда купить дешевую VPS будет проще, а если на DigitalOcean, то там вообще есть готовые виртуалки. </p><p>Но сегодня речь пойдет о том, как настроить на своем сервере, ну или не совсем на своем или не совсем на сервере, у кого-то есть корпоративный сервер, работающий 24/7, а кому то можно просто старый ноутбук или неттоп повесить рядом с роутером в коридоре и всё настроить. Еще в будущем рассмотрим такой вариант, как выгрузка всего блога в формате html для размещения на github (бесплатно) или на слабом компьютере типа Raspberry Pi или умный роутер с флешкой может сгодиться, в случае со статическим блогом не надо nodejs,php,mysql, ничего не надо, только любой веб-сервер и ftp/sftp чтобы грузить блог со своего компа. Ну сегодня не об этом, опять я отвлекся.</p><p>В общем, нам нужен docker и nginx, сам nginx у меня стоит без контейнера, он проксирует все контейнеры, разные сайты на разных технологиях устроены, иногда нужны разные версии ПО для разных проектов, уже имел опыт поломки зависимостей пакетов, когда вся система рухнула, поэтому сейчас контейнеризирую. О том, как установить docker можно почитать на официальном сайте.</p><h2 id="--1">Установка самого блога в контейнер</h2><p>В общем, создаем папку для нашего блога, там будет храниться весь контент, при переезде можете разворачивать контейнер и контент перенести с базой.</p><pre><code>mkdir /var/www/mysite
</code></pre><p> После этого создадим конфиг</p><pre><code>nano /var/www/mysite/config.json</code></pre><p>И впишем конфиг, тут всё уже предрешено, вам только url поменять надо на свой, все остальные пути это внутренние пути в контейнере</p><pre><code>{
  "url": "http://tipa-mysite.ru",
  "server": {
    "port": 2368,
    "host": "0.0.0.0"
  },
  "database": {
    "client": "sqlite3",
    "connection": {
      "filename": "/var/lib/ghost/content/data/ghost.db"
    }
  },
  "mail": {
    "transport": "Direct"
  },
  "logging": {
    "transports": [
      "file",
      "stdout"
    ]
  },
  "process": "systemd",
  "paths": {
    "contentPath": "/var/lib/ghost/content"
  }
}</code></pre><p>Дальше просто создадим контейнер, который будет доступен на порту 3001</p><pre><code>docker run -d \
--restart=always \
--name tipa-mysite.ru \
-p 3001:2368 \
-v /var/www/mysite/content:/var/lib/ghost/content \
-v /var/www/mysite/config.json:/var/lib/ghost/config.production.json \
ghost</code></pre><p>Если будет проксироваться с nginx из этого же компа, то ограничим на локалхост, чтобы извне только было по 80/443 на nginx доступно, а сам контейнер недоступен будет</p><pre><code>docker run -d \
--restart=always \
--name tipa-mysite.ru \
-p 127.0.0.1:3001:2368 \
-v /var/www/tech-research.ru/content:/var/lib/ghost/content \
-v /var/www/mysite/config.json:/var/lib/ghost/config.production.json \
ghost</code></pre><p>Теперь открываем URL <strong> tipa-mysite.ru/ghost</strong> там регистрируем нашего первого пользователя, пишем site title это не для пользователя, а для сайта, оно будет вот внизу писаться</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/03/------------1.png" class="kg-image" alt loading="lazy"></figure><p>При регистрации еще можно создать других редакторов этого блога.</p><p></p><h3 id="-https-">Правильная настройка https (с костылями)</h3><p>Добавить https достаточно просто, если у вас установлен nginx и certbot от letsencrypt, но вот сам движок нужно донастроить, иначе у вас все sitemap будут по-старому на http, а это плохо для СЕО.</p><p>Достаточно в конфиге <code>config.json</code> изменить url на https, но дальше происходит нечто невероятное - блог начинает сам по себе редиректить на https с https, ведь наш nginx по 3001 порту обращается и без шифрования, а контейнер думает что надо бы перенаправить на https и сайт вылетает с бесконечным цикличным редиректом, чтобы это исправить - надо в nginx прописать заголовок <code>X-Forwarded-Proto</code> равным <code>https</code>, чтобы движок думал что итак всё норм и мы на протоколе https.</p><p>  вот так:</p><pre><code> location /
        {
        access_log off;
        proxy_pass http://127.0.0.1:3001;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https; # эта строка фиксит редирект
        proxy_set_header Nginx-Https "on";
        proxy_connect_timeout 2s;
        }</code></pre><p>Решение костыльное, но пойдет, позже разберемся и в этой теме</p><h3 id="--2">Подсветка кода</h3><p>Для того, чтобы списать код, нужно три косых кавычки вбить (```) и пробел или enter</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/05/------------5.png" class="kg-image" alt loading="lazy"></figure><p>Но чтобы подсвечивался код, вам нужно или изначально выбрать тему типа как у меня, где всё это есть, либо использовать casper, тогда нужно зайти в админку, там Code injection</p><p>В шапку кидаем</p><pre><code>&lt;link rel="stylesheet"
      href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/styles/monokai-sublime.min.css"&gt;
&lt;script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/highlight.min.js"&gt;&lt;/script&gt;</code></pre><p>А в футер</p><pre><code>&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt;</code></pre><p>Вроде получилось...</p><p>Вместо <code>monokai-sublime.min.css</code> можно вписать другой стиль, подробнее можете посмотреть тут демку <a href="https://highlightjs.org/?ref=tech-research.ru">https://highlightjs.org/</a>, главное писать ссылки на файлы min.css, меняя <strong>monokai-sublime </strong>на понравившийся стиль</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2020/05/------------6.png" class="kg-image" alt loading="lazy"><figcaption>Стиль solarized-light</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2020/05/------------7.png" class="kg-image" alt loading="lazy"><figcaption>Стиль railscasts</figcaption></figure><h3 id="-ghost">Добавление комментариев в блог Ghost</h3><p>Сегодня поговорим о том, как вставить комментарии на блог Ghost, будем использовать сервис комментариев Disqus. Вообще, статья может пригодиться для таких сайтов, как wix, blogger, wordpress, joomla и других, пусть эта статья будет о том, как добавить комментарии Discus на популярные движки сайтов, но на примере блога на Ghost.</p><ol><li>Заходим на сайт <a href="https://disqus.com/?ref=tech-research.ru">https://disqus.com/</a></li><li>Если не авторизованы, то авторизуемся, скорей всего у вас уже есть учетная запись, через которую вы комментировали другие сайты.</li></ol><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/03/------------4.png" class="kg-image" alt loading="lazy"></figure><p>заходим через твиттер, фейсбук или гугл</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/03/------------5.png" class="kg-image" alt loading="lazy"></figure><p>3. Дальше в самом низу жмем <strong>Install disqus</strong></p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/03/------------6.png" class="kg-image" alt loading="lazy"></figure><p></p><p>4. Тут выбираем I want to install Disqus on my site (я хочу установить Discus на мой сайт).</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/03/------------7.png" class="kg-image" alt loading="lazy"></figure><p>5. Заполняем форму, вписываем название сайта, выбираем категорию, язык, жмем кнопочку Create site</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/03/------------8.png" class="kg-image" alt loading="lazy"></figure><p>6. На следующем этапе у нас выбор тарифа, ну выбираем пока Basic, т.к. он бесплатный, а мы еще даже 9 долларов в месяц не зарабатываем на своем новом блоге. Тут еще есть Free, но в нем написано что для сайтов где нет рекламы и вообще полностью некоммерческие. Позже еще подумаем, может быть хватит средств на оплату Plus...</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/03/------------9.png" class="kg-image" alt loading="lazy"></figure><p>7. На следующем этапе выбираем движок, у нас это Ghost</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/03/------------10.png" class="kg-image" alt loading="lazy"></figure><p>8. Теперь у нас есть инструкция и код для вставки, тут написано что в папке шаблона надо найти файл post.hbs (<code>yourghostdir/content/themes/casper/</code>) и в нем вписать перед закрывающимся {{/post}} код (где-то внутри), я вставил код перед &lt;/article&gt;</p><p>Нужно перезагрузить блог или же просто выбрать другую тему, а потом снова основную.</p><p>Получаем то, что теперь видно внизу данной статьи, прошу прощения за рекламу, я постарался засунуть ее в конце статей, чтобы вас это отвлекало только после полного прочтения и перед комментированием.</p><p></p><h3 id="-ghost-">Облако тегов в Ghost блоге</h3><p>Итак, открываем файл шаблона <code>default.hbs</code>, в нем перед открывающимся тегом <code>&lt;footer&gt;</code> вставим для начала такой код</p><pre><code>{{#get "tags" limit="all"}}
  {{#foreach tags}}
    &lt;a href="{{url}}"&gt;{{name}}&lt;/a&gt;
  {{/foreach}}
{{/get}}</code></pre><p> В результате получим вот такой выхлоп перед футером</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/03/image-9.png" class="kg-image" alt loading="lazy"></figure><p>Как видим, вывело абсолютно все теги, которые есть на сайте, теперь попробуем стилизовать это всё.</p><ol><li>Обернем это всё в div class="tag_list"</li><li>Добавим заголовок, чтобы было понятно что это такое, но т.к. это у нас не столь заголовок статьи/содержимого, сколько просто поясняющий элемент, мы не будм его оборачивать тегами &lt;h1&gt; - &lt;h6&gt;, а закинем в тег &lt;span class="header_bl"&gt; и стилизуем</li><li>Сами теги закинем в список &lt;ul&gt;/&lt;li&gt; и тоже стилизуем, поехали...</li></ol><p>Сам код у нас будет выглядеть вот так</p><pre><code>&lt;div class="tag_list"&gt;
   &lt;div class="inner"&gt;
       &lt;span class="header_bl"&gt;Список тегов&lt;/span&gt;
		&lt;ul&gt;

{{#get "tags" limit="all"}}

  {{#foreach tags}}
    &lt;li&gt;&lt;a href="{{url}}"&gt;{{name}}&lt;/a&gt;&lt;/li&gt;
  {{/foreach}}
{{/get}}

		&lt;/ul&gt;

	&lt;/div&gt;
&lt;/div&gt;</code></pre><p>Выхлоп получился вот таким (кстати, чтобы увидеть изменения - надо перезапустить Ghost или же просто через админку выбрать другой шаблон и снова свой).</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/03/image-11.png" class="kg-image" alt loading="lazy"></figure><p>Теперь будем стилизовать этот блок, по идее, исходник нашего screen.css находится в папке темы в папке <code>assets/css</code> но действующий файл (минимизированный) находится в <code>assets/built/</code> самое простое решение будет просто подправить уже в папке built, как пересобрать тему, мы рассмотрим (вероятно) позднее, сейчас просто добавим свой стиль css в Ghost для собственных доработок шаблонов...</p><p>Допишем в <code>default.hbs</code> в раздел head, сразу после <code>screen.css</code> свой <code>custom.css</code> </p><pre><code>    {{!-- Styles'n'Scripts --}}
    &lt;link rel="stylesheet" type="text/css" href="{{asset "built/screen.css"}}" /&gt;
    &lt;link rel="stylesheet" type="text/css" href="{{asset "css/custom.css"}}" /&gt;</code></pre><p>Дальше создадим /assets/css/custom.css и впишем в него следущие строчки для стилизации</p><pre><code>.tag_list {
border-top: 1px solid #d9d9d9;
padding: 10px;
background:#fff;
}

.header_bl {
font-size:15px;
font-weight:bold;
text-transform:uppercase; 
}


.tag_list ul {
padding:5px 0; 
}

.tag_list ul li {
display:inline-block;
margin: 4px;
padding:0;
}

.tag_list ul li a {
display: inline-block;
background: #fbfbfb;
box-shadow: 0 0 3px #d0d0d0;
border: 1px solid #d0d0d0;
padding: 3px 5px;
font-size: 13px;
border-radius:4px;
color:#777;
}

.tag_list ul li a:hover
{
text-decoration:none;
box-shadow: none;
color:#666;
}</code></pre><p>В результате вот такое получается</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2019/03/image-12.png" class="kg-image" alt loading="lazy"></figure><p></p><p>Стили и верстка не претендуют на звание эталонной, я больше по бэкэнду специализируюсь, статья носит ознакомительный характер, вы можете стилизовать свой блог индивидуально.</p><p></p><p></p><h3 id="-ghost-casper">Дополнительные теги в статье в блоге Ghost, тема Casper</h3><p>В некоторых сторонних темах дополнительные теги выводятся сразу, но в Casper, только один главный тег и больше ничего, это тоже можно поправить...</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2020/05/------------8.png" class="kg-image" alt loading="lazy"><figcaption>Вот так показывает</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech-research.ru/content/images/2020/05/------------9.png" class="kg-image" alt loading="lazy"><figcaption>а хочется вот так</figcaption></figure><p>В <a href="https://docs.ghost.org/api/handlebars-themes/helpers/tags/?ref=tech-research.ru">документации на Ghost</a> есть описание этих моментов.</p><p>В общем так, заходим в папку нашего шаблона, открываем файл post.hbs</p><p>и перед строчкой</p><pre><code>&lt;h1 class="post-full-title"&gt;{{title}}&lt;/h1&gt;</code></pre><p>прописываем</p><pre><code>{{tags from="2" separator=" | " prefix="Дополнительные теги: "}}</code></pre><p><code>from="2"</code> - означает что нужно вывести тег, начиная со второго,</p><p><code>separator=" | "</code> - означает что между тегами нужно поставить такой символ и плюс от него пробелы слева и справа,</p><p>а <code>prefix</code> - дает указание в начале всего этого перечисления указать такой текст.</p><p>В итоге, у нас получится вот такой код</p><pre><code>...

&lt;header class="post-full-header"&gt;
                &lt;section class="post-full-meta"&gt;
                    &lt;time class="post-full-meta-date" datetime="{{date format="YYYY-MM-DD"}}"&gt;{{date format="D MMMM Y$

                    {{#primary_tag}}
                        &lt;span class="date-divider"&gt;/&lt;/span&gt; &lt;a href="{{url}}"&gt;{{name}}&lt;/a&gt;
                    {{/primary_tag}}

                &lt;/section&gt;

                {{tags from="2" separator=" | " prefix="Дополнительные теги: "}}





                &lt;h1 class="post-full-title"&gt;{{title}}&lt;/h1&gt;
            &lt;/header&gt;
    
...</code></pre><p></p><p></p><h3 id="-ghost-1">Турбо-страницы Яндекс на блоге Ghost </h3><p>Либо турбо страницы, либо свой кастомный RSS</p><p>В общем, алгоритм такой</p><ol><li>Открываем файл settings/routes.yaml</li><li>Приводим его примерно к такому виду (после routes: добавить три своих строчки)</li></ol><pre><code>routes:
  /turbo-rss/:
    template: turbo-rss
    content_type: text/xml

collections:
  /:
    permalink: /{slug}/
    template: index

taxonomies:
  tag: /tag/{slug}/
  author: /author/{slug}/</code></pre><p>3. В корне шаблона создаем файл turbo-rss.hbs</p><pre><code>&lt;?xml version = "1.0" encoding = "UTF-8"?&gt;
&lt;rss
  xmlns:yandex="http://news.yandex.ru"
  xmlns:media="http://search.yahoo.com/mrss/"
  xmlns:turbo="http://turbo.yandex.ru"
  version="2.0"&gt;
&lt;channel&gt;
&lt;title&gt;&lt;![CDATA[ {{@blog.title}} ]]&gt;&lt;/title&gt;
&lt;description&gt;&lt;![CDATA[ {{@blog.description}} ]]&gt;&lt;/description&gt;
&lt;link&gt;{{@blog.url}}&lt;/link&gt;
&lt;language&gt;ru&lt;/language&gt;
&lt;image&gt;
    &lt;url&gt;{{@blog.url}}/favicon.png&lt;/url&gt;
    &lt;title&gt;{{@blog.title}}&lt;/title&gt;
    &lt;link&gt;{{@blog.url}}&lt;/link&gt;
&lt;/image&gt;
&lt;lastBuildDate&gt;{{date format="YYYY-MM-DDTHH:mm:ss ZZ"}}&lt;/lastBuildDate&gt;

{{#get "posts" filter="tags:-[en]" limit="all"}}
    {{#foreach posts}}
    &lt;item turbo="true"&gt;
        &lt;title&gt;&lt;![CDATA[ {{title}} ]]&gt;&lt;/title&gt;
        &lt;link&gt;{{url absolute="true"}}&lt;/link&gt;
        &lt;turbo:topic&gt;&lt;![CDATA[ {{title}} ]]&gt;&lt;/turbo:topic&gt;
        &lt;turbo:source&gt;{{url absolute="true"}}&lt;/turbo:source&gt;
        &lt;author&gt;&lt;![CDATA[ {{author.name}} ]]&gt;&lt;/author&gt;
        &lt;pubDate&gt;{{date format="YYYY-MM-DDTHH:mm:ss ZZ"}}&lt;/pubDate&gt;
        &lt;media:content url="{{feature_image}}" medium="image"/&gt;
        &lt;turbo:content&gt;&lt;![CDATA[ {{content}} ]]&gt;&lt;/turbo:content&gt;
    &lt;/item&gt;
    {{/foreach}}
{{/get}}

&lt;/channel&gt;
&lt;/rss&gt;</code></pre><p>4. Рестарт Ghost, чтобы изменения вступили в силу.</p><p>Пример для турбо RSS взят вот у этого хорошего человека на <a href="https://github.com/chimai/Casper/blob/master/turbo-ru.hbs?ref=tech-research.ru">GitHub</a>, но его формат даты имеет привязку к локали, я поменял на более интернациональный формат даты...</p><p><a href="https://yandex.ru/dev/turbo/doc/rss/markup-docpage/?ref=tech-research.ru">Тут пример разметки RSS для турбо от Яндекса</a></p><p>После подключения в вебмастере можно увидеть примеры своих статей...</p><figure class="kg-card kg-image-card"><img src="https://tech-research.ru/content/images/2020/02/------------21.png" class="kg-image" alt loading="lazy"></figure><p>(c) картинка взята с сайта Yandex.ru</p><p></p><p>Продолжение следует...</p> ]]></turbo:content>
    </item>

</channel>
</rss>
