<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Posts | norre</title><link>https://www.norre.org/ru/post/</link><atom:link href="https://www.norre.org/ru/post/index.xml" rel="self" type="application/rss+xml"/><description>Posts</description><generator>Source Themes Academic (https://sourcethemes.com/academic/)</generator><language>ru</language><copyright>no rights reserved, 2020</copyright><image><url>https://www.norre.org/img/carrot.jpg</url><title>Posts</title><link>https://www.norre.org/ru/post/</link></image><item><title>Pixies - Gouge Away | ru</title><link>https://www.norre.org/ru/post/2020/video/pixies_gouge_away/</link><pubDate>Sun, 05 Jul 2020 21:14:00 +0800</pubDate><guid>https://www.norre.org/ru/post/2020/video/pixies_gouge_away/</guid><description>
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
&lt;iframe src="https://www.youtube.com/embed/7aSbf406xaw" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" allowfullscreen title="YouTube Video">&lt;/iframe>
&lt;/div></description></item><item><title>129 Die In Jet | ru</title><link>https://www.norre.org/ru/post/2020/129_die_in_jet/</link><pubDate>Sun, 05 Jul 2020 19:59:00 +0800</pubDate><guid>https://www.norre.org/ru/post/2020/129_die_in_jet/</guid><description>&lt;p>&lt;img src="https://gallery.norre.org/images/2020/01/30/IMG_2751.jpg" alt="1">&lt;/p></description></item><item><title>Ansible For Devops, осуждение</title><link>https://www.norre.org/ru/post/2020/ansible-for-devops/</link><pubDate>Sun, 01 Mar 2020 23:43:00 +0800</pubDate><guid>https://www.norre.org/ru/post/2020/ansible-for-devops/</guid><description>&lt;p>Взял тут книгу по Ansible, непонятное в ней начинается с первых же страниц:&lt;/p>
&lt;ol>
&lt;li>Clear - Ansible uses a simple syntax (YAML) and is easy for anyone
(developers, sysadmins, managers) to understand. APIs are simple and
sensible.&lt;/li>
&lt;/ol>
&lt;p>Угу, если не принимать во внимание indentation и сложность (и неоднозначность)
синтаксиса YAML.&lt;/p>
&lt;ol>
&lt;li>Fast - Fast to learn, fast to set up—especially considering you don’t need to
install extra agents or daemons on all your servers!&lt;/li>
&lt;/ol>
&lt;p>Ага, если не учитывать довольно значительное количество значений по умолчанию,
которые совершенно не очевидны, если не заглядывать в документацию. Кстати,
хорошая оговорка про то, что fast в значении fast to learn/set up (что не вполне
верно), но не в значении fast to execute. Исполняются же плейбуки жутко
медленно.&lt;/p>
&lt;ol>
&lt;li>Complete - Ansible does three things in one, and does them very well.&lt;/li>
&lt;/ol>
&lt;p>Ну да, если не учитывать тот факт, что всякий раз, когда мне надо что-то
автоматизировать, мне приходится колхозить либо дополнительные скрипты, либо api
вызовы непосредственно из Ansible. Не то, что бы это была беда самого ансибля,
конечно, но.&lt;/p>
&lt;ol>
&lt;li>Efficient - No extra software on your servers means more resources for your
applications. Also, since Ansible modules work via JSON, Ansible is
extensible with modules written in a programming language you already know.&lt;/li>
&lt;/ol>
&lt;p>В целом, наверное, правда. &amp;lsquo;Efficient&amp;rsquo; as in &amp;lsquo;clientless&amp;rsquo;.&lt;/p>
&lt;ol>
&lt;li>Secure - Ansible uses SSH, and requires no extra open ports or potentially -
vulnerable daemons on your servers.&lt;/li>
&lt;/ol>
&lt;p>Ну в целом тоже, наверное, правда. Но ставить в заслугу продукту то, что он
работает через безопасный транспорт как-то, не знаю, слишком уж по-хипстерски.&lt;/p>
&lt;p>Дальше идет пример с модулем &lt;code>ping&lt;/code>.&lt;/p>
&lt;blockquote>
&lt;p>&lt;code>ansible example -m ping -u [username]&lt;/code>&lt;/p>
&lt;/blockquote>
&lt;p>И поясняется:&lt;/p>
&lt;blockquote>
&lt;p>If everything worked, you should see a message that shows &lt;code>www.example.com | success &amp;gt;&amp;gt;&lt;/code>, then the result of your ping.&lt;/p>
&lt;/blockquote>
&lt;p>Это довольно типичный, кстати, пример, который в целом хорошо иллюстрирует то,
что мне не нравится в ансибле:&lt;/p>
&lt;ol>
&lt;li>Нигде не упоминается, что это не &lt;code>icmp ping&lt;/code>. Я знаю, что в актуальной
документации специально оговаривается, что ребята, это не &lt;code>icmp&lt;/code>, если хотите
&lt;code>icmp&lt;/code> то делайте &lt;code>net_ping&lt;/code> и проч и проч НО: проблема в том, что этот самый
&lt;code>ping&lt;/code> не надо было называть в точности так же, как и самую распространенную
утилиту диагностики сетевого уровня. Это плохой дизайн, хреновая идея, это
запутывает. Еще один пример корневого плохого дизайна это стандартная пара
ключей &lt;code>src&lt;/code> / &lt;code>dest&lt;/code>, которая используется в множестве модулей Ansible.
Присмотритесь: не &lt;code>src&lt;/code> / &lt;code>dst&lt;/code>, но &lt;code>src&lt;/code> / &lt;code>dest&lt;/code>. Никогда так не делайте.&lt;/li>
&lt;li>Нигде (в этом конкретном примере в книге) не упоминается, как эта команда
работает и что она действительно делает. Это в целом тоже часть философии
Ansible - под капот нужно заглядывать только тогда, когда это действительно
необходимо (по мнению архитекторов Ansible). Это, конечно, неправильно.&lt;/li>
&lt;/ol>
&lt;p>В официальной документации Ansible все не лучше. Практически каждый модуль
документирован так, что приходится лезть в код, чтобы разобраться, что именно
происходит и как именно надо этот модуль использовать. Как-то излишне стремно
для продукта, который собственно создан для YAML-программистов, которые не
должны знать ничего кроме ямла.&lt;/p>
&lt;p>При этом сам продукт довольно полезный и в целом, если забить на некоторые
оговорки, неплохой - в своей нише и для своих целей. Использую его постоянно, в
целом успешно и эффективно (поздняя редакция - потихоньку ухожу в сторону
Nornir). Но осадочек присутствует, да.&lt;/p>
&lt;h2 id="ссылки">Ссылки&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://www.ansiblefordevops.com/">https://www.ansiblefordevops.com/&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Threnos: On Thorns I Lay</title><link>https://www.norre.org/ru/post/2020/threnos_on_thorns_i_lay/</link><pubDate>Sun, 01 Mar 2020 22:28:00 +0800</pubDate><guid>https://www.norre.org/ru/post/2020/threnos_on_thorns_i_lay/</guid><description>
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
&lt;iframe src="https://www.youtube.com/embed/oy9F5phgbNs" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" allowfullscreen title="YouTube Video">&lt;/iframe>
&lt;/div>
&lt;!-- raw HTML omitted --></description></item><item><title>Сооружения</title><link>https://www.norre.org/ru/post/2020/structures/</link><pubDate>Tue, 25 Feb 2020 11:09:00 +0800</pubDate><guid>https://www.norre.org/ru/post/2020/structures/</guid><description>&lt;p>
&lt;a href="https://gallery.norre.org/album/ovu" target="_blank" rel="noopener">&lt;img src="https://gallery.norre.org/images/2020/01/30/IMG_6372.jpg" alt="IMG_6372.jpg">&lt;/a>&lt;/p></description></item><item><title>Неожиданное открытие</title><link>https://www.norre.org/ru/post/2020/til/</link><pubDate>Mon, 24 Feb 2020 14:03:00 +0800</pubDate><guid>https://www.norre.org/ru/post/2020/til/</guid><description>&lt;p>Сегодня я выяснил, что в &lt;code>evil-mode&lt;/code> есть поддержка &lt;code>surround.vim&lt;/code>. Дальше, лениво
копирую документацию (см. ссылки ниже).&lt;/p>
&lt;p>It&amp;rsquo;s easiest to explain with examples. Press &lt;code>cs&amp;quot;'&lt;/code> inside&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">&amp;#34;Hello world!&amp;#34;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>to change it to&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">&amp;#39;Hello world!&amp;#39;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now press &lt;code>cs'&amp;lt;q&amp;gt;&lt;/code> to change it to&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">&amp;lt;q&amp;gt;Hello world!&amp;lt;/q&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>To go full circle, press &lt;code>cst&amp;quot;&lt;/code> to get&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">&amp;#34;Hello world!&amp;#34;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>To remove the delimiters entirely, press &lt;code>ds&amp;quot;&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">Hello world!
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now with the cursor on &amp;ldquo;Hello&amp;rdquo;, press &lt;code>ysiw]&lt;/code> (&lt;code>iw&lt;/code> is a text object).&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">[Hello] world!
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Let&amp;rsquo;s make that braces and add some space (use &lt;code>}&lt;/code> instead of &lt;code>{&lt;/code> for no space): &lt;code>cs]{&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">{ Hello } world!
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now wrap the entire line in parentheses with &lt;code>yssb&lt;/code> or &lt;code>yss)&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">({ Hello } world!)
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Revert to the original text: &lt;code>ds{ds)&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">Hello world!
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Emphasize hello: &lt;code>ysiw&amp;lt;em&amp;gt;&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">&amp;lt;em&amp;gt;Hello&amp;lt;/em&amp;gt; world!
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Finally, let&amp;rsquo;s try out visual mode. Press a capital &lt;code>V&lt;/code> (for linewise visual mode) followed by &lt;code>S&amp;lt;p class&lt;/code>&amp;quot;important&amp;quot;&amp;gt;=.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">&amp;lt;p class=&amp;#34;important&amp;#34;&amp;gt;
&amp;lt;em&amp;gt;Hello&amp;lt;/em&amp;gt; world!
&amp;lt;/p&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="ссылки">Ссылки&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://github.com/tpope/vim-surround">https://github.com/tpope/vim-surround&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>TextFSM - Изменение стейта</title><link>https://www.norre.org/ru/post/2020/textfsm/text_fsm/</link><pubDate>Mon, 24 Feb 2020 13:39:00 +0800</pubDate><guid>https://www.norre.org/ru/post/2020/textfsm/text_fsm/</guid><description>&lt;h2 id="что">Что?&lt;/h2>
&lt;p>&lt;code>TextFSM&lt;/code> это питоновский модуль для парсинга (плохо) форматированного текста.
Изначально был спроектирован для парсинга вывода cli разных устройств - в
частности, сетевых.&lt;/p>
&lt;p>В &lt;code>TextFSM&lt;/code> существует три важных сущности: &lt;code>ввод&lt;/code>, &lt;code>список правил&lt;/code> и &lt;code>вывод&lt;/code>.&lt;/p>
&lt;p>Вывод cli я буду называть &lt;code>ввод&lt;/code> (хе-хе) - потому что это та информация, которую
нам нужно распарсить. Этот вывод мы скармливаем машине конечных автоматов
&lt;code>TextFSM&lt;/code>, которая обрабатывает (парсит) его в соответствии со &lt;code>списком правил&lt;/code>.
Получившийся текст уходит в &lt;code>вывод&lt;/code>.&lt;/p>
&lt;h2 id="как">Как?&lt;/h2>
&lt;p>&lt;code>TextFSM&lt;/code> это final state machine - машина конечных автоматов. В простейшем
случае, в &lt;code>TextFSM&lt;/code> есть два состояния: &lt;code>Start&lt;/code> (обязательно должно присутствовать в
файле шаблона) и &lt;code>EOF&lt;/code> - implicit (подразумеваемое) состояние, переход на которое
происходит когда мы прочитали весь файл.&lt;/p>
&lt;p>Алгоритм &lt;code>FSM&lt;/code> примерно такой:&lt;/p>
&lt;ol>
&lt;li>&lt;code>FSM&lt;/code> читает строчку из &lt;code>ввода&lt;/code>;&lt;/li>
&lt;li>&lt;code>FSM&lt;/code> проверяет, матчится ли эта строчка с правилами из &lt;code>списка правил&lt;/code>. Список
правил для каждой строчки из &lt;code>ввода&lt;/code> проверяется сверху вниз, с первой строки
списка правил;&lt;/li>
&lt;li>Если строчка матчится одной из строчек &lt;code>списка правил&lt;/code>, FSM выполняет действие
и переходит к следующей строчке &lt;code>ввода&lt;/code>, снова ее сверяя со &lt;code>списком правил&lt;/code>,
начиная с первой строчки списка. Также, в этом шаге могут заполняться
значения переменных.&lt;/li>
&lt;/ol>
&lt;p>Подробнее про алгоритм &lt;code>FSM&lt;/code>, действия и правила можно почитать в документации
(см. Ссылки)&lt;/p>
&lt;h2 id="зачем">Зачем?&lt;/h2>
&lt;p>Если у нас простой вывод с повторяющимися значенями, то можно использовать один
стейт, наполняя строчку значениями отматченных переменных. Если вывод менее
структурирован, то, вероятнее всего, придется использовать дополнительные стейты.&lt;/p>
&lt;h2 id="fsm-с-одним-состоянием--не-считая-eof">FSM с одним состоянием (не считая EOF)&lt;/h2>
&lt;p>Одного стейта достаточно, когда &lt;code>ввод&lt;/code> однозначно определяет разделитель между
строчками &lt;code>вывода&lt;/code>, как, например, тут:&lt;/p>
&lt;p>[ &lt;code>Ввод&lt;/code> ]&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-c" data-lang="c">Server group radius
Sharecount &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span> sg_unconfigured &lt;span style="color:#f92672">=&lt;/span> FALSE
Type &lt;span style="color:#f92672">=&lt;/span> standard Memlocks &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
Server(&lt;span style="color:#ae81ff">10.14.121.20&lt;/span>&lt;span style="color:#f92672">:&lt;/span>&lt;span style="color:#ae81ff">1814&lt;/span>,&lt;span style="color:#ae81ff">1815&lt;/span>) Transactions:
Authen: &lt;span style="color:#ae81ff">6&lt;/span> Author: &lt;span style="color:#ae81ff">0&lt;/span> Acct: &lt;span style="color:#ae81ff">0&lt;/span>
Server_auto_test_enabled: FALSE
Keywrap enabled: FALSE
Server(&lt;span style="color:#ae81ff">10.3.121.20&lt;/span>&lt;span style="color:#f92672">:&lt;/span>&lt;span style="color:#ae81ff">1814&lt;/span>,&lt;span style="color:#ae81ff">1815&lt;/span>) Transactions:
Authen: &lt;span style="color:#ae81ff">3&lt;/span> Author: &lt;span style="color:#ae81ff">33&lt;/span> Acct: &lt;span style="color:#ae81ff">333&lt;/span>
Server_auto_test_enabled: FALSE
Keywrap enabled: FALSE
Server(&lt;span style="color:#ae81ff">10.4.12.26&lt;/span>&lt;span style="color:#f92672">:&lt;/span>&lt;span style="color:#ae81ff">1814&lt;/span>,&lt;span style="color:#ae81ff">1815&lt;/span>) Transactions:
Authen: &lt;span style="color:#ae81ff">4&lt;/span> Author: &lt;span style="color:#ae81ff">0&lt;/span> Acct: &lt;span style="color:#ae81ff">0&lt;/span>
Server_auto_test_enabled: FALSE
Keywrap enabled: FALSE
Server(&lt;span style="color:#ae81ff">10.129.111.20&lt;/span>&lt;span style="color:#f92672">:&lt;/span>&lt;span style="color:#ae81ff">1814&lt;/span>,&lt;span style="color:#ae81ff">1815&lt;/span>) Transactions:
Authen: &lt;span style="color:#ae81ff">5&lt;/span> Author: &lt;span style="color:#ae81ff">0&lt;/span> Acct: &lt;span style="color:#ae81ff">555&lt;/span>
Server_auto_test_enabled: FALSE
Keywrap enabled: FALSE
Server(&lt;span style="color:#ae81ff">172.30.2.123&lt;/span>&lt;span style="color:#f92672">:&lt;/span>&lt;span style="color:#ae81ff">1812&lt;/span>,&lt;span style="color:#ae81ff">1813&lt;/span>) Transactions:
Authen: &lt;span style="color:#ae81ff">0&lt;/span> Author: &lt;span style="color:#ae81ff">0&lt;/span> Acct: &lt;span style="color:#ae81ff">0&lt;/span>
Server_auto_test_enabled: TRUE
Keywrap enabled: FALSE
Server group SERVER_GROUP_2
Sharecount &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span> sg_unconfigured &lt;span style="color:#f92672">=&lt;/span> FALSE
Type &lt;span style="color:#f92672">=&lt;/span> standard Memlocks &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
Server(&lt;span style="color:#ae81ff">172.30.10.123&lt;/span>&lt;span style="color:#f92672">:&lt;/span>&lt;span style="color:#ae81ff">1812&lt;/span>,&lt;span style="color:#ae81ff">1813&lt;/span>) Transactions:
Authen: &lt;span style="color:#ae81ff">2249&lt;/span> Author: &lt;span style="color:#ae81ff">0&lt;/span> Acct: &lt;span style="color:#ae81ff">22424&lt;/span>
Server_auto_test_enabled: TRUE
Keywrap enabled: FALSE
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Эту конструкцию можно распарсить так:&lt;/p>
&lt;p>[ &lt;code>Список правил&lt;/code> ]&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-c" data-lang="c">Value Filldown &lt;span style="color:#a6e22e">NAME&lt;/span> (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>S&lt;span style="color:#f92672">+&lt;/span>)
Value Filldown SHARECOUNT (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value Filldown SG_UNCONFIGURED (TRUE&lt;span style="color:#f92672">|&lt;/span>FALSE)
Value Filldown TYPE (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>w&lt;span style="color:#f92672">+&lt;/span>)
Value Filldown MEMLOCKS (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value Required SERVER_IP (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>.&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>.&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>.&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value AUTH_PORT (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value ACC_PORT (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value AUTO_TEST_ENABLED (TRUE&lt;span style="color:#f92672">|&lt;/span>FALSE)
Value KEYWRAP_ENABLED (TRUE&lt;span style="color:#f92672">|&lt;/span>FALSE)
Value AUTHEN_COUNT (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value AUTHOR_COUNT (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value ACCT_COUNT (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Start
&lt;span style="color:#f92672">^&lt;/span>Server group &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{NAME}
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>Sharecount &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{SHARECOUNT}.&lt;span style="color:#f92672">*&lt;/span>sg_unconfigured &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{SG_UNCONFIGURED}
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>Type &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{TYPE}.&lt;span style="color:#f92672">*&lt;/span>Memlocks &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{MEMLOCKS}
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>Server&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>(&lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{SERVER_IP}&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>&lt;span style="color:#f92672">:&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{AUTH_PORT},&lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{ACC_PORT}&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>)
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>Authen: &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{AUTHEN_COUNT}.&lt;span style="color:#f92672">*&lt;/span>Author: &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{AUTHOR_COUNT}.&lt;span style="color:#f92672">*&lt;/span>Acct: &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{ACCT_COUNT}
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>Server_auto_test_enabled: &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{AUTO_TEST_ENABLED}
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>Keywrap enabled: &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{KEYWRAP_ENABLED} &lt;span style="color:#f92672">-&amp;gt;&lt;/span> Record
&lt;/code>&lt;/pre>&lt;/div>&lt;pre>&lt;code class="language-mermaid" data-lang="mermaid">graph TD;
Start--&amp;gt;EOF;
&lt;/code>&lt;/pre>&lt;p>[ &lt;code>Вывод&lt;/code> ]&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-python" data-lang="python">[&lt;span style="color:#e6db74">&amp;#39;NAME&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;SHARECOUNT&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;SG_UNCONFIGURED&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;TYPE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;MEMLOCKS&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;SERVER_IP&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;AUTH_PORT&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;ACC_PORT&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;AUTO_TEST_ENABLED&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;KEYWRAP_ENABLED&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;AUTHEN_COUNT&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;AUTHOR_COUNT&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;ACCT_COUNT&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;radius&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;standard&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;10.14.121.20&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1814&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1815&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;6&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;radius&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;standard&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;10.3.121.20&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1814&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1815&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;3&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;33&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;333&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;radius&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;standard&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;10.4.12.26&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1814&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1815&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;4&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;radius&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;standard&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;10.129.111.20&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1814&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1815&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;5&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;555&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;radius&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;standard&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;172.30.2.123&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1812&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1813&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;TRUE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;SERVER_GROUP_2&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;standard&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;172.30.10.123&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1812&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1813&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;TRUE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;2249&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;22424&amp;#39;&lt;/span>]
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Обратите внимание на строчку &lt;code>Keywrap enabled:&lt;/code>. Она идет в конце каждой секции и
на ней отрабатывает действие &lt;code>Record&lt;/code> - которое записывает накопленные значения в
строчку &lt;code>вывода&lt;/code>.&lt;/p>
&lt;h2 id="fsm-с-двумя-состояниями--не-считая-eof">FSM с двумя состояниями (не считая EOF)&lt;/h2>
&lt;p>[ &lt;code>Ввод&lt;/code> ]&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-c" data-lang="c">total number of groups:&lt;span style="color:#ae81ff">3&lt;/span>
following RADIUS server groups are configured:
group radius:
server: all configured radius servers
deadtime is &lt;span style="color:#ae81ff">0&lt;/span>
group RADIUS_GROUP_A:
server: &lt;span style="color:#ae81ff">10.65.101.22&lt;/span> on auth&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1814&lt;/span>, acct&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1815&lt;/span>
server: &lt;span style="color:#ae81ff">10.110.101.22&lt;/span> on auth&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1814&lt;/span>, acct&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1815&lt;/span>
server: &lt;span style="color:#ae81ff">10.194.101.22&lt;/span> on auth&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1814&lt;/span>, acct&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1815&lt;/span>
server: &lt;span style="color:#ae81ff">10.10.10.27&lt;/span> on auth&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1814&lt;/span>, acct&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1815&lt;/span>
deadtime is &lt;span style="color:#ae81ff">0&lt;/span>
vrf is management
Source interface mgmt0
group RADIUS_GROUP_B:
server: &lt;span style="color:#ae81ff">172.40.2.14&lt;/span> on auth&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1812&lt;/span>, acct&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1813&lt;/span>
deadtime is &lt;span style="color:#ae81ff">10&lt;/span>
Source interface loopback0
&lt;/code>&lt;/pre>&lt;/div>&lt;p>[ &lt;code>Список правил&lt;/code> ]&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-c" data-lang="c">Value Required &lt;span style="color:#a6e22e">NAME&lt;/span> (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>S&lt;span style="color:#f92672">+&lt;/span>)
Value List SERVER (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>.&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>.&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>.&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+|&lt;/span>all configured radius servers)
Value DEADTIME (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value List AUTH_PORT (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value List ACCT_PORT (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value VRF (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>S&lt;span style="color:#f92672">+&lt;/span>)
Value SOURCE_INTERFACE (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>S&lt;span style="color:#f92672">+&lt;/span>)
Start
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>group &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{NAME}&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#f92672">-&amp;gt;&lt;/span> Group
Group
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>server:&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>s&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{SERVER}&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>s&lt;span style="color:#f92672">*&lt;/span>on auth&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{AUTH_PORT}, acct&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{ACCT_PORT}
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>server:&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>s&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{SERVER} &lt;span style="color:#f92672">-&amp;gt;&lt;/span> AllServers
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>vrf is &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{VRF}
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>Source interface &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{SOURCE_INTERFACE} &lt;span style="color:#f92672">-&amp;gt;&lt;/span> Record Start
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>deadtime is &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{DEADTIME}
AllServers
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>deadtime is &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{DEADTIME} &lt;span style="color:#f92672">-&amp;gt;&lt;/span> Record Start
&lt;/code>&lt;/pre>&lt;/div>&lt;pre>&lt;code class="language-mermaid" data-lang="mermaid">graph TD;
Start--&amp;gt;AllServers;
AllServers--&amp;gt;Start;
Start--&amp;gt;EOF;
&lt;/code>&lt;/pre>&lt;p>[ &lt;code>Вывод&lt;/code> ]&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-python" data-lang="python">[&lt;span style="color:#e6db74">&amp;#39;NAME&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;SERVER&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;DEADTIME&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;AUTH_PORT&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;ACCT_PORT&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;VRF&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;SOURCE_INTERFACE&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;radius&amp;#39;&lt;/span>, [&lt;span style="color:#e6db74">&amp;#39;all configured radius servers&amp;#39;&lt;/span>], &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>, [], [], &lt;span style="color:#e6db74">&amp;#39;&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;RADIUS_GROUP_A&amp;#39;&lt;/span>, [&lt;span style="color:#e6db74">&amp;#39;10.65.101.22&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;10.110.101.22&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;10.194.101.22&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;10.10.10.27&amp;#39;&lt;/span>], &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>, [&lt;span style="color:#e6db74">&amp;#39;1814&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1814&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1814&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1814&amp;#39;&lt;/span>], [&lt;span style="color:#e6db74">&amp;#39;1815&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1815&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1815&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1815&amp;#39;&lt;/span>], &lt;span style="color:#e6db74">&amp;#39;management&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;mgmt0&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;RADIUS_GROUP_B&amp;#39;&lt;/span>, [&lt;span style="color:#e6db74">&amp;#39;172.40.2.14&amp;#39;&lt;/span>], &lt;span style="color:#e6db74">&amp;#39;10&amp;#39;&lt;/span>, [&lt;span style="color:#e6db74">&amp;#39;1812&amp;#39;&lt;/span>], [&lt;span style="color:#e6db74">&amp;#39;1813&amp;#39;&lt;/span>], &lt;span style="color:#e6db74">&amp;#39;&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;loopback0&amp;#39;&lt;/span>]
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Ага, но почему так хитро? Потому что в группе &lt;code>radius&lt;/code> последняя строчка перед
следющей группой это &lt;code>deadtime is 0&lt;/code>, а в остальных группах последняя строчка это
&lt;code>Source interface&lt;/code>. Для обработки этих разных групп нужны разные списки правил,
которые раскидываются по разным стейтам (&lt;code>Start&lt;/code> и &lt;code>AllServers&lt;/code>).&lt;/p>
&lt;p>Условие перехода на стейт &lt;code>AllServers&lt;/code> - строчка &lt;code>server: all configured radius servers&lt;/code>, которая матчится правилом &lt;code>^.*server:\s*${SERVER} -&amp;gt; AllServers&lt;/code>.&lt;/p>
&lt;p>В стейте &lt;code>AllServers&lt;/code> мы доходим до строчки &lt;code>deadtime is&lt;/code>, записываем состояние и
возвращаемся в стейт &lt;code>Start&lt;/code>.&lt;/p>
&lt;p>Если &lt;code>FSM&lt;/code> остается в стейте &lt;code>Start&lt;/code>, запись состояния происходит после матчинга
строчки &lt;code>Source interface&lt;/code>.&lt;/p>
&lt;h2 id="ссылки">Ссылки&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://github.com/google/textfsm/wiki/TextFSM">https://github.com/google/textfsm/wiki/TextFSM&lt;/a>&lt;/li>
&lt;/ul></description></item><item><title>Про Алексу</title><link>https://www.norre.org/ru/post/2019/on_alexa/</link><pubDate>Wed, 11 Dec 2019 21:24:00 +0800</pubDate><guid>https://www.norre.org/ru/post/2019/on_alexa/</guid><description>&lt;p>На декабрьской вписке в Сан Франциско (славный викторианский домик на Mars
Street, минут десять в гору от Castro) в числе прочих замечательных штук были
две умных колонки Amazon Echo (плюс амазоновский сабвуфер). Чумовые устройства,
совершенно.&lt;/p>
&lt;p>Кроме очевидного голосового управления (&lt;code>Alexa, play some ambient&lt;/code>) эти штуковины
теперь умеют сбиваться в стаи. В приложении Alexa можно настроить группы
колонок - эти две стоят в спальне, поэтому назовем эту группу &lt;code>bedroom&lt;/code>,
а эти две стоят в кухне, поэтому называются &lt;code>kitchen&lt;/code> - и управлять
этими группами по отдельности. Включать музыку в жилой комнате или
только в кухне. Плюс к тому, колонки каким-то образом координируются и
раскидывают стерео звук друг на друга.&lt;/p>
&lt;p>Голосовое управление до сих пор не очень удобное, но в целом работает. Надо
внятно сказать &lt;code>Alexa&lt;/code> - тогда колонки убавят громкость и начнут прислушиваться.
Затем можно сказать что-нибудь вроде &lt;code>set timer to 10 minutes&lt;/code> или &lt;code>play Pixies&lt;/code>,
или, например, &lt;code>shut up&lt;/code>, чтобы Алекса замолчала. Можно попросить поставить
будильник или закрыть дверь (если в ней есть совместимый умный замок). Можно
запустить рецепт IFTT. Можно подключить свой аккаунт Spotify и попросить
проиграть тот или иной плейлист.&lt;/p>
&lt;p>Зашел после работы в ближайший Best Buy поглядеть амазоновские устройства
поближе и посмотреть, что еще из подобного есть рынке. Стенд Amazon Alexa стоит
прямо напротив стенда Google (гугловская серия устройств для умного дома теперь
называется Google Nest - гнездо). У обоих есть маленькие умные колонки , умные
дисплеи (Amazon Echo Show и Google Nest Hub), камеры наблюдения, термостаты,
звонки и прочие устройства.&lt;/p>
&lt;p>Город будущего уже появился на горизонте.&lt;/p></description></item><item><title>Быть экспертом</title><link>https://www.norre.org/ru/post/2019/being_an_expert/</link><pubDate>Mon, 07 Oct 2019 22:54:00 +0800</pubDate><guid>https://www.norre.org/ru/post/2019/being_an_expert/</guid><description>&lt;p>По мотивам одной из начальных глав книги &lt;code>Pragmatic Thinking and Learning: Refactor Your Wetware by Andy Hunt&lt;/code>. Эта книга, вроде бы, есть в русском
переводе, я не смог найти сходу.&lt;/p>
&lt;p>Вокруг экспертизы, уровней экспертизы и профессионализма, постоянно происходит
какой-то нездоровый (подземный) шум, вполне характерный для ситуации когда
термин употребляют люди, плохо понимающие значение этого термина. Интуитивно
понятно, что если человек эксперт, то в предмете он разбирается. Это, конечно
же, так, но, у этого состояния, оказывается, присутствуют прелюбопытнейшие
побочки.&lt;/p>
&lt;p>Вкратце, отличие начинающих от экспертов такое:&lt;/p>
&lt;p>Новичкам нужно знать &lt;code>точно&lt;/code>, как делать то или иное действие. Им необходимы
однозначные вводные, не зависящие от контекста. Такие вводные, кстати, в
современном энтерпрайзе называются &lt;code>runbooks&lt;/code> - сборники процедур и правил на
каждый случай. Они заведомо предназначены для новичков и, как следствие,
перегружены лишним смысловым мусором - тем более лишним, чем более близок к
эксперту человек, их выполняющий.&lt;/p>
&lt;p>Эксперта легко отличить от других. Эксперт делает свою работу без видимых
усилий. Новички и продвинутые те же самые задачи будут выполнять (гораздо) менее
эффективно. Возможно в процессе работы им потребуется обратиться к документации
или помощи знакомого профессионала или эксперта. Возможно, неоднократно.&lt;/p>
&lt;p>Большинство людей обладают экспертизой во множестве вещей - например,
большинство физически и психически здоровых взрослых эксперты в хождении. Не
самое легкое занятие, между прочим. Достаточно взглянуть на детей, которые с
трудом держат равновесие и передвигаются - ходить поначалу невероятно сложно.
Этот процесс становится элементарным, как только человек достигает уровня
эксперта.&lt;/p>
&lt;p>Уровень новичка доступен опять же каждому - достаточно сесть, к примеру, за
любой музыкальный инструмент, поставить перед собой ноты и испытать острый
приступ отчаяния. Поздравления, вы начинающий. Впереди - безрадостность и, если
хватит усидчивости, прогресс.&lt;/p>
&lt;p>Эксперт эффективен в своем деле прежде всего потому, что он действует
интуитивно, минуя сознание. Эксперту не нужно тратить время на размышление над
проблемой, он совершает необходимые действия не задумываясь, руководствуясь
огромным опытом, который перешел в состояние инстинкта.&lt;/p>
&lt;p>Обещанные интересные побочки следующие:&lt;/p>
&lt;ul>
&lt;li>Стремление стать экспертом объясняется (во многом) тем, что экспертом быть
гораздо проще, чем новичком. Гораздо круче, проще и прибыльнее делать работу
быстро, не задумываясь и не напрягаясь, чем медленно, потея и фрустрируя от
нехватки времени.&lt;/li>
&lt;li>Эксперт совершенно не обязательно сможет удачно обучать других, менее
эффективных товарищей. Причина в интуитивной природе эксперта. &amp;ldquo;Это все равно
что стакан кому-нибудь описывать или, не дай бог, рюмку: только пальцами
шевелишь и чертыхаешься от полного бессилия&amp;rdquo; - очень похоже. Гораздо более
эффективным учителем может быть профессионал, не достигший еще уровня
экспертизы. Чувак, еще не ставший магом.&lt;/li>
&lt;/ul>
&lt;h2 id="ссылки">Ссылки&lt;/h2>
&lt;p>
&lt;a href="https://www.goodreads.com/book/show/3063393-pragmatic-thinking-and-learning" target="_blank" rel="noopener">ISBN 9781934356050&lt;/a>&lt;/p></description></item><item><title>No Rights Reserved</title><link>https://www.norre.org/ru/post/2020/video/norre/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://www.norre.org/ru/post/2020/video/norre/</guid><description>&lt;h2 id="drafts">Drafts&lt;/h2>
&lt;h3 id="series">Series &lt;!-- raw HTML omitted -->[0/3]&lt;!-- raw HTML omitted -->&lt;/h3>
&lt;h4 id="why-though-собственно-зачем">Why though? | Собственно, зачем? &lt;!-- raw HTML omitted -->[0/3]&lt;!-- raw HTML omitted -->&lt;/h4>
&lt;p>[ &lt;code>IDEA&lt;/code> ] - серия постов про разное и всякое, не концентрируясь на &amp;ldquo;как&amp;rdquo;, но
вместо этого делать упор на &amp;ldquo;почему&amp;rdquo;. Почему &lt;code>git&lt;/code> это очень удобно и зачем это
нужно всякому? А вот почему - и пара примеров и после набор элементарных команд.&lt;/p>
&lt;p>Так же можно делать пометку &amp;ldquo;уровень сложности&amp;rdquo; - начальный гит к примеру
легкий, а вот емакс это уже наверное ближе к &amp;ldquo;очень сложно&amp;rdquo;. Хотя, есть
варианты.&lt;/p>
&lt;p>Алсо, давать литературу и learning path.&lt;/p>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>&lt;!-- raw HTML omitted -->TODO&lt;!-- raw HTML omitted --> VI(m) and derivatives&lt;/p>
&lt;p>Because: vim motions.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>&lt;!-- raw HTML omitted -->TODO&lt;!-- raw HTML omitted --> EMACS&lt;/p>
&lt;p>Because: org-mode (show the general stuff)&lt;/p>
&lt;/li>
&lt;/ul>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>&lt;!-- raw HTML omitted -->TODO&lt;!-- raw HTML omitted --> GIT&lt;/p>
&lt;p>Because: show how to version control stuff.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h3 id="longreads">Longreads &lt;!-- raw HTML omitted -->[1/8]&lt;!-- raw HTML omitted -->&lt;/h3>
&lt;h4 id="про-методологию-поиска-в-интернете">&lt;!-- raw HTML omitted -->TODO&lt;!-- raw HTML omitted --> Про методологию поиска в интернете&lt;/h4>
&lt;p>&lt;a href="https://www.reddit.com/r/RBI/comments/cbham7/how%5Fi%5Ffind%5Fstuff/">https://www.reddit.com/r/RBI/comments/cbham7/how%5Fi%5Ffind%5Fstuff/&lt;/a>&lt;/p>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>English text&lt;/p>
&lt;p>Based on the response and requests made in this thread, I&amp;rsquo;m going to attempt to
lay out how I go about finding people, places, things, whatever using almost
entirely open source, freely available tools and resources. A few of the tools I
use aren&amp;rsquo;t free (mostly Photoshop and tools like the NGP VAN voter database),
but there are frequently free analogs you can use.&lt;/p>
&lt;p>As I&amp;rsquo;ve thought through how to write this, it occurred to me that I should
probably just use the above linked thread as kind of a case study. It would be
impossible to write out a step by step guide to tracking shit down, as every
search is unique, but I can show you my methodology, and my thinking at each
step. As a background on me, I&amp;rsquo;ve always been incredibly curious and eager to
learn new things and was an early explorer of the primitive internet, BBS, etc
back in the early 90&amp;rsquo;s. As an adult, I joined the Army and became a recon
platoon leader, where among other things, I worked on teams to find/capture high
value targets. Later in life I&amp;rsquo;ve done some tracing for people needing to find
people for legal reasons, and I&amp;rsquo;ve done oppo research for political candidates.
It&amp;rsquo;s totally a hobby now, but something I think I&amp;rsquo;m pretty good at.&lt;/p>
&lt;p>So here&amp;rsquo;s how I do it. Every search is based on a funnel principle. I always
want to load the top of the funnel with absolutely as much information as I can,
and then start working my way down, discarding irrelevant info and prioritizing
potential leads. So, in the thread about the mystery hotel in Thailand, here&amp;rsquo;s
what I did.&lt;/p>
&lt;p>First up, want to analyze in great detail all the available info. Naturally, I
started with the photos linked here. I go over each photo very closely. No
object, feature, reflection, plant, or design element is too small to notice. In
photo 1, a couple of things jumped out. The blue notebook on the table was a big
one, and the unique layout of the outdoor kitchen area. The uniquely shaped pool
furniture stood out to me as well. The biggest value in this photo is that it
gives a good sense of the layout of the room, the unique design of the pool, the
kitchenette, and the doors/windows. All of the elements will come into play in
the next step.&lt;/p>
&lt;p>The second photo was by far the most helpful, as it gave a full 360 degree view
of the room using the reflection. It also showed us a couple of unique features.
The indoor/outdoor shower is a big one. If you&amp;rsquo;re looking for something you know
is a vacation spot, it&amp;rsquo;s likely people would notice/comment on features like
that. The fact that it has the six cut in boxes adjacent the shower fixture, and
the look of the fixture itself also was important. The unique sink to the right
of the picture with the glass suspended over it was very unusual. Finally, the
fluffy red towels were a big clue. That&amp;rsquo;s relatively unique, and very visually
recognizable. My first line of thinking was that since this is probably a nice,
but relatively cheap accommodation in a third world country, it was possible
these unique red towels could have stained someone&amp;rsquo;s bathing suit or clothes,
which is something people very likely would negatively review online, and could
be a huge help.&lt;/p>
&lt;p>The third photo provided some more detail on the kitchen, and a good layout of
the objects in the entertainment center, and on the table, as well as the
position of the kitchen utilities. Notice also the roof patterns, outdoor AC
unit, and smoked glass behind the kitchenette. All of these could prove very
helpful.&lt;/p>
&lt;p>So once I&amp;rsquo;d gone through and made extensive mental notes on the unique features,
I created in my head (though on paper works even better) a 360 degree layout of
the villa, in a way that I could kind of mentally pan and move around. The point
of this is to become so familiar with what you are looking for that you can
easily recognize it if you see it from other angles, or you notice visually
similar things in other photos (appliances, fixtures, bedding, art, furniture,
etc). This applies to literally every search. You want to become so familiar
with what you are looking for that the subconscious pattern recognition parts of
your brain fire off when you see something that connects with what you are
looking for.&lt;/p>
&lt;p>The next thing I do is think about the intangibles around what I&amp;rsquo;m looking for.
I had very little info on the missing boyfriend, but I could infer a few things.
The girlfriend came to reddit, specifically RBI for help. This indicates that
she&amp;rsquo;s pretty computer literate, and probably a somewhat frequent redditor. That
probably means her BF is too. It also means, combined with the fact that he is
backpacking alone in Thailand that they are young and adventurous. That made is
seem likely that he wasn&amp;rsquo;t exactly at the Grand Hyatt, but probably a small
hotel, or likely if not specifically an AirBnb, someplace that isn&amp;rsquo;t far off
from that in price, quality, etc.&lt;/p>
&lt;p>So once I feel very familiar with the target, I start at the top of that funnel
and go for the very big, very easy threads to start digging at. The red towels
just felt like an easy initial search. I went to google and started searching
combinations of Thailand, Ko Samui, and &amp;ldquo;red towel(s)&amp;quot;. I actually found a
negative review of a place that looked somewhat similar complaining exactly
about what I had guessed, the red towels at a Thai resort had bled onto their
white bathing suit. It&amp;rsquo;s a shot in the dark, but hey, it almost worked. It
wasn&amp;rsquo;t this place, but it was a decent early lead that didn&amp;rsquo;t pan out
unfortunately.&lt;/p>
&lt;p>From there, I went on TripAdvisor and other travel sites, and searched for
combinations of Ko Samui and indoor/outdoor shower, private pool, red towel,
blue notebook, and other unique identifiers from the pictures. That wasn&amp;rsquo;t super
productive, but not entirely a dry hole. It gave me some insight into Ko Samui,
a place I&amp;rsquo;ve never been. I started to get a feel for the quality of
neighborhoods, which geographic areas were better/worse/more likely to host
lower end travel or AirBnb, and so on.&lt;/p>
&lt;p>Once I felt like I had a couple of geographic target areas in mind, I went o
AirBnB and started searching open rooms in those areas. This was the most
laborious part of the process, but ultimately the one that worked. I was rapid
fire scrolling through listings, as there are hundreds, but since I had built
such a robust scene of the hotel in my head, it was just a matter of quickly
matching patterns. I landed on a few places with matching outdoor furniture,
which felt promising. Ultimately though, it was that blue notebook on the table
outside that gave it away.&lt;/p>
&lt;p>On about the 300th AirBnB listing I scrolled past, I saw the notebook. I
instantly knew I had found maybe not the exact place, but somewhere connected to
it. From there it was a matter of identifying exactly where it was geolocated
using user reviews and comments that gave away details like proximity to a 7-11
and the beach. Then I just drew a little radius around the 7-11 and searched
inside it. Pretty soon I landed on the Samui Boat Lagoon and knew that was the
spot. A little more google image searching of that phrase exactly, and I found
what I believe is either the exact room the boyfriend was in, or one that was
layed out almost identically.&lt;/p>
&lt;p>So now that I&amp;rsquo;ve typed that all out, it&amp;rsquo;s probably a lot less exciting that I
(or you) had hoped. But searching like this is just recognizing which details
are important, building familiarity with the target, having a sense of where to
look, and then just pattern matching using open source tools. The part I didn&amp;rsquo;t
really touch on is how to use your personal network of contacts to help with
this, but I don&amp;rsquo;t really have many close contacts in SE Asia these days, so that
was not an option here. Despite that, using people on the ground has been
immensely helpful to me in finding things, places, and people. Sometimes
something as simple as &amp;ldquo;Hey, what part of your country do you think this is?&amp;rdquo;
can yield really valuable context and clues.&lt;/p>
&lt;p>So assuming the mods are cool with it, I&amp;rsquo;m happy to answer questions about this,
about other interesting searches I&amp;rsquo;ve completed, or almost anything else. Happy
to talk tradecraft, things you can do to make your brain really good at
observing and retaining detailed info, and an anything else.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h4 id="cisco-and-scp">&lt;!-- raw HTML omitted -->DRFT&lt;!-- raw HTML omitted --> Cisco and SCP&lt;/h4>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>What&lt;/p>
&lt;p>How many ways do you have to `scp` the file to a router&amp;rsquo;s or switch&amp;rsquo;s flash? A couple, at least.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>How&lt;/p>
&lt;ul>
&lt;li>Receive a file on Cisco from a remote SCP server&lt;/li>
&lt;/ul>
&lt;p>You logged in to a Cisco box and getting this file from a remove SCP.&lt;/p>
&lt;p>`copy scp://*username*@*remote host*//*remote path*/*remote filename* flash:`&lt;/p>
&lt;ul>
&lt;li>Send a file from a SCP server to a Cisco box&lt;/li>
&lt;/ul>
&lt;p>You are logged on a Linux box and sending the file to a remote Cisco.&lt;/p>
&lt;p>`scp &lt;strong>local filename&lt;/strong> &lt;strong>remote user*@*Cisco address&lt;/strong>:flash:/*destination filename*`&lt;/p>
&lt;ul>
&lt;li>Get a file from Cisco&lt;/li>
&lt;/ul>
&lt;p>You are logged in to your Cisco box and getting this file from another Cisco device.&lt;/p>
&lt;p>First off, enable an SCP server on the remote guy. You should be able to `ssh`
to this box and know the credentials (obviously).&lt;/p>
&lt;p>`ip scp server enable`&lt;/p>
&lt;p>Now, copy it:&lt;/p>
&lt;p>`copy scp://*remote user*@*remote cisco*/*remote filename* flash:*local filename*`&lt;/p>
&lt;ul>
&lt;li>Send a file to Cisco (from Cisco)&lt;/li>
&lt;/ul>
&lt;p>`copy flash:*local filename* scp://*remote user*@*remote cisco*/*remote filename*`&lt;/p>
&lt;/li>
&lt;/ul>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>Notes&lt;/p>
&lt;p>SCP number unknown&lt;!-- raw HTML omitted -->*&lt;!-- raw HTML omitted -->Though
&lt;a href="http://www.scp-wiki.net/random:random-scp" target="_blank" rel="noopener">this&lt;/a> one looks quite close to the case.&lt;!-- raw HTML omitted -->&lt;!-- raw HTML omitted -->.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>Fun fact&lt;/p>
&lt;!-- raw HTML omitted -->
&lt;p>The beauty of this solution keeps me amazed up to this day. Last time I checked
it was 2019 and we still do not have a progress indicator of any sort. Keep
counting `!`'s and &lt;code>~pray~&lt;/code> multiply it by 512.&lt;/p>
&lt;p>The rest of the cryptic symbols are here:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Character&lt;/th>
&lt;th>Description&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>`.`&lt;/td>
&lt;td>For net transfers, a period indicates that the copy process timed out. Many periods in a row typically mean that the copy process may fail.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>`O`&lt;/td>
&lt;td>For net transfers, an uppercase O indicates that a packet was received out of order and the copy process may fail.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>`e`&lt;/td>
&lt;td>For flash erasures, a lowercase e indicates that a device is being erased.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>`E`&lt;/td>
&lt;td>An uppercase E indicates an error. The copy process may fail.&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>`V`&lt;/td>
&lt;td>A series of uppercase Vs indicates the progress during the verification of the image checksum.&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>[Link][2]
[2]: &lt;a href="https://www.cisco.com/E-Learning/bulk/public/tac/cim/cib/using%5Fcisco%5Fios%5Fsoftware/cmdrefs/copy.htm">https://www.cisco.com/E-Learning/bulk/public/tac/cim/cib/using%5Fcisco%5Fios%5Fsoftware/cmdrefs/copy.htm&lt;/a>&lt;/p>
&lt;/li>
&lt;/ul>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>Links&lt;/p>
&lt;ol>
&lt;li>&lt;a href="https://linuxacademy.com/blog/linux/ssh-and-scp-howto-tips-tricks/">https://linuxacademy.com/blog/linux/ssh-and-scp-howto-tips-tricks/&lt;/a>&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ul>
&lt;h4 id="про-джона-макафи-основателя-компании-virgin">&lt;!-- raw HTML omitted -->TODO&lt;!-- raw HTML omitted --> Про Джона Макафи, основателя компании Virgin&lt;/h4>
&lt;p>Найти здесь про то, как он трахнул кита. Замечательная история же.
&lt;a href="https://twitter.com/officialmcafee/status/1010682321106821125?lang=en">https://twitter.com/officialmcafee/status/1010682321106821125?lang=en&lt;/a>&lt;/p>
&lt;p>&lt;a href="https://www.reddit.com/r/OutOfTheLoop/comments/ae04as/whats%5Fup%5Fwith%5Fjohn%5Fmcafees%5Ftweets%5Fabout%5Ffucking/">https://www.reddit.com/r/OutOfTheLoop/comments/ae04as/whats%5Fup%5Fwith%5Fjohn%5Fmcafees%5Ftweets%5Fabout%5Ffucking/&lt;/a>&lt;/p>
&lt;h4 id="digital-borrowing">&lt;!-- raw HTML omitted -->DRFT&lt;!-- raw HTML omitted --> Digital Borrowing&lt;/h4>
&lt;p>Libby, спустя 21 день, без предупреждения отобрал у меня &amp;ldquo;Hearts in Atlantis&amp;rdquo;,
не дав дослушать. Книга начитывается что-то около 20 часов, из которых мне
оставалось прослушать часа четыре - оставалась последняя часть - про то, как
Бобби возвращается домой. Слушал я в основном на беговой дорожке и я банально не
выбегаю такое количество времени в месяц.&lt;/p>
&lt;p>(note: libby это онлайн сервис для прослушивания аудиокниг)&lt;/p>
&lt;p>В моем детстве продлить библиотечную книгу было довольно просто - достаточно
было прийти и заявить об этом. Сейчас, насколько я понимаю, все обстоит примерно
так же. Вот (совершенно случайная)
&lt;a href="https://www.gold.ac.uk/library/using/borrowing/renewals/" target="_blank" rel="noopener">ссылка&lt;/a> на секцию
Обновления, обыкновенной библиотеки Goldsmiths University of London:&lt;/p>
&lt;p>How to renew your loans of books from the library&lt;/p>
&lt;ul>
&lt;li>Online - онлайн&lt;/li>
&lt;li>Students App - через приложение&lt;/li>
&lt;li>In the library - сходив ногами в библиотеку&lt;/li>
&lt;li>By phone or email - по телефону или имейлу&lt;/li>
&lt;/ul>
&lt;p>Важная оговорка: You will not be able to renew books yourself if your account is
blocked or the item is reserved - вы не сможете продлить книгу, если ваш аккаунт
заблокирован &lt;strong>или эта книга уже зарезервирована кем-то другим&lt;/strong>. Здраво, в целом.
Речь ведь идет о физических книгах.&lt;/p>
&lt;p>Впрочем, как оказалось, Libby тоже
&lt;a href="https://help.libbyapp.com/6039.htm" target="_blank" rel="noopener">позволяет продлять книги&lt;/a>. С
некоторыми ограничениями, впрочем. Я не смог продлить книгу, которую мне надо
сдать через 9 дней - приложение заявило, что это можно сделать только через 6
дней - то есть за 3 дня до истечения срока. Разумно. Было бы еще неплохо
получить напоминание о том, что срок аренды книги скоро истекает, конечно.&lt;/p>
&lt;p>Взять книгу обратно я могу только через 2 недели. Почему так - не совсем
понятно, потому что книга выдается на 21 день. Просто посчитать, что это не 2
недели, а 3. Ну, тут видимо расчет на сознательного слушателя, который закончит
книгу за меньшее время. Ладно.&lt;/p>
&lt;p>В статусе Сердец в Атлантиде теперь написано такое: 1 copy in use, 0 people
waiting - 1 копия используется, никто не ожидает.&lt;/p>
&lt;p>Если у вас до сих пор не возникло странного ощущения что здесь что-то немного не
так, наводящий вопрос: сколько копий этого текста используется в настоящий
момент? Текста, который вы сейчас читаете.&lt;/p>
&lt;p>Из спортивного интереса я решил поглядеть, что там у конкурентов.&lt;/p>
&lt;p>##
&lt;a href="https://www.audible.com/" target="_blank" rel="noopener">audible.com&lt;/a>&lt;/p>
&lt;p>Аудибль это сервис от Амазона. Амазон это ребята, которые хостят основную часть
современного интернета. Еще они делают электронные книжки Киндл.&lt;/p>
&lt;p>На главной странице мне было предложено вписаться в тестовый месяц использования:&lt;/p>
&lt;p>✓ Free membership for 30 days with 1 audiobook + 2 Audible Originals.
✓ After trial, 3 titles each month: 1 audiobook + 2 Audible Originals.&lt;/p>
&lt;p>То есть за стоимость подписки (15 долларов в месяц) предлагается к прослушиванию
одна книга. Audible Originals это книги, начитанные специально для Аудибль. В
списке Best-Selling Audible Originals я не увидел ни одного знакомого автора.&lt;/p>
&lt;p>Это, впрочем, говорит только об уровне моей начитанности.&lt;/p>
&lt;p>В списке Commitment-free guarantee (гарантия отсутствия обязательств) следующее:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>You won’t be charged until after 30 days - деньги снимут только после
испытательного месяца.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Don’t like an audiobook? Swap it for free - если книга не понравилась, ее
можно поменять за так. Это хорошо (см. audiobooks)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Cancel anytime, no questions asked - тут говорят о том, что подписка может
быть отменена в любое время. Это действительно важно знать заранее, это
совершенно не та вещь, которую можно ожидать, когда подписываешься на сервис.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>Выдержки из
&lt;a href="https://audible.custhelp.com/app/answers/list/c/3081" target="_blank" rel="noopener">FAQ&lt;/a>:&lt;/p>
&lt;p>What happens to my audiobooks if I cancel my membership?&lt;/p>
&lt;p>Nothing at all. Your books are yours to keep. You can continue to listen to them
on any of your devices or our app.&lt;/p>
&lt;p>Что произойдет с моими аудиокнигами, если я отменю подписку?&lt;/p>
&lt;p>Ничего. Вы сохраните книги и сможете слушать их на любых устройствах или на
нашем приложении.&lt;/p>
&lt;p>Это круто. Однако:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Для проигрывания на mp3 плеерах предлагается установить приложение (под
Windows).
&lt;a href="https://audible.custhelp.com/app/answers/detail/a%5Fid/5076/kw/mp3" target="_blank" rel="noopener">Список&lt;/a> поддерживаемых устройств таков:&lt;/p>
&lt;ul>
&lt;li>Kindle (разные)&lt;/li>
&lt;li>Sandisk MP3 Players&lt;/li>
&lt;li>Creative MP3 Players&lt;/li>
&lt;li>Garmin &amp;amp; Tom Tom GPS Devices&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>Под Мак вроде как
&lt;a href="https://audible.custhelp.com/app/answers/detail/a%5Fid/4647/" target="_blank" rel="noopener">можно&lt;/a> скачать книги напрямую, но
скачиваются они в непонятном формате `aax`, который еще надо постараться
перетащить в `mp3`.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>What are Geographic Restrictions and how do they affect shopping on Audible?&lt;/p>
&lt;p>When publishers decide to publish a work, they acquire the rights to distribute
that particular audiobook in certain regions of the world. Frequently, the
rights for an audiobook are split among several companies, each of whom publish
for different countries. Audible must abide by these restrictions, though it may
occasionally inconvenience the customer.&lt;/p>
&lt;p>Тут говорится о том, что издатели аудиокниг по разным причинам могуть владеть
правами на распространение только в определененных (не всех) странах. Это
значит, что в стране А в списке может присутствовать книга Б, а в стране В ее
может и не быть. Упс.&lt;/p>
&lt;p>&lt;a href="https://audible.custhelp.com/app/answers/detail/a%5Fid/5006/kw/mp3">https://audible.custhelp.com/app/answers/detail/a%5Fid/5006/kw/mp3&lt;/a>&lt;/p>
&lt;p>Can I convert my Audible audiobooks into MP3 files?&lt;/p>
&lt;p>Unfortunately, Audible audio files cannot be converted into MP3 or any other
file format.The reason for this is because we utilize security technologies to
protect the intellectual property rights of our content providers and authors.&lt;/p>
&lt;p>Можно ли сконвертировать книгу Аудибль в mp3?&lt;/p>
&lt;p>Нет, нельзя. Причина проста - защита интеллектуальной собственности провайдеров
контента и авторов.&lt;/p>
&lt;p>Из смешного:&lt;/p>
&lt;p>&lt;a href="https://audible.custhelp.com/app/answers/detail/a%5Fid/4468">https://audible.custhelp.com/app/answers/detail/a%5Fid/4468&lt;/a>
Will audiobooks be downloaded to my computer with the Audible Cloud Player?&lt;/p>
&lt;p>No content will be downloaded to your computer while using the Audible Cloud
Player because the audio is being streamed on your computer through your
Internet connection.&lt;/p>
&lt;p>Тут говорят о том, что при стриминге аудиокниги никакой контент не будет
загружен на компьютер. Технически, это, конечно, не так. Технически, никакой
разницы между загрузкой и стримингом не существует. Появляется эта разница
только когда контент, загруженный из интернета &lt;strong>удаляется&lt;/strong> с вашего компьютера.
То есть, на самом деле &amp;ldquo;стриминговый&amp;rdquo; контент это такой, который принудительно
удаляется с накопителя после загрузки. Такие дела.&lt;/p>
&lt;p>##
&lt;a href="https://www.audiobooks.com/" target="_blank" rel="noopener">audiobooks.com&lt;/a>&lt;/p>
&lt;p>Выдержки из
&lt;a href="https://www.audiobooks.com/faqs" target="_blank" rel="noopener">FAQ&lt;/a>:&lt;/p>
&lt;p>What is a book credit?&lt;/p>
&lt;p>1 book credit allows you to listen to any audiobook in our library. If you find
yourself wanting to listen to more books, you can add book credits to your
subscription as you go.&lt;/p>
&lt;p>Can I listen to more than one audiobook per month?&lt;/p>
&lt;p>Absolutely! With our subscription plan, one credit is automatically added to
your account each month. To get more, you can either purchase top-up credits
through the website or claim books instantly using our InstaCredit feature in
the app.&lt;/p>
&lt;p>То есть - месячная подписка стоит около 15 долларов. В подписку входит 1 книга в
месяц (плюс выбор из нескольких книг, меняющийся каждый месяц - это почему-то
называется VIP Rewards - Вознаграждение Особо Важным Персонам). Насколько я
понимаю, это аналог подписки Sony PSN, в которую каждый месяц включается
несколько бесплатных игр.&lt;/p>
&lt;p>Раньше у них
&lt;a href="https://www.cnet.com/news/all-you-can-hear-audiobooks-headed-your-way-at-audiobooks-com/" target="_blank" rel="noopener">была возможность&lt;/a> слушать книги безо всяких
ограничений. Стоило это несколько немилосердно - 25 долларов в месяц - но, в
целом, это была неплохая опция. Впрочем, они
&lt;a href="https://www.cnet.com/news/audiobooks-com-cancels-all-you-can-hear-plan/" target="_blank" rel="noopener">отменили&lt;/a>
эту возможность спустя примерно год. Упс.&lt;/p>
&lt;p>В этом месяце в списке VIP Rewards было 17 книг. Из всех авторов я знал только Кормака
Маккарти (с его Дорогой), но его Дорогу я уже читал.&lt;/p>
&lt;p>Это, впрочем, говорит только об уровне моей начитанности.&lt;/p>
&lt;p>Дальше:&lt;/p>
&lt;p>Why do I always have to listen to a preview?&lt;/p>
&lt;p>Our combined Preview and Play button allows you to listen to an audiobook before
committing. If you don&amp;rsquo;t like the audiobook, stop at any time. Around the
three-minute mark of most books, you&amp;rsquo;ll be prompted to hit &amp;ldquo;Continue&amp;rdquo;. If you&amp;rsquo;re
enjoying the narrator and story when you get to this point, hit &amp;ldquo;Continue&amp;rdquo; and
keep listening. If not, preview a few more until you find a great listen.&lt;/p>
&lt;p>Здесь говорится о том, что прежде чем начать слушать книгу, за которую вы
заплатили месячную подписку, вы сможете с этой книгой ознакомиться в течение
трех минут. Я на выбор карандаша обычно трачу больше времени. Не говоря уже о
книге.&lt;/p>
&lt;p>Why is this book unavailable to me?&lt;/p>
&lt;p>When publishers get the rights to books, they may only get the rights to
distribute in certain countries. We have to honor that distribution, so these
books will be regionally restricted. If it were up to us, all audiobooks would
be available worldwide!&lt;/p>
&lt;p>Снова, географические ограничения на проигрывание контента.&lt;/p>
&lt;p>Can I cancel my membership?&lt;/p>
&lt;p>Some relationships just aren&amp;rsquo;t meant to be, which is why there are absolutely no
restrictions on when you can cancel your Audiobooks.com membership. Go to the My
Account section of the website (the link is in the top right when you&amp;rsquo;re logged
in) and cancel online with the click of a link.&lt;/p>
&lt;p>Можно ли отменить подписку? Да! Однако, в отличие от аудибля, тут ни слова о
том, что уже прослушанные / приобретенные книги остаются у слушателя. Ладно.&lt;/p>
&lt;p>Как обычно, мой основной вопрос - идет ли часть моей оплаты напрямую авторам или
их наследникам? В FAQ обоих сервисов про это не написано. Я задал вопрос через
специальную форму для задавания вопросов, на audiobooks - пока жду ответа. На
Аудибле удобной формы для задавания вопросов найти не удалось.&lt;/p>
&lt;p>Вот ответ от audiobooks:&lt;/p>
&lt;p>Hi there,&lt;/p>
&lt;p>Thanks for your message.&lt;/p>
&lt;p>Yes we do have contracts set in place with the authors/publishers. Unfortunately I do not have an exact amount as it would depend on that specific contract/book.&lt;/p>
&lt;p>Best,&lt;/p>
&lt;p>Tara
Customer Service Representative
Tell us about your experience and you&amp;rsquo;ll be entered in our daily draw for a free credit&lt;/p>
&lt;p>&amp;mdash;&amp;ndash; Original Message &amp;mdash;&amp;ndash;&lt;/p>
&lt;p>Hi guys,
I could not find this question in FAQ: do my subscription money go to the authors and their respective heirs? How much exactly?
Thank you!&lt;/p>
&lt;ol>
&lt;li>&amp;ldquo;Занимать&amp;rdquo; цифровые копии безусловно противоестественно. Цифровая природа
подразумевает дубликаты, копиии, идентичные оригиналам. Стоимость создания
цифрового дубликата пренебрежимо мала.&lt;/li>
&lt;li>&lt;/li>
&lt;/ol>
&lt;p>Противоестественно: то, чего не сущестует в природе. То, что идет против природы
вещей. Ограничивать возможность пользоваться цифровой копией книги настолько же
противоестественно, как предлагать читать физическую копию книги нескольким
читателям одновременно. Это не только противоестественно, но даже как-то
жестоко.&lt;/p>
&lt;p>Ограничение свободы перемещения - наверное, лучшая аналогия. Государства и
границы в текущем их виде по большому счету наследие прошлого. Границы
государств решают проблемы, которые существовали тысячи лет. Цифровые границы в
свою очередь создают проблемы, которые никогда не существовали до этого.&lt;/p>
&lt;p>TODO: Почитать про права на книги, библиотечные практики.
Почему происходит именно так?
DRM&lt;/p>
&lt;h4 id="lm-datasource">&lt;!-- raw HTML omitted -->TODO&lt;!-- raw HTML omitted --> LM Datasource&lt;/h4>
&lt;p>&lt;a href="https://orgmode.org/manual/results.html">https://orgmode.org/manual/results.html&lt;/a>&lt;/p>
&lt;p>Goal - create a datasource in lm to check that RIPE objects are in fact being
advertised.&lt;/p>
&lt;p>Datasource: Multinstance&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-http" data-lang="http">&lt;span style="color:#960050;background-color:#1e0010">GET https://stat.ripe.net/data/prefix-routing-consistency/data.json?resource=200.87.101.0/24
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">{
&amp;#34;status&amp;#34;: &amp;#34;ok&amp;#34;,
&amp;#34;server_id&amp;#34;: &amp;#34;app001&amp;#34;,
&amp;#34;status_code&amp;#34;: 200,
&amp;#34;version&amp;#34;: &amp;#34;0.7&amp;#34;,
&amp;#34;cached&amp;#34;: false,
&amp;#34;see_also&amp;#34;: [],
&amp;#34;time&amp;#34;: &amp;#34;2019-10-08T07:49:57.418825&amp;#34;,
&amp;#34;messages&amp;#34;: [],
&amp;#34;data_call_status&amp;#34;: &amp;#34;supported - based on version 1.1&amp;#34;,
&amp;#34;process_time&amp;#34;: 1058,
&amp;#34;build_version&amp;#34;: &amp;#34;2019.9.25.129&amp;#34;,
&amp;#34;query_id&amp;#34;: &amp;#34;20191008074956-61055de0-7676-434d-a0dc-756ff8b79ffa&amp;#34;,
&amp;#34;data&amp;#34;: {
&amp;#34;routes&amp;#34;: [
{
&amp;#34;origin&amp;#34;: 6568,
&amp;#34;irr_sources&amp;#34;: [],
&amp;#34;in_whois&amp;#34;: false,
&amp;#34;asn_name&amp;#34;: &amp;#34;Entel S.A. - EntelNet&amp;#34;,
&amp;#34;prefix&amp;#34;: &amp;#34;200.87.0.0/17&amp;#34;,
&amp;#34;in_bgp&amp;#34;: true
},
{
&amp;#34;origin&amp;#34;: 6568,
&amp;#34;irr_sources&amp;#34;: [
&amp;#34;NTTCOM&amp;#34;
],
&amp;#34;in_whois&amp;#34;: true,
&amp;#34;asn_name&amp;#34;: &amp;#34;Entel S.A. - EntelNet&amp;#34;,
&amp;#34;prefix&amp;#34;: &amp;#34;200.87.0.0/16&amp;#34;,
&amp;#34;in_bgp&amp;#34;: true
},
{
&amp;#34;origin&amp;#34;: 6568,
&amp;#34;irr_sources&amp;#34;: [
&amp;#34;NTTCOM&amp;#34;
],
&amp;#34;in_whois&amp;#34;: true,
&amp;#34;asn_name&amp;#34;: &amp;#34;Entel S.A. - EntelNet&amp;#34;,
&amp;#34;prefix&amp;#34;: &amp;#34;200.87.96.0/20&amp;#34;,
&amp;#34;in_bgp&amp;#34;: true
},
{
&amp;#34;origin&amp;#34;: 6568,
&amp;#34;irr_sources&amp;#34;: [
&amp;#34;RADB&amp;#34;
],
&amp;#34;in_whois&amp;#34;: true,
&amp;#34;asn_name&amp;#34;: &amp;#34;Entel S.A. - EntelNet&amp;#34;,
&amp;#34;prefix&amp;#34;: &amp;#34;200.87.101.0/24&amp;#34;,
&amp;#34;in_bgp&amp;#34;: false
}
],
&amp;#34;query_starttime&amp;#34;: &amp;#34;2019-10-08T00:00:00&amp;#34;,
&amp;#34;query_endtime&amp;#34;: &amp;#34;2019-10-08T00:00:00&amp;#34;,
&amp;#34;resource&amp;#34;: &amp;#34;200.87.101.0/24&amp;#34;
}
}
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Groovy iterate over list:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-groovy" data-lang="groovy">&lt;span style="color:#66d9ef">def&lt;/span> list &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">[&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>&lt;span style="color:#f92672">,&lt;/span>&lt;span style="color:#ae81ff">2&lt;/span>&lt;span style="color:#f92672">,&lt;/span>&lt;span style="color:#ae81ff">3&lt;/span>&lt;span style="color:#f92672">,&lt;/span>&lt;span style="color:#ae81ff">4&lt;/span>&lt;span style="color:#f92672">]&lt;/span>
&lt;span style="color:#66d9ef">for&lt;/span>&lt;span style="color:#f92672">(&lt;/span>item &lt;span style="color:#66d9ef">in&lt;/span> list&lt;span style="color:#f92672">){&lt;/span>
println item
&lt;span style="color:#f92672">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Acitve discovery script&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-groovy" data-lang="groovy">&lt;span style="color:#f92672">import&lt;/span> groovy.json.JsonSlurper
&lt;span style="color:#66d9ef">def&lt;/span> staturl &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;https://stat.ripe.net/data/prefix-routing-consistency/data.json?resource=8.18.221.0/24&amp;#34;&lt;/span> &lt;span style="color:#75715e">// TODO: use ##wildvalue## instead of hardcoding
&lt;/span>&lt;span style="color:#75715e">&lt;/span>
response &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> URL &lt;span style="color:#f92672">(&lt;/span> staturl &lt;span style="color:#f92672">+&lt;/span>
URLEncoder&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">encode&lt;/span>&lt;span style="color:#f92672">(&lt;/span>
&lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>&lt;span style="color:#f92672">,&lt;/span>
&lt;span style="color:#e6db74">&amp;#39;UTF-8&amp;#39;&lt;/span> &lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">).&lt;/span>&lt;span style="color:#a6e22e">text&lt;/span>
String jsonString &lt;span style="color:#f92672">=&lt;/span> response
JsonSlurper slurper &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> JsonSlurper&lt;span style="color:#f92672">()&lt;/span>
Map parsedJson &lt;span style="color:#f92672">=&lt;/span> slurper&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">parseText&lt;/span>&lt;span style="color:#f92672">(&lt;/span>jsonString&lt;span style="color:#f92672">)&lt;/span>
&lt;span style="color:#66d9ef">def&lt;/span> id&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">0&lt;/span>
&lt;span style="color:#75715e">// Build wildvalue
&lt;/span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">for&lt;/span>&lt;span style="color:#f92672">(&lt;/span>route &lt;span style="color:#66d9ef">in&lt;/span> parsedJson&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">data&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">routes&lt;/span>&lt;span style="color:#f92672">){&lt;/span>
println id &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#e6db74">&amp;#34;##&amp;#34;&lt;/span> &lt;span style="color:#f92672">+&lt;/span> route&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">asn_name&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">replaceAll&lt;/span>&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">&amp;#39;\\=:# &amp;#39;&lt;/span>&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#e6db74">&amp;#39;&amp;#39;&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#e6db74">&amp;#34;##&amp;#34;&lt;/span> &lt;span style="color:#f92672">+&lt;/span> route&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">prefix&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#e6db74">&amp;#34;##&amp;#34;&lt;/span> &lt;span style="color:#f92672">+&lt;/span> route&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">in_whois&lt;/span> &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#e6db74">&amp;#34;:&amp;#34;&lt;/span> &lt;span style="color:#f92672">+&lt;/span> route&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">in_bgp&lt;/span>
id&lt;span style="color:#f92672">++&lt;/span>
&lt;span style="color:#f92672">}&lt;/span>
&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>parsedJson&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">status_code&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#ae81ff">200&lt;/span> &lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
println &lt;span style="color:#e6db74">&amp;#34;Status code is not 200: &amp;#34;&lt;/span> &lt;span style="color:#f92672">+&lt;/span> parsedJson&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">status_code&lt;/span>
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>&lt;span style="color:#f92672">;&lt;/span>
&lt;span style="color:#f92672">}&lt;/span>
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>&lt;span style="color:#f92672">;&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Result:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>WildValue&lt;/th>
&lt;th>WildAlias&lt;/th>
&lt;th>WildValue2&lt;/th>
&lt;th>Description&lt;/th>
&lt;th>Properties&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>0&lt;/td>
&lt;td>LEVEL3 - Level 3 Parent, LLC&lt;/td>
&lt;td>true:true&lt;/td>
&lt;td>8.0.0.0/9&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>1&lt;/td>
&lt;td>AIRBNB - Airbnb, Inc.&lt;/td>
&lt;td>true:true&lt;/td>
&lt;td>8.18.221.0/24&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>2&lt;/td>
&lt;td>LEVEL3 - Level 3 Parent, LLC&lt;/td>
&lt;td>false:true&lt;/td>
&lt;td>8.16.0.0/12&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>Collector attributes script&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-groovy" data-lang="groovy">String in_whois &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;##WILDVALUE2##&amp;#34;&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">split&lt;/span>&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">&amp;#39;:&amp;#39;&lt;/span>&lt;span style="color:#f92672">)[&lt;/span>&lt;span style="color:#ae81ff">0&lt;/span>&lt;span style="color:#f92672">]&lt;/span>
String in_bgp &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;##WILDVALUE2##&amp;#34;&lt;/span>&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">split&lt;/span>&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">&amp;#39;:&amp;#39;&lt;/span>&lt;span style="color:#f92672">)[&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>&lt;span style="color:#f92672">]&lt;/span>
&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>in_whois &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#34;true&amp;#34;&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">{&lt;/span>
println &lt;span style="color:#e6db74">&amp;#34;in_whois is true&amp;#34;&lt;/span>
&lt;span style="color:#f92672">}&lt;/span>
&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#f92672">(&lt;/span>in_bgp &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#34;true&amp;#34;&lt;/span> &lt;span style="color:#f92672">){&lt;/span>
println &lt;span style="color:#e6db74">&amp;#34;in_bgp is true&amp;#34;&lt;/span>
&lt;span style="color:#f92672">}&lt;/span>
&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Split string&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-groovy" data-lang="groovy">String str1&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#e6db74">&amp;#34;blah:doot:boop&amp;#34;&lt;/span>
println str1&lt;span style="color:#f92672">.&lt;/span>&lt;span style="color:#a6e22e">split&lt;/span>&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#e6db74">&amp;#39;:&amp;#39;&lt;/span>&lt;span style="color:#f92672">)[&lt;/span>&lt;span style="color:#ae81ff">2&lt;/span>&lt;span style="color:#f92672">]&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>ASN Routing Consistency
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>WildValue&lt;/th>
&lt;th>WildAlias&lt;/th>
&lt;th>WildValue2&lt;/th>
&lt;th>Description&lt;/th>
&lt;th>Properties&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>0&lt;/td>
&lt;td>8.18.221.0/24&lt;/td>
&lt;td>true:true&lt;/td>
&lt;td>&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>1&lt;/td>
&lt;td>38.68.202.0/24&lt;/td>
&lt;td>true:true&lt;/td>
&lt;td>&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>2&lt;/td>
&lt;td>2620:127:d000::/40&lt;/td>
&lt;td>true:false&lt;/td>
&lt;td>&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;/li>
&lt;/ul>
&lt;h4 id="being-an-expert">&lt;!-- raw HTML omitted -->DRFT&lt;!-- raw HTML omitted --> Being an expert&lt;/h4>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>&lt;!-- raw HTML omitted -->TODO&lt;!-- raw HTML omitted --> Being an expert&lt;/p>
&lt;p>Expert.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>&lt;!-- raw HTML omitted -->DONE&lt;!-- raw HTML omitted --> Быть экспертом 📚&lt;/p>
&lt;p>По мотивам одной из начальных глав книги &lt;code>Pragmatic Thinking and Learning: Refactor Your Wetware by Andy Hunt&lt;/code>. Эта книга, вроде бы, есть в русском
переводе, я не смог найти сходу.&lt;/p>
&lt;p>Вокруг экспертизы, уровней экспертизы и профессионализма, постоянно происходит
какой-то нездоровый (подземный) шум, вполне характерный для ситуации когда
термин употребляют люди, плохо понимающие значение этого термина. Интуитивно
понятно, что если человек эксперт, то в предмете он разбирается. Это, конечно
же, так, но, у этого состояния, оказывается, присутствуют прелюбопытнейшие
побочки.&lt;/p>
&lt;p>Вкратце, отличие начинающих от экспертов такое:&lt;/p>
&lt;p>Новичкам нужно знать &lt;code>точно&lt;/code>, как делать то или иное действие. Им необходимы
однозначные вводные, не зависящие от контекста. Такие вводные, кстати, в
современном энтерпрайзе называются &lt;code>runbooks&lt;/code> - сборники процедур и правил на
каждый случай. Они заведомо предназначены для новичков и, как следствие,
перегружены лишним смысловым мусором - тем более лишним, чем более близок к
эксперту человек, их выполняющий.&lt;/p>
&lt;p>Эксперта легко отличить от других. Эксперт делает свою работу без видимых
усилий. Новички и продвинутые те же самые задачи будут выполнять (гораздо) менее
эффективно. Возможно в процессе работы им потребуется обратиться к документации
или помощи знакомого профессионала или эксперта. Возможно, неоднократно.&lt;/p>
&lt;p>Большинство людей обладают экспертизой во множестве вещей - например,
большинство физически и психически здоровых взрослых эксперты в хождении. Не
самое легкое занятие, между прочим. Достаточно взглянуть на детей, которые с
трудом держат равновесие и передвигаются - ходить поначалу невероятно сложно.
Этот процесс становится элементарным, как только человек достигает уровня
эксперта.&lt;/p>
&lt;p>Уровень новичка доступен опять же каждому - достаточно сесть, к примеру, за
любой музыкальный инструмент, поставить перед собой ноты и испытать острый
приступ отчаяния. Поздравления, вы начинающий. Впереди - безрадостность и, если
хватит усидчивости, прогресс.&lt;/p>
&lt;p>Эксперт эффективен в своем деле прежде всего потому, что он действует
интуитивно, минуя сознание. Эксперту не нужно тратить время на размышление над
проблемой, он совершает необходимые действия не задумываясь, руководствуясь
огромным опытом, который перешел в состояние инстинкта.&lt;/p>
&lt;p>Обещанные интересные побочки следующие:&lt;/p>
&lt;ul>
&lt;li>Стремление стать экспертом объясняется (во многом) тем, что экспертом быть
гораздо проще, чем новичком. Гораздо круче, проще и прибыльнее делать работу
быстро, не задумываясь и не напрягаясь, чем медленно, потея и фрустрируя от
нехватки времени.&lt;/li>
&lt;li>Эксперт совершенно не обязательно сможет удачно обучать других, менее
эффективных товарищей. Причина в интуитивной природе эксперта. &amp;ldquo;Это все равно
что стакан кому-нибудь описывать или, не дай бог, рюмку: только пальцами
шевелишь и чертыхаешься от полного бессилия&amp;rdquo; - очень похоже. Гораздо более
эффективным учителем может быть профессионал, не достигший еще уровня
экспертизы. Чувак, еще не ставший магом.&lt;/li>
&lt;/ul>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>Ссылки&lt;/p>
&lt;p>
&lt;a href="https://www.goodreads.com/book/show/3063393-pragmatic-thinking-and-learning" target="_blank" rel="noopener">ISBN 9781934356050&lt;/a>&lt;/p>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="shorties">Shorties &lt;!-- raw HTML omitted -->[0/3]&lt;!-- raw HTML omitted -->&lt;/h3>
&lt;h4 id="paypal">&lt;!-- raw HTML omitted -->TODO&lt;!-- raw HTML omitted --> Paypal&lt;/h4>
&lt;p>Here&amp;rsquo;s a fine example of &amp;lsquo;global practices&amp;rsquo;. At least, this story has a good ending.&lt;/p>
&lt;blockquote>
&lt;p>Fun story. There was a period of time early in PayPal&amp;rsquo;s life (1998 or 1999
probably?) when they were growing exponentially and had 3 customer service reps.
They were getting over 10,000 emails per day and simply did not respond to any
of them, as it would be impossible to keep up. Then people started calling their
corporate numbers and dialing random extensions to find someone to talk to. Then
every desk&amp;rsquo;s phone was ringing 24 hours a day, so they unplugged them all and
used cell phones. One guy even showed up at the office&amp;rsquo;s front door, so they had
to install a card reader to keep non-employees out. It was several months where
PayPal had millions of users and there was no customer support whatsoever. Just
none. If your money was gone or something, nobody was going to know or help you
with it. I think that&amp;rsquo;s worse than Twitch right now. Anyway, that&amp;rsquo;s how PayPal
ran for a few months until they solved it in one fell swoop, by opening up a 200
seat call center for support. The day the support center went live, support
responses went from non-existent to same day. And the founders don&amp;rsquo;t regret
running the company like that, since focusing on new customers instead of
existing customers during that time period is what led them to dominate the
online payments market and become a billion dollar company while their
competitors no longer exist. This all came out of an interview with one of the
founders in the past.&lt;/p>
&lt;/blockquote>
&lt;p>
&lt;a href="https://www.reddit.com/r/LivestreamFail/comments/cjd7nc/twitch%5Fbans%5Fstreamer%5Findefinitely%5Fdue%5Fto%5Fhaving/evd6bjw" target="_blank" rel="noopener">Link&lt;/a>&lt;/p>
&lt;h4 id="markdown-here">&lt;!-- raw HTML omitted -->TODO&lt;!-- raw HTML omitted --> Markdown Here&lt;/h4>
&lt;p>&lt;a href="https://markdown-here.com/">https://markdown-here.com/&lt;/a>&lt;/p>
&lt;h4 id="evil-keybindings-in-org-super-agenda">&lt;!-- raw HTML omitted -->POST&lt;!-- raw HTML omitted --> evil keybindings in org-super-agenda&lt;/h4>
&lt;p>If you&amp;rsquo;re using &lt;code>Doom Emacs&lt;/code> - add this to your &lt;code>config.el&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-emacs-lisp" data-lang="emacs-lisp">(after! evil-org-agenda
(setq org-super-agenda-header-map
(&lt;span style="color:#a6e22e">copy-keymap&lt;/span> evil-org-agenda-mode-map)))
&lt;/code>&lt;/pre>&lt;/div>&lt;p>If case you&amp;rsquo;re using vanilla Emacs use &lt;code>eval-before-load&lt;/code>. The &lt;code>after!&lt;/code> macro is
built on &lt;code>eval-before-load&lt;/code>, actually.&lt;/p>
&lt;h4 id="links">Links&lt;/h4>
&lt;p>!
&lt;a href="image%5c_10742.png">TShirt Print&lt;/a>&lt;/p>
&lt;p>Today&amp;rsquo;s links:&lt;/p>
&lt;ul>
&lt;li>
&lt;a href="https://reddit.com/r/emacs/comments/cjgsu1/i%5Fhave%5Fbeen%5Fusing%5Femacs%5Ffor%5Fover%5F10%5Fyears%5Fand%5Fi/" target="_blank" rel="noopener">I have been using Emacs for over 10 years and have never met another Emacs user&lt;/a> - the truth as it is.&lt;/li>
&lt;li>
&lt;a href="http://ganarts.ru/" target="_blank" rel="noopener">This TShirt does not exist&lt;/a> - neural-network generated TShort prints. A hipster&amp;rsquo;s paradise.&lt;/li>
&lt;li>
&lt;a href="http://listentothe.cloud/" target="_blank" rel="noopener">Listen to the clouds&lt;/a> - listen to the airports&amp;rsquo; live radio transmission mixed with ambient music.&lt;/li>
&lt;li>
&lt;a href="https://www.youtube.com/playlist?list=PLpdKaoNaDwSJkEMY21w2N2SO12CkGoY71" target="_blank" rel="noopener">Radio frequency for the Wi-Fi professional&lt;/a> - 20 videos with RF course. A nice one.&lt;/li>
&lt;li>
&lt;a href="https://tls.ulfheim.net/" target="_blank" rel="noopener">The illustrated TLS connection&lt;/a> - an absolutely wonderful resource. If you&amp;rsquo;ve ever wondered how TLS works.&lt;/li>
&lt;li>
&lt;a href="https://www.reddit.com/r/assholedesign/comments/bzb422/apparently%5F950%5Fwasnt%5Fenough%5Ffor%5Fmy%5Ftv%5Fso%5Fsamsung/" target="_blank" rel="noopener">Samsung TV shows adverts in main menu&lt;/a> - cool story.
&lt;a href="https://www.reddit.com/r/assholedesign/comments/bzb422/apparently%5F950%5Fwasnt%5Fenough%5Ffor%5Fmy%5Ftv%5Fso%5Fsamsung/eqrzodk/" target="_blank" rel="noopener">This&lt;/a> comment is particularly frightening:&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>I am not sure the make of the tv you have, but I am assuming that you
probably matched the soundbar and it&amp;rsquo;s samsung. In 2016 I spent nearly $2,000 on
my Samsung TV and soundbar. Right after, like seriously, days after the 1 year
warranty was done, I started getting full screen pop up ads. They would happen
regardless of what I was doing.&lt;/p>
&lt;/blockquote>
&lt;blockquote>
&lt;p>Imagine trying to play a game, and every 90 or so seconds the game would
basically minimize and the pop up would take over. You would have to navigate
out of the ad to resume, but it would just happen again a few minutes later.&lt;/p>
&lt;/blockquote>
&lt;blockquote>
&lt;p>The fix was hard resetting the tv and disconnecting from power and network.&lt;/p>
&lt;/blockquote>
&lt;blockquote>
&lt;p>Absolutely ridiculous&lt;/p>
&lt;/blockquote>
&lt;p>So it goes.&lt;/p>
&lt;p>&lt;a href="http://www.vimgolf.com/">http://www.vimgolf.com/&lt;/a>
&lt;a href="https://www.moolenaar.net/habits.html">https://www.moolenaar.net/habits.html&lt;/a>
&lt;a href="https://www.moolenaar.net/">https://www.moolenaar.net/&lt;/a>&lt;/p>
&lt;h2 id="posts-personal-blog">Posts :@personal-blog:&lt;/h2>
&lt;p>No rights reserved.&lt;/p>
&lt;h3 id="2019-posts">2019 Posts&lt;/h3>
&lt;h4 id="про-алексу">&lt;!-- raw HTML omitted -->DONE&lt;!-- raw HTML omitted --> Про Алексу&lt;/h4>
&lt;p>На декабрьской вписке в Сан Франциско (славный викторианский домик на Mars
Street, минут десять в гору от Castro) в числе прочих замечательных штук были
две умных колонки Amazon Echo (плюс амазоновский сабвуфер). Чумовые устройства,
совершенно.&lt;/p>
&lt;p>Кроме очевидного голосового управления (&lt;code>Alexa, play some ambient&lt;/code>) эти штуковины
теперь умеют сбиваться в стаи. В приложении Alexa можно настроить группы
колонок - эти две стоят в спальне, поэтому назовем эту группу &lt;code>bedroom&lt;/code>,
а эти две стоят в кухне, поэтому называются &lt;code>kitchen&lt;/code> - и управлять
этими группами по отдельности. Включать музыку в жилой комнате или
только в кухне. Плюс к тому, колонки каким-то образом координируются и
раскидывают стерео звук друг на друга.&lt;/p>
&lt;p>Голосовое управление до сих пор не очень удобное, но в целом работает. Надо
внятно сказать &lt;code>Alexa&lt;/code> - тогда колонки убавят громкость и начнут прислушиваться.
Затем можно сказать что-нибудь вроде &lt;code>set timer to 10 minutes&lt;/code> или &lt;code>play Pixies&lt;/code>,
или, например, &lt;code>shut up&lt;/code>, чтобы Алекса замолчала. Можно попросить поставить
будильник или закрыть дверь (если в ней есть совместимый умный замок). Можно
запустить рецепт IFTT. Можно подключить свой аккаунт Spotify и попросить
проиграть тот или иной плейлист.&lt;/p>
&lt;p>Зашел после работы в ближайший Best Buy поглядеть амазоновские устройства
поближе и посмотреть, что еще из подобного есть рынке. Стенд Amazon Alexa стоит
прямо напротив стенда Google (гугловская серия устройств для умного дома теперь
называется Google Nest - гнездо). У обоих есть маленькие умные колонки , умные
дисплеи (Amazon Echo Show и Google Nest Hub), камеры наблюдения, термостаты,
звонки и прочие устройства.&lt;/p>
&lt;p>Город будущего уже появился на горизонте.&lt;/p>
&lt;h3 id="2020-posts">2020 Posts&lt;/h3>
&lt;h4 id="today-i-learned--vim-surround">Today I Learned (vim surround)&lt;/h4>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>&lt;!-- raw HTML omitted -->TODO&lt;!-- raw HTML omitted --> Today I Learned :vim:emacs:evil:surround:&lt;/p>
&lt;p>Today I learned that &lt;code>evil-mode&lt;/code> has support of &lt;code>surround.vim&lt;/code>. Here, I am lazily
copying the documentation (see the link below):&lt;/p>
&lt;!-- raw HTML omitted -->
&lt;p>It&amp;rsquo;s easiest to explain with examples. Press &lt;code>cs&amp;quot;'&lt;/code> inside&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">&amp;#34;Hello world!&amp;#34;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>to change it to&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">&amp;#39;Hello world!&amp;#39;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now press &lt;code>cs'&amp;lt;q&amp;gt;&lt;/code> to change it to&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">&amp;lt;q&amp;gt;Hello world!&amp;lt;/q&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>To go full circle, press &lt;code>cst&amp;quot;&lt;/code> to get&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">&amp;#34;Hello world!&amp;#34;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>To remove the delimiters entirely, press &lt;code>ds&amp;quot;&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">Hello world!
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now with the cursor on &amp;ldquo;Hello&amp;rdquo;, press &lt;code>ysiw]&lt;/code> (&lt;code>iw&lt;/code> is a text object).&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">[Hello] world!
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Let&amp;rsquo;s make that braces and add some space (use &lt;code>}&lt;/code> instead of &lt;code>{&lt;/code> for no space): &lt;code>cs]{&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">{ Hello } world!
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now wrap the entire line in parentheses with &lt;code>yssb&lt;/code> or &lt;code>yss)&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">({ Hello } world!)
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Revert to the original text: &lt;code>ds{ds)&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">Hello world!
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Emphasize hello: &lt;code>ysiw&amp;lt;em&amp;gt;&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">&amp;lt;em&amp;gt;Hello&amp;lt;/em&amp;gt; world!
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Finally, let&amp;rsquo;s try out visual mode. Press a capital &lt;code>V&lt;/code> (for linewise visual mode) followed by &lt;code>S&amp;lt;p class&lt;/code>&amp;quot;important&amp;quot;&amp;gt;=.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">&amp;lt;p class=&amp;#34;important&amp;#34;&amp;gt;
&amp;lt;em&amp;gt;Hello&amp;lt;/em&amp;gt; world!
&amp;lt;/p&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>Links&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://github.com/tpope/vim-surround">https://github.com/tpope/vim-surround&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>&lt;!-- raw HTML omitted -->DONE&lt;!-- raw HTML omitted --> Неожиданное открытие :vim:emacs:evil:surround:&lt;/p>
&lt;p>Сегодня я выяснил, что в &lt;code>evil-mode&lt;/code> есть поддержка &lt;code>surround.vim&lt;/code>. Дальше, лениво
копирую документацию (см. ссылки ниже).&lt;/p>
&lt;!-- raw HTML omitted -->
&lt;p>It&amp;rsquo;s easiest to explain with examples. Press &lt;code>cs&amp;quot;'&lt;/code> inside&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">&amp;#34;Hello world!&amp;#34;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>to change it to&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">&amp;#39;Hello world!&amp;#39;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now press &lt;code>cs'&amp;lt;q&amp;gt;&lt;/code> to change it to&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">&amp;lt;q&amp;gt;Hello world!&amp;lt;/q&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>To go full circle, press &lt;code>cst&amp;quot;&lt;/code> to get&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">&amp;#34;Hello world!&amp;#34;
&lt;/code>&lt;/pre>&lt;/div>&lt;p>To remove the delimiters entirely, press &lt;code>ds&amp;quot;&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">Hello world!
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now with the cursor on &amp;ldquo;Hello&amp;rdquo;, press &lt;code>ysiw]&lt;/code> (&lt;code>iw&lt;/code> is a text object).&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">[Hello] world!
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Let&amp;rsquo;s make that braces and add some space (use &lt;code>}&lt;/code> instead of &lt;code>{&lt;/code> for no space): &lt;code>cs]{&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">{ Hello } world!
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now wrap the entire line in parentheses with &lt;code>yssb&lt;/code> or &lt;code>yss)&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">({ Hello } world!)
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Revert to the original text: &lt;code>ds{ds)&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">Hello world!
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Emphasize hello: &lt;code>ysiw&amp;lt;em&amp;gt;&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">&amp;lt;em&amp;gt;Hello&amp;lt;/em&amp;gt; world!
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Finally, let&amp;rsquo;s try out visual mode. Press a capital &lt;code>V&lt;/code> (for linewise visual mode) followed by &lt;code>S&amp;lt;p class&lt;/code>&amp;quot;important&amp;quot;&amp;gt;=.&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-text" data-lang="text">&amp;lt;p class=&amp;#34;important&amp;#34;&amp;gt;
&amp;lt;em&amp;gt;Hello&amp;lt;/em&amp;gt; world!
&amp;lt;/p&amp;gt;
&lt;/code>&lt;/pre>&lt;/div>&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>Ссылки&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://github.com/tpope/vim-surround">https://github.com/tpope/vim-surround&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h4 id="еще-один-пример-хорошего-дизайна">&lt;!-- raw HTML omitted -->DRFT&lt;!-- raw HTML omitted --> Еще один пример хорошего дизайна&lt;/h4>
&lt;p>В моих новых наушниках Jabra Elite 85h музло ставится на паузу, когда снимаешь
наушники, и продолжает играть когда надеваешь их обратно. Это пример потрясного
прозрачного для пользователя дизайна продукта. Такое поведение совершенно
естественно, привыкаешь к этому моментально.&lt;/p>
&lt;p>Еще из примеров потрясного дизайна - включение подсветки приборной панели
автомобиля ручкой включения фар. То есть происходит следующее: стало темно,
плохо видно панель, ты включаешь подсветку панели и заодно включаешь фары.
То что эти два действия совмещены в одном - совершенно гениальное решение.&lt;/p>
&lt;h4 id="textfsm-state-change">&lt;!-- raw HTML omitted -->DONE&lt;!-- raw HTML omitted --> TextFSM - State Change &lt;!-- raw HTML omitted -->[2/2]&lt;!-- raw HTML omitted -->&lt;/h4>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>&lt;!-- raw HTML omitted -->DONE&lt;!-- raw HTML omitted --> TextFSM - Изменение стейта :automation:textfsm:nornir::&lt;/p>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>Что?&lt;/p>
&lt;p>&lt;code>TextFSM&lt;/code> это питоновский модуль для парсинга (плохо) форматированного текста.
Изначально был спроектирован для парсинга вывода cli разных устройств - в
частности, сетевых.&lt;/p>
&lt;!-- raw HTML omitted -->
&lt;p>В &lt;code>TextFSM&lt;/code> существует три важных сущности: &lt;code>ввод&lt;/code>, &lt;code>список правил&lt;/code> и &lt;code>вывод&lt;/code>.&lt;/p>
&lt;p>Вывод cli я буду называть &lt;code>ввод&lt;/code> (хе-хе) - потому что это та информация, которую
нам нужно распарсить. Этот вывод мы скармливаем машине конечных автоматов
&lt;code>TextFSM&lt;/code>, которая обрабатывает (парсит) его в соответствии со &lt;code>списком правил&lt;/code>.
Получившийся текст уходит в &lt;code>вывод&lt;/code>.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>Как?&lt;/p>
&lt;p>&lt;code>TextFSM&lt;/code> это final state machine - машина конечных автоматов. В простейшем
случае, в &lt;code>TextFSM&lt;/code> есть два состояния: &lt;code>Start&lt;/code> (обязательно должно присутствовать в
файле шаблона) и &lt;code>EOF&lt;/code> - implicit (подразумеваемое) состояние, переход на которое
происходит когда мы прочитали весь файл.&lt;/p>
&lt;p>Алгоритм &lt;code>FSM&lt;/code> примерно такой:&lt;/p>
&lt;ol>
&lt;li>&lt;code>FSM&lt;/code> читает строчку из &lt;code>ввода&lt;/code>;&lt;/li>
&lt;li>&lt;code>FSM&lt;/code> проверяет, матчится ли эта строчка с правилами из &lt;code>списка правил&lt;/code>. Список
правил для каждой строчки из &lt;code>ввода&lt;/code> проверяется сверху вниз, с первой строки
списка правил;&lt;/li>
&lt;li>Если строчка матчится одной из строчек &lt;code>списка правил&lt;/code>, FSM выполняет действие
и переходит к следующей строчке &lt;code>ввода&lt;/code>, снова ее сверяя со &lt;code>списком правил&lt;/code>,
начиная с первой строчки списка. Также, в этом шаге могут заполняться
значения переменных.&lt;/li>
&lt;/ol>
&lt;p>Подробнее про алгоритм &lt;code>FSM&lt;/code>, действия и правила можно почитать в документации
(см. Ссылки)&lt;/p>
&lt;/li>
&lt;/ul>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>Зачем?&lt;/p>
&lt;p>Если у нас простой вывод с повторяющимися значенями, то можно использовать один
стейт, наполняя строчку значениями отматченных переменных. Если вывод менее
структурирован, то, вероятнее всего, придется использовать дополнительные стейты.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>FSM с одним состоянием (не считая EOF)&lt;/p>
&lt;p>Одного стейта достаточно, когда &lt;code>ввод&lt;/code> однозначно определяет разделитель между
строчками &lt;code>вывода&lt;/code>, как, например, тут:&lt;/p>
&lt;p>[ &lt;code>Ввод&lt;/code> ]&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-c" data-lang="c">Server group radius
Sharecount &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span> sg_unconfigured &lt;span style="color:#f92672">=&lt;/span> FALSE
Type &lt;span style="color:#f92672">=&lt;/span> standard Memlocks &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
Server(&lt;span style="color:#ae81ff">10.14.121.20&lt;/span>&lt;span style="color:#f92672">:&lt;/span>&lt;span style="color:#ae81ff">1814&lt;/span>,&lt;span style="color:#ae81ff">1815&lt;/span>) Transactions:
Authen: &lt;span style="color:#ae81ff">6&lt;/span> Author: &lt;span style="color:#ae81ff">0&lt;/span> Acct: &lt;span style="color:#ae81ff">0&lt;/span>
Server_auto_test_enabled: FALSE
Keywrap enabled: FALSE
Server(&lt;span style="color:#ae81ff">10.3.121.20&lt;/span>&lt;span style="color:#f92672">:&lt;/span>&lt;span style="color:#ae81ff">1814&lt;/span>,&lt;span style="color:#ae81ff">1815&lt;/span>) Transactions:
Authen: &lt;span style="color:#ae81ff">3&lt;/span> Author: &lt;span style="color:#ae81ff">33&lt;/span> Acct: &lt;span style="color:#ae81ff">333&lt;/span>
Server_auto_test_enabled: FALSE
Keywrap enabled: FALSE
Server(&lt;span style="color:#ae81ff">10.4.12.26&lt;/span>&lt;span style="color:#f92672">:&lt;/span>&lt;span style="color:#ae81ff">1814&lt;/span>,&lt;span style="color:#ae81ff">1815&lt;/span>) Transactions:
Authen: &lt;span style="color:#ae81ff">4&lt;/span> Author: &lt;span style="color:#ae81ff">0&lt;/span> Acct: &lt;span style="color:#ae81ff">0&lt;/span>
Server_auto_test_enabled: FALSE
Keywrap enabled: FALSE
Server(&lt;span style="color:#ae81ff">10.129.111.20&lt;/span>&lt;span style="color:#f92672">:&lt;/span>&lt;span style="color:#ae81ff">1814&lt;/span>,&lt;span style="color:#ae81ff">1815&lt;/span>) Transactions:
Authen: &lt;span style="color:#ae81ff">5&lt;/span> Author: &lt;span style="color:#ae81ff">0&lt;/span> Acct: &lt;span style="color:#ae81ff">555&lt;/span>
Server_auto_test_enabled: FALSE
Keywrap enabled: FALSE
Server(&lt;span style="color:#ae81ff">172.30.2.123&lt;/span>&lt;span style="color:#f92672">:&lt;/span>&lt;span style="color:#ae81ff">1812&lt;/span>,&lt;span style="color:#ae81ff">1813&lt;/span>) Transactions:
Authen: &lt;span style="color:#ae81ff">0&lt;/span> Author: &lt;span style="color:#ae81ff">0&lt;/span> Acct: &lt;span style="color:#ae81ff">0&lt;/span>
Server_auto_test_enabled: TRUE
Keywrap enabled: FALSE
Server group SERVER_GROUP_2
Sharecount &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span> sg_unconfigured &lt;span style="color:#f92672">=&lt;/span> FALSE
Type &lt;span style="color:#f92672">=&lt;/span> standard Memlocks &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
Server(&lt;span style="color:#ae81ff">172.30.10.123&lt;/span>&lt;span style="color:#f92672">:&lt;/span>&lt;span style="color:#ae81ff">1812&lt;/span>,&lt;span style="color:#ae81ff">1813&lt;/span>) Transactions:
Authen: &lt;span style="color:#ae81ff">2249&lt;/span> Author: &lt;span style="color:#ae81ff">0&lt;/span> Acct: &lt;span style="color:#ae81ff">22424&lt;/span>
Server_auto_test_enabled: TRUE
Keywrap enabled: FALSE
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Эту конструкцию можно распарсить так:&lt;/p>
&lt;p>[ &lt;code>Список правил&lt;/code> ]&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-c" data-lang="c">Value Filldown &lt;span style="color:#a6e22e">NAME&lt;/span> (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>S&lt;span style="color:#f92672">+&lt;/span>)
Value Filldown SHARECOUNT (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value Filldown SG_UNCONFIGURED (TRUE&lt;span style="color:#f92672">|&lt;/span>FALSE)
Value Filldown TYPE (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>w&lt;span style="color:#f92672">+&lt;/span>)
Value Filldown MEMLOCKS (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value Required SERVER_IP (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>.&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>.&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>.&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value AUTH_PORT (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value ACC_PORT (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value AUTO_TEST_ENABLED (TRUE&lt;span style="color:#f92672">|&lt;/span>FALSE)
Value KEYWRAP_ENABLED (TRUE&lt;span style="color:#f92672">|&lt;/span>FALSE)
Value AUTHEN_COUNT (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value AUTHOR_COUNT (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value ACCT_COUNT (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Start
&lt;span style="color:#f92672">^&lt;/span>Server group &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{NAME}
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>Sharecount &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{SHARECOUNT}.&lt;span style="color:#f92672">*&lt;/span>sg_unconfigured &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{SG_UNCONFIGURED}
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>Type &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{TYPE}.&lt;span style="color:#f92672">*&lt;/span>Memlocks &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{MEMLOCKS}
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>Server&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>(&lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{SERVER_IP}&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>&lt;span style="color:#f92672">:&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{AUTH_PORT},&lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{ACC_PORT}&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>)
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>Authen: &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{AUTHEN_COUNT}.&lt;span style="color:#f92672">*&lt;/span>Author: &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{AUTHOR_COUNT}.&lt;span style="color:#f92672">*&lt;/span>Acct: &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{ACCT_COUNT}
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>Server_auto_test_enabled: &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{AUTO_TEST_ENABLED}
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>Keywrap enabled: &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{KEYWRAP_ENABLED} &lt;span style="color:#f92672">-&amp;gt;&lt;/span> Record
&lt;/code>&lt;/pre>&lt;/div>&lt;pre>&lt;code class="language-mermaid" data-lang="mermaid">graph TD;
Start--&amp;gt;EOF;
&lt;/code>&lt;/pre>&lt;p>[ &lt;code>Вывод&lt;/code> ]&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-python" data-lang="python">[&lt;span style="color:#e6db74">&amp;#39;NAME&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;SHARECOUNT&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;SG_UNCONFIGURED&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;TYPE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;MEMLOCKS&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;SERVER_IP&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;AUTH_PORT&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;ACC_PORT&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;AUTO_TEST_ENABLED&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;KEYWRAP_ENABLED&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;AUTHEN_COUNT&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;AUTHOR_COUNT&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;ACCT_COUNT&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;radius&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;standard&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;10.14.121.20&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1814&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1815&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;6&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;radius&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;standard&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;10.3.121.20&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1814&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1815&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;3&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;33&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;333&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;radius&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;standard&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;10.4.12.26&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1814&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1815&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;4&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;radius&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;standard&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;10.129.111.20&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1814&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1815&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;5&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;555&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;radius&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;standard&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;172.30.2.123&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1812&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1813&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;TRUE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;SERVER_GROUP_2&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;standard&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;172.30.10.123&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1812&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1813&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;TRUE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;2249&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;22424&amp;#39;&lt;/span>]
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Обратите внимание на строчку &lt;code>Keywrap enabled:&lt;/code>. Она идет в конце каждой секции и
на ней отрабатывает действие &lt;code>Record&lt;/code> - которое записывает накопленные значения в
строчку &lt;code>вывода&lt;/code>.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>FSM с двумя состояниями (не считая EOF)&lt;/p>
&lt;p>[ &lt;code>Ввод&lt;/code> ]&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-c" data-lang="c">total number of groups:&lt;span style="color:#ae81ff">3&lt;/span>
following RADIUS server groups are configured:
group radius:
server: all configured radius servers
deadtime is &lt;span style="color:#ae81ff">0&lt;/span>
group RADIUS_GROUP_A:
server: &lt;span style="color:#ae81ff">10.65.101.22&lt;/span> on auth&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1814&lt;/span>, acct&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1815&lt;/span>
server: &lt;span style="color:#ae81ff">10.110.101.22&lt;/span> on auth&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1814&lt;/span>, acct&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1815&lt;/span>
server: &lt;span style="color:#ae81ff">10.194.101.22&lt;/span> on auth&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1814&lt;/span>, acct&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1815&lt;/span>
server: &lt;span style="color:#ae81ff">10.10.10.27&lt;/span> on auth&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1814&lt;/span>, acct&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1815&lt;/span>
deadtime is &lt;span style="color:#ae81ff">0&lt;/span>
vrf is management
Source interface mgmt0
group RADIUS_GROUP_B:
server: &lt;span style="color:#ae81ff">172.40.2.14&lt;/span> on auth&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1812&lt;/span>, acct&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1813&lt;/span>
deadtime is &lt;span style="color:#ae81ff">10&lt;/span>
Source interface loopback0
&lt;/code>&lt;/pre>&lt;/div>&lt;p>[ &lt;code>Список правил&lt;/code> ]&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-c" data-lang="c">Value Required &lt;span style="color:#a6e22e">NAME&lt;/span> (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>S&lt;span style="color:#f92672">+&lt;/span>)
Value List SERVER (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>.&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>.&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>.&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+|&lt;/span>all configured radius servers)
Value DEADTIME (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value List AUTH_PORT (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value List ACCT_PORT (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value VRF (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>S&lt;span style="color:#f92672">+&lt;/span>)
Value SOURCE_INTERFACE (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>S&lt;span style="color:#f92672">+&lt;/span>)
Start
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>group &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{NAME}&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#f92672">-&amp;gt;&lt;/span> Group
Group
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>server:&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>s&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{SERVER}&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>s&lt;span style="color:#f92672">*&lt;/span>on auth&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{AUTH_PORT}, acct&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{ACCT_PORT}
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>server:&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>s&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{SERVER} &lt;span style="color:#f92672">-&amp;gt;&lt;/span> AllServers
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>vrf is &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{VRF}
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>Source interface &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{SOURCE_INTERFACE} &lt;span style="color:#f92672">-&amp;gt;&lt;/span> Record Start
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>deadtime is &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{DEADTIME}
AllServers
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>deadtime is &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{DEADTIME} &lt;span style="color:#f92672">-&amp;gt;&lt;/span> Record Start
&lt;/code>&lt;/pre>&lt;/div>&lt;pre>&lt;code class="language-mermaid" data-lang="mermaid">graph TD;
Start--&amp;gt;AllServers;
AllServers--&amp;gt;Start;
Start--&amp;gt;EOF;
&lt;/code>&lt;/pre>&lt;p>[ &lt;code>Вывод&lt;/code> ]&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-python" data-lang="python">[&lt;span style="color:#e6db74">&amp;#39;NAME&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;SERVER&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;DEADTIME&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;AUTH_PORT&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;ACCT_PORT&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;VRF&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;SOURCE_INTERFACE&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;radius&amp;#39;&lt;/span>, [&lt;span style="color:#e6db74">&amp;#39;all configured radius servers&amp;#39;&lt;/span>], &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>, [], [], &lt;span style="color:#e6db74">&amp;#39;&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;RADIUS_GROUP_A&amp;#39;&lt;/span>, [&lt;span style="color:#e6db74">&amp;#39;10.65.101.22&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;10.110.101.22&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;10.194.101.22&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;10.10.10.27&amp;#39;&lt;/span>], &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>, [&lt;span style="color:#e6db74">&amp;#39;1814&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1814&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1814&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1814&amp;#39;&lt;/span>], [&lt;span style="color:#e6db74">&amp;#39;1815&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1815&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1815&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1815&amp;#39;&lt;/span>], &lt;span style="color:#e6db74">&amp;#39;management&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;mgmt0&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;RADIUS_GROUP_B&amp;#39;&lt;/span>, [&lt;span style="color:#e6db74">&amp;#39;172.40.2.14&amp;#39;&lt;/span>], &lt;span style="color:#e6db74">&amp;#39;10&amp;#39;&lt;/span>, [&lt;span style="color:#e6db74">&amp;#39;1812&amp;#39;&lt;/span>], [&lt;span style="color:#e6db74">&amp;#39;1813&amp;#39;&lt;/span>], &lt;span style="color:#e6db74">&amp;#39;&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;loopback0&amp;#39;&lt;/span>]
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Ага, но почему так хитро? Потому что в группе &lt;code>radius&lt;/code> последняя строчка перед
следющей группой это &lt;code>deadtime is 0&lt;/code>, а в остальных группах последняя строчка это
&lt;code>Source interface&lt;/code>. Для обработки этих разных групп нужны разные списки правил,
которые раскидываются по разным стейтам (&lt;code>Start&lt;/code> и &lt;code>AllServers&lt;/code>).&lt;/p>
&lt;p>Условие перехода на стейт &lt;code>AllServers&lt;/code> - строчка &lt;code>server: all configured radius servers&lt;/code>, которая матчится правилом &lt;code>^.*server:\s*${SERVER} -&amp;gt; AllServers&lt;/code>.&lt;/p>
&lt;p>В стейте &lt;code>AllServers&lt;/code> мы доходим до строчки &lt;code>deadtime is&lt;/code>, записываем состояние и
возвращаемся в стейт &lt;code>Start&lt;/code>.&lt;/p>
&lt;p>Если &lt;code>FSM&lt;/code> остается в стейте &lt;code>Start&lt;/code>, запись состояния происходит после матчинга
строчки &lt;code>Source interface&lt;/code>.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>Ссылки&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://github.com/google/textfsm/wiki/TextFSM">https://github.com/google/textfsm/wiki/TextFSM&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>&lt;!-- raw HTML omitted -->DONE&lt;!-- raw HTML omitted --> TextFSM - Changing a state :automation:textfsm:nornir::&lt;/p>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>What?&lt;/p>
&lt;p>&lt;code>TextFSM&lt;/code> is a python module for parsing (badly) formatted text. It was originally
designed to parse the output of cli from different devices - in particular, the
network.&lt;/p>
&lt;!-- raw HTML omitted -->
&lt;p>In &lt;code>TextFSM&lt;/code> there are three important entities: &lt;code>input&lt;/code>, &lt;code>list of rules&lt;/code> and &lt;code>output&lt;/code>.&lt;/p>
&lt;p>The CLI output I&amp;rsquo;m going to call &lt;code>input&lt;/code> (hehehe) because that&amp;rsquo;s the information
that we need to parse. That&amp;rsquo;s the conclusion we&amp;rsquo;re feeding to the FSM. &lt;code>TextFSM&lt;/code>,
which processes (parses) it according to the &lt;code>list of rules&lt;/code>. The resulting text
goes into &lt;code>output&lt;/code>.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>How?&lt;/p>
&lt;p>&lt;code>TextFSM&lt;/code> is a final state machine. In the simplest case, in &lt;code>TextFSM&lt;/code> there are two
states: &lt;code>Start&lt;/code> (must be present in the template file) and &lt;code>EOF&lt;/code> - an implicit state
to which the transition happens when FSM reaches the end of the file.&lt;/p>
&lt;p>The &lt;code>FSM&lt;/code> alrorithm is something like this:&lt;/p>
&lt;ol>
&lt;li>&lt;code>FSM&lt;/code> reads a line from &lt;code>input&lt;/code>;&lt;/li>
&lt;li>&lt;code>FSM&lt;/code> checks if this line matches the rules from the &lt;code>list of rules&lt;/code>. List of the
rules for each line of &lt;code>input&lt;/code> is checked from top to bottom, starting from the
first line of the list of rules;&lt;/li>
&lt;li>If a line matches one of the rules in the &lt;code>list of rules&lt;/code>, the FSM executes the
action and goes to the next line of &lt;code>input&lt;/code>, checking it against the &lt;code>list of rules&lt;/code> again, starting on the first line of the list, again. Also, in this
step, &lt;code>FSM&lt;/code> can fill in the variable values.&lt;/li>
&lt;/ol>
&lt;p>More information on the algorithm, actions and rules can be found in the
documentation. (see &lt;strong>References&lt;/strong>)&lt;/p>
&lt;/li>
&lt;/ul>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>Why?&lt;/p>
&lt;p>If we have a simple output with repeating values, we can use only one state, filling
the string with the values of matched variables. If the output is less
structured, you will most likely have to use additional states.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>FSM with one state (except EOF)&lt;/p>
&lt;p>One stage is enough when &lt;code>input&lt;/code> clearly defines the separator between the lines
of &lt;code>output&lt;/code>, as for example here:&lt;/p>
&lt;p>[ &lt;code>Input&lt;/code> ]&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-c" data-lang="c">Server group radius
Sharecount &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span> sg_unconfigured &lt;span style="color:#f92672">=&lt;/span> FALSE
Type &lt;span style="color:#f92672">=&lt;/span> standard Memlocks &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
Server(&lt;span style="color:#ae81ff">10.14.121.20&lt;/span>&lt;span style="color:#f92672">:&lt;/span>&lt;span style="color:#ae81ff">1814&lt;/span>,&lt;span style="color:#ae81ff">1815&lt;/span>) Transactions:
Authen: &lt;span style="color:#ae81ff">6&lt;/span> Author: &lt;span style="color:#ae81ff">0&lt;/span> Acct: &lt;span style="color:#ae81ff">0&lt;/span>
Server_auto_test_enabled: FALSE
Keywrap enabled: FALSE
Server(&lt;span style="color:#ae81ff">10.3.121.20&lt;/span>&lt;span style="color:#f92672">:&lt;/span>&lt;span style="color:#ae81ff">1814&lt;/span>,&lt;span style="color:#ae81ff">1815&lt;/span>) Transactions:
Authen: &lt;span style="color:#ae81ff">3&lt;/span> Author: &lt;span style="color:#ae81ff">33&lt;/span> Acct: &lt;span style="color:#ae81ff">333&lt;/span>
Server_auto_test_enabled: FALSE
Keywrap enabled: FALSE
Server(&lt;span style="color:#ae81ff">10.4.12.26&lt;/span>&lt;span style="color:#f92672">:&lt;/span>&lt;span style="color:#ae81ff">1814&lt;/span>,&lt;span style="color:#ae81ff">1815&lt;/span>) Transactions:
Authen: &lt;span style="color:#ae81ff">4&lt;/span> Author: &lt;span style="color:#ae81ff">0&lt;/span> Acct: &lt;span style="color:#ae81ff">0&lt;/span>
Server_auto_test_enabled: FALSE
Keywrap enabled: FALSE
Server(&lt;span style="color:#ae81ff">10.129.111.20&lt;/span>&lt;span style="color:#f92672">:&lt;/span>&lt;span style="color:#ae81ff">1814&lt;/span>,&lt;span style="color:#ae81ff">1815&lt;/span>) Transactions:
Authen: &lt;span style="color:#ae81ff">5&lt;/span> Author: &lt;span style="color:#ae81ff">0&lt;/span> Acct: &lt;span style="color:#ae81ff">555&lt;/span>
Server_auto_test_enabled: FALSE
Keywrap enabled: FALSE
Server(&lt;span style="color:#ae81ff">172.30.2.123&lt;/span>&lt;span style="color:#f92672">:&lt;/span>&lt;span style="color:#ae81ff">1812&lt;/span>,&lt;span style="color:#ae81ff">1813&lt;/span>) Transactions:
Authen: &lt;span style="color:#ae81ff">0&lt;/span> Author: &lt;span style="color:#ae81ff">0&lt;/span> Acct: &lt;span style="color:#ae81ff">0&lt;/span>
Server_auto_test_enabled: TRUE
Keywrap enabled: FALSE
Server group SERVER_GROUP_2
Sharecount &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span> sg_unconfigured &lt;span style="color:#f92672">=&lt;/span> FALSE
Type &lt;span style="color:#f92672">=&lt;/span> standard Memlocks &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
Server(&lt;span style="color:#ae81ff">172.30.10.123&lt;/span>&lt;span style="color:#f92672">:&lt;/span>&lt;span style="color:#ae81ff">1812&lt;/span>,&lt;span style="color:#ae81ff">1813&lt;/span>) Transactions:
Authen: &lt;span style="color:#ae81ff">2249&lt;/span> Author: &lt;span style="color:#ae81ff">0&lt;/span> Acct: &lt;span style="color:#ae81ff">22424&lt;/span>
Server_auto_test_enabled: TRUE
Keywrap enabled: FALSE
&lt;/code>&lt;/pre>&lt;/div>&lt;p>This structure can be parsed this way:&lt;/p>
&lt;p>[ &lt;code>List of rules&lt;/code> ]&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-c" data-lang="c">Value Filldown &lt;span style="color:#a6e22e">NAME&lt;/span> (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>S&lt;span style="color:#f92672">+&lt;/span>)
Value Filldown SHARECOUNT (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value Filldown SG_UNCONFIGURED (TRUE&lt;span style="color:#f92672">|&lt;/span>FALSE)
Value Filldown TYPE (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>w&lt;span style="color:#f92672">+&lt;/span>)
Value Filldown MEMLOCKS (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value Required SERVER_IP (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>.&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>.&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>.&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value AUTH_PORT (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value ACC_PORT (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value AUTO_TEST_ENABLED (TRUE&lt;span style="color:#f92672">|&lt;/span>FALSE)
Value KEYWRAP_ENABLED (TRUE&lt;span style="color:#f92672">|&lt;/span>FALSE)
Value AUTHEN_COUNT (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value AUTHOR_COUNT (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value ACCT_COUNT (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Start
&lt;span style="color:#f92672">^&lt;/span>Server group &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{NAME}
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>Sharecount &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{SHARECOUNT}.&lt;span style="color:#f92672">*&lt;/span>sg_unconfigured &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{SG_UNCONFIGURED}
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>Type &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{TYPE}.&lt;span style="color:#f92672">*&lt;/span>Memlocks &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{MEMLOCKS}
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>Server&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>(&lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{SERVER_IP}&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>&lt;span style="color:#f92672">:&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{AUTH_PORT},&lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{ACC_PORT}&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>)
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>Authen: &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{AUTHEN_COUNT}.&lt;span style="color:#f92672">*&lt;/span>Author: &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{AUTHOR_COUNT}.&lt;span style="color:#f92672">*&lt;/span>Acct: &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{ACCT_COUNT}
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>Server_auto_test_enabled: &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{AUTO_TEST_ENABLED}
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>Keywrap enabled: &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{KEYWRAP_ENABLED} &lt;span style="color:#f92672">-&amp;gt;&lt;/span> Record
&lt;/code>&lt;/pre>&lt;/div>&lt;pre>&lt;code class="language-mermaid" data-lang="mermaid">graph TD;
Start--&amp;gt;EOF;
&lt;/code>&lt;/pre>&lt;p>[ &lt;code>Output&lt;/code> ]&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-python" data-lang="python">[&lt;span style="color:#e6db74">&amp;#39;NAME&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;SHARECOUNT&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;SG_UNCONFIGURED&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;TYPE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;MEMLOCKS&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;SERVER_IP&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;AUTH_PORT&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;ACC_PORT&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;AUTO_TEST_ENABLED&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;KEYWRAP_ENABLED&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;AUTHEN_COUNT&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;AUTHOR_COUNT&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;ACCT_COUNT&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;radius&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;standard&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;10.14.121.20&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1814&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1815&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;6&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;radius&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;standard&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;10.3.121.20&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1814&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1815&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;3&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;33&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;333&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;radius&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;standard&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;10.4.12.26&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1814&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1815&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;4&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;radius&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;standard&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;10.129.111.20&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1814&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1815&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;5&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;555&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;radius&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;standard&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;172.30.2.123&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1812&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1813&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;TRUE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;SERVER_GROUP_2&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;standard&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;172.30.10.123&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1812&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1813&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;TRUE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;FALSE&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;2249&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;22424&amp;#39;&lt;/span>]
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Note the line &lt;code>Keywrap enabled:&lt;/code>. It goes in the end of each section and triggers
the the &lt;code>Record&lt;/code> action - which writes the accumulated values to &lt;code>output&lt;/code>.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>FSM with two states (except EOF)&lt;/p>
&lt;p>[ &lt;code>Input&lt;/code> ]&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-c" data-lang="c">total number of groups:&lt;span style="color:#ae81ff">3&lt;/span>
following RADIUS server groups are configured:
group radius:
server: all configured radius servers
deadtime is &lt;span style="color:#ae81ff">0&lt;/span>
group RADIUS_GROUP_A:
server: &lt;span style="color:#ae81ff">10.65.101.22&lt;/span> on auth&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1814&lt;/span>, acct&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1815&lt;/span>
server: &lt;span style="color:#ae81ff">10.110.101.22&lt;/span> on auth&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1814&lt;/span>, acct&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1815&lt;/span>
server: &lt;span style="color:#ae81ff">10.194.101.22&lt;/span> on auth&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1814&lt;/span>, acct&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1815&lt;/span>
server: &lt;span style="color:#ae81ff">10.10.10.27&lt;/span> on auth&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1814&lt;/span>, acct&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1815&lt;/span>
deadtime is &lt;span style="color:#ae81ff">0&lt;/span>
vrf is management
Source interface mgmt0
group RADIUS_GROUP_B:
server: &lt;span style="color:#ae81ff">172.40.2.14&lt;/span> on auth&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1812&lt;/span>, acct&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#ae81ff">1813&lt;/span>
deadtime is &lt;span style="color:#ae81ff">10&lt;/span>
Source interface loopback0
&lt;/code>&lt;/pre>&lt;/div>&lt;p>[ &lt;code>List of rules&lt;/code> ]&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-c" data-lang="c">Value Required &lt;span style="color:#a6e22e">NAME&lt;/span> (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>S&lt;span style="color:#f92672">+&lt;/span>)
Value List SERVER (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>.&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>.&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>.&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+|&lt;/span>all configured radius servers)
Value DEADTIME (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value List AUTH_PORT (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value List ACCT_PORT (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>d&lt;span style="color:#f92672">+&lt;/span>)
Value VRF (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>S&lt;span style="color:#f92672">+&lt;/span>)
Value SOURCE_INTERFACE (&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>S&lt;span style="color:#f92672">+&lt;/span>)
Start
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>group &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{NAME}&lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#f92672">-&amp;gt;&lt;/span> Group
Group
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>server:&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>s&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{SERVER}&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>s&lt;span style="color:#f92672">*&lt;/span>on auth&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{AUTH_PORT}, acct&lt;span style="color:#f92672">-&lt;/span>port &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{ACCT_PORT}
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>server:&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>s&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{SERVER} &lt;span style="color:#f92672">-&amp;gt;&lt;/span> AllServers
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>vrf is &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{VRF}
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>Source interface &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{SOURCE_INTERFACE} &lt;span style="color:#f92672">-&amp;gt;&lt;/span> Record Start
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>deadtime is &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{DEADTIME}
AllServers
&lt;span style="color:#f92672">^&lt;/span>.&lt;span style="color:#f92672">*&lt;/span>deadtime is &lt;span style="color:#960050;background-color:#1e0010">$&lt;/span>{DEADTIME} &lt;span style="color:#f92672">-&amp;gt;&lt;/span> Record Start
&lt;/code>&lt;/pre>&lt;/div>&lt;pre>&lt;code class="language-mermaid" data-lang="mermaid">graph TD;
Start--&amp;gt;AllServers;
AllServers--&amp;gt;Start;
Start--&amp;gt;EOF;
&lt;/code>&lt;/pre>&lt;p>[ &lt;code>Output&lt;/code> ]&lt;/p>
&lt;div class="highlight">&lt;pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4">&lt;code class="language-python" data-lang="python">[&lt;span style="color:#e6db74">&amp;#39;NAME&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;SERVER&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;DEADTIME&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;AUTH_PORT&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;ACCT_PORT&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;VRF&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;SOURCE_INTERFACE&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;radius&amp;#39;&lt;/span>, [&lt;span style="color:#e6db74">&amp;#39;all configured radius servers&amp;#39;&lt;/span>], &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>, [], [], &lt;span style="color:#e6db74">&amp;#39;&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;RADIUS_GROUP_A&amp;#39;&lt;/span>, [&lt;span style="color:#e6db74">&amp;#39;10.65.101.22&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;10.110.101.22&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;10.194.101.22&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;10.10.10.27&amp;#39;&lt;/span>], &lt;span style="color:#e6db74">&amp;#39;0&amp;#39;&lt;/span>, [&lt;span style="color:#e6db74">&amp;#39;1814&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1814&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1814&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1814&amp;#39;&lt;/span>], [&lt;span style="color:#e6db74">&amp;#39;1815&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1815&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1815&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;1815&amp;#39;&lt;/span>], &lt;span style="color:#e6db74">&amp;#39;management&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;mgmt0&amp;#39;&lt;/span>]
[&lt;span style="color:#e6db74">&amp;#39;RADIUS_GROUP_B&amp;#39;&lt;/span>, [&lt;span style="color:#e6db74">&amp;#39;172.40.2.14&amp;#39;&lt;/span>], &lt;span style="color:#e6db74">&amp;#39;10&amp;#39;&lt;/span>, [&lt;span style="color:#e6db74">&amp;#39;1812&amp;#39;&lt;/span>], [&lt;span style="color:#e6db74">&amp;#39;1813&amp;#39;&lt;/span>], &lt;span style="color:#e6db74">&amp;#39;&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;loopback0&amp;#39;&lt;/span>]
&lt;/code>&lt;/pre>&lt;/div>&lt;p>Ok, but why do we need 2 states? Because in the group &lt;code>radius&lt;/code> the last line
before the next group is &lt;code>deadtime is 0&lt;/code>, and in other groups the last line is
&lt;code>Source interface&lt;/code>. To process these different groups, you need different rule
lists, which go to different states (&lt;code>Start&lt;/code> and &lt;code>AllServers&lt;/code>).&lt;/p>
&lt;p>The condition that triggers the transition to &lt;code>AllServers&lt;/code> state - the string
&lt;code>server: all configured radius servers&lt;/code>, that is getting matched by this rule:
&lt;code>^.*server:\s*${SERVER} -&amp;gt; AllServers&lt;/code>.&lt;/p>
&lt;p>In the state &lt;code>AllServers&lt;/code> FSM reaches the line &lt;code>deadtime is&lt;/code>, writes the state and
returns to the state &lt;code>Start&lt;/code>.&lt;/p>
&lt;p>If &lt;code>FSM&lt;/code> stays in the state &lt;code>Start&lt;/code>, the state of the collected variables is getting
written after the &lt;code>Source interface&lt;/code> line is getting matched.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>Links&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://github.com/google/textfsm/wiki/TextFSM">https://github.com/google/textfsm/wiki/TextFSM&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h4 id="ansible-for-devops-ru-en">Ansible For Devops [ru/en]&lt;/h4>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>&lt;!-- raw HTML omitted -->DONE&lt;!-- raw HTML omitted --> Ansible For Devops [ru] :ansible:осуждение:&lt;/p>
&lt;p>Взял тут книгу по Ansible, непонятное в ней начинается с первых же страниц:&lt;/p>
&lt;ol>
&lt;li>Clear - Ansible uses a simple syntax (YAML) and is easy for anyone
(developers, sysadmins, managers) to understand. APIs are simple and
sensible.&lt;/li>
&lt;/ol>
&lt;p>Угу, если не принимать во внимание indentation и сложность (и неоднозначность)
синтаксиса YAML.&lt;/p>
&lt;ol>
&lt;li>Fast - Fast to learn, fast to set up—especially considering you don’t need to
install extra agents or daemons on all your servers!&lt;/li>
&lt;/ol>
&lt;p>Ага, если не учитывать довольно значительное количество значений по умолчанию,
которые совершенно не очевидны, если не заглядывать в документацию. Кстати,
хорошая оговорка про то, что fast в значении fast to learn/set up (что не вполне
верно), но не в значении fast to execute. Исполняются же плейбуки жутко
медленно.&lt;/p>
&lt;ol>
&lt;li>Complete - Ansible does three things in one, and does them very well.&lt;/li>
&lt;/ol>
&lt;p>Ну да, если не учитывать тот факт, что всякий раз, когда мне надо что-то
автоматизировать, мне приходится колхозить либо дополнительные скрипты, либо api
вызовы непосредственно из Ansible. Не то, что бы это была беда самого ансибля,
конечно, но.&lt;/p>
&lt;ol>
&lt;li>Efficient - No extra software on your servers means more resources for your
applications. Also, since Ansible modules work via JSON, Ansible is
extensible with modules written in a programming language you already know.&lt;/li>
&lt;/ol>
&lt;p>В целом, наверное, правда. &amp;lsquo;Efficient&amp;rsquo; as in &amp;lsquo;clientless&amp;rsquo;.&lt;/p>
&lt;ol>
&lt;li>Secure - Ansible uses SSH, and requires no extra open ports or potentially -
vulnerable daemons on your servers.&lt;/li>
&lt;/ol>
&lt;p>Ну в целом тоже, наверное, правда. Но ставить в заслугу продукту то, что он
работает через безопасный транспорт как-то, не знаю, слишком уж по-хипстерски.&lt;/p>
&lt;p>Дальше идет пример с модулем &lt;code>ping&lt;/code>.&lt;/p>
&lt;blockquote>
&lt;p>&lt;code>ansible example -m ping -u [username]&lt;/code>&lt;/p>
&lt;/blockquote>
&lt;p>И поясняется:&lt;/p>
&lt;blockquote>
&lt;p>If everything worked, you should see a message that shows &lt;code>www.example.com | success &amp;gt;&amp;gt;&lt;/code>, then the result of your ping.&lt;/p>
&lt;/blockquote>
&lt;p>Это довольно типичный, кстати, пример, который в целом хорошо иллюстрирует то,
что мне не нравится в ансибле:&lt;/p>
&lt;ol>
&lt;li>Нигде не упоминается, что это не &lt;code>icmp ping&lt;/code>. Я знаю, что в актуальной
документации специально оговаривается, что ребята, это не &lt;code>icmp&lt;/code>, если хотите
&lt;code>icmp&lt;/code> то делайте &lt;code>net_ping&lt;/code> и проч и проч НО: проблема в том, что этот самый
&lt;code>ping&lt;/code> не надо было называть в точности так же, как и самую распространенную
утилиту диагностики сетевого уровня. Это плохой дизайн, хреновая идея, это
запутывает. Еще один пример корневого плохого дизайна это стандартная пара
ключей &lt;code>src&lt;/code> / &lt;code>dest&lt;/code>, которая используется в множестве модулей Ansible.
Присмотритесь: не &lt;code>src&lt;/code> / &lt;code>dst&lt;/code>, но &lt;code>src&lt;/code> / &lt;code>dest&lt;/code>. Никогда так не делайте.&lt;/li>
&lt;li>Нигде (в этом конкретном примере в книге) не упоминается, как эта команда
работает и что она действительно делает. Это в целом тоже часть философии
Ansible - под капот нужно заглядывать только тогда, когда это действительно
необходимо (по мнению архитекторов Ansible). Это, конечно, неправильно.&lt;/li>
&lt;/ol>
&lt;p>В официальной документации Ansible все не лучше. Практически каждый модуль
документирован так, что приходится лезть в код, чтобы разобраться, что именно
происходит и как именно надо этот модуль использовать. Как-то излишне стремно
для продукта, который собственно создан для YAML-программистов, которые не
должны знать ничего кроме ямла.&lt;/p>
&lt;p>При этом сам продукт довольно полезный и в целом, если забить на некоторые
оговорки, неплохой - в своей нише и для своих целей. Использую его постоянно, в
целом успешно и эффективно (поздняя редакция - потихоньку ухожу в сторону
Nornir). Но осадочек присутствует, да.&lt;/p>
&lt;!-- raw HTML omitted -->
&lt;ul>
&lt;li>
&lt;p>Ссылки&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://www.ansiblefordevops.com/">https://www.ansiblefordevops.com/&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h2 id="photos">Photos&lt;/h2>
&lt;h3 id="structures">Structures&lt;/h3>
&lt;h4 id="structures">&lt;!-- raw HTML omitted -->DONE&lt;!-- raw HTML omitted --> Structures&lt;/h4>
&lt;p>
&lt;a href="https://gallery.norre.org/album/ovu" target="_blank" rel="noopener">&lt;img src="https://gallery.norre.org/images/2020/01/30/IMG_6372.jpg" alt="IMG_6372.jpg">&lt;/a>&lt;/p>
&lt;h4 id="сооружения">&lt;!-- raw HTML omitted -->DONE&lt;!-- raw HTML omitted --> Сооружения&lt;/h4>
&lt;p>
&lt;a href="https://gallery.norre.org/album/ovu" target="_blank" rel="noopener">&lt;img src="https://gallery.norre.org/images/2020/01/30/IMG_6372.jpg" alt="IMG_6372.jpg">&lt;/a>&lt;/p>
&lt;h3 id="129-die-in-jet">129 Die In Jet&lt;/h3>
&lt;h4 id="129-die-in-jet">&lt;!-- raw HTML omitted -->DONE&lt;!-- raw HTML omitted --> 129 Die In Jet&lt;/h4>
&lt;p>&lt;img src="https://gallery.norre.org/images/2020/01/30/IMG_2751.jpg" alt="129 Die In Jet">&lt;/p>
&lt;h4 id="129-die-in-jet-ru">&lt;!-- raw HTML omitted -->DONE&lt;!-- raw HTML omitted --> 129 Die In Jet | ru&lt;/h4>
&lt;p>&lt;img src="https://gallery.norre.org/images/2020/01/30/IMG_2751.jpg" alt="1">&lt;/p>
&lt;h2 id="links">Links&lt;/h2>
&lt;h3 id="google-dataset-search">&lt;!-- raw HTML omitted -->TODO&lt;!-- raw HTML omitted --> Google Dataset Search&lt;/h3>
&lt;p>&lt;a href="https://toolbox.google.com/datasetsearch">https://toolbox.google.com/datasetsearch&lt;/a>&lt;/p>
&lt;h2 id="music">Music&lt;/h2>
&lt;h3 id="threnos-on-thorns-i-lay--ru-en">Threnos: On Thorns I Lay (ru/en)&lt;/h3>
&lt;h4 id="threnos-on-thorns-i-lay-ru">&lt;!-- raw HTML omitted -->DONE&lt;!-- raw HTML omitted --> Threnos: On Thorns I Lay [ru]&lt;/h4>
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
&lt;iframe src="https://www.youtube.com/embed/oy9F5phgbNs" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" allowfullscreen title="YouTube Video">&lt;/iframe>
&lt;/div>
&lt;!-- raw HTML omitted -->
&lt;h4 id="threnos-on-thorns-i-lay-en">&lt;!-- raw HTML omitted -->DONE&lt;!-- raw HTML omitted --> Threnos: On Thorns I Lay [en]&lt;/h4>
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
&lt;iframe src="https://www.youtube.com/embed/oy9F5phgbNs" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" allowfullscreen title="YouTube Video">&lt;/iframe>
&lt;/div>
&lt;!-- raw HTML omitted -->
&lt;h2 id="video">Video&lt;/h2>
&lt;h3 id="cure-the-forest">&lt;!-- raw HTML omitted -->DONE&lt;!-- raw HTML omitted --> Cure | The Forest&lt;/h3>
&lt;h2 id="awesomeness">Awesomeness&lt;/h2></description></item></channel></rss>