<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
	<title>Веб-журнал Ярослава де ла Пенья Смирнова</title>
	<link href="https://www.yaroslavps.com/ru/weblog/feed.xml/" rel="self" type="application/atom+xml"/>
	<link href="https://www.yaroslavps.com/"/>
	<generator uri="https://www.getzola.org/">Zola</generator>
	<updated>2023-02-10T22:38:08+00:00</updated>
	<id>https://www.yaroslavps.com/ru/weblog/feed.xml/</id>
	<entry xml:lang="ru">
		<title>Введение в Generic Netlink, или Как Общаться с Linux Kernel</title>
		<published>2023-02-10T22:38:08+00:00</published>
		<updated>2023-02-10T22:38:08+00:00</updated>
		<link href="https://www.yaroslavps.com/ru/weblog/genl-intro/" type="text/html"/>
		<id>https://www.yaroslavps.com/ru/weblog/genl-intro/</id>
		<content type="html">&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;www.yaroslavps.com&#x2F;ru&#x2F;weblog&#x2F;genl-intro&#x2F;genl-tux.png&quot; alt=&quot;Туксу написали&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Пишете какой-то код в ядерном пространстве и хотите обращаться к нему из уютного
пользовательского пространства? Вы не пишете ядерный код, но хотите обращаться к
ядру Линукс? Налейте себе немного кофе или чая, присаживаетесь поудобнее, и
читайте далее!&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;Недавно я начал работать в ядерном пространстве Линукса, а точнее разрабатывать
модули ядра. Одно из API которое мне пришлось изучить это Generic Netlink. Как
часто бывает с большинством API Линукс, за исключением чётко
задокументированного кода, документация устаревшая, желает оставлять лучшего,
или вовсе отсутствует.&lt;&#x2F;p&gt;
&lt;p&gt;Соответственно я решил сделать маленький пример для себя чтобы научиться
пользоваться Generic Netlink&#x27;ом для общения с ядерным кодом, и вместе с ним
простое вводящее руководство для своих коллег и любого другого человека,
заинтересованный в использовании Generic Netlink, но не очень понимающий откуда
начинать.&lt;&#x2F;p&gt;
&lt;p&gt;В данном руководстве будет рассказано о следующем:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Регистрация семейств (families) Generic Netlink в ядре.&lt;&#x2F;li&gt;
&lt;li&gt;Регистрация операции Generic Netlink и их обработка в ядре.&lt;&#x2F;li&gt;
&lt;li&gt;Регистрация мультикастных групп Generic Netlink в ядре.&lt;&#x2F;li&gt;
&lt;li&gt;Как отправлять &quot;уведомления&quot; через Generic Netlink из ядра.&lt;&#x2F;li&gt;
&lt;li&gt;Подключение к Generic Netlink с пользовательской программы.&lt;&#x2F;li&gt;
&lt;li&gt;Разрешение семейств и мультикастных групп Generic Netlink с пользовательской
программы.&lt;&#x2F;li&gt;
&lt;li&gt;Отправка сообщения в семейство Generic Netlink с пользовательской программы.&lt;&#x2F;li&gt;
&lt;li&gt;Подписка к мультикастной группы Generic Netlink с пользовательской программы.&lt;&#x2F;li&gt;
&lt;li&gt;Получение сообщений и событий Generic Netlink с пользовательской программы.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;chto-takoe-netlink&quot;&gt;Что такое Netlink?&lt;&#x2F;h2&gt;
&lt;p&gt;Netlink — сокетный домен созданный с целью предоставления интерфейса IPC для
ядра Linux, в основном для коммуникации ядро&amp;lt;-&amp;gt;пользователь. Netlink был
создан изначально с целью замены устаревшего &lt;code&gt;ioctl()&lt;&#x2F;code&gt;, предоставляя более
гибкий и удобный способ общения между ядром и пользовательскими программами.&lt;&#x2F;p&gt;
&lt;p&gt;Коммуникации в Netlink&#x27;е происходят через обычные BSD-сокеты используя домен
&lt;code&gt;AF_NETLINK&lt;&#x2F;code&gt;. Тем не менее, есть удобные готовые библиотеки которые упрощают
работу с Netlink с пользовательского пространства например, libnl&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Netlink используется напрямую только в уже давно его использующих подсистемах
ядра Linux, через такие семейства Netlink как &lt;code&gt;NETLINK_ROUTE&lt;&#x2F;code&gt;,
&lt;code&gt;NETLINK_SELINUX&lt;&#x2F;code&gt;, и проч. В ядро больше не добавляются новые семейства Netlink,
и не планируется добавления новых семейств. Основная проблема классического
Netlink в том, что он использует статическое выделения идентификаторов,
ограниченные 32-м уникальным семействам. Это приводит к очень жёсткому
ограничению и может привести к конфликтам между разными модулями которые хотят
выделить себе новое семейство.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;predstavliaia-generic-netlink&quot;&gt;Представляя Generic Netlink&lt;&#x2F;h2&gt;
&lt;p&gt;Generic Netlink был создан с целью улучшения Netlink и упрощения работы с ним.
Он не является отдельным доменном, а является расширением Netlink. Более того,
он является семейством Netlink — &lt;code&gt;NETLINK_GENERIC&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Generic Netlink существует ещё с 2005 года и является уже довольно известным и
хорошо установившимся интерфейсом для IPC между ядром и пользовательским
пространством. Среди хорошо известных пользователей Generic Netlink, подсистемы
802.11, ACPI, Wireguard и другие.&lt;&#x2F;p&gt;
&lt;p&gt;Основные особенности Generic Netlink по сравнению с классическим Netlink&#x27;ом
— динамическая регистрация семейств, интроспекция и упрощенный API со стороны
ядра. Данное руководство сосредоточенное в основном на Generic Netlink, так как
это ныне стандартный способ общения с пространством ядра.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;www.yaroslavps.com&#x2F;ru&#x2F;weblog&#x2F;genl-intro&#x2F;01-diagram.png&quot; alt=&quot;Generic Netlink bus diagram&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;
&lt;p&gt;Диаграмма шины Generic Netlink&lt;&#x2F;p&gt;
&lt;&#x2F;figcaption&gt;
&lt;h2 id=&quot;nemnogo-teorii&quot;&gt;Немного теории&lt;&#x2F;h2&gt;
&lt;p&gt;Как я выше упомянул, Netlink работает через стандартные BSD-сокеты. Сообщения в
Netlink всегда начинаются с заголовка Netlink, после которого идёт заголовка
протокола, то есть, в случае с Generic Netlink, его заголовок.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;soobshcheniia-netlink&quot;&gt;Сообщения Netlink&lt;&#x2F;h3&gt;
&lt;p&gt;Заголовки выглядит следующим образом:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;www.yaroslavps.com&#x2F;ru&#x2F;weblog&#x2F;genl-intro&#x2F;02-nlmsghdr.png&quot; alt=&quot;Netlink header&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;
&lt;p&gt;Заголовок Netlink&lt;&#x2F;p&gt;
&lt;&#x2F;figcaption&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;www.yaroslavps.com&#x2F;ru&#x2F;weblog&#x2F;genl-intro&#x2F;03-genlmsghdr.png&quot; alt=&quot;Generic Netlink header&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;
&lt;p&gt;Заголовок Generic Netlink&lt;&#x2F;p&gt;
&lt;&#x2F;figcaption&gt;
&lt;p&gt;Или же, если перевести в код C:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;C&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-C &quot;&gt;&lt;code class=&quot;language-C&quot; data-lang=&quot;C&quot;&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;nlmsghdr {
&lt;&#x2F;span&gt;&lt;span&gt;	__u32		nlmsg_len;
&lt;&#x2F;span&gt;&lt;span&gt;	__u16		nlmsg_type;
&lt;&#x2F;span&gt;&lt;span&gt;	__u16		nlmsg_flags;
&lt;&#x2F;span&gt;&lt;span&gt;	__u32		nlmsg_seq;
&lt;&#x2F;span&gt;&lt;span&gt;	__u32		nlmsg_pid;
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct &lt;&#x2F;span&gt;&lt;span&gt;genlmsghdr {
&lt;&#x2F;span&gt;&lt;span&gt;	__u8	cmd;
&lt;&#x2F;span&gt;&lt;span&gt;	__u8	version;
&lt;&#x2F;span&gt;&lt;span&gt;	__u16	reserved;
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Значение полей в заголовках:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Length — длина всего сообщения, включая заголовок.&lt;&#x2F;li&gt;
&lt;li&gt;Type — идентификатор семейства Netlink, в нашем случае Generic Netlink.&lt;&#x2F;li&gt;
&lt;li&gt;Flags — «do» или «dump»; чуть ниже будет подробнее.&lt;&#x2F;li&gt;
&lt;li&gt;Sequence — номер последовательности; также ниже подробнее.&lt;&#x2F;li&gt;
&lt;li&gt;Port ID — ставим в него 0, так как мы отправляем с ядра.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;и для Generic Netlink:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Command: идентификатор операции для данного семейства Generic Netlink.&lt;&#x2F;li&gt;
&lt;li&gt;Version: версия протокола нашего семейства Generic Netlink.&lt;&#x2F;li&gt;
&lt;li&gt;Reserved: зарезервированное поле, не используется.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Большинство полей довольно простые и понятные и заголовок обычно не заполняется
вручную самим пользователем Netlink. Большинство информации, которая содержится
в заголовках, предоставляется пользователю через API, когда тот обращается к
разным его функциям. Часть из этой информации это такие вещи как флаги и номер
последовательности.&lt;&#x2F;p&gt;
&lt;p&gt;Существуют три вида операций-сообщений, которые чаще всего исполняются через
сокет Netlink:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Операция «do»&lt;&#x2F;li&gt;
&lt;li&gt;Операция «dump»&lt;&#x2F;li&gt;
&lt;li&gt;И мультикастные сообщения или асинхронные уведомления.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Существует множество разных способов отправить сообщения через Netlink, но это
те, которые чаще всего применяются в Generic Netlink.&lt;&#x2F;p&gt;
&lt;p&gt;Операция «do» это сообщения предназначено для вида операции где пользовательская
программа отправляет сообщение и получает ответ в виде подтверждения
(acknowledgment) ошибки, или возможно даже сообщение с запрашиваемой информации.&lt;&#x2F;p&gt;
&lt;p&gt;Операция «dump» служит для того чтобы получатель «вывалил» или выложил
запрашиваемую информацию. Обычно это информация, которая не помешается в больше
чем в одном сообщении. Пользовательская программа отправляет одно сообщение и
получает несколько сообщений до получения сообщения &lt;code&gt;NLMSG_DONE&lt;&#x2F;code&gt;, указывающее на
окончание операции.&lt;&#x2F;p&gt;
&lt;p&gt;Вид операции, то есть, будь это «do» или «dump», задаётся с помощью поля
«flags»:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;NLM_F_REQUEST | NLM_F_ACK&lt;&#x2F;code&gt; — do.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP&lt;&#x2F;code&gt; — dump.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Пора поговорить про третий вид сообщений — мультикастные сообщения. Они
используются для того, чтобы уведомлять пользователей, которые подписанные на
них через мультикастную группу Generic Netlink.&lt;&#x2F;p&gt;
&lt;p&gt;Как мы уже видели, также существует поле «sequence number» в заголовке Netlink.
Несмотря на это, в отличие от других протоколов коммуникации, Netlink не
манипулирует и не проверяет правильность номера последовательности. Он
предоставлен для удобства пользователей, чтобы было проще отслеживать запросы и
ответы. На практике чаще всего пользовательская программа сама увеличивает с
каждым отправленным сообщением этот номер, а модуль ядра отправляет ответ с тем
же номером. Мультикастные сообщения обычно отправляются с номером
последовательности равным 0.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;gruz-soobshcheniia&quot;&gt;Груз сообщения&lt;&#x2F;h3&gt;
&lt;p&gt;Netlink предоставляет систему атрибутов для кодирования данных с полезной
информацией об их вид и длины. Атрибуты позволяют проверить правильность данных
и позволяют, проще и не ломая обратную совместимость, расширять протоколы.&lt;&#x2F;p&gt;
&lt;p&gt;Также возможна кодировка своих собственных типов, таких как собственные
структуры в одном атрибуте. Тем не менее, рекомендуется использовать один
атрибут строго на одно поле данных.&lt;&#x2F;p&gt;
&lt;p&gt;Атрибуты кодируются в формате LTV (длина-тип-значение), и они заполнены так
чтобы каждый атрибут был выравнен по 4 байта. Длина полей, как в заголовке как в
атрибуте, всегда включает в себя заголовок, но не заполнение для выравнивания.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;www.yaroslavps.com&#x2F;ru&#x2F;weblog&#x2F;genl-intro&#x2F;04-nlattr.png&quot; alt=&quot;Netlink attribute diagram&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;
&lt;p&gt;Диаграмма атрибутов Netlink&lt;&#x2F;p&gt;
&lt;&#x2F;figcaption&gt;
&lt;p&gt;Порядок атрибутов в сообщении Netlink, следовательно и в сообщении Generic
Netlink, не гарантирован. По этой причине следует пройтись по ним и
проанализировать.&lt;&#x2F;p&gt;
&lt;p&gt;Netlink предоставляет возможность проверять правильность сообщения используя так
называемые &quot;политики валидации атрибутов&quot;, представлены в структуре &lt;code&gt;struct nla_policy&lt;&#x2F;code&gt;. Мне лично кажется немного странным и недостатком то, что это
структура не экспортирована в пользовательское пространство. Получается что
валидация происходит по умолчанию только в пространстве ядра. Проверку также
можно осуществить с стороны пользовательского пространства, и libnl
предоставляет свою собственную &lt;code&gt;struct nla_policy&lt;&#x2F;code&gt; но оно отличается от ядерного
что означает что по сути нужно дублировать код для того, чтобы делать проверку с
обеих сторон.&lt;&#x2F;p&gt;
&lt;p&gt;Виды сообщения и операции определяются с так называемыми командами Netlink.
Команда коррелирует к одному виду сообщения и также может коррелировать к одной
операции.&lt;&#x2F;p&gt;
&lt;p&gt;Каждая команда или вид сообщения могут иметь один и более атрибутов.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;semeistva&quot;&gt;Семейства&lt;&#x2F;h3&gt;
&lt;p&gt;Я уже упоминал семейства в данной статье и в разных контекстах. К сожалению, как
часто бывает в мире компьютерного программирования, вещи зачастую не названы
лучшим способом, и мы оказываемся в таких ситуациях где не сразу понятно о чём
речь идёт.&lt;&#x2F;p&gt;
&lt;p&gt;У сокетов есть семейства, для наших нужд мы используем семейство &lt;code&gt;AF_NETLINK&lt;&#x2F;code&gt;.
У Netlink&#x27;а тоже есть семейства, которых всего 32. Их не планируется расширять и
добавлять новые семейства в ядро Linux; семейство, которым мы пользуемся,
&lt;code&gt;NETLINK_GENERIC&lt;&#x2F;code&gt;. И наконец, у нас есть семейства Generic Netlink, в отличие от
семейств Netlink их можно динамически регистрировать и их может быть
зарегистрировано до 1024 в одно и то же время.&lt;&#x2F;p&gt;
&lt;p&gt;Семейства Generic Netlink идентифицируются с помощью строк, например, &quot;nl80211&quot;.
Так как семейства регистрируются динамическим образом, это значит что их
идентификационный номер может отличаться от компьютера к компьютеру и от сеанса
к сеансу, поэтому сначала нам нужно разрешить семейство перед тем, как
отправлять сообщения.&lt;&#x2F;p&gt;
&lt;p&gt;Generic Netlink сам по себе предоставляет одно статически выделено семейство,
которое называется &lt;code&gt;nlctrl&lt;&#x2F;code&gt;, которое предоставляет команду для разрешения всех
остальных семейств Generic Netlink. Оно также, с недавних пор, предоставляет
команду для интроспекции операций и получения политик с пользовательское
пространства, тем не менее в данной статье мы ей не будем пользоваться.&lt;&#x2F;p&gt;
&lt;p&gt;Ещё один момент, который стоит учитывать, это то, что один сокет Generic Netlink
не привязан к одному только семейству. Сокет Generic Netlink может общаться с
любым семейством, ему лишь нужно предоставить ID семейства в сообщении, размещая
его в поле &quot;type&quot;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;mul-tikastnye-gruppy&quot;&gt;Мультикастные группы&lt;&#x2F;h3&gt;
&lt;p&gt;Есть сообщения которые нам нужно отправить асинхронно пользовательским
программам для того, чтобы уведомить их о каком-то событии или просто
предоставить информацию как только она становится доступной. Для этого
существуют мультикастные группы.&lt;&#x2F;p&gt;
&lt;p&gt;Мультикастные группы Generic Netlink, так же как и семейства, регистрируются
динамически с помощью названия, содержащееся в строке, и получают численное ID
после успешной регистрации. То есть, их также необходимо разрешать перед тем как
подписаться на них. Как только программа на них подпишется, она начнёт получать
все сообщения отправленные в группу.&lt;&#x2F;p&gt;
&lt;p&gt;Дабы предотвратить путаницы чисел последовательности с уникастными сообщениями,
и упростить обработку полученных ответов, рекомендуется использовать отдельный
сокет для мультикастных сообщений.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pora-ruki-pomochit&quot;&gt;Пора руки помочить&lt;&#x2F;h2&gt;
&lt;p&gt;Это далеко не всё, о чём можно написать про Generic Netlink и особенно
классический Netlink. Тем не менее это были самые важные понятия которые нужные
для работы с Generic Netlink. Как бы то не было, не столь интересно просто знать
о чём-то, сколько применять эти знания на практике.&lt;&#x2F;p&gt;
&lt;p&gt;Я сделал пример применения Generic Netlink, который состоит из двух частей.
Модуль ядра и пользовательская программа.&lt;&#x2F;p&gt;
&lt;p&gt;Модуль ядра предоставляет одну операцию Generic Netlink и одну мультикастную
группу. Структура сообщения одинаковая как для операции &lt;code&gt;do&lt;&#x2F;code&gt; как для
мультикастного сообщения. Первое принимает сообщение с строкой текста, выводит
его в журнал ядра, и отправляет обратно своё собственное собщение; второе
отправляет уведомление при получении строки текста из &lt;code&gt;sysfs&lt;&#x2F;code&gt;, дублируя его.&lt;&#x2F;p&gt;
&lt;p&gt;Пользовательская программа подключается к Generic Netlink, подписывается к
мультикастной группу, отправляет сообщение нашему семейству и выводит на экран
полученное сообщение.&lt;&#x2F;p&gt;
&lt;p&gt;Далее я разъясню всё по шагам с помощью листингов кода. Полный исходный код для
обеих частей можно найти здесь: &lt;a href=&quot;https:&#x2F;&#x2F;git.yaroslavps.com&#x2F;genltest&#x2F;&quot;&gt;https:&#x2F;&#x2F;git.yaroslavps.com&#x2F;genltest&#x2F;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;prostranstvo-iadra&quot;&gt;Пространство ядра&lt;&#x2F;h3&gt;
&lt;p&gt;Использовать Generic Netlink с ядерного пространства довольно просто.
Единственное что нам нужно чтобы начать работу, это подключить хедер
&lt;code&gt;net&#x2F;genetlink.h&lt;&#x2F;code&gt;. Вот все заголовочные, которые нам нужны для нашего модуля:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;C&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-C &quot;&gt;&lt;code class=&quot;language-C&quot; data-lang=&quot;C&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;linux&#x2F;module.h&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;net&#x2F;genetlink.h&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Также нам понадобятся некоторые определения и энумерации, которые также должны
быть доступны пользовательской программе. Мы их поместим в заголовочный файл с
названием &lt;code&gt;genltest.h&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;C&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-C &quot;&gt;&lt;code class=&quot;language-C&quot; data-lang=&quot;C&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;#define &lt;&#x2F;span&gt;&lt;span&gt;GENLTEST_GENL_NAME &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;genltest&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;#define &lt;&#x2F;span&gt;&lt;span&gt;GENLTEST_GENL_VERSION &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;1
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;#define &lt;&#x2F;span&gt;&lt;span&gt;GENLTEST_MC_GRP_NAME &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;mcgrp&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Attributes *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;genltest_attrs {
&lt;&#x2F;span&gt;&lt;span&gt;	GENLTEST_A_UNSPEC,
&lt;&#x2F;span&gt;&lt;span&gt;	GENLTEST_A_MSG,
&lt;&#x2F;span&gt;&lt;span&gt;	__GENLTEST_A_MAX,
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;#define &lt;&#x2F;span&gt;&lt;span&gt;GENLTEST_A_MAX (__GENLTEST_A_MAX &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Commands *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span&gt;genltest_cmds {
&lt;&#x2F;span&gt;&lt;span&gt;	GENLTEST_CMD_UNSPEC,
&lt;&#x2F;span&gt;&lt;span&gt;	GENLTEST_CMD_ECHO,
&lt;&#x2F;span&gt;&lt;span&gt;	__GENLTEST_CMD_MAX,
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;#define &lt;&#x2F;span&gt;&lt;span&gt;GENLTEST_CMD_MAX (__GENLTEST_CMD_MAX &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;В нём мы определили название нашего семейства, версия его протокола, название
нашей мультикастной группы, и атрибуты, которыми мы будем пользоваться в наших
сообщениях.&lt;&#x2F;p&gt;
&lt;p&gt;Обратно в нашем ядерном коде, мы создаём политику валидации для нашей команды
«echo»:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;C&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-C &quot;&gt;&lt;code class=&quot;language-C&quot; data-lang=&quot;C&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Attribute validation policy for our echo command *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;static &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span&gt; nla_policy echo_pol[GENLTEST_A_MAX &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;	[GENLTEST_A_MSG] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;{ .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;type &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; NLA_NUL_STRING },
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Делаем массив с нашими операциями:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;C&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-C &quot;&gt;&lt;code class=&quot;language-C&quot; data-lang=&quot;C&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Operations for our Generic Netlink family *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;static &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span&gt; genl_ops genl_ops[] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;	{
&lt;&#x2F;span&gt;&lt;span&gt;		.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;cmd	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; GENLTEST_CMD_ECHO,
&lt;&#x2F;span&gt;&lt;span&gt;		.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;policy &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; echo_pol,
&lt;&#x2F;span&gt;&lt;span&gt;		.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;doit	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; echo_doit,
&lt;&#x2F;span&gt;&lt;span&gt;	 },
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Массив с нашими мультикастными группами:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;C&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-C &quot;&gt;&lt;code class=&quot;language-C&quot; data-lang=&quot;C&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Multicast groups for our family *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;static const &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span&gt; genl_multicast_group genl_mcgrps[] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;	{ .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;name &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; GENLTEST_MC_GRP_NAME },
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;И наконец структуру, описывающую наше семейство, содержащее всего, что мы сейчас
определяли:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;C&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-C &quot;&gt;&lt;code class=&quot;language-C&quot; data-lang=&quot;C&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Generic Netlink family *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;static &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span&gt; genl_family genl_fam &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;	.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;name	  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; GENLTEST_GENL_NAME,
&lt;&#x2F;span&gt;&lt;span&gt;	.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;version  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; GENLTEST_GENL_VERSION,
&lt;&#x2F;span&gt;&lt;span&gt;	.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;maxattr  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; GENLTEST_A_MAX,
&lt;&#x2F;span&gt;&lt;span&gt;	.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;ops	  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; genl_ops,
&lt;&#x2F;span&gt;&lt;span&gt;	.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;n_ops	  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;ARRAY_SIZE&lt;&#x2F;span&gt;&lt;span&gt;(genl_ops),
&lt;&#x2F;span&gt;&lt;span&gt;	.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;mcgrps	  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; genl_mcgrps,
&lt;&#x2F;span&gt;&lt;span&gt;	.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;n_mcgrps &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;ARRAY_SIZE&lt;&#x2F;span&gt;&lt;span&gt;(genl_mcgrps),
&lt;&#x2F;span&gt;&lt;span&gt;};
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;При инициализации нашего модуля, нам необходимо зарегистрировать наше семейство
в Generic Netlink. Для этого нам необходимо передать нашу структуру с помощью
функции:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;C&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-C &quot;&gt;&lt;code class=&quot;language-C&quot; data-lang=&quot;C&quot;&gt;&lt;span&gt;ret &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;genl_register_family&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;genl_fam);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;unlikely&lt;&#x2F;span&gt;&lt;span&gt;(ret)) {
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;pr_crit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;failed to register generic netlink family&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;&#x2F; etc...
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;И конечно не забыть освободить всё что с ним связано при выходе:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;C&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-C &quot;&gt;&lt;code class=&quot;language-C&quot; data-lang=&quot;C&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;unlikely&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;genl_unregister_family&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;genl_fam))) {
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;pr_err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;failed to unregister generic netlink family&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Как вы наверняка уже заметили, мы предоставили функцию &lt;code&gt;echo_doit&lt;&#x2F;code&gt; для обратного
вызова для нашей команды &quot;echo&quot;. Она выглядит следующим образом:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;C&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-C &quot;&gt;&lt;code class=&quot;language-C&quot; data-lang=&quot;C&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Handler for GENLTEST_CMD_ECHO messages received *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;static &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;echo_doit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span&gt; sk_buff &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;skb&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span&gt; genl_info &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;info&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;		ret &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;void	       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;hdr;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span&gt; sk_buff &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;msg;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Check if the attribute is present and print it *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(info-&amp;gt;attrs[GENLTEST_A_MSG]) {
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;str &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;nla_data&lt;&#x2F;span&gt;&lt;span&gt;(info-&amp;gt;attrs[GENLTEST_A_MSG]);
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;pr_info&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;message received: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;%s\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, str);
&lt;&#x2F;span&gt;&lt;span&gt;	} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;pr_info&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;empty message received&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Allocate a new buffer for the reply *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;	msg &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;nlmsg_new&lt;&#x2F;span&gt;&lt;span&gt;(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span&gt;msg) {
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;pr_err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;failed to allocate message buffer&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return -&lt;&#x2F;span&gt;&lt;span&gt;ENOMEM;
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Put the Generic Netlink header *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;	hdr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;genlmsg_put&lt;&#x2F;span&gt;&lt;span&gt;(msg, info-&amp;gt;snd_portid, info-&amp;gt;snd_seq, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;genl_fam, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;			  GENLTEST_CMD_ECHO);
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span&gt;hdr) {
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;pr_err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;failed to create genetlink header&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;nlmsg_free&lt;&#x2F;span&gt;&lt;span&gt;(msg);
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return -&lt;&#x2F;span&gt;&lt;span&gt;EMSGSIZE;
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* And the message *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;((ret &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;nla_put_string&lt;&#x2F;span&gt;&lt;span&gt;(msg, GENLTEST_A_MSG,
&lt;&#x2F;span&gt;&lt;span&gt;				  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Hello from Kernel Space, Netlink!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;))) {
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;pr_err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;failed to create message string&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;genlmsg_cancel&lt;&#x2F;span&gt;&lt;span&gt;(msg, hdr);
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;nlmsg_free&lt;&#x2F;span&gt;&lt;span&gt;(msg);
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;goto&lt;&#x2F;span&gt;&lt;span&gt; out;
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Finalize the message and send it *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;genlmsg_end&lt;&#x2F;span&gt;&lt;span&gt;(msg, hdr);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	ret &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;genlmsg_reply&lt;&#x2F;span&gt;&lt;span&gt;(msg, info);
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;pr_info&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;reply sent&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;out:
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; ret;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Если вкратце, для обработки команды вида «do» нужно:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Извлечь данные входящего сообщения со структуры &lt;code&gt;genl_info&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Выделить память для ответа.&lt;&#x2F;li&gt;
&lt;li&gt;Вставить заголовок Generic Netlink в буфере сообщения; обратите внимания на
то, что мы используем тот же ID порта и номер последовательности что и во
входящем сообщении, так как это ответное сообщение.&lt;&#x2F;li&gt;
&lt;li&gt;Вставить все атрибуты с полезным грузом.&lt;&#x2F;li&gt;
&lt;li&gt;Отправить ответ.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Теперь посмотрим как отправить мультикастное сообщение. Я использовал sysfs в
этом примере дабы сделать его более интересным. Я создал «kobj», который
называется &lt;code&gt;genltest&lt;&#x2F;code&gt;, который содержит атрибут &lt;code&gt;ping&lt;&#x2F;code&gt;, с которого мы собственно
продублируем то, что в него будет записано. Для краткости, я упущу со статьи код
с sysfs, просто предоставлю функцию, которая формирует и отправляет сообщение:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;C&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-C &quot;&gt;&lt;code class=&quot;language-C&quot; data-lang=&quot;C&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Multicast ping message to our genl multicast group *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;static &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;echo_ping&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;char &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;size_t &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;cnt&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;		ret &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;void	       &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;hdr;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Allocate message buffer *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span&gt; sk_buff &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;skb &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;genlmsg_new&lt;&#x2F;span&gt;&lt;span&gt;(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;unlikely&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span&gt;skb)) {
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;pr_err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;failed to allocate memory for genl message&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return -&lt;&#x2F;span&gt;&lt;span&gt;ENOMEM;
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Put the Generic Netlink header *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;	hdr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;genlmsg_put&lt;&#x2F;span&gt;&lt;span&gt;(skb, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;genl_fam, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, GENLTEST_CMD_ECHO);
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;unlikely&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span&gt;hdr)) {
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;pr_err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;failed to allocate memory for genl header&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;nlmsg_free&lt;&#x2F;span&gt;&lt;span&gt;(skb);
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return -&lt;&#x2F;span&gt;&lt;span&gt;ENOMEM;
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* And the message *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;((ret &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;nla_put_string&lt;&#x2F;span&gt;&lt;span&gt;(skb, GENLTEST_A_MSG, buf))) {
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;pr_err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;unable to create message string&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;genlmsg_cancel&lt;&#x2F;span&gt;&lt;span&gt;(skb, hdr);
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;nlmsg_free&lt;&#x2F;span&gt;&lt;span&gt;(skb);
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; ret;
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Finalize the message *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;genlmsg_end&lt;&#x2F;span&gt;&lt;span&gt;(skb, hdr);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Send it over multicast to the 0-th mc group in our array. *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;	ret &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;genlmsg_multicast&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;genl_fam, skb, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, GFP_KERNEL);
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(ret &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;== -&lt;&#x2F;span&gt;&lt;span&gt;ESRCH) {
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;pr_warn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;multicast message sent, but nobody was listening...&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;	} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;else if &lt;&#x2F;span&gt;&lt;span&gt;(ret) {
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;pr_err&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;failed to send multicast genl message&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;	} &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;pr_info&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;multicast message sent&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; ret;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Процесс довольно похож на операцию «do», с тем отличием что мы не отвечаем на
запрос, а отправляем асинхронное сообщение. В связи с этим, мы задаём 0 в
качестве последовательного номера, так как он нам в данном случае не нужен, и
также задаём 0 для ID порта, порт&#x2F;PID ядра. Также мы отправляем сообщение через
функцию &lt;code&gt;genlmsg_multicast()&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;На этом всё со стороны ядра. Теперь взглянем на пользовательскую часть.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;pol-zovatel-skoe-prostranstvo&quot;&gt;Пользовательское пространство&lt;&#x2F;h3&gt;
&lt;p&gt;Netlink является сокетным семейством, что делает возможным пользоваться им через
стандартное API сокетов. Достаточно открыть сокет и далее писать и читать
сообщения через него, примерно так:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;C&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-C &quot;&gt;&lt;code class=&quot;language-C&quot; data-lang=&quot;C&quot;&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; fd &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;socket&lt;&#x2F;span&gt;&lt;span&gt;(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Format request message... *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* ... *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Send it *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;send&lt;&#x2F;span&gt;&lt;span&gt;(fd, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;req, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;sizeof&lt;&#x2F;span&gt;&lt;span&gt;(req), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Receive response *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;recv&lt;&#x2F;span&gt;&lt;span&gt;(fd, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;resp, BUF_SIZE, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Do something with response... *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* ... *&#x2F;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Тем не менее лучше использовать libnl&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; или похожую библиотеку, так как они
предоставляют более удобный интерфейс к Generic Netlink, что предотвращает
некоторые ошибки, и реализует код, который бы всего равно пришлось написать. Эту
же библиотеку я буду использовать для своего примера.&lt;&#x2F;p&gt;
&lt;p&gt;Для начала нам нужно подключить некоторые хедеры с libnl:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;C&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-C &quot;&gt;&lt;code class=&quot;language-C&quot; data-lang=&quot;C&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;netlink&#x2F;socket.h&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;netlink&#x2F;netlink.h&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;netlink&#x2F;genl&#x2F;ctrl.h&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;netlink&#x2F;genl&#x2F;genl.h&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;netlink&#x2F;genl&#x2F;family.h&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;А также совместный хедер, который мы создали когда писали ядерный модуль:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;C&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-C &quot;&gt;&lt;code class=&quot;language-C&quot; data-lang=&quot;C&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;#include &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;..&#x2F;ks&#x2F;genltest.h&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;В примере я также сделал маленький макрос для вывода ошибок:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;C&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-C &quot;&gt;&lt;code class=&quot;language-C&quot; data-lang=&quot;C&quot;&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;#define &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;prerr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;fprintf&lt;&#x2F;span&gt;&lt;span&gt;(stderr, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;error: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; __VA_ARGS__)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Как я упомянул ранее, проще использовать отдельные сокеты под юникаст и
мультикаст сообщения. Поэтому здесь открываем два сокета для общения через
Generic Netlink:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;C&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-C &quot;&gt;&lt;code class=&quot;language-C&quot; data-lang=&quot;C&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Allocate netlink socket and connect to generic netlink *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;static &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;conn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span&gt; nl_sock &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;**&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;sk&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;sk &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;nl_socket_alloc&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span&gt;sk) {
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return -&lt;&#x2F;span&gt;&lt;span&gt;ENOMEM;
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;genl_connect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;sk);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;*
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; * ...
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span&gt; nl_sock &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;ucsk, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;mcsk;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;*
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; * We use one socket to receive asynchronous &amp;quot;notifications&amp;quot; over
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; * multicast group, and another for ops. We do this so that we don&amp;#39;t mix
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; * up responses from ops with notifications to make handling easier.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;((ret &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;conn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;ucsk)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;|| &lt;&#x2F;span&gt;&lt;span&gt;(ret &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;conn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;mcsk))) {
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;prerr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;failed to connect to generic netlink&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;goto&lt;&#x2F;span&gt;&lt;span&gt; out;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Далее нам нужно разрешить ID семейства Generic Netlink, к которому мы хотим
подключиться:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;C&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-C &quot;&gt;&lt;code class=&quot;language-C&quot; data-lang=&quot;C&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Resolve the genl family. One family for both unicast and multicast. *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; fam &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;genl_ctrl_resolve&lt;&#x2F;span&gt;&lt;span&gt;(ucsk, GENLTEST_GENL_NAME);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(fam &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;prerr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;failed to resolve generic netlink family: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;%s\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;	      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;strerror&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;fam));
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;goto&lt;&#x2F;span&gt;&lt;span&gt; out;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Сокет (Generic) Netlink никак не ассоциируется с семейством, а ID семейства нам
пригодится позже для отправки сообщения.&lt;&#x2F;p&gt;
&lt;p&gt;Библиотека libnl может отслеживать номер последовательности за нас, но нам это
не нужно для мультикастных сообщений, поэтому и выключаем его:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;C&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-C &quot;&gt;&lt;code class=&quot;language-C&quot; data-lang=&quot;C&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;nl_socket_disable_seq_check&lt;&#x2F;span&gt;&lt;span&gt;(mcsk);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Нам также необходимо разрешить название мультикастной группы. В данном случае мы
сразу задействуем полученный ID для того, чтобы подписаться к данной группе и
начать получать уведомления:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;C&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-C &quot;&gt;&lt;code class=&quot;language-C&quot; data-lang=&quot;C&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Resolve the multicast group. *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; mcgrp &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;genl_ctrl_resolve_grp&lt;&#x2F;span&gt;&lt;span&gt;(mcsk, GENLTEST_GENL_NAME,
&lt;&#x2F;span&gt;&lt;span&gt;				  GENLTEST_MC_GRP_NAME);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(mcgrp &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;prerr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;failed to resolve generic netlink multicast group: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;%s\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;	      &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;strerror&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;mcgrp));
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;goto&lt;&#x2F;span&gt;&lt;span&gt; out;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Join the multicast group. *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;((ret &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;nl_socket_add_membership&lt;&#x2F;span&gt;&lt;span&gt;(mcsk, mcgrp) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)) {
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;prerr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;failed to join multicast group: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;%s\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;strerror&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;ret));
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;goto&lt;&#x2F;span&gt;&lt;span&gt; out;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Нам нужно поменять обратный вызов на наш, для того, чтобы мы могли получить и
обработать входящие сообщения:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;C&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-C &quot;&gt;&lt;code class=&quot;language-C&quot; data-lang=&quot;C&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Modify the callback for replies to handle all received messages *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;static inline &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;set_cb&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span&gt; nl_sock &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;sk&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return -&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;nl_socket_modify_cb&lt;&#x2F;span&gt;&lt;span&gt;(sk, NL_CB_VALID, NL_CB_CUSTOM,
&lt;&#x2F;span&gt;&lt;span&gt;				    echo_reply_handler, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff8942;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;*
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; * ...
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;((ret &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;set_cb&lt;&#x2F;span&gt;&lt;span&gt;(ucsk)) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;|| &lt;&#x2F;span&gt;&lt;span&gt;(ret &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;set_cb&lt;&#x2F;span&gt;&lt;span&gt;(mcsk))) {
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;prerr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;failed to set callback: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;%s\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;strerror&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;ret));
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;goto&lt;&#x2F;span&gt;&lt;span&gt; out;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Как вы могли заметить, обратный вызов одинаков для обеих сокетов, так как мы по
сути получаем одинаковое по типу сообщение как для операции «do» так для
асинхронных сообщений. Функция выглядит следующим образом:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;C&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-C &quot;&gt;&lt;code class=&quot;language-C&quot; data-lang=&quot;C&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;*
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; * Handler for all received messages from our Generic Netlink family, both
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; * unicast and multicast.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;static &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;echo_reply_handler&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span&gt; nl_msg &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;msg&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;arg&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;		   err	   &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span&gt; genlmsghdr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;genlhdr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;nlmsg_data&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;nlmsg_hdr&lt;&#x2F;span&gt;&lt;span&gt;(msg));
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span&gt; nlattr	  &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;tb[GENLTEST_A_MAX &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;];
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Parse the attributes *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;	err &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;nla_parse&lt;&#x2F;span&gt;&lt;span&gt;(tb, GENLTEST_A_MAX, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;genlmsg_attrdata&lt;&#x2F;span&gt;&lt;span&gt;(genlhdr, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;),
&lt;&#x2F;span&gt;&lt;span&gt;			&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;genlmsg_attrlen&lt;&#x2F;span&gt;&lt;span&gt;(genlhdr, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;), &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff8942;&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(err) {
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;prerr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;unable to parse message: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;%s\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;strerror&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;err));
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; NL_SKIP;
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Check that there&amp;#39;s actually a payload *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span&gt;tb[GENLTEST_A_MSG]) {
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;prerr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;msg attribute missing from message&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; NL_SKIP;
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Print it! *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;message received: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;%s\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;nla_get_string&lt;&#x2F;span&gt;&lt;span&gt;(tb[GENLTEST_A_MSG]));
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; NL_OK;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;В целом ничего особенно, по большей части очень похоже на то, что мы делали в
ядерной части. Основное отличие в том, что в ядерном коде сообщение уже было
распарсенное за нас ядерным API, а здесь нам даётся выбор пройти по атрибутам
вручную или спарсить их всех в массив с помощью функции библиотеки.&lt;&#x2F;p&gt;
&lt;p&gt;Далее, нам надо отправить сообщение в ядерное пространство:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;C&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-C &quot;&gt;&lt;code class=&quot;language-C&quot; data-lang=&quot;C&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Send (unicast) GENLTEST_CMD_ECHO request message *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;static &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;send_echo_msg&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span&gt; nl_sock &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;sk&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;int &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;fam&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt;	       err &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span&gt; nl_msg &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;msg &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;nlmsg_alloc&lt;&#x2F;span&gt;&lt;span&gt;();
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span&gt;msg) {
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return -&lt;&#x2F;span&gt;&lt;span&gt;ENOMEM;
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Put the genl header inside message buffer *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;hdr &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;genlmsg_put&lt;&#x2F;span&gt;&lt;span&gt;(msg, NL_AUTO_PORT, NL_AUTO_SEQ, fam, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;				GENLTEST_CMD_ECHO, GENLTEST_GENL_VERSION);
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;!&lt;&#x2F;span&gt;&lt;span&gt;hdr) {
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return -&lt;&#x2F;span&gt;&lt;span&gt;EMSGSIZE;
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Put the string inside the message. *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;	err &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;nla_put_string&lt;&#x2F;span&gt;&lt;span&gt;(msg, GENLTEST_A_MSG,
&lt;&#x2F;span&gt;&lt;span&gt;			     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;Hello from User Space, Netlink!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(err &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;lt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;		&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return -&lt;&#x2F;span&gt;&lt;span&gt;err;
&lt;&#x2F;span&gt;&lt;span&gt;	}
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;message sent&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Send the message. *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;	err &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;nl_send_auto&lt;&#x2F;span&gt;&lt;span&gt;(sk, msg);
&lt;&#x2F;span&gt;&lt;span&gt;	err &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; err &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;? &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;0 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; err;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;nlmsg_free&lt;&#x2F;span&gt;&lt;span&gt;(msg);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; err;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;*
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; * ...
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Send unicast message and listen for response. *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;((ret &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;send_echo_msg&lt;&#x2F;span&gt;&lt;span&gt;(ucsk, fam))) {
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;prerr&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;failed to send message: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;%s\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;strerror&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;ret));
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Также не сильно отличается от ядерного API. Теперь нам следует единовременное
слушать для получения ответа и &quot;бесконечно&quot; для получения уведомлений:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;C&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-C &quot;&gt;&lt;code class=&quot;language-C&quot; data-lang=&quot;C&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;listening for messages&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;nl_recvmsgs_default&lt;&#x2F;span&gt;&lt;span&gt;(ucsk);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Listen for &amp;quot;notifications&amp;quot;. *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fdb082;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;) {
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;nl_recvmsgs_default&lt;&#x2F;span&gt;&lt;span&gt;(mcsk);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Не забываем перед выходом программы закрывать и освобождать наши сокеты:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;C&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-C &quot;&gt;&lt;code class=&quot;language-C&quot; data-lang=&quot;C&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;* Disconnect and release socket *&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;static &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;void &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8cdaff;&quot;&gt;disconn&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fbdfb5;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span&gt; nl_sock &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt;sk&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;nl_close&lt;&#x2F;span&gt;&lt;span&gt;(sk);
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;nl_socket_free&lt;&#x2F;span&gt;&lt;span&gt;(sk);
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&#x2F;*
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; * ...
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt; *&#x2F;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;disconn&lt;&#x2F;span&gt;&lt;span&gt;(ucsk);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;disconn&lt;&#x2F;span&gt;&lt;span&gt;(mcsk);
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;На этом всё!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;podvodia-itogi&quot;&gt;Подводя итоги&lt;&#x2F;h2&gt;
&lt;p&gt;Старые способы взаимодействия с ядром и его различными подсистемами через такие
интерфейса как «sysfs» и в особенности «ioctl» имеют немало недостатков и в них
отсутствуют некоторые очень нужные в современном мире функции, такие как
асинхронные операции и структурированные форматы данных.&lt;&#x2F;p&gt;
&lt;p&gt;Netlink, и его расширенная форма, Generic Netlink, предоставляют очень гибкий
способ общения с ядром, и они решают многие недостатки и проблемы интерфейсов
былых времён. Это не идеальное решение (например, не совсем по-Юниксовому), но
это однозначно лучший способ который есть, на данным момент, для того, чтобы
передавать в и из ядра более сложные вещи чем простые параметры.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;post-scriptum&quot;&gt;Post scriptum&lt;&#x2F;h2&gt;
&lt;p&gt;Когда я начал изучать Generic Netlink, версия 6.0 ядра ещё не была выпущенной
(stable). Ввиду того что только недавно в этой же версии была добавлена в
документацию замечательная страница-введение в Netlink&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, и того что я смотрел
в версии документации «latest» (на тот момент v5.19), я её не заметил до того,
как я уже начал писать свою статью.&lt;&#x2F;p&gt;
&lt;p&gt;Не уверен, начал ли я бы писать эту статью, если бы я раньше увидел ту страницу
ядерских доков. Тем не менее в конечном итоге я считаю что оно того стоило, так
как это статья получилась неплохим добавлением к странице официальных доков,
для желающих сразу помочить руки, особенно, учитывая что здесь предоставляется
живой пример.&lt;&#x2F;p&gt;
&lt;p&gt;Тем не менее, несомненно прочитайте официальную документацию ядра! Та страница
покрывает некоторые моменты, о которых я мог не упомянуть.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Оригинальный сайт с информацией &lt;a href=&quot;https:&#x2F;&#x2F;www.infradead.org&#x2F;~tgr&#x2F;libnl&#x2F;&quot;&gt;https:&#x2F;&#x2F;www.infradead.org&#x2F;~tgr&#x2F;libnl&#x2F;&lt;&#x2F;a&gt;,
актуальное репо: &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;thom311&#x2F;libnl&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;thom311&#x2F;libnl&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Хорошая вводная статья по Netlink, с самих доков ядра:
&lt;a href=&quot;https:&#x2F;&#x2F;kernel.org&#x2F;doc&#x2F;html&#x2F;latest&#x2F;userspace-api&#x2F;netlink&#x2F;intro.html&quot;&gt;https:&#x2F;&#x2F;kernel.org&#x2F;doc&#x2F;html&#x2F;latest&#x2F;userspace-api&#x2F;netlink&#x2F;intro.html&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
	</entry>
	<entry xml:lang="ru">
		<title>Время крипты настало</title>
		<published>2022-04-15T20:54:32+00:00</published>
		<updated>2022-04-19T23:06:37+00:00</updated>
		<link href="https://www.yaroslavps.com/ru/weblog/time-to-use-crypto/" type="text/html"/>
		<id>https://www.yaroslavps.com/ru/weblog/time-to-use-crypto/</id>
		<content type="html">&lt;p&gt;Криптовалюты уже целое десятилетие как существуют. Любой кто пользовался
интернетом хоть раз слышал про так называемые «криптовалюты». Однако большинство
людей до сих пор не поняли основную суть крипты. Не смотря на всё, последние
события нам показывают насколько важна эта технология и почему она лучше чем
традиционные конкуренты.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;Уже давно ушли времена когда достаточно для человека обмениваться одним
продуктом или услугой на другой. Теперь у нас лучший способ обмена капиталом
через нашей валютной системой. Ушли времена золотого стандарта, настали времена
мгновенных глобальных сделок, используя электронные средства для денежных
обменов.&lt;&#x2F;p&gt;
&lt;p&gt;Однако, хоть и мы много чего положительного получили, также и получили очень
много проблем нарушающих свободу и приватности. Если нужно продавать или
покупать электронными средствами, то необходимо пройти через десяток
посредников, каждый из которых получает свою долю от сделки, у каждого из
которых имеются свои правила, и у каждого из которых есть возможность
отслеживать что и когда каждый человек продаёт и покупает.&lt;&#x2F;p&gt;
&lt;p&gt;Иными словами, мы принимаем участие в Оруэлловской финансовой системе, которая
решает как, когда и с кем мы имеем право торговать. Хуже всего это то, что мы
добровольно в ней принимаем участие.&lt;&#x2F;p&gt;
&lt;p&gt;Многие сочтут аргументы, против централизованного контроля финансов, паранойей,
но уже есть много прецедентов, которые доказывают вредность централизованных
финансов для возможности людей торговать свободно и беспрепятственно.&lt;&#x2F;p&gt;
&lt;p&gt;Начиная с людьми чьё мнение считается невыгодным для тех, кто правят, и доходя
до сегодняшних событий, когда «отменяют» целую страну потому, что государство
этой страны сделало что-то, что власть имущим не нравится. Ни кого не удивит что
мы ограничены правилами тех, кто владеют системой. Ведь это же их система и они
придумывают правила. Но это не значит что нет других вариантов.&lt;&#x2F;p&gt;
&lt;p&gt;Криптовалюты нам в помощь. По сравнению традиционными финансовыми система,
которые упираются на центральных авторитетов чтобы писать и применять правила,
чтобы чеканить или печатать деньги тем самым сокращая капитал людей которые
держат данную валюту на их произвол.&lt;&#x2F;p&gt;
&lt;p&gt;Суть криптовалюты в том чтобы ни один единственный человек не управлял системой.
Существуют правила по которым все соглашаются играть, и каждый из участников
наблюдает над друг другом. Если выявляется нарушение правил или какая-нибудь
манипуляция другими участника, они не позволяют такому быть и попросту не
принимают эти действия.&lt;&#x2F;p&gt;
&lt;p&gt;Коротко говоря криптовалюта это сеть в которой любой может принять участие,
отдавая часть своих компьютерных ресурсов для того, чтобы сеть работала,
генерируя блоки, содержащие транзакции и возможно новые единицы валюты. Ни один
из участников сети не может самостоятельно поменять правила. Система
математически не позволяет людям её обмануть (например, потратив дважды одни и
те же деньги) пока это лицо не владеет больше 50% мощностей сети, что по крайней
мере для Биткойн и большинства криптовалют уже практически невозможно.&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Однако, не все криптовалюты одинаковы. Биткойн самая популярная и самая ценная
благодаря тому что она была самой первой. В своё время когда она была
анонсирована и запущена таинственным Сатоси Накамото это было что-то
революционным. Она и по сей день таковой является, но она не без своих
недостатков.&lt;&#x2F;p&gt;
&lt;p&gt;Самый большой недостаток Биткойна это отсутствие приватности. Честно говоря,
меня даже удивляет что государства не продвигают Биткойн&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, учитывая насколько
просто отслеживать в нём транзакции. И это вообще не какая-то бага или недочёт
системы, это фишка самой системы. Для того, чтобы начальная задумка блокчейна
работала, необходима публичная история транзакций.&lt;&#x2F;p&gt;
&lt;p&gt;У Биткойна и ряд других проблем — недостаточная производительность, алгоритм
доказательства выполненной работы подвергается к централизации, или по крайней
мере усложняет участие в сети для более мелких участников, из-за того что для
него очень легко производить ASIC&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Тем не менее, у Биткойна всё ещё самое главное преимущество крипты. Это
&lt;strong&gt;децентрализованная&lt;&#x2F;strong&gt; валюта. Ни один человек, ни одна корпорация, ни
государство не контролируют его. Каждый может создать сколько угодно адресов
(аналог банковского счёта) в всего пару кликов. Не надо вводить никаких
персональных данных о себе или предоставлять документы.&lt;&#x2F;p&gt;
&lt;p&gt;К счастью самый большой недостаток Биткойна, отсутствие приватности, исправлен в
других криптовалютах, например, в Monero&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#4&quot;&gt;4&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Monero, по моему мнению,
предоставляет наибольшее количество преимуществ с наименьшем количеством
недостатков. Она не только полностью децентрализованная как Биткойн, но и также
предоставляет полную приватность по умолчанию. Никто кроме отправителя и
получателя не знает ни объём сделки ни кто кому перевёл средства.&lt;&#x2F;p&gt;
&lt;p&gt;Помимо этого, я также считаю что Монеро намного проще использовать. Легче
участвовать в «майнинге», благодаря его алгоритму доказательства выполненной
работы, транзакции проходят быстрее и комиссии ниже. Как по мне это валюта за
которой стоит будущее крипты.&lt;&#x2F;p&gt;
&lt;p&gt;Я уже несколько время назад начал пользоваться криптой, а конкретнее Монеро, и
был заинтересован технологией ещё в начале 2010-ых когда только узнал про
крипту. Тем не менее никогда не являлся активным пользователем крипты. Но теперь
всё поменялось.&lt;&#x2F;p&gt;
&lt;p&gt;24го февраля Российское государство решило что пора что-то сделать с конфликтом,
который уже 8 лет проходил на территории Украины. Конечно, США это понравилось и
теперь они по сути вывели «культуру отмена» на новый уровень своим образом
«отменяя» всю Россию.&lt;&#x2F;p&gt;
&lt;p&gt;Что самое ироничное из всей этой ситуации это то, что санкции больше всего
ударили по людям которые ни при чём в этом конфликте, а ещё они и ударили по
людям, которые они якобы решились защитить. Кто бы подумал что у многих
русских есть родственники на Украине.&lt;&#x2F;p&gt;
&lt;p&gt;Так же и лицемерие вышло на новые уровни. Я уже даже не говорю про американское
государство, от них то и стоило ожидать такие реакции, всё-таки в нашем мире
сильный всегда прав. Меня поражают отсутствие собственной воли других
государств и корпорации, которые якобы «поддерживают Украину» «приостанавливая
взаимодействие с Россией». Но что-то от них ни слову когда американское
&lt;del&gt;светящиеся ниггеры&lt;&#x2F;del&gt; государство вторглось или бомбардировало другие
государства далеко за её пределами. Но сейчас не об этом.&lt;&#x2F;p&gt;
&lt;p&gt;Суть в том, что возможность россиян и украинцев торговать с другими людьми
ограничено из-за решений нескольких политиков и бизнесменов. Украина больше
всего страдает от ситуации, так как стала жертвой очередного конфликта между
США&#x2F;НАТО и Россией. И те из нас, которые живут в России, не могут нормально
торговать с остальным миром, или даже перевести деньги родственникам в других
странах.&lt;&#x2F;p&gt;
&lt;p&gt;Эти проблемы можно решить лишь полностью децентрализованной электронной валютой.&lt;&#x2F;p&gt;
&lt;p&gt;Я считаю, и сильно надеюсь, что крипта никогда не заменит наличные. Я бы конечно
предпочёл чтобы мы торговались не фиатными валютами, но про это уже в другой
раз. То, что я действительно считаю это то, что криптовалюты должны стать
стандартом для электронного перевода средств.&lt;&#x2F;p&gt;
&lt;p&gt;Меня волнует не то, кто во главе, будь это корпорация или государство. Для меня
они такое же зло, ведь ни первый ни второй не придерживается ни твоих ни моих
интересов&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#5&quot;&gt;5&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Единственное решение это система, которая не контролируется
никем.&lt;&#x2F;p&gt;
&lt;p&gt;Лично я, после начала &lt;del&gt;войны&lt;&#x2F;del&gt; спецоперации начал пользоваться более активно
криптой, особенно как способ сбережения. Сейчас инфляция, как в России как и за
её пределами, очень высокая, что значит что фиатные деньги попросту
обесценивается если их не тратить&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#6&quot;&gt;6&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;. Сейчас даже накопительный счёт не особо
выгодно. Но, криптовалюты в общей сложности дефляционные. Хоть и не такие
хорошие средства сбережения как золото или недвижимость, но всё равно неплохой
вариант для сбережении.&lt;&#x2F;p&gt;
&lt;p&gt;Резюмируя, причины по которым я считаю что криптовалюты это лучший способ
электронной торговли:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Нет центрального авторитета. Никто не может изъять твои средства без твоего
ведома, просто потому, что кто-то (банк, государство, т.д и т.п.) так сказал.
Только если кто-то заполучил доступ к твоим ключам возможное потеря средств.&lt;&#x2F;li&gt;
&lt;li&gt;Нет никаких соглашений или договоров с куча нюансами. Любой может свободно
создать адрес без ограничений, без документов, полностью анонимно.&lt;&#x2F;li&gt;
&lt;li&gt;Никто не может «печатать» или создавать новые единицы валюты на произвол, так
как это делают Центробанк или Федеральный резерв, что связанно со следующим:&lt;&#x2F;li&gt;
&lt;li&gt;Крипта не страдает инфляцией; на данный момент большая часть криптовалют
довольно волатильные, но в целом они не теряют, а наоборот, растут в стоимости
по отношению к фиатным валютам.&lt;&#x2F;li&gt;
&lt;li&gt;И, в случае с Монеро: транзакции полностью приватные; никакое государство или
корпорация не отслеживает то, на что ты тратишь деньги или от кого ты их
получаешь.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;В эти сложные времена берегите себя, не доверяйте никому, с которыми вы лично не
знакомы.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Это очень краткое и простое объяснение того, как большинство криптовалют
работают. Если Вам интересно узнать больше, я советую Вам начать с белой книги
биткойна. &lt;a href=&quot;https:&#x2F;&#x2F;bitcoin.org&#x2F;en&#x2F;bitcoin-paper&quot;&gt;https:&#x2F;&#x2F;bitcoin.org&#x2F;en&#x2F;bitcoin-paper&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Учитывая то насколько государства любят отслеживать и шпионить над своими
людьми и &lt;del&gt;обкрадывать их&lt;&#x2F;del&gt; изымать с них как можно больше налогов.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;Интегральная схема, специализированная для решения конкретной задачи.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;4&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;4&lt;&#x2F;sup&gt;
&lt;p&gt;Больше информации можно найти на официальном сайте Monero:
&lt;a href=&quot;https:&#x2F;&#x2F;www.getmonero.org&#x2F;&quot;&gt;https:&#x2F;&#x2F;www.getmonero.org&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;5&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;5&lt;&#x2F;sup&gt;
&lt;p&gt;Государство &lt;em&gt;должно&lt;&#x2F;em&gt; работать согласно интересам его народа; на деле так
никогда не было и никогда не будет.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;6&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;6&lt;&#x2F;sup&gt;
&lt;p&gt;На самом это всегда так, просто они теперь ещё сильнее обесцениваются.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
	</entry>
	<entry xml:lang="ru">
		<title>Как я отлаживаю программы в Vim</title>
		<published>2022-01-25T19:49:30+00:00</published>
		<updated>2022-01-25T19:49:30+00:00</updated>
		<link href="https://www.yaroslavps.com/ru/weblog/debugging-in-vim/" type="text/html"/>
		<id>https://www.yaroslavps.com/ru/weblog/debugging-in-vim/</id>
		<content type="html">&lt;p&gt;Мне нравиться использовать отдельные инструменты для разных задач, но также мне
нравится когда эти инструменты хорошо интегрируются с моими остальными
инструментами. К сожалению я не видел достаточной информации в интернете насчёт
возможного процесса отладки программ посредством Vim. Информация, точнее, есть,
но она разбросана по всему интернету. И так я решил написать о моём процессе
написания и отладки с Vim.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;Многие, а может и большинство, IDE уже имеют встроенные функции отладки
программ. Но также эти IDE не vim, и чаще всего они включаю в себя куча других
сомнительных функций. И нет, «Vim mode» плагины не считаются, большинство из них
даже половина функционала Vim&#x27;а не включают в себя.&lt;&#x2F;p&gt;
&lt;p&gt;Я обожаю vim (на самом деле использую neovim, кому какая разница), и я считаю
его лучшим текстовым редактором. Я даже в полном серьёзе считаю что у Vim&#x27;а
лучшее UI&#x2F;UX из любой программы. Да, он далеко не самая интуитивная программа
(&lt;a href=&quot;https:&#x2F;&#x2F;www.yaroslavps.com&#x2F;ru&#x2F;weblog&#x2F;debugging-in-vim&#x2F;#exit-vim&quot;&gt;вставьте мем про выхода из Vim&#x27;а&lt;&#x2F;a&gt;), но выучить основные азы не так
сложно как кажется зато как только их выучить сложно будет пользоваться чем-то
другим. Короче говоря, Vim это не программа а образ жизни.&lt;&#x2F;p&gt;
&lt;p&gt;Проблема заключается в том, что стать продвинутым пользователем вима всё-таки
занимает немалого времени. А чтобы эффективно разрабатывать программы, не
достаточно просто напечатать код программы. Так же необходимо быстро
перемещаться по исходным файлам, быстро исправлять самые банальные ошибки (вроде
опечатках), свести к минимуму механические задачи (например с помощью
автозаполнения), и конечно, отладка и профилировка.&lt;&#x2F;p&gt;
&lt;p&gt;К счастью как Vim как и Neovim уже несколько лет предоставляют функционал для
интегрирования инструментов разработки и отладки с лёгкостью. Так как я
пользуюсь Neovim, то соответственно некоторые моменты могут отличаться от
ванильного Vim.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;instrumenty-razrabotki&quot;&gt;Инструменты разработки&lt;&#x2F;h2&gt;
&lt;p&gt;В старые добрые времена для каждого редактора&#x2F;IDE отдельно должны были быть
разработаны плагины или компоненты. То есть, для каждой комбинации редактора и
языка программирования выполнялся труд по разработке инструмента, что означала
что далеко не все редакторы и не все языки имели достаточные инструменты для
разработки и отладки.&lt;&#x2F;p&gt;
&lt;p&gt;К счастью, Мелкомягкие поступили совсем не по Мелкомягкому и вместо того чтобы
встроить совершенно новую реализацию среды разработки для VSCode, они
разработали так называемый Language Server Protocol&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;, и с помощью Red Hat и
других выложили в опен сорс и превратили его в некий стандарт.&lt;&#x2F;p&gt;
&lt;p&gt;Если коротко говоря, то Language Server Protocol (LSP) это просто JSON RPC
протокол для общения между сервером, который предоставляет функции для
разработки программ, как например, автозаполнение, статический анализ, переход
на определение, и т.д., и клиент, то есть, IDE или редактор, который отображает
результат всех этих действий. Среди редакторов, которые поддерживают LSP,
находится Vim. В Neovim&#x27;е это поддержка даже встроена.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;lsp&quot;&gt;LSP&lt;&#x2F;h3&gt;
&lt;p&gt;Затем чтобы использовать LSP в neovim, необходимо включить плагин и настроить
LSP сервер(а) ваш(его&#x2F;их) язык(а&#x2F;ов). Хорошо то, что настройка этого функционала
довольно проста, так как есть официальный плагин который уже предоставляет
настройки по умолчанию для многих LSP разных языков.&lt;&#x2F;p&gt;
&lt;p&gt;Я пользуюсь &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;junegunn&#x2F;vim-plug&quot;&gt;vim-plug&lt;&#x2F;a&gt; чтобы управлять
своими планинами, поэтому я сначала с его помощью добавил плагин
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;neovim&#x2F;nvim-lspconfig&quot;&gt;lspconfig&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;vim&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-vim &quot;&gt;&lt;code class=&quot;language-vim&quot; data-lang=&quot;vim&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&amp;quot;...
&lt;&#x2F;span&gt;&lt;span&gt;	Plug &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;#39;neovim&#x2F;nvim-lspconfig&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&amp;quot;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Затем я его настроил под себя, добавляя конфигурации для LSP сервера C, Go,
Rust, Python, и Javascript, языки, которыми я чаще всего пользуюсь:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;vim&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-vim &quot;&gt;&lt;code class=&quot;language-vim&quot; data-lang=&quot;vim&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&amp;quot; LSP
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;set&lt;&#x2F;span&gt;&lt;span&gt; omnifunc=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;v:lua&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;vim&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;lsp&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;omnifunc
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;lua require&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;#39;lspconfig&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;clangd&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;setup{filetypes = { &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;quot;c&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;quot;cpp&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;quot;objc&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;quot;objcpp&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;quot;ch&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; }}
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;lua require&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;#39;lspconfig&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;gopls&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;setup{}
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;lua require&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;#39;lspconfig&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;pylsp&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;setup{}
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;lua require&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;#39;lspconfig&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;rls&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;setup{}
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;lua require&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;#39;lspconfig&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;tsserver&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;setup{}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&amp;quot; LSP keybinds
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;nmap &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;lt;silent&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; gd &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;lt;cmd&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;lua&lt;&#x2F;span&gt;&lt;span&gt; vim&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;lsp&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;buf&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;definition&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;lt;CR&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;nmap &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;lt;silent&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; gD &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;lt;cmd&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;lua&lt;&#x2F;span&gt;&lt;span&gt; vim&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;lsp&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;buf&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;declaration&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;lt;CR&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;nmap &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;lt;silent&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; gK &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;lt;cmd&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;lua&lt;&#x2F;span&gt;&lt;span&gt; vim&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;lsp&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;buf&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;hover&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;lt;CR&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;nmap &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;lt;silent&amp;gt; &amp;lt;leader&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;n &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;lt;cmd&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;lua&lt;&#x2F;span&gt;&lt;span&gt; vim&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;lsp&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;buf&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;rename&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;lt;CR&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;nmap &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;lt;silent&amp;gt; &amp;lt;leader&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;b &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;lt;cmd&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;lua&lt;&#x2F;span&gt;&lt;span&gt; vim&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;lsp&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;buf&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;formatting&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;lt;CR&amp;gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&amp;quot; neovim overrides my omnifunc with whatever ccomplete is, so I use this
&lt;&#x2F;span&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;autocmd &lt;&#x2F;span&gt;&lt;span&gt;FileType c,ch,header,cpp &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6699cc;&quot;&gt;setlocal&lt;&#x2F;span&gt;&lt;span&gt; omnifunc=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;v:lua&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;vim&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;lsp&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;omnifunc
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ну и конечно, затем чтобы пользоваться функционалом, необходимо установить LSP
сервера. В случае Go и Rust, он уже входит в их официальные тулчейны. Для C
необходимо установить clang, насколько я знаю GCC не предоставляет имплементацию
сервера LSP.&lt;&#x2F;p&gt;
&lt;p&gt;Привязка клавиш в моей конфигурации позволяют мне переходить к определению с
&lt;code&gt;gd&lt;&#x2F;code&gt; к декларации с &lt;code&gt;gD&lt;&#x2F;code&gt;, открыть всплывающее окно с информации имплементации и
документирующими комментариями с &lt;code&gt;gK&lt;&#x2F;code&gt;, переименовать переменные с &lt;code&gt;&amp;lt;leader&amp;gt;n&lt;&#x2F;code&gt;
(leader в моей конфигурации это пробел), и скормить исходный файл утилиты
форматирования кода (например, gofmt) с &lt;code&gt;&amp;lt;leader&amp;gt;b&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;drugie-plaginy&quot;&gt;Другие плагины&lt;&#x2F;h3&gt;
&lt;p&gt;LSP предоставляет большинство функций, которые стоит ожидать от IDE, но так же
есть и другие плагины, которые улучшают процесс редактирования кода. В том
числе:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;vim&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-vim &quot;&gt;&lt;code class=&quot;language-vim&quot; data-lang=&quot;vim&quot;&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&amp;quot;...
&lt;&#x2F;span&gt;&lt;span&gt;	Plug &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;#39;ervandew&#x2F;supertab&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;	Plug &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;#39;majutsushi&#x2F;tagbar&amp;#39;
&lt;&#x2F;span&gt;&lt;span&gt;	Plug &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;#39;tpope&#x2F;vim-commentary&amp;#39;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;&amp;quot;...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Первый из них, &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ervandew&#x2F;supertab&quot;&gt;supertab&lt;&#x2F;a&gt;, делает более
удобным автозаполнение. По умолчанию автозаполнение &lt;code&gt;omnifunc&lt;&#x2F;code&gt; привязано к
&amp;lt;C-x&amp;gt;&amp;lt;C-o&amp;gt;, что не очень удобно. Обычно в консольных терминалах и в других
редакторах клавиша Tab вызывает функцию автозаполнения, что казалось бы
разумным. Но иногда также есть необходимость вставить символ табуляции вручную.
Для этого и годиться этот плагин. После нажатия на клавишу Tab, он
автоматически, в зависимости от контекста, либо вставляет символ табуляции либо
вызывает автозаполнения.&lt;&#x2F;p&gt;
&lt;p&gt;Далее &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;preservim&#x2F;tagbar&quot;&gt;tagbar&lt;&#x2F;a&gt;. Данный плагин позволяет
открывать панель со списком глобальных перемен, определений структур данных, и
функции в текущем исходном файле. Для его работы требуются ctags.&lt;&#x2F;p&gt;
&lt;p&gt;Наконец &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tpope&#x2F;vim-commentary&quot;&gt;vim-commentary&lt;&#x2F;a&gt;, который
предоставляет возможность легко и быстро закомментировать несколько строк
одновременно. Не так прямо и полезно как другие плагины, но тем не менее.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;otladka&quot;&gt;Отладка&lt;&#x2F;h2&gt;
&lt;p&gt;Рано или поздно в процессе разработки программного обеспечения вы столкнётесь с
ошибкой, которая приведёт к неправильно исполнению программы. Можно найти
проблему вручную выпяливая код и чеща себе голову. Но есть и способ получше.
Можно открыть отладчик и анализировать программу наблюдая за её исполнение
пошагово.&lt;&#x2F;p&gt;
&lt;p&gt;Некоторое время, по крайней мере с C и языками поддерживаемые gdb, я просто
открывал gdb в другом окне с терминалом и оставлял открытым в другом окне Vim с
исходным кодом. Но появились пару новинок в Vim&#x27;е, которые сделали этот процесс
намного удобнее.&lt;&#x2F;p&gt;
&lt;p&gt;Первая это &lt;code&gt;terminal&lt;&#x2F;code&gt;, которая как имя и полагает, является терминальным
эмулятором внутри самого вима. Если коротко, то оно позволяет открывать новый
терминал внутри буфера вима. Лично для меня этот функционал сам по себе не очень
полезный, так как я пользуюсь плиточным оконным менеджером, которые мне и так
уже предоставляет возможность быстро и удобно перемещаться по окнам. Тем не
менее, этот плагин делает возможным следующий плагин, который зависит от него.&lt;&#x2F;p&gt;
&lt;p&gt;Звезда нашего шоу — &lt;code&gt;Termdebug&lt;&#x2F;code&gt;, плагин, который встроенный как в Vim (версия &amp;gt;=
8.1) так и в Neovim. То, что он делает это открывать два буфера, один с консолью
gdb, а второй с выходом отлаживаемой программы. В буфере с консолью пви можно
традиционным способом пользоваться gdb вводя в неё команды, или через команды
вима.&lt;&#x2F;p&gt;
&lt;p&gt;Для того, чтобы начать пользоваться Termbug&#x27;ом, необходимо сначала подгрузить
плагин:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;vim&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-vim &quot;&gt;&lt;code class=&quot;language-vim&quot; data-lang=&quot;vim&quot;&gt;&lt;span&gt;:packadd termdebug
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Затем запускаем его передавая название бинарного файла, который требуется
отлаживать:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;vim&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-vim &quot;&gt;&lt;code class=&quot;language-vim&quot; data-lang=&quot;vim&quot;&gt;&lt;span&gt;:Termdebug &lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;&amp;lt;путь к бинарнику&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;После запуска появятся два буфера, один с выводом отлаживаемой программы и
второй с консолью gdb. Оба буфера терминалы. Для того чтобы пользоваться
терминальными буферами в виме, нужно перейти в режим вставки чтобы печатать в
терминале. Чтобы выйти из режима вставки необходимо ввести &amp;lt;C-\&amp;gt;&amp;lt;C-n&amp;gt;.
Почему не Esc? А потому, что некоторые терминальные программы пользуются им,
например, режим vi в bash или zsh. Ну или например другая истанция вима внутриа
вима, почему бы и нет ¯\&lt;em&gt;(ツ)&lt;&#x2F;em&gt;&#x2F;¯.&lt;&#x2F;p&gt;
&lt;p&gt;После того, как открыли Termdebug, можно запустить отлаживаемую программу
традиционным способом с gdb. Или из самого вима с &lt;code&gt;:Run &amp;lt;аргументы&amp;gt;&lt;&#x2F;code&gt;. Другие
полезные команды: &lt;code&gt;:Break&lt;&#x2F;code&gt; для того, чтобы вставить точку остановки в текущей
строке кода, &lt;code&gt;:Clear&lt;&#x2F;code&gt; чтобы её удалить, &lt;code&gt;:Continue&lt;&#x2F;code&gt; для того чтобы продолжить
выполнение программы и т.д.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.yaroslavps.com&#x2F;ru&#x2F;weblog&#x2F;debugging-in-vim&#x2F;debugging-session.png&quot;&gt;&lt;img src=&quot;https:&#x2F;&#x2F;www.yaroslavps.com&#x2F;ru&#x2F;weblog&#x2F;debugging-in-vim&#x2F;debugging-session.png&quot; alt=&quot;Снимок примера отладки программы в Vim&quot; &#x2F;&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;
&lt;p&gt;Пример отладки программы в Vim.&lt;&#x2F;p&gt;
&lt;&#x2F;figcaption&gt;
&lt;p&gt;Что делает это замечательным это то, что можно наблюдать за процессом отладки
прямиком из исходного файла. Не надо постоянно вводить &lt;code&gt;list&lt;&#x2F;code&gt; в gdb, можно
просто переходить по файлам и ставить или удалять точки установки.&lt;&#x2F;p&gt;
&lt;p&gt;Конечно, так как по сути отладка-то происходит в gdb, то правила и те же.
Например, необходимо компилировать программу с символами для отладки, т.е. с
флагом &lt;code&gt;-g&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;posleslovie&quot;&gt;Послесловие&lt;&#x2F;h2&gt;
&lt;p&gt;Это только некоторые плагины, которые помогают мне более эффективно писать и
отлаживать программы в виме. Этот текст не является подробным туториалом
настройки вима или правильной отладки программ. Им я просто хотел показать как
можно удобно и легко пользоваться вимом наряду с другими инструментами для
упрощения разработки и отладки ПО. Существует множество информации в интернете
насчёт того, как правильно настроить вим, или как отлаживать программы с gdb или
другими утилитами как valgrind или ASan.&lt;&#x2F;p&gt;
&lt;p&gt;Если хочется узнать больше про LSP в neovim, советую почитать страницу помощи в
neovim вводя &lt;code&gt;:help lsp&lt;&#x2F;code&gt;. Аналогично для Termdebugger &lt;code&gt;:help Termdebugger&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Если вам интересно, то моя конфигурация вима доступна по ссылке
&lt;a href=&quot;https:&#x2F;&#x2F;git.yaroslavps.com&#x2F;configs&#x2F;vimrice&#x2F;&quot;&gt;https:&#x2F;&#x2F;git.yaroslavps.com&#x2F;configs&#x2F;vimrice&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;figcaption id=&quot;exit-vim&quot;&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;www.yaroslavps.com&#x2F;ru&#x2F;weblog&#x2F;debugging-in-vim&#x2F;quit-vim.jpg&quot; alt=&quot;Как выйти из вима&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Если вы никогда не пользовались вимом, и вы повелись на то, чтобы его открыть,
после того как прочитали этот текст, и вы не можете выйти из него то, эта
картинка вам в помощь.&lt;&#x2F;p&gt;
&lt;&#x2F;figcaption&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Не полностью соответствует философии Юникс, но по большей мере да, в том
плане что это программа, которая делает одну вещь и делает её хорошо. Да, я
тоже в шоке, не ожидал такого от Microsoft. Больше информации по LSP можно
прочитать здесь: &lt;a href=&quot;https:&#x2F;&#x2F;microsoft.github.io&#x2F;language-server-protocol&#x2F;&quot;&gt;https:&#x2F;&#x2F;microsoft.github.io&#x2F;language-server-protocol&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
	</entry>
	<entry xml:lang="ru">
		<title>День Мёртвых</title>
		<published>2021-10-18T19:56:58+00:00</published>
		<updated>2021-10-18T19:56:58+00:00</updated>
		<link href="https://www.yaroslavps.com/ru/weblog/dia-de-muertos/" type="text/html"/>
		<id>https://www.yaroslavps.com/ru/weblog/dia-de-muertos/</id>
		<content type="html">&lt;p&gt;Довольно часто друзья и знакомые спрашивают в чём заключается знаменитый
мексиканский праздник — день мёртвых. Затем чтобы было проще объяснить
особенности дня мёртвых я решил написать краткий текст, который расскажет
немного о празднике.  Здесь я также напишу что можно сделать чтобы украсить
пространство на день мёртвых.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;Начну я с того, что расскажу немного истории и контекста дня мёртвых.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;nemnogo-istorii&quot;&gt;Немного истории&lt;&#x2F;h2&gt;
&lt;p&gt;Праздник дня мёртвых исконно мексиканский праздник. Данный праздник является
сливом разных культур. С одной стороны имеются традиции коренных народов
Мексики и их поклонению смерти, а с другой огромное влияние оказало принесённые
испанцами традиции и католическая религия.&lt;&#x2F;p&gt;
&lt;p&gt;Насколько сильно повлияли традиции доиспанских народов или испанские традиции,
сложно сказать. Но как бы то не было, праздник очень много чему обязан
католичеству , и христианству в целом. Он очень тесно связан с собором (или
днём) всех святых, и днём всех усопших верных.&lt;&#x2F;p&gt;
&lt;p&gt;Но всё же это уникальный праздник со своими особенностями. К тому же, стоит
отметить что праздник не одинаково отмечают по всей стране. У каждого региона
есть свои разновидности праздника.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sut-prazdnika&quot;&gt;Суть праздника&lt;&#x2F;h2&gt;
&lt;p&gt;Считается что в день мёртвых, духи мёртвых возвращаются в мир живых чтобы
провести время с родными и близкими. Их близкие в мире живых подготавливают
алтари в их честь и духи питаются сущностью пищи, оставленная для них в данных
алтарях.&lt;&#x2F;p&gt;
&lt;p&gt;Смерть, для многих в Мексике, особенно в день мёртвых, не значит отсутствие
чего-либо. Смерть — часть жизни, и она материализуется в этих алтарях.&lt;&#x2F;p&gt;
&lt;p&gt;День мёртвых отмечается 1-го и 2-го ноября, что соответствует католическим
праздникам всех святых и всех усопших верных соответственно. Однако, в празднике
дня мёртвых 1-ое ноября посвящается детям, а 2-ое ноября взрослым.&lt;&#x2F;p&gt;
&lt;p&gt;Праздник в основном семейный, и многие семьи в Мексики ставят алтари у себя дома
в честь близких для них людей, которые уже погибли. Однако и во многих городах и
посёлков Мексики праздник разрастается в нечто больше, и люди собираются вместе
чтобы вспоминать и почтить мёртвых.&lt;&#x2F;p&gt;
&lt;p&gt;Самое главное в празднике, это сохранить память о людей, которые больше не
находятся с нами в этом мире.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ukrasheniia-na-den-miortvykh&quot;&gt;Украшения на день мёртвых&lt;&#x2F;h2&gt;
&lt;p&gt;Существует множество предметов используемые в качестве украшения и для
составления алтаря. Далее список самых значимых предметов используемые для
украшения и для алтаря:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.yaroslavps.com&#x2F;ru&#x2F;weblog&#x2F;dia-de-muertos&#x2F;papel-picado&quot;&gt;Papel picado&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.yaroslavps.com&#x2F;ru&#x2F;weblog&#x2F;dia-de-muertos&#x2F;#tsvety-i-lepestki&quot;&gt;Лепестки&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.yaroslavps.com&#x2F;ru&#x2F;weblog&#x2F;dia-de-muertos&#x2F;#tsvety-i-lepestki&quot;&gt;Цветы&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.yaroslavps.com&#x2F;ru&#x2F;weblog&#x2F;dia-de-muertos&#x2F;#altar&quot;&gt;Алтарь&lt;&#x2F;a&gt;
&lt;ul&gt;
&lt;li&gt;Свечи&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.yaroslavps.com&#x2F;ru&#x2F;weblog&#x2F;dia-de-muertos&#x2F;#tsvety-i-lepestki&quot;&gt;Цветы&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.yaroslavps.com&#x2F;ru&#x2F;weblog&#x2F;dia-de-muertos&#x2F;#khleb-miortvykh&quot;&gt;Хлеб мёртвых&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;www.yaroslavps.com&#x2F;ru&#x2F;weblog&#x2F;dia-de-muertos&#x2F;#sakharnye-cherepa&quot;&gt;Сахарные черепа&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Портреты покойных&lt;&#x2F;li&gt;
&lt;li&gt;Любимая еда покойных&lt;&#x2F;li&gt;
&lt;li&gt;Фигурки или изображения святых&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;papel-picado&quot;&gt;Papel picado&lt;&#x2F;h3&gt;
&lt;p&gt;Папель пикадо это такой вид бумажного искусства из Мексики, который используется
для украшение домов, ресторанов, улиц; в общем, почти любое место можно им
украсить. Это такие флажки сделанные из папиросной бумаги (в Мексике её называют
китайской) с вырезанным узором или рисунком. Его несложно сделать самому дома с
помощью ножниц или ножа, но его также продают уже готовым и можно приобрести
даже в некоторой довольно известной китайской торговой площадки.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;www.yaroslavps.com&#x2F;ru&#x2F;weblog&#x2F;dia-de-muertos&#x2F;papel-picado.jpg&quot; alt=&quot;Papel picado&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;
&lt;p&gt;Papel picado — фото
&lt;a href=&quot;https:&#x2F;&#x2F;www.flickr.com&#x2F;photos&#x2F;gozalewis&#x2F;4533466093&quot;&gt;timlewisnm&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;figcaption&gt;
&lt;p&gt;Этими флажками часто украшают праздники. Один из таких праздников, в котором они
всегда применяются, это день мёртвых. На день мёртвых рисунки на флажках
делаются по тематике дня мёртвых. Например, очень известный персонаж из
Мексиканского фольклора — Катрина.&lt;&#x2F;p&gt;
&lt;p&gt;Их вешают как правило на потолок и вокруг алтаря.&lt;&#x2F;p&gt;
&lt;p&gt;Если интересно самому сделать, в конце статьи&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; оставлю ссылку на видео в
котором можно посмотреть процесс его изготовления. Видео на испанском, но тем не
менее сам процесс несложный и его можно рассмотреть на видео.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;la-calavera-catrina&quot;&gt;La Calavera Catrina&lt;&#x2F;h3&gt;
&lt;p&gt;«Череп Катрина» или просто «Катрина» довольно известный персонаж в Мексике
появившийся впервые в гравюре мексиканского художника Хосе Гуадалупе Посада в
1913 году.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;www.yaroslavps.com&#x2F;ru&#x2F;weblog&#x2F;dia-de-muertos&#x2F;catrina.jpg&quot; alt=&quot;La Calavera Catrina&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;
&lt;p&gt;La Calavera Catrina&lt;&#x2F;p&gt;
&lt;&#x2F;figcaption&gt;
&lt;p&gt;Катрина самый известный персонаж из серии персонажей мексиканского
фольклора «Calaveras» что на русском «Черепа». Эти «Калаверы» имеют также
литературный вариант. «Литературные калаверы» — исконно мексиканские
стихотворные сочинения сатирического характера и часто сочиняются в преддверии
дня мёртвых с целью высмеять как мёртвых как и живых и напомнить о том, что все
мы когда-нибудь умрём.&lt;&#x2F;p&gt;
&lt;p&gt;Хоть и изначально персонаж был создан в качестве критики бедных мексиканцев,
которые пытались подражать европейцев дорогими украшениями и одеждой, персонаж
быстро вошёл в мексиканский фольклор как один из основных символов смерти и дня
мёртвых.&lt;&#x2F;p&gt;
&lt;p&gt;Её образ в день мёртвых можно встретить в папель пикадо, в плакатах и разных
рисунках.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;altar&quot;&gt;Алтарь&lt;&#x2F;h3&gt;
&lt;p&gt;Алтарь это самая важная часть ритуала дня мёртвых. Это то, что позволяет духам
покойных вернуться на время праздника чтобы провести время с близким и
наслаждаться подношением оставленного их близкими.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;www.yaroslavps.com&#x2F;ru&#x2F;weblog&#x2F;dia-de-muertos&#x2F;altar.jpg&quot; alt=&quot;Пример алтаря&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;
&lt;p&gt;Пример алтаря — фото
&lt;a href=&quot;https:&#x2F;&#x2F;www.flickr.com&#x2F;photos&#x2F;eneas&#x2F;4072192627&#x2F;&quot;&gt;Eneas de Troya&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;figcaption&gt;
&lt;p&gt;Конструкция алтаря состоит из ступенчатой структуры, которая может быть
созданной из столов или коробок, покрыта скатертью или полотном. На каждом
уровне или ступеньке алтаря ставятся разные украшения и подношения для
покойного чью смерть чтят. Примеры предметов, которые можно найти на Алтаре:
свечи, цветы, хлеб мёртвых, сахарные черепа, любимая еда покойных, фигурки и
изображения святых, портреты покойных, папель пикадо и другие предметы в
зависимости от региона страны. Но самыми важными это портреты близких покойных и
подношение для их духов.&lt;&#x2F;p&gt;
&lt;p&gt;Также вокруг алтаря и по дороге к нему сыпят лепестки бархатцев.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tsvety-i-lepestki&quot;&gt;Цветы и лепестки&lt;&#x2F;h3&gt;
&lt;p&gt;Для украшения алтаря и могил мёртвых используются в основном два вида цветков:
бархатцы прямостоячие и целозия серебристая. Самый важный и значительный из них
бархатцы, растения чьей центр происхождение находится в Мексике.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;www.yaroslavps.com&#x2F;ru&#x2F;weblog&#x2F;dia-de-muertos&#x2F;cempasuchil.jpg&quot; alt=&quot;«Семпасучиль»&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;
&lt;p&gt;Бархатцы прямостоячие «семпасучиль» — фото
&lt;a href=&quot;https:&#x2F;&#x2F;flickr.com&#x2F;photos&#x2F;cristian2222&#x2F;8146297400&quot;&gt;Cristian Bernardo Velasco&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;figcaption&gt;
&lt;p&gt;Бархатцы использовались ещё до времён испанской империи коренными народами не
только как украшение, но также как источник жёлтой краски, из-за чего и
использовался в алтарях и подношений мёртвых. По традиции эти цветы ставят на
алтаре а также его лепестки используются чтобы отметить дорогу к алтарю.
Бархатцы известные в Мексике под названием «семпасучиль», происходящее из языка
науатль.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;www.yaroslavps.com&#x2F;ru&#x2F;weblog&#x2F;dia-de-muertos&#x2F;flor-terciopelo.jpg&quot; alt=&quot;Целозия серебристая&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;
&lt;p&gt;Целозия серебристая — фото
&lt;a href=&quot;https:&#x2F;&#x2F;www.flickr.com&#x2F;photos&#x2F;adaduitokla&#x2F;6180982759&#x2F;&quot;&gt;Ahmad Fuad Morad&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;figcaption&gt;
&lt;p&gt;Но бархатцы, или «семпасучиль» не единственные цветы, которые используются чтобы
разукрасить день мёртвых. Ещё одно такое растение — целозия серебристая. Её
обычно ставят на алтарях вместе с бархатцами в качестве подношения мёртвым. Один
интересный факт данного растения заключается в том, что оно не только служит
красивым орнаментом, но оно также съедобное.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;khleb-miortvykh&quot;&gt;Хлеб мёртвых&lt;&#x2F;h3&gt;
&lt;p&gt;Хлеб мёртвых один из самых известных символов дня мёртвых, который можно найти в
любом алтаре. Его пекут специально ко дню мёртвых. Его используют не только в
качестве подношения, но он также является вкусным и популярным кондитерским
изделием во время праздника дня мёртвых&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;www.yaroslavps.com&#x2F;ru&#x2F;weblog&#x2F;dia-de-muertos&#x2F;pan-muertos.jpg&quot; alt=&quot;Хлеб мёртвых&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;
&lt;p&gt;Хлеб мёртвых — фото
&lt;a href=&quot;https:&#x2F;&#x2F;www.flickr.com&#x2F;photos&#x2F;hexenesi&#x2F;4115486988&quot;&gt;J.P. C.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;figcaption&gt;
&lt;p&gt;Хлеб мёртвых сладкий хлеб в виде полушара, который символизирует череп, с
четырьмя «косточками» сверху. Как правило он состоит из пшеничной муки, молока,
дрожжей, сахара, соля, масла и часто ещё добавляют чуточку аниса и апельсина.
Это очень вкусный хлеб, и одно из моих любимых кондитерских изделий.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sakharnye-cherepa&quot;&gt;Сахарные черепа&lt;&#x2F;h3&gt;
&lt;p&gt;В Мексике имеется большое разнообразие конфеток и сладостей, в том числе такие,
которые готовятся специально для определённых праздников. Череп очень известный
символ дня мёртвых в Мексике, и поэтому нельзя было не разукрасить алтари без
черепов. Одни такой способ использовать черепа в качестве украшения и подношения
это сахарные черепа — кондитерские изделия в форме черепа.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;www.yaroslavps.com&#x2F;ru&#x2F;weblog&#x2F;dia-de-muertos&#x2F;calaverita.jpg&quot; alt=&quot;Сахарные черепа&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;figcaption&gt;
&lt;p&gt;Сахарный череп — фото
&lt;a href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:Calavera.jpg&quot;&gt;Nathaniel C. Sheetz&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;figcaption&gt;
&lt;p&gt;Сахарные черепа имеют много разновидностей, но в основном они изготавливаются из
пасты сделанной из сахара и лимонного сока. Пасту лепят в форму черепа и потом
добавляют поверх него другие украшения, также из сахара, но с каким-нибудь
растительном красителем.&lt;&#x2F;p&gt;
&lt;p&gt;В некоторых случаях используются черепа изготовленные из глины, вместо сахарных
черепов&lt;sup class=&quot;footnote-reference&quot;&gt;&lt;a href=&quot;#3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;v-zakliuchenii&quot;&gt;В заключении&lt;&#x2F;h2&gt;
&lt;p&gt;Праздник мёртвых один из самых больших праздников в Мексике и, естественно, в
таком коротком тексте не расскажешь всё о нём. Тем не менее, я надеюсь что это
информация помогла всем тем, кто не был особо знаком праздником или не имел
представления о нём. Ну или по крайней мере тем, кому я отправил ссылку на этот
текст.&lt;&#x2F;p&gt;
&lt;p&gt;Уже приближается праздник дня мёртвых, так что если вы хотите почтить память
близких вам людей, которые уже покинули этот мир, то у вас в распоряжении уже
есть основная информация как это сделать по-мексикански.&lt;&#x2F;p&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;1&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;1&lt;&#x2F;sup&gt;
&lt;p&gt;Инструкции по изготовлению папель пикадо —
&lt;a href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=d-HyDirNyA0&quot;&gt;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=d-HyDirNyA0&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;2&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;2&lt;&#x2F;sup&gt;
&lt;p&gt;Это очень вкусный хлеб и один из моих любимых. Возможно скоро, когда у
меня появится духовка, я постараюсь приготовить его. Если у меня удастся его
приготовить то я обязательно напишу рецепт по нему в своей
&lt;a href=&quot;&#x2F;ru&#x2F;food&#x2F;&quot;&gt;книге рецептов&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;div class=&quot;footnote-definition&quot; id=&quot;3&quot;&gt;&lt;sup class=&quot;footnote-definition-label&quot;&gt;3&lt;&#x2F;sup&gt;
&lt;p&gt;Но черепа из глины не съешь.&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
</content>
	</entry>
	<entry xml:lang="ru">
		<title>Введение в Linux и Bash, часть III</title>
		<published>2019-01-11T08:23:00+00:00</published>
		<updated>2019-01-11T08:23:00+00:00</updated>
		<link href="https://www.yaroslavps.com/ru/weblog/intro-to-linux-and-bash-pt3/" type="text/html"/>
		<id>https://www.yaroslavps.com/ru/weblog/intro-to-linux-and-bash-pt3/</id>
		<content type="html">&lt;p&gt;Новый год, новый пост. В данной, третьей и последней, части этого туториала,
будут несколько команд и программ которые являются стандартной частью
большинства дистрибутивов Линукса. Больше всего внимания я буду выделять
программ, которые манипулируют вывод текст других программ и файлов. Также в
этом посте мы поговорим о регулярных выражений (коротко - regex, от английского
Regular Expression), очень мощный инструмент для поиска текста&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;&lt;h2 id=&quot;fil-try&quot;&gt;Фильтры&lt;&#x2F;h2&gt;
&lt;p&gt;Программы, которые манипулируют потоки текста и возвращают его в стандартный
вывод, часто зовут фильтрами. Скорее всего вы уже знакомы с первой командой, о
которой я будут писать.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;cat&quot;&gt;cat&lt;&#x2F;h3&gt;
&lt;p&gt;Данная команда позволяет посмотреть содержимое текстового файла (или файлов).
Название программы ни как не связанна с котейками, а происходит от слово
конкатенация. Самое простое применение данной программы - просмотр текстовых
файлов. Просто пишите cat а затем путь файла. Однако, как можно предположить
исходя из названии программы, она также позволяет соединять несколько текстовых
файлов или потоков в один. Например&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents&#x2F;notes$&lt;&#x2F;span&gt;&lt;span&gt; cat sample.txt
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Pepe&lt;&#x2F;span&gt;&lt;span&gt;    cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Tide&lt;&#x2F;span&gt;&lt;span&gt; Pods   lame
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Uganda&lt;&#x2F;span&gt;&lt;span&gt; Knuckles cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Thanos&lt;&#x2F;span&gt;&lt;span&gt;  cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;JPEG&lt;&#x2F;span&gt;&lt;span&gt;    ok
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Despacito&lt;&#x2F;span&gt;&lt;span&gt;   lame
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Bowsette&lt;&#x2F;span&gt;&lt;span&gt;    cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Harold&lt;&#x2F;span&gt;&lt;span&gt;  cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Sans&lt;&#x2F;span&gt;&lt;span&gt;    coolest
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Minions&lt;&#x2F;span&gt;&lt;span&gt; lamest
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;NPC&lt;&#x2F;span&gt;&lt;span&gt; cool
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;А теперь допустим что мы хотим соединить соджержимое данного файла с файлом
&#x27;sample2.txt&#x27;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents&#x2F;notes$&lt;&#x2F;span&gt;&lt;span&gt; cat sample.txt sample2.txt
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Pepe&lt;&#x2F;span&gt;&lt;span&gt;    cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Tide&lt;&#x2F;span&gt;&lt;span&gt; Pods   lame
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Uganda&lt;&#x2F;span&gt;&lt;span&gt; Knuckles cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Thanos&lt;&#x2F;span&gt;&lt;span&gt;  cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;JPEG&lt;&#x2F;span&gt;&lt;span&gt;    ok
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Despacito&lt;&#x2F;span&gt;&lt;span&gt;   lame
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Bowsette&lt;&#x2F;span&gt;&lt;span&gt;    cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Harold&lt;&#x2F;span&gt;&lt;span&gt;  cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Sans&lt;&#x2F;span&gt;&lt;span&gt;    coolest
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Minions&lt;&#x2F;span&gt;&lt;span&gt; lamest
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;NPC&lt;&#x2F;span&gt;&lt;span&gt; cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Troll&lt;&#x2F;span&gt;&lt;span&gt; Face  old
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Can&lt;&#x2F;span&gt;&lt;span&gt; haz chezburger  really old
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;ROFLcopter&lt;&#x2F;span&gt;&lt;span&gt;  super old
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Dancing&lt;&#x2F;span&gt;&lt;span&gt; baby    ancient
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Как обычно, у данной команды есть несколько параметров, как например параметр
-n чтобы показать номер строки&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents&#x2F;notes$&lt;&#x2F;span&gt;&lt;span&gt; cat&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt; -n&lt;&#x2F;span&gt;&lt;span&gt; sample.txt
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;  Pepe    cool
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;  Tide Pods   lame
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;  Uganda Knuckles cool
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;  Thanos  cool
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span&gt;  JPEG    ok
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;  Despacito   lame
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;7&lt;&#x2F;span&gt;&lt;span&gt;  Bowsette    cool
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span&gt;  Harold  cool
&lt;&#x2F;span&gt;&lt;span&gt;     &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;9&lt;&#x2F;span&gt;&lt;span&gt;  Sans    coolest
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;  Minions lamest
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;11&lt;&#x2F;span&gt;&lt;span&gt;  NPC cool
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;И как я уже рассказывал в предыдущей части, вы можете узнать больше о команде,
используя программу man (&#x27;man cat&#x27;).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;head&quot;&gt;head&lt;&#x2F;h3&gt;
&lt;p&gt;Данная команда довольно простая, она показывает первые n строки текстового
файла&#x2F;потока. Введите head, затем -n и количество строк вы желаете увидеть, а
затем петь файла. Например, допустим что мы хотим увидеть первые 5 строк&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents&#x2F;notes$&lt;&#x2F;span&gt;&lt;span&gt; head&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt; -n&lt;&#x2F;span&gt;&lt;span&gt; 5 sample.txt
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Pepe&lt;&#x2F;span&gt;&lt;span&gt;    cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Tide&lt;&#x2F;span&gt;&lt;span&gt; Pods   lame
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Uganda&lt;&#x2F;span&gt;&lt;span&gt; Knuckles cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Thanos&lt;&#x2F;span&gt;&lt;span&gt;  cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;JPEG&lt;&#x2F;span&gt;&lt;span&gt;    ok
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Если мы не передаем количетсво строк, по умолчанию она выводит первые 10 строк.
Для просто напишите head а затем путь файла.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tail&quot;&gt;tail&lt;&#x2F;h3&gt;
&lt;p&gt;Работает также как head, но в отличие от нее, данная команда показывает
последние строки текста. Допустим мы хотим увидеть последние три строки&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents&#x2F;notes$&lt;&#x2F;span&gt;&lt;span&gt; tail&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt; -n&lt;&#x2F;span&gt;&lt;span&gt; 3 sample.txt
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Sans&lt;&#x2F;span&gt;&lt;span&gt;    coolest
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Minions&lt;&#x2F;span&gt;&lt;span&gt; lamest
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;NPC&lt;&#x2F;span&gt;&lt;span&gt; cool
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Также как и с предыдущей командой, по умолчанию выводятся 10 строк.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sort&quot;&gt;sort&lt;&#x2F;h3&gt;
&lt;p&gt;С данной командой все очень просто. Она сортирует текст. Например&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents&#x2F;notes$&lt;&#x2F;span&gt;&lt;span&gt; sort sample.txt
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Bowsette&lt;&#x2F;span&gt;&lt;span&gt;    cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Despacito&lt;&#x2F;span&gt;&lt;span&gt;   lame
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Harold&lt;&#x2F;span&gt;&lt;span&gt;  cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;JPEG&lt;&#x2F;span&gt;&lt;span&gt;    ok
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Minions&lt;&#x2F;span&gt;&lt;span&gt; lamest
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;NPC&lt;&#x2F;span&gt;&lt;span&gt; cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Pepe&lt;&#x2F;span&gt;&lt;span&gt;    cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Sans&lt;&#x2F;span&gt;&lt;span&gt;    coolest
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Thanos&lt;&#x2F;span&gt;&lt;span&gt;  cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Tide&lt;&#x2F;span&gt;&lt;span&gt; Pods   lame
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Uganda&lt;&#x2F;span&gt;&lt;span&gt; Knuckles cool
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;sed&quot;&gt;sed&lt;&#x2F;h3&gt;
&lt;p&gt;sed довольная мощная утилита которая позволяет манипулировать и модифицировать
текст. Однако, в данном туториале я не буду углубляться в подробностях работы с
программой, но покажу пару пару самых используемых команд.&lt;&#x2F;p&gt;
&lt;p&gt;Для работы с данной программой, необходимо передать своего рода скрирта (sed
script), который укажет программе что делать с текстом. Первый и самый простой
способ использовать sed, это использовать его в качестве программы head, то
есть, получить первые b строк текста. Например, допустим что нам необходимо
получить первые 7 строк из файла sample.txt&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents&#x2F;notes$&lt;&#x2F;span&gt;&lt;span&gt; sed &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;7q&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; sample.txt
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Pepe&lt;&#x2F;span&gt;&lt;span&gt;    cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Tide&lt;&#x2F;span&gt;&lt;span&gt; Pods   lame
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Uganda&lt;&#x2F;span&gt;&lt;span&gt; Knuckles cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Thanos&lt;&#x2F;span&gt;&lt;span&gt;  cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;JPEG&lt;&#x2F;span&gt;&lt;span&gt;    ok
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Despacito&lt;&#x2F;span&gt;&lt;span&gt;   lame
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Bowsette&lt;&#x2F;span&gt;&lt;span&gt;    cool
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;А если более подробно объяснить что данная команда делает, то она говорит
программе чтобы она вывела 7 строк, и затем вышла (q).&lt;&#x2F;p&gt;
&lt;p&gt;Другой случай, и сокрее всего самое распространенное применение данной
команды, это операция поиска и замены текста. Основная синтаксис данной
операции выгладит следующим образцом - &#x27;s&#x2F;&amp;lt;поиск&amp;gt;&#x2F;&amp;lt;замена&amp;gt;&#x2F;&#x27;.&lt;&#x2F;p&gt;
&lt;p&gt;По умолчанию данная команда заменяет только первое совпадение в каждой строке,
тем не менее мы может указать какие и сколько совпадении мы хотим заменить.
Например, если мы добавим двойку в конце команды (&#x27;s&#x2F;&lt;search&gt;&#x2F;&lt;replace&gt;&#x2F;2&#x27;)
она заменит только вторые совпадения в каждой строке.&lt;&#x2F;p&gt;
&lt;p&gt;Но а что если мы хотим заменить все совпадения во всех строках? Все очень
просто - достаточно добавить букву g в конец. Допустим что мы хотим заменить
все подстроки &quot;cool&quot; на &quot;dank&quot; в файле sample.txt&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents&#x2F;notes$&lt;&#x2F;span&gt;&lt;span&gt; sed &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;s&#x2F;cool&#x2F;dank&#x2F;g&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; sample.txt
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Pepe&lt;&#x2F;span&gt;&lt;span&gt;    dank
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Tide&lt;&#x2F;span&gt;&lt;span&gt; Pods   lame
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Uganda&lt;&#x2F;span&gt;&lt;span&gt; Knuckles dank
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Thanos&lt;&#x2F;span&gt;&lt;span&gt;  dank
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;JPEG&lt;&#x2F;span&gt;&lt;span&gt;    ok
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Despacito&lt;&#x2F;span&gt;&lt;span&gt;   lame
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Bowsette&lt;&#x2F;span&gt;&lt;span&gt;    dank
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Harold&lt;&#x2F;span&gt;&lt;span&gt;  dank
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Sans&lt;&#x2F;span&gt;&lt;span&gt;    dankest
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Minions&lt;&#x2F;span&gt;&lt;span&gt; lamest
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;NPC&lt;&#x2F;span&gt;&lt;span&gt; dank
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Обратите внимание на то что команду которую мы передаем sed&#x27;у находится в
кавычках. Конечно это только одни из самых основных применении.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;grep&quot;&gt;grep&lt;&#x2F;h3&gt;
&lt;p&gt;Это последняя программа-фильтр, о которой я расскажу. Я покажу самое основное
применение данной программы, а затем, после того как расскажу о регулярных
выражений, покажу ее более интересные применения.&lt;&#x2F;p&gt;
&lt;p&gt;grep - программа, которая выполняет поиск выражения переданный ей
пользователем, и выводит на экран строки, совпадавшие с условиями поиска.
Допустим, например, что мы хотим увидеть только крутые (cool) мемы&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents&#x2F;notes$&lt;&#x2F;span&gt;&lt;span&gt; grep &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;cool&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; sample.txt
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Pepe&lt;&#x2F;span&gt;&lt;span&gt;    cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Uganda&lt;&#x2F;span&gt;&lt;span&gt; Knuckles cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Thanos&lt;&#x2F;span&gt;&lt;span&gt;  coolcharacter
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Bowsette&lt;&#x2F;span&gt;&lt;span&gt;    cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Harold&lt;&#x2F;span&gt;&lt;span&gt;  cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Sans&lt;&#x2F;span&gt;&lt;span&gt;    coolest
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;NPC&lt;&#x2F;span&gt;&lt;span&gt; cool
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;То, что мы передали grep&#x27;у является самым простым видом регулярного выражения.
По факту мы указали программе чтобы нам показала строки где содержится
подстрока &quot;cool&quot;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;reguliarnye-vyrazheniia&quot;&gt;Регулярные выражения&lt;&#x2F;h2&gt;
&lt;p&gt;Регулярное выражение - язык поиска и манипуляции подстроками в тексте. Для
поиска используется строка текста, часто называемая строка-образец или
&quot;шаблон&quot;, состоящая из символов, которые задают правило поиска. Регулярные
выражения применяются в многих программах и языках программирования, таких как
например редакторов текста и поисков, и естественно, может быть довольно
полезным в терминале.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;antrakt&quot;&gt;Антракт&lt;&#x2F;h3&gt;
&lt;p&gt;Перед тем как объяснить как работать с регулярными выражениями, хочу показать
пару символов, облегчающие жизнь при работе с файлами в терминале -
символы-джокеры (на англ. wildcards). В терминале они - звездочка (*) и
вопросительный знак (?). Как раз из-за их специального применения, их нельзя
использовать в названиях файлов.&lt;&#x2F;p&gt;
&lt;p&gt;Начнем со звездочки. Звездочка озночает что на ее месте может быть любое
количество любых символов. Например, чтобы искать файлы, чье название
начинается с sa&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents&#x2F;notes$&lt;&#x2F;span&gt;&lt;span&gt; ls sa&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;saturday.txt&lt;&#x2F;span&gt;&lt;span&gt; sample.txt sample2.txt sample.png
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Другой пример, найти файлы чье название просто содержит подстроку sa&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents&#x2F;notes$&lt;&#x2F;span&gt;&lt;span&gt; ls &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;sa&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;asado.png&lt;&#x2F;span&gt;&lt;span&gt; saturday.txt sample.txt sample2.txt sample.png
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Вопросительный знак указывает на то что, на его месте должен быть символ, любой
символ. Допустим что, мы хотим посмотреть все файлы которые называются sample,
у которых есть трех-символьное расширение&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents&#x2F;notes$&lt;&#x2F;span&gt;&lt;span&gt; ls sample.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;???
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;sample.txt&lt;&#x2F;span&gt;&lt;span&gt; sample.png
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Символы-джокеры очень полезные когда необходимо манипулировать несколько файлов
с похожими названиями. Однако, если названия файлов не похоже никак, нам
придется использовать фигурные скобки, чтобы указать список файлов. Например&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents&#x2F;notes$&lt;&#x2F;span&gt;&lt;span&gt; rm {monday.txt,december1999.txt,saturday.txt}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;obratno-k-regex&quot;&gt;Обратно к regex&lt;&#x2F;h3&gt;
&lt;p&gt;А теперь я объясню основные части и символы регулярных выражении, а затем вам
покажу как их использовать в grep&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.&lt;&#x2F;code&gt; - Точка означает один символ (любой символ). Например, &#x27;be.r&#x27; найдет нам
bear, beer, befr, и т.д.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;*&lt;&#x2F;code&gt; - Предыдущий элемент совпадает 0 или больше раз. Например &#x27;an*t&#x27; нам
найдет at, ant, annt, annnt, и т.д.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;+&lt;&#x2F;code&gt; - Предыдущий элемент совпадает один или больше раз. Например &#x27;an+t&#x27; нам
найдет ant, annt, annt, и т.д.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;?&lt;&#x2F;code&gt; - Предыдущий элемент совпадает 0 или один раз. Например &#x27;an?t&#x27; нам найдет
at и ant.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;{n}&lt;&#x2F;code&gt; - Предыдущий элемент совпадает ровно n раз.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;{min, }&lt;&#x2F;code&gt; - Предыдущий элемент совпадает хотя бы min раз&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;{min, max}&lt;&#x2F;code&gt; - Предыдущий элемент совпадает хотя бы min раз и не больше max
раз.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;|&lt;&#x2F;code&gt; - Логический оператор ИЛИ. Например, &#x27;gray|grey&#x27; нам найдет gray и grey.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;()&lt;&#x2F;code&gt; - Круглые скобки группируют несколько символов в один элемент. Например
&#x27;gr(a|e)y&#x27; нам найдет gray и grey.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;[abc]&lt;&#x2F;code&gt; - Совпадает если один из символов, который внутри скобок,
присуствует.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;[^abc]&lt;&#x2F;code&gt; - Совпадает если нет ни одного, из которых внутри скобок.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;[a-d]&lt;&#x2F;code&gt; - Диапазон символов. То есть a, b, c и&#x2F;или d.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;^&lt;&#x2F;code&gt; - Начало строки.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;$&lt;&#x2F;code&gt; - Конец строки.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;А теперь, ради примера с grep, допустим что, мы хотим найти все строки в
которых содержится &quot;cool&quot; или &quot;ok&quot; в них. В этом случае нам нужна вертикальная
черта &quot;|&quot;. Однако, если использовать grep без параметров, нам нужно будет
напечатать слеш перед ней &quot;|&quot;. Поэтому лучше использовать команду egrep,
которая является сокращением &quot;grep -E&quot;, затем чтобы включить расширенные
регулярные выражения. Например&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents&#x2F;notes$&lt;&#x2F;span&gt;&lt;span&gt; egrep &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;cool|ok&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; sample.txt
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Pepe&lt;&#x2F;span&gt;&lt;span&gt;    cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Uganda&lt;&#x2F;span&gt;&lt;span&gt; Knuckles cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Thanos&lt;&#x2F;span&gt;&lt;span&gt;  cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;JPEG&lt;&#x2F;span&gt;&lt;span&gt;    ok
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Bowsette&lt;&#x2F;span&gt;&lt;span&gt;    cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Harold&lt;&#x2F;span&gt;&lt;span&gt;  cool
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Sans&lt;&#x2F;span&gt;&lt;span&gt;    coolest
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;NPC&lt;&#x2F;span&gt;&lt;span&gt; cool
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;А теперь допустим что, нам неоюходимо найти все строки с буквой &#x27;t&#x27; в качестве
последнего символа в строке&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents&#x2F;notes$&lt;&#x2F;span&gt;&lt;span&gt; egrep &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;t$&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; sample.txt
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Sans&lt;&#x2F;span&gt;&lt;span&gt;    coolest
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Minions&lt;&#x2F;span&gt;&lt;span&gt; lamest
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Я уже продемонстрировал применение regex&#x27;ов с grep&#x27;ом (и&#x2F;или egrep). А теперь я
хочу вам показать более практический пример с sed&#x27;ом. Да, в sed&#x27;e помимо
собственного языка, можно еще и регулярные выражения использовать.&lt;&#x2F;p&gt;
&lt;p&gt;Допустим у нас есть файл который выглядит следующим образом&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents&#x2F;notes$&lt;&#x2F;span&gt;&lt;span&gt; cat shortcuts
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# Some shortcuts
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;d       ~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;Documents
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;D       ~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;Downloads
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;m       ~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;Music
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;pp      ~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;Pictures
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;vv      ~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;Videos
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;s       ~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;.scripts &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# My scripts
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;cf      ~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;.config &lt;&#x2F;span&gt;&lt;span style=&quot;color:#6d6d6d;&quot;&gt;# My configs
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Как вы могли заметить, в нашем файле много пустых строк, и много комментарри,
которые полезные для человека, но бесполезные для компьютера. Начнем с того
что, удалим комментарии, для этого мы будем использовать команду sed&#x27;а для
поиска и замены, только в нашем случае мы хотим заменить комментарии на
пустоту. Затем нам понадобится вставить регулярное выражение, которое поможет
нам найти комментарии - &#x27;#.*&#x27;. Этот шаблон переводится как - найди символ &#x27;#&#x27; и
все что после него находится. А теперь давайте мы все совместим&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents&#x2F;notes$&lt;&#x2F;span&gt;&lt;span&gt; sed &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;s&#x2F;#.*&#x2F;&#x2F;g&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; shortcuts
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;d       ~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;Documents
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;D       ~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;Downloads
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;m       ~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;Music
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;pp      ~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;Pictures
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;vv      ~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;Videos
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;s       ~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;.scripts
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;cf      ~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;.config
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Вот и мы избавились от комментариев. Тем не менее нам еще осталось избавится от
пустых строк, и если вы заметили, комментарии были удалены, но перед некоторыми
из них остались пробелы.&lt;&#x2F;p&gt;
&lt;p&gt;И так, давайте мы сначала улучшим нашу команду, для этого нам нужно найти там
где есть 0 или больше пробелов перед комментарии, но как нам обозначит пробелы
в sed&#x27;е? Все очень просто с &#x27;\s&#x27;, таким образом наша команда а теперь выглядет
вот так &#x27;s&#x2F;\s*#.*&#x2F;&#x2F;g&#x27;.&lt;&#x2F;p&gt;
&lt;p&gt;А теперь нам нужно избавится от пустых строк. Для этого нам нужно ввести еще
одну команду sed&#x27;а, но мы можем ее ввести вместе с предыдущей командой
отделяя их точкой и запетой (;). Нам осталось придумать как найти пустую
строку, все очень просто - &#x27;^$&#x27;, то есть, найти ту строку где ее начало и ее
конец находятся вместе. Нам осталось указать sed чтобы он удалил эту строку, и
вот я вам расскажу еще одну команду sed - команду для удаления (d), и так...&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents&#x2F;notes$&lt;&#x2F;span&gt;&lt;span&gt; sed &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;s&#x2F;\s*#.*&#x2F;&#x2F;g; &#x2F;^$&#x2F;d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; shortcuts
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;d       ~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;Documents
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;D       ~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;Downloads
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;m       ~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;Music
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;pp      ~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;Pictures
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;vv      ~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;Videos
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;s       ~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;.scripts
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;cf      ~&lt;&#x2F;span&gt;&lt;span&gt;&#x2F;.config
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Конечно, когда мы вводим эту команду, она не переписывает файл, она всего лишь
выводит на экран результат операции. Если вам необходимо переписать исходный
файл вы можете передать sed параметр &#x27;-i.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;konveier-i-perenapravlenie&quot;&gt;Конвейер и перенаправление&lt;&#x2F;h3&gt;
&lt;p&gt;Последнее о чем я буду писать в этом туториале не команда и не программа, но
очень полезная вещь, которая есть во всех Unix и Unix-подобных системах -
конвейер. Конвейер - это цепочка перенаправляющая вывод процесса или процессов
в стандартный ввод других процессов. В том числе есть и операторы которые
позволяют перенаправлять вывод программы в файл и наоборот.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;perenapravlenie-v-i-iz-failov&quot;&gt;Перенаправление в и из файлов&lt;&#x2F;h3&gt;
&lt;p&gt;Допустим что мы хотим повторить последний пример, но в этот раз мы хотим
записать результат в файл. Мы уже знаем как переписать оригинальный файл, но в
этот раз мы хотим записать результат в новый файл. Для этого нам понадобятся
операторы перенаправления Unix&#x27;а &#x27;&amp;gt;&#x27; и &#x27;&amp;gt;&amp;gt;&#x27;. Первый оператор переписывает файл,
если указанный файл уже существует, а второй просто добавляет поток текста в
конец файла. В этом случае безразлично какой из этих операторов использовать,
ибо мы хотим записать поток текста на новый файл&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents&#x2F;notes$&lt;&#x2F;span&gt;&lt;span&gt; sed &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;s&#x2F;\s*#.*&#x2F;&#x2F;g; &#x2F;^$&#x2F;d&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; shortcuts &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; shortcuts_clean
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Так же существует оператор перенаправления ИЗ файла в стандартный ввод
программы - &#x27;&amp;lt;&#x27;. Однако, в большинство случаях достаточно передать путь файла в
качестве аргумента.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;konveier&quot;&gt;Конвейер&lt;&#x2F;h3&gt;
&lt;p&gt;А теперь я вам покажу как перенаправить вывод одной программы в другую. Чтобы
перенаправить вывод из одной программы в другую, достаточно ввести команду
первой программы, затем ввести вертикальную черту (|), а затем команду второй
программы. Допустим мы хотим увидит первые три файлы в нашей директории, для
этого мы можем направить вывод ls в head, вот так&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents&#x2F;notes$&lt;&#x2F;span&gt;&lt;span&gt; ls &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;head&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt; -n&lt;&#x2F;span&gt;&lt;span&gt; 3
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;asado.png
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;monday.txt
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;sample.txt
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;А теперь вернемся к файлу sample.txt. Допустим что сначала мы хотим
отсортировать все строки файла, и хотим оставить только те строки с &quot;cool&quot; и
&quot;lame&quot;. Затем, мы хотим заменить неправильные старые термины, на современные,
то есть &quot;cool&quot; на &quot;dank&quot; и &quot;lame&quot; на &quot;normie&quot;. И наконец, мы хотим это
сохранить в файл. И вот как все это выгладит&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents&#x2F;notes$&lt;&#x2F;span&gt;&lt;span&gt; egrep &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;cool|lame&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; sample.txt &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;sort &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;sed &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;s&#x2F;cool&#x2F;dank&#x2F;g;s&#x2F;lame&#x2F;normie&#x2F;g&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; memes.txt
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Взглядываем в файл и...&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents&#x2F;notes$&lt;&#x2F;span&gt;&lt;span&gt; cat memes.txt
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Bowsette&lt;&#x2F;span&gt;&lt;span&gt;    dank
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Despacito&lt;&#x2F;span&gt;&lt;span&gt;   normie
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Harold&lt;&#x2F;span&gt;&lt;span&gt;  dank
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Minions&lt;&#x2F;span&gt;&lt;span&gt; normiest
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;NPC&lt;&#x2F;span&gt;&lt;span&gt; dank
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Pepe&lt;&#x2F;span&gt;&lt;span&gt;    dank
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Sans&lt;&#x2F;span&gt;&lt;span&gt;    dankest
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Thanos&lt;&#x2F;span&gt;&lt;span&gt;  dank
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Tide&lt;&#x2F;span&gt;&lt;span&gt; Pods   normie
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Uganda&lt;&#x2F;span&gt;&lt;span&gt; Knuckles dank
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;И вот и все&lt;&#x2F;p&gt;
&lt;h2 id=&quot;post-scriptum&quot;&gt;Post scriptum&lt;&#x2F;h2&gt;
&lt;p&gt;Перед тем как закончить с этим туториалом, я хочу вам показать еще несколько
программ, которые могут вам пригодится&lt;&#x2F;p&gt;
&lt;h3 id=&quot;less&quot;&gt;less&lt;&#x2F;h3&gt;
&lt;p&gt;Данная команда вам пригодится когда, например, некоторая программа выводит
слишком много текста. В таком случае, достаточно перенаправить вывод текста
первой программы к less используя оператор конвейера (|), также как я вам
только что показал. Используя эту команду вы можете листать текст используя
стрелочки или vim-клавиши (hjkl). Так же вы можете искать термины введя слеш
(&#x2F;).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;tar&quot;&gt;tar&lt;&#x2F;h3&gt;
&lt;p&gt;Это de facto официальная программа Линукса для архивирования и сжатия файлов в
формате .tar. Чаще всего используется формат сжатия gunzip (.gz), но есть и
другие форматы сжатия.&lt;&#x2F;p&gt;
&lt;p&gt;Есть два основных способов использовать эту программу. Первый чтобы
разархивировать&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents&#x2F;notes$&lt;&#x2F;span&gt;&lt;span&gt; tar&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt; -xzvf&lt;&#x2F;span&gt;&lt;span&gt; oldnotes.tar.gz
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Второй чтобы архивировать и сжать&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents&#x2F;notes$&lt;&#x2F;span&gt;&lt;span&gt; tar&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt; -czvf&lt;&#x2F;span&gt;&lt;span&gt; allnotes.tar.gz &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Как обычно, вы можете узнать больше об этой программе используя утилиту man
(&#x27;man tar&#x27;).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ssh-and-scp&quot;&gt;ssh and scp&lt;&#x2F;h3&gt;
&lt;p&gt;Скорее всего вы уже слышали или даже работали с ssh, даже если вы не работали
до этого с Ликусом или Unix&#x2F;Unix-подобных системах. Это программа позволяет
подключится через терминал к другим компьютером через сеть (например,
интернет), в том числе и к серверам.&lt;&#x2F;p&gt;
&lt;p&gt;Допустим вы хотите подключится к серверу с ip 180.80.8.20 и пользователь tux&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~$&lt;&#x2F;span&gt;&lt;span&gt; ssh tux@180.80.8.20
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Здесь мы предполагаем что мы подключаемся через стандартный порт ssh (22), иначе
придется его передать используя параметр -p а затем номер порта.&lt;&#x2F;p&gt;
&lt;p&gt;А теперь поговорим о scp. Это программа позволяет передать файлы из одного
компьютера в другого используя протокол ssh&#x27;а. Допустим что мы хотим отправить
файл с локального компьютер в тот же самый сервер, что и в прошлом примере&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~$&lt;&#x2F;span&gt;&lt;span&gt; scp somefile tux@180.80.8.20:&#x2F;home&#x2F;tux&#x2F;directory&#x2F;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Если бы мы хотели наоборот, получить, а не отправить, то мы просто поменяли
порядок аргументов, примерно вот так&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~$&lt;&#x2F;span&gt;&lt;span&gt; scp tux@180.80.8.20:&#x2F;home&#x2F;tux&#x2F;directory&#x2F;somefile directory&#x2F;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Так же как и с ssh порт по умолчанию 22, то есть если использовать другой порт,
нужно его указать, только в отличие от ssh, параметр -P вместо -p и нужно его
ввести сразу после &quot;scp.&lt;&#x2F;p&gt;
&lt;p&gt;Вот и на этом все. Надеюсь вам этот туториал помог. С наступившим 2019.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="ru">
		<title>Введение в Linux и Bash, часть II</title>
		<published>2018-12-31T09:20:00+00:00</published>
		<updated>2018-12-31T09:20:00+00:00</updated>
		<link href="https://www.yaroslavps.com/ru/weblog/intro-to-linux-and-bash-pt2/" type="text/html"/>
		<id>https://www.yaroslavps.com/ru/weblog/intro-to-linux-and-bash-pt2/</id>
		<content type="html">&lt;p&gt;И так, год подходит к концу, и я так еще не написал вторую часть туториала про
Bash и Linux. Надо бы написать хотя бы один пост в этом, последнем месяце года.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;В этой части, я расскажу чуть больше про инструменты и команды в Linux и
Unix-подобных системах, которые вам пригодятся при работе в терминале. Все или
большинство из этих программ являются частью основного набора программ и утилит
большинства бистрибутивов Linux и Unix&#x2F;Unix-подобных систем.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rabota-s-failami&quot;&gt;Работа с файлами&lt;&#x2F;h2&gt;
&lt;p&gt;В предыдущей части я стал объяснять подробно как работать с файлами. Однако,
возможность манипулировать файлы является очень полезным и важным функционалом
компьютерных систем.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sozdat-fail&quot;&gt;Создать файл&lt;&#x2F;h3&gt;
&lt;p&gt;Обычно, если хотим создать файл, мы используем определенную программу специально
предназначена для создания и редактирования определенного вида файлов. Например,
vim для редактирования и записи текстовых файлов. Однако есть утилита которая
позволяет создавать пустые файлы - touch.&lt;&#x2F;p&gt;
&lt;p&gt;Вы можете создать пустой файл введя touch и последовательно название или путь
файла который вы хотите создать, например&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;user@host:~$ touch example.txt
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;А теперь у нас пустой файл в &quot;&#x2F;home&#x2F;user&#x2F;example.txt&quot;. Но, я немного соврал,
когда сказал что данная команда для того чтобы создавать пустые файлы. На самом
деле, она сначала проверяет наличия файла, затем, если он существует, она
редактировает его даты и время доступа и редактирования, иначе он создает пустой
файл, как в данном случае. Очень редко когда данная команда на самом деле
понадобится, поскольку в большинство случаях сами программы для редактирования
файлов могут также их создавать. Тем не менее бывают случаи когда она может
пригодится.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sozdat-direktorii&quot;&gt;Создать директорий&lt;&#x2F;h3&gt;
&lt;p&gt;Сейчас у нас будет что-то поинтереснее, как создать директорий. Создавать
директории довольно просто, команда - mkdir. Например&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;user@host:~$ mkdir foo
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Мы только что создали директорий &quot;foo&quot; в &quot;&#x2F;home&#x2F;user&#x2F;&quot;. Не забудьте что мы
всегда передаем путь файла, будь они относительными или абсолютными (если вы не
помните что это значит, прочитайте первую часть). В данном случае, мы используем
относительный путь содержающий только название директория.&lt;&#x2F;p&gt;
&lt;p&gt;Если бы мы использовали абсолютный путь, он выглядел бы таким образом -
&quot;&#x2F;home&#x2F;user&#x2F;foo&quot;. Нам бы пришлось убедиться в том что директории &quot;home&quot; и &quot;user&quot;
существуют. Однако, существует очень подезный флажок, которые мы можем передать
команде, чтобы она создавала родительские директории при необходимости - -p&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;user@host:~$ mkdir -p &#x2F;tmp&#x2F;foo&#x2F;bar
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Если директории &quot;tmp&quot; и&#x2F;или &quot;foo&quot; не существуют, он их автоматический сделает,
вместе с &quot;bar&quot; внутри их.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;peremeshchenie-i-pereimenovaniia&quot;&gt;Перемещение и переименования&lt;&#x2F;h3&gt;
&lt;p&gt;Это довольно просто, и обе действия можно выполнить одной командой - mv, что
происходит с английского move.&lt;&#x2F;p&gt;
&lt;p&gt;Если вам необходимо переименовать файл или директорий, переместите его в тот же
самый директорий, с новым&#x2F;другим названием, например&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;user@host:~$ mv untitled titled
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;А вот если потребуется переместить в другую локацию, просто укажите путь новой
локации в качестве второго аргумента. Не забудьте что оба аргумента являются
путями, либо относительными либо абсолютными&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;user@host:~$ mv titled Documents&#x2F;titled
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;kopirovat&quot;&gt;Копировать&lt;&#x2F;h3&gt;
&lt;p&gt;Копирование похоже на перемещения, отличие просто в названии команды - cp.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;user@host:~$ cp titled Documents&#x2F;titled2
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Однако, копирование директории отличается немного от копирования файлов. Чтобы
копировать директории, нужно использовать флаг -r. Он указывает что операция
должна быть рекурсивной, то есть, нужно скопировать каждый файл и поддиректорию
внутри директории (и файлы внутри этих поддиректории и в поддиректории
поддиректории и... ну то есть, рекурсия) в указанный путь. То есть что-то похоже
на это&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;user@host:~$ cp -r dir dir-copy
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;udalit&quot;&gt;Удалить&lt;&#x2F;h3&gt;
&lt;p&gt;Удалять файлы довольно просто, достаточно ввести rm а затем путь файла&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;user@host:~$ rm title
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Однако, чтобы удалять директории не так просто. Один способ - использовать
команду rmdir, но она только работает на пустых директориях.&lt;&#x2F;p&gt;
&lt;p&gt;Второй вариант, использовать ту же команду что и для файлов, но используя флаг
-r чтобы удалить файлы рекурсивно, также как и с командой cp. Будьте
внимательные при использовании этой команды, ибо она удаляет все файлы внутри
директории, вместе с директорией.&lt;&#x2F;p&gt;
&lt;p&gt;Итак, чтобы удалить директорию и все содержимое, нам понадобиться ввести
следующую команду&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;user@host:~$ rm -r dir
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;У этой команды есть еще один флаг, чтобы принудительно удалить файлы без
вопросов - флаг -f. Этот аргумент может пригодится, например, когда нужно
удалить сразу несколько файлов, и среди них есть специльные файлы, как скрытые
файлы (те, у которых точка перед названием) и вам не хочется подтвердить
действие перед каждым файлом.&lt;&#x2F;p&gt;
&lt;p&gt;Следует быть ОЧЕНЬ осторожным перед тем как использовать этот флаг, особенно
если вы собираетесь ввести команду под root пользователем. Поверьте, вам будет
очень неприятно если вы введете например &quot;sudo rm -rf &#x2F;&quot; и у вас полетят
полностью система и файлы. Если вы не садист, конечно.&lt;&#x2F;p&gt;
&lt;p&gt;Пример ситуации когда данное сочетание флагов с командой rm может пригодится
это, когда вам необходимо удалить репозиторий git, поскольку в них содержатся
множество специальных скрытых файлов, которые git использует затем чтобы следить
за коммитами и прочее. Пример использования команды&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;user@host:~$ rm -rf somerepo
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;kontrol-dostupa&quot;&gt;Контроль доступа&lt;&#x2F;h3&gt;
&lt;p&gt;В Unix и Unix-подобных системах существует довольно прочная система для контроля
прав доступа. Она позволяет определять полномочия определеных пользователей или
групп пользователей над определенными файлам, создавая безопасную среду для
компьютеров с множество пользователями.&lt;&#x2F;p&gt;
&lt;p&gt;У каждого файла три вида прав доступа, которые определяют что можно с ними
делать. Каждое право обозначается одной буквой английского алфавита&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;r - чтение: пользователь имеет право читать данный файл.&lt;&#x2F;li&gt;
&lt;li&gt;w - запись: пользователь может писать&#x2F;редактровать данный файл (включая
возможность его удалять).&lt;&#x2F;li&gt;
&lt;li&gt;x - выполнение: файл может быть выполнен пользователем, если он является
программой или скриптом.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Так же существует три разных наборов человек к которым могут относится права
доступа&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;u - пользователь&#x2F;владелец: пользователь, которому принадлежит файл. Обычно это
тот же самый пользователь, который создал файл, но владелца можно поменять.&lt;&#x2F;li&gt;
&lt;li&gt;g - группа: каждый принадлежит определенной группе пользователей. Это может
быть группа одного пользователя (у каждого пользователя есть своя
однопользовательская группа), или общая группа.&lt;&#x2F;li&gt;
&lt;li&gt;o - другие: Все остальные кто не являются владелцем или ну состоит в группе.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Если вы читали первую часть туториала, вы наверное помните что я рассказывал про
команду &quot;ls -l&quot; чтобы посмотреть дополнительную информацию о файлах, включая
права доступа&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;user@host:~&#x2F;Documents$ ls -l
&lt;&#x2F;span&gt;&lt;span&gt;drwxr-xr-x  2 user user  4.0K Jul  18 04:20 Books
&lt;&#x2F;span&gt;&lt;span&gt;-rwxr-xr--  1 user group 350  Jul  18 04:20 run.py
&lt;&#x2F;span&gt;&lt;span&gt;-rw-r--r--  1 user user  1.2M Jul  18 04:20 picture.png
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Первые десять символов в каждой строке - права доступа для файла в данной
строке.&lt;&#x2F;p&gt;
&lt;p&gt;Первый символ в данном сочетаний символов определяет является ли файл обычным
файлом или другим видом. Если первым символом является буква d, то это
директория, если там просто черточка (тире&#x2F;дефис), то это обычный файл. Там
также может быть другая буква, как например l для ссылок, но это уже не входит в
рамках данного поста.&lt;&#x2F;p&gt;
&lt;p&gt;Следующие 9 символов разделяются в свое время в сочетание из трех символов,
каждое для определенного набора пользователей. Первые три символа после символа
вида файла это права для владелца, следующие три для группы, и последние три для
отсальных.&lt;&#x2F;p&gt;
&lt;p&gt;В каждом из этих сочетании из трех букв, права доступа в порядке чтение, запись,
выполнение. Наличие буквы означает что у данного набора пользвателей данно это
право, отсуствие значит нет такого права для данного набора пользоваетелей.&lt;&#x2F;p&gt;
&lt;p&gt;Возьмем в качестве примера файл &quot;run.py&quot;. Исходя из информации на экране мы
можем определить что это обычный файл (нет буквы d), владелец (user) имеет право
читать, записывать и выполнять его; группа пользователей (в группе group) имеет
право на чтение и выполнения, но не записи; и остальные только могут его читать.&lt;&#x2F;p&gt;
&lt;p&gt;Наверное вы заметили что почти всегда у директории присуствует право на
выполнение (буква x), однако это означает что-то немножко иное в отличие от
файлов. Буква &quot;x&quot; у директориях означает что есть право на вход в директорию и
есть доступ к файлам внутри директории. Право на чтения директории всего лишь
означает что можно смотреть на то какие файлы содержатся в директории, и право
на запись означает что есть то чтобы записывать файла внутри директории.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;izmenit-prava&quot;&gt;Изменить права&lt;&#x2F;h3&gt;
&lt;p&gt;Существует очень полезная команда которая позволяет менять права на доступ
файлов - chmod.&lt;&#x2F;p&gt;
&lt;p&gt;Чтобы изменить права на файле, необходимо ввести chmod и затем права и путь
файла. Есть два способа чтобы менять права, легкий но более долгий способ
используя буквы, и более быстрый но не совсем легкий используя восмеричный код.
Начнем с более легкого.&lt;&#x2F;p&gt;
&lt;p&gt;Более легкий способ состоит из трех частей&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Кто - пользователь&#x2F;владелец, группа, остальные или все (u, g, o, или a)&lt;&#x2F;li&gt;
&lt;li&gt;Дать или отменить право, &quot;+&quot; чтобы дать, &quot;-&quot; чтобы отменить&lt;&#x2F;li&gt;
&lt;li&gt;Право которое мы меняем - чтение, запись или испольнение (r, w, или x)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Допустим у нас есть скрипт для которого мы хотим дать право на запуск для всех
пользователей.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;user@host:~&#x2F;Documents&#x2F;stuff$ ls -l
&lt;&#x2F;span&gt;&lt;span&gt;-rw-r--r-- 1 user group  420  April 20 6:59  script.sh
&lt;&#x2F;span&gt;&lt;span&gt;user@host:~&#x2F;Documents&#x2F;stuff$ chmod a+x script.sh
&lt;&#x2F;span&gt;&lt;span&gt;-rwxr-xr-x 1 user group  420  April 20 6:59  script.sh
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Как можно заметить, после запуска команды все пользователи компьютера имеют
право на выполнения скрипта. А теперь допустим что мы передумали и хотим
отменить право выполнения для всех пользователей кроме владелца, мы могли бы
ввести o-r и затем g-r, но мы можем также совмещать следующим образом&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;user@host:~&#x2F;Documents&#x2F;stuff$ chmod go-r script.sh
&lt;&#x2F;span&gt;&lt;span&gt;-rwx--x--x 1 user group  420  April 20 6:59  script.sh
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;А теперь пора выучить быстрый способ. Его сложнее запомнить, поскольку еще
нужны базовые понимания двоичной системы счисления. Грубо говоря, оно работает
подовая три цифры в восьмеричной системе счисления (то есть 0-7) каждая из
которых обозначает бит права для каждого набора пользователей
(пользователь&#x2F;владелец, группа, другие).&lt;&#x2F;p&gt;
&lt;p&gt;Получается у нас три возможные права (чтение, запись и выполнение) и 2^3 нам
дает 8 возможных сочетании прав, и вот почему у нас восьмеричная система.
Следующая таблица поможет определить отношение нужной цифры для определенного
сочетания прав&lt;&#x2F;p&gt;
&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Восьмеричная система&lt;&#x2F;td&gt;
      &lt;td&gt;Двоичная система&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0&lt;&#x2F;td&gt;
      &lt;td&gt;001&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1&lt;&#x2F;td&gt;
      &lt;td&gt;001&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2&lt;&#x2F;td&gt;
      &lt;td&gt;010&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3&lt;&#x2F;td&gt;
      &lt;td&gt;011&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4&lt;&#x2F;td&gt;
      &lt;td&gt;100&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr&gt;
      &lt;td&gt;5&lt;&#x2F;td&gt;
      &lt;td&gt;101&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr&gt;
      &lt;td&gt;6&lt;&#x2F;td&gt;
      &lt;td&gt;110&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
    &lt;tr&gt;
      &lt;td&gt;7&lt;&#x2F;td&gt;
      &lt;td&gt;111&lt;&#x2F;td&gt;
    &lt;&#x2F;tr&gt;
  &lt;&#x2F;tbody&gt;
&lt;&#x2F;table&gt;
&lt;p&gt;Зная как переводятся цифры в двоичную становится намного проще знать к какой
комбинации прав она относится, ибо каждая цифра в сочетании трех бинарных цифр
относится к одному виду прав в выше указанному порядке (r, w, x). Если у нас
единица (1) это означает что есть данное право, а ноль (0) означает его
отсуствие. И так, например, 6 означает что у нас есть право на чтение и запись,
поскольку 6 = 110 = rw-.&lt;&#x2F;p&gt;
&lt;p&gt;Допустим что мы хотим поменять права доступа к файлу таким образом чтобы
владелец мог читать, записывать и выполнять; группа имела право на чтения и
выполнения; и остальные могли только выполнять. Для этого мы ввели что-то
подобное&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;user@host:~&#x2F;Documents&#x2F;stuff$ chmod 751 script.sh
&lt;&#x2F;span&gt;&lt;span&gt;user@host:~&#x2F;Documents&#x2F;stuff$ ls -l
&lt;&#x2F;span&gt;&lt;span&gt;-rwxr-x--x 1 user group  420  April 20 6:59  script.sh
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Если вы меняете права доступа директория, новые права будут изменены только для
самой директории, не включая файлы и поддиректории внутри. Чтобы также изменить
права для всех файлов внутри директории, необходимо использовать флаг рекурсии -
-R (обратите внимания на то что, в chmod флаг рекурсии обозначается большой
буквой R в отличие от cp или rm).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;pomeniat-vladeltsa&quot;&gt;Поменять владелца&lt;&#x2F;h3&gt;
&lt;p&gt;Менять владельца файла проще чем менять права. Чтобы поменять владельца необходимо
использовать команду chown. Например, допустим мы хотим поменять пользователя,
которого владеет файлом&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;user@host:~&#x2F;.logs$ ls -l
&lt;&#x2F;span&gt;&lt;span&gt;-rw-r--r-- 1 root root  69  April 20 6:59  some.log
&lt;&#x2F;span&gt;&lt;span&gt;user@host:~&#x2F;.logs$ sudo chown user some.log
&lt;&#x2F;span&gt;&lt;span&gt;user@host:~&#x2F;.logs$ ls -l
&lt;&#x2F;span&gt;&lt;span&gt;-rw-r--r-- 1 user root  69  April 20 6:59  some.log
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Поскольку файл не принадлежал тому же самому владельцу с которого мы выполняем
команды, нам необходимо выполнить команду через sudo чтобы повысить наши
права. Чтобы иметь возможность повышать права вашего пользователя, необходимо
чтобы ваш пользователь состоял в файле &quot;sudoers&quot; и&#x2F;или в группе &quot;wheel&quot; зависимо
от дистрибутива&#x2F;ОС. В большинство случаев (если вы пользуетесь
&quot;домашним&#x2F;дестктопным&quot; дистро) у вас уже будут права на sudo, в любом случае
быстрый поиск в интернете поможет вам найти информацию о том как поменять
настройки прав в вашем дистрибутиве&#x2F;ОС.&lt;&#x2F;p&gt;
&lt;p&gt;А теперь допустим что вы хотели поменять и пользователя и группу которому
принадлежит файл, в таком случае мы бы ввели следующее&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;user@host:~&#x2F;.logs$ ls -l
&lt;&#x2F;span&gt;&lt;span&gt;-rw-r--r-- 1 root root  69  April 20 6:59  some.log
&lt;&#x2F;span&gt;&lt;span&gt;user@host:~&#x2F;.logs$ sudo chown user:group some.log
&lt;&#x2F;span&gt;&lt;span&gt;user@host:~&#x2F;.logs$ ls -l
&lt;&#x2F;span&gt;&lt;span&gt;-rw-r--r-- 1 user group  69  April 20 6:59  some.log
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Также как и с chmod, если вам необходимо поменять владелца рекурсивной в
директории, вам нужно использовать флаг -R.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;epilog-sovety&quot;&gt;Эпилог&#x2F;Советы&lt;&#x2F;h2&gt;
&lt;p&gt;В предыдущей части я забыл написать о том как ввести пути с пробедами. Нельзя
просто так печатать пути с пробелами, ибо пробел означает переход к следующему
аргументу.&lt;&#x2F;p&gt;
&lt;p&gt;Есть два способа печатать пути, названия файлов и другие аргументы с пробелами.
Первый способ - кавычки. Например&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;user@host:~&#x2F;Documents$ rm &amp;quot;Shopping List.txt&amp;quot;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Второй - экранирования символа с помощью символа &quot;&quot; перед пробелом. Например&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;user@host:~&#x2F;Documents$ rm Shopping\ List.txt
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Еще одно о чем я хотел рассказать - мануалы (man). Почти (если не все)
дистрибутивы Линукса имеют мануалы.&lt;&#x2F;p&gt;
&lt;p&gt;Не всегда необходимо обращаться к интернету если вы забыли как пользоваться
определнной командой. Если вы однажды оказались без интернета и вы хотите
узнать побольше об одной команде, man отличный оффлайн ресурс.&lt;&#x2F;p&gt;
&lt;p&gt;Не говоря уже о том что проще и быстрее делать все сразу с терминала не
переключаясь к браузеру чтобы искать нужную информацию.&lt;&#x2F;p&gt;
&lt;p&gt;Чтобы прочитать мануал определенной команды, введите man и затем название
команды. Например &quot;man chmod&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Вы можете пользоваться клавишами vim (hjkl) для перемещения. Введите &#x2F;&amp;lt;термин&amp;gt;
чтобы искать этот термин, а затем нажмите на n чтобы найти следующее совпадение.&lt;&#x2F;p&gt;
&lt;p&gt;Это все на данный момент. С новым 2019-м годом!&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="ru">
		<title>Введение в Linux и Bash</title>
		<published>2018-11-05T23:53:00+00:00</published>
		<updated>2018-11-05T23:53:00+00:00</updated>
		<link href="https://www.yaroslavps.com/ru/weblog/intro-to-linux-and-bash/" type="text/html"/>
		<id>https://www.yaroslavps.com/ru/weblog/intro-to-linux-and-bash/</id>
		<content type="html">&lt;p&gt;Недавно я решил познакомить друга с великолепным миром Линукса, и как например,
человек переезжает в совсем новый город, его нужно познакомить с городом, как
передвигаться по городу, где все нужные заведения и т.д. В принципе и также
когда человек переходит на новую ОС, ему нужно привыкнуть к новой среде,
создавать новые привычки, особенно когда это касается мира линукса. Собственно
этот туториал я пишу для моего друга и любого другого человека который
заинтересован Линуксом, но хотят научится использовать его более эффективно,
т.е. высше уровня рядового пользователя.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;Скорее всего вам уже известно, но Линукс на самом деле сам по себе не ОС, а ядро
которое используется совместно с набором комонентов и программ GNU (вставьте
здесь шутки и мемы про GNU&#x2F;Linux (или GNU+Linux)), и есть несколько вариантов,
или точнее - дистрибутивов, так называемого GNU&#x2F;Linux.&lt;&#x2F;p&gt;
&lt;p&gt;Если только собираетесь установить Линукс и еще не решились какой дистрибутив
выбрать, здесь маленткий, который может помочь вам выбрать:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Manjaro - Лично я пользуюсь этим дистрибутивом. У него есть несколько вариации
с разными рабочими средами, например KDE или GNOME. Это дистрибутив &quot;rolling
release&quot;, что означает то, что у него будет более новые пакеты чем у
классических дистро, в замен меньшей стабильности системы. Его довольно легко
установить и использовать (если выбрать что-то вроде KDE или GNOME).&lt;&#x2F;li&gt;
&lt;li&gt;Ubuntu - Самый известный дистрибутив. Является один из самых легких в
использовании. Более стабильный чем Manjaro (хоть и не всегда). Если вы просто
хотите установить ОС в которой уже все настроена и не хотите выбирать рабочую
среду (или вы не знаете что такое рабочая среда), скорее всего этот дистро для
вас.&lt;&#x2F;li&gt;
&lt;li&gt;Debian - Один из самых стабильных дистро. Его не так легко установить как
Ubuntu или Manjaro, но все же не сложно. Собственно Ubuntu разработан на
основе Debian&#x27;а. Его скорее всего придется настроить под себя (лично меня не
нравятся дефолтные настройки GNOME&#x27;а), но если вы хотите стабильный,
провереный дистрибутив, то он для вас. Один минус для некоторых - поумолчанию
не подключены репозитории с &quot;несвободным&quot; софтом, придется подключить самому
если нуждаетесь в проприетарном софте.&lt;&#x2F;li&gt;
&lt;li&gt;Fedora - По стабильностью и сложности установки&#x2F;пользования похож на Ubuntu
(то есть довольный просто). У него такой же минус как и у Debian - отсуствия
&quot;несвобоного&quot; софта в главном репозиторий.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Если при чтения списка вам словосочетание &quot;рабочая среда&quot; оказалась незнакомой,
то грубо говоря, это набор программ которые предоставляют вам графический
интерфейс для взаимодейстмия с системой. Как выглядит ОС не так сильно зависит
от дистро, в основном оно зависит от рабочей среды.&lt;&#x2F;p&gt;
&lt;p&gt;Установили Линукс? Отлично, можем начать.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;failovaia-struktura&quot;&gt;Файловая структура&lt;&#x2F;h2&gt;
&lt;p&gt;Если вы привыкли работать с Windows, то есть некоторые моменты, то первое что вы
заметите это то, что файловая структура выглядит немного иначе. Windows, из-за
наследства MS-DOS, использует буквы для обозначения дисков, томов и файловых
систем. В Линукс, как и в других Unix-подобных системах (например macOS, BSD)
это немного иначе.&lt;&#x2F;p&gt;
&lt;p&gt;В Линуксе всё являтся файлом, в том числе и устройства подключенных к вашему
компьютеру. От клавиатуры до накопителя. Папки (или директории) тоже файлы.&lt;&#x2F;p&gt;
&lt;p&gt;Разные диски или накопители монтируются в определеной папке, и в этой папке
будут размещатся файлы данного накопителя. Монтировать и демонтировать диски,
флэшки и тд можно самому, но нечего боятся, если вы установили какой-нибудь из
самых популярных дистро, то система сделать это для вас автоматический, и
создаст ярлык в браузере файлов или на рабочем столе.&lt;&#x2F;p&gt;
&lt;p&gt;В Линуксе есть корневая папка&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;&#x2F;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Внутри нее все файлы и поддиректории вашей системы.&lt;&#x2F;p&gt;
&lt;p&gt;В Линуксе, у каждого пользователя есть своя &quot;домашняя папка&quot;. В вашей домашней
папки будут размещаться ваши файлы, документы. Домашняя папка пользователя
&quot;user&quot;, например, будет распологатся здесь&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;&#x2F;home&#x2F;user
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Но вы можете перейти к этой папке используя символ ~. Например, если в консоле
вы введете&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; cd &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;~
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;То это комманда вас переместит в вашую домашнюю папку (например, &#x2F;home&#x2F;user).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;terminal-bash&quot;&gt;Терминал - Bash&lt;&#x2F;h2&gt;
&lt;p&gt;Самая полезная программа в линуксе, это скорее всего терминал. Да, рядовой
пользователь может и без нее жить, но это довольно гибкий и полезный инструмент.
Очень часто задачу на самом деле проще и быстрее реализовать в текстовой среде
чем в графической. Очевидно быстрее научится пользоватся графической средой, но
после того как вы научитесь пользоватся текстовой средой (терминал), вы сможете
работать более эффективно.&lt;&#x2F;p&gt;
&lt;p&gt;Пример того как может выглядить ваша коммандная строка&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~$
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Первая часть - пользователь через которого вы зашли в систему. Вторая после
символа &quot;@&quot; - hostname, или название вашего устройства в сети.&lt;&#x2F;p&gt;
&lt;p&gt;Вслед за &quot;:&quot; - директория в котором вы находитесь в данный момент. В этом случае
символ &quot;~&quot; указывает что мы находемся в домашнем каталоге нашего пользователя.
Чтобы посмотреть абсолютный путь, мы можем ввести комманду &quot;pwd&quot;.&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~$&lt;&#x2F;span&gt;&lt;span&gt; pwd
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;&#x2F;home&#x2F;user
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~$
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Символ &quot;$&quot; указывает на то что мы сейчас работаем через обычного пользователя. В
Линуксе и во всех *nix системах, есть такая вещь как &quot;супер пользователь&quot;, или
root пользователь. У обычных пользователей нет полный доступ к важным файлам
системы, или к файлам других пользователей. У root, доступ есть на всю систему.
Когда вы авторизованные через root, символ &quot;$&quot; меняется на &quot;#&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Но о правах и о root пользователе, попозже поговорим.&lt;&#x2F;p&gt;
&lt;p&gt;Чтобы открыть терминал, достаточно зайти в меню программ&#x2F;приложений и нажать на
его иконку или названия. Не могу объяснить подробнее где располагается ярлык
терминала, поскольку оно будет отличатся в зависимо от дистрибутива.&lt;&#x2F;p&gt;
&lt;p&gt;Для того, чтобы начать работать в терминале, необходимо познакомится с основными
коммандами, начиная с коммандами для навигации.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;navigatsiia-v-terminale&quot;&gt;Навигация в терминале&lt;&#x2F;h3&gt;
&lt;p&gt;Еще один момент, который стоит учесть при работе с Линуксом и *nix системами,
это то, что реестр учитывается. Если в Windows&#x27;е файл README.TXT и readme.txt
один и то же самый, то в Линуксе и Unix-подобных системах это разные файлы.&lt;&#x2F;p&gt;
&lt;p&gt;Для перемещения по директориям, мы пришем в коммандой строке &quot;cd &amp;lt;путь&amp;gt;&quot;. Путь
может быть относительным или абсолютным.&lt;&#x2F;p&gt;
&lt;p&gt;Относительный путь, это, например, название папки которая находится внутри той
директории где мы находимся. Или иными словами, путь относительно того где мы
находимся.&lt;&#x2F;p&gt;
&lt;p&gt;Абсолютный путь, это путь относительно корневой директории (или root на английском).&lt;&#x2F;p&gt;
&lt;p&gt;Например, если мы хотим переместится в каталог &quot;Documents&quot; внутри &#x2F;home&#x2F;user&#x2F;, и
мы уже в &#x2F;home&#x2F;user&#x2F;, то мы можем просто ввести&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~$&lt;&#x2F;span&gt;&lt;span&gt; cd Documents
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents$
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;А если бы нам надо было перейти на эту же папку с совершено другого каталога, то
нам бы пришлось ввести&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:&#x2F;var$&lt;&#x2F;span&gt;&lt;span&gt; cd &#x2F;home&#x2F;user&#x2F;Documents
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents$
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Чтобы перейти на корневого каталога данной директории мы используем две точки
&quot;..&quot;. Например&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents$&lt;&#x2F;span&gt;&lt;span&gt; cd ..
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~$
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&quot;..&quot; означает корневой каталог данной директории. А также есть &quot;.&quot; который
означает данная директория.&lt;&#x2F;p&gt;
&lt;p&gt;Есть еще одна комманда, которая поможет вам при навигации в коммандой строке -
ls. Это комманда позволяет увидет содержимое данной директорий&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents$&lt;&#x2F;span&gt;&lt;span&gt; ls
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Books&lt;&#x2F;span&gt;&lt;span&gt;       todo.txt    picture.png
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Она также принимает параметры и аргументы, например, чтобы увидеть скрытые
файлы, добавьте параметр &quot;-a&quot;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents$&lt;&#x2F;span&gt;&lt;span&gt; ls&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt; -a
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Books&lt;&#x2F;span&gt;&lt;span&gt;    .secret    todo.txt    picture.png
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Скрытые файлы и каталоги в Линуксе начинаются с точкой (например, скрытый
каталог &quot;.secret&quot;).&lt;&#x2F;p&gt;
&lt;p&gt;Также есть параметр &quot;-l&quot; который показывает содержимое в списке с
допольнительной информация, такой как разрещения (больше о них в следующей
части), количество файлов в каталоге, владелец файла (пользователь и группа),
размер, дата создания&#x2F;модификации, и название самого файла. Например&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents$&lt;&#x2F;span&gt;&lt;span&gt; ls&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt; -l
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;drwxr-xr-x&lt;&#x2F;span&gt;&lt;span&gt;  2 user user 4.0K Jul  18 04:20 Books
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;-rw-r--r--&lt;&#x2F;span&gt;&lt;span&gt;  1 user user 350  Jul  18 04:20 todo.txt
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;-rw-r--r--&lt;&#x2F;span&gt;&lt;span&gt;  1 user user 1.2M Jul  18 04:20 picture.png
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Также параметры можно совмещать&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents$&lt;&#x2F;span&gt;&lt;span&gt; ls&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt; -al
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;drwxr-xr-x&lt;&#x2F;span&gt;&lt;span&gt;  2 user user 4.0K Jul  18 04:20 Books
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;drwxr-xr-x&lt;&#x2F;span&gt;&lt;span&gt;  5 user user 4.0K Jul  18 04:20 .secret
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;-rw-r--r--&lt;&#x2F;span&gt;&lt;span&gt;  1 user user 350  Jul  18 04:20 todo.txt
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;-rw-r--r--&lt;&#x2F;span&gt;&lt;span&gt;  1 user user 1.2M Jul  18 04:20 picture.png
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Можно смотреть содержимое другого каталога не переходя на него, передавая его
название&#x2F;путь в качестве последнего аргумента, например&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~&#x2F;Documents$&lt;&#x2F;span&gt;&lt;span&gt; ls&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt; -l&lt;&#x2F;span&gt;&lt;span&gt; Books
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;drwxr-xr-x&lt;&#x2F;span&gt;&lt;span&gt; 12 user user 4.0K Jul  18 04:20 Lessons
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;-rw-r--r--&lt;&#x2F;span&gt;&lt;span&gt;  1 user user 2.3M Jul  18 04:20 Crime and Punishment.pdf
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;shortkaty&quot;&gt;Шорткаты&lt;&#x2F;h3&gt;
&lt;p&gt;Перед тем как завершить первую часть этого туториала, хотелось бы написать про
несколько &quot;шорткатов&quot; при работе в bash&#x27;е.&lt;&#x2F;p&gt;
&lt;p&gt;Первое это перемещение по истории коммандов. Каждый раз когда вы вводите
комманду в терминале, она сохраняется в истории. Вы можете перемещаться по
истории комманд терминала используя стрелки вверх и вниз. Чтобы последнюю
комманду повторить, вы можете один раз нажать на стрелку вверх, а затем можно ее
дописать или переписать и нажать клавишу ввода. Чтобы повторить более старые
комманды, вы можете несколько раз нажать на стрелку вверх до нужной комманды, а
стрелку вниз если пропустили нужную комманду.&lt;&#x2F;p&gt;
&lt;p&gt;Еще есть очень полезная штука в баше - автозполнение. При нажатии на клавишу
&quot;Таб&quot; баш попытается заполнить для вас комманду.&lt;&#x2F;p&gt;
&lt;p&gt;Например, допустим вы находитесь в корневом каталоге, и вы хотите перейти в путь
&quot;&#x2F;home&#x2F;user&#x2F;&quot;. Вы можете начать печатать &quot;cd h&quot; нажать на &quot;Таб&quot; и у вас
получится &quot;cd home&#x2F;&quot; затем дописать букву &quot;u&quot; и снова нажать на клавишу &quot;Таб&quot; и
в итоге у вас получится &quot;cd home&#x2F;user&#x2F;&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;Если будут несколько возможных вариантов автодополнения, то при одном нажатии
ничего не получится. Это значит, что либо нет такого каталога, либо есть
несколько возможных вариантов для автозаполнение. Во втором случае можно два
раза подряд нажать на клавишу &quot;Таб&quot; и баш вам покажет все возможные варианты,
например&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~$&lt;&#x2F;span&gt;&lt;span&gt; cd Do
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;Documents&#x2F;&lt;&#x2F;span&gt;&lt;span&gt; Downloads&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;user@host:~$&lt;&#x2F;span&gt;&lt;span&gt; cd Do
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;В таком случае мы, например, можем допечатать &quot;cd Doc&quot; и снова нажать на &quot;Таб&quot; и
у нас получится &quot;cd Documents&#x2F;&quot;. Однако, если при двойном нажатие ничего не
выводится, значит что вариантов для автозаполнения.&lt;&#x2F;p&gt;
&lt;p&gt;В начале может показаться немного не понятно как система автозаполнения
работает, поэтому следует самому попробовать воспользоватся ей на практике
самому.&lt;&#x2F;p&gt;
&lt;p&gt;На этом пока все, в следующей части расскажу побольше о работе в терминале.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="ru">
		<title>Новый выпуск w3blog - версия 0.5</title>
		<published>2018-10-10T12:04:00+00:00</published>
		<updated>2018-10-10T12:04:00+00:00</updated>
		<link href="https://www.yaroslavps.com/ru/weblog/w3blog-v05-release/" type="text/html"/>
		<id>https://www.yaroslavps.com/ru/weblog/w3blog-v05-release/</id>
		<content type="html">&lt;p&gt;После несколько месяцев без особого свободного времени, оно наконец появилось и
мне удалось сесть за работу над моим движком для блогов. Это обновление приносит
некоторые улучшении и новые фишки для w3blog.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;Первым делом, я избавился от лишнего в клиентской части. Избавился от Bootstrap
и JQuery, и полностью переписал дефолтный CSS. А теперь приятно смотреть на
дефолтный стиль страницы, таблицв стилей без сжатия весит всего 5.6К (По
сравнению с 138К для сжатого CSS Bootstrap), и конечно сайт так же стал более
легким за счет избавления JQuery (который в принципе нужен был бутстрапу).&lt;&#x2F;p&gt;
&lt;p&gt;v0.4 - дефолтный вид&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;www.yaroslavps.com&#x2F;ru&#x2F;weblog&#x2F;w3blog-v05-release&#x2F;v04.png&quot; alt=&quot;v0.4&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;дефолтный вид в v0.5&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;www.yaroslavps.com&#x2F;ru&#x2F;weblog&#x2F;w3blog-v05-release&#x2F;v05.png&quot; alt=&quot;v0.5&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;И говоря про улучшения, комментарии наконец содержат дату публикации. Кажется я
забыл добавить столь полезную функцию.&lt;&#x2F;p&gt;
&lt;p&gt;Новые фишки:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Динамическая прогрузка постов на главной и страницах категорий и архива - Если
вы включите эту фичу, вместо обычных кнопок пагинации, появится в конце
страницы кнопка для прогрузки следующих постов через AJAX. Таким образом не
подгружается целая страница заново. Включите добавляя &lt;code&gt;&#x27;dynamic_load&#x27;: True&lt;&#x2F;code&gt; в
&lt;code&gt;WEBLOG_SETTINGS&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Бесконечное пролистывание страницы для динамической прогрузки - Когда эта
опция и динамическая прогрузка включены, после пролистывания до конца
страницы, следующие посты автоматически прогружаются через AJAX. Включите
динамическую прогрузку (см. выше) и добавьте &lt;code&gt;&#x27;infinite_load&#x27;: True&lt;&#x2F;code&gt; в
&lt;code&gt;WEBLOG_SETTINGS&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Плавающая боковая панель - Действия этой функции, сделать так чтобы боковая
панель плавала рядом с контентом после пролистывания страницы ниже
навигационной строки. Для активации добавьте &lt;code&gt;&#x27;floating_sidebar&#x27;: True&lt;&#x2F;code&gt; в
&lt;code&gt;WEBLOG_SETTINGS&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Это собственно все изменения внесены в этом новом релизе. Если вы уже
пользуйтесь w3blog&#x27;ом, и вы используете свои собственны таблицы стилей, вам
придется их переделать, поскольку шаблоны немного изменились с поседней (0.4)
версей. В основном изменились классы HTML&#x2F;CSS.&lt;&#x2F;p&gt;
&lt;p&gt;Были планы и для другие фичи для этого релиза, но я решил их оставить на
следующие релизы.Один из них является способ добавления элементов&#x2F;HTML в боковую
панель, без необходимости переписывание шаблонов w3blog&#x27;а. К сожалению я пока не
нашел нормальный способ разработать такую функцию.&lt;&#x2F;p&gt;
&lt;p&gt;Если у вас возникли проблемы при испоьзованию w3blog, или у вас есть советы либо
комментарии, первый и наилучший вариант это открыть &quot;issue&quot; на странице
Github&#x27;а. Если вдруг у вас нет аккаунта Github (и вы не желаете создать аккаунт,
увы) напишите мне на адрес электронной почты
&lt;a href=&quot;mailto:contact@yaroslavps.com&quot;&gt;contact@yaroslavps.com&lt;&#x2F;a&gt;. Однако, если вы
пользуетесь одним из больших провайдеров электронной почты (например mail.ru,
gmail) то возможно ваш провайдер заблокирует мое письмо с ответом, либо отправит
в спам.&lt;&#x2F;p&gt;
&lt;p&gt;If you have any issues with w3blog, or maybe even suggestions, the first option
would be to open an issue on its Github page, if you don&#x27;t have a Github
account (and don&#x27;t want to create one), you can write me an email at
&lt;a href=&quot;mailto:contact@yaroslavps.com&quot;&gt;contact@yaroslavps.com&lt;&#x2F;a&gt;. However, if you are
using one of the big email providers (e.g. outlook or gmail), my response could
be blocked by your provider.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Yaroslav-95&#x2F;w3blog&quot;&gt;Страница GitHub&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="ru">
		<title>Легкий и халявный SSL с Let&#x27;s Encrypt</title>
		<published>2018-08-12T22:28:00+00:00</published>
		<updated>2018-08-12T22:28:00+00:00</updated>
		<link href="https://www.yaroslavps.com/ru/weblog/ssl-with-lets-encrypt/" type="text/html"/>
		<id>https://www.yaroslavps.com/ru/weblog/ssl-with-lets-encrypt/</id>
		<content type="html">&lt;p&gt;Всем нам известно насколько важна безопасность в веб-разработке, и не только в
вебе. И не надо забыть про тот самый SEO Google который повышает рейтинг сайтов
которые работают с https вместо старого доброго http. (Хоть мне плевать на
Google, но мои клиенты так не думают, также как основная часть аудитории этой
статьи)&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;Возможно вы давно хотели добавить SSL сертификат для своего сайта или сервиса,
но чувак, они же деньги стоят! А вот вы ошибаетесь (Если вы уже знали про Let&#x27;s
Encrypt, то прощу прошение за такое бесполезное введение).&lt;&#x2F;p&gt;
&lt;p&gt;В этом туториале я коротко объясню как сгенерировать сертификат SSL с Let&#x27;s
Encrypt с помощью Certbot используя nginx. В моем случае я его устанавливал на
Debian Stretch, комманда для установки Certbot может отличатся для вас в
зависимости от вашей ОСи.&lt;&#x2F;p&gt;
&lt;p&gt;Перед тем как начать, устанавливаем&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;# apt-get install certbot
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;До того как мы сможем установить сертификат, нам нужно настроить nginx для
установки и последовательной продления сертификата. Для этого нам понадобится
поменять дефолтный файл настройки сервера nginx. Нам это необходимо сделать для
того чтобы, сервер Let&#x27;s Encrypt смог прочитать файл &quot;челленджа&quot; сгенерирован
Certbot&#x27;ом и убедится в том что домен(ы) действительно наш(и).&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;server {
&lt;&#x2F;span&gt;&lt;span&gt;        listen 80 default_server;
&lt;&#x2F;span&gt;&lt;span&gt;        listen [::]:80 default_server;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        server_name _;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        # This is so that Let&amp;#39;s Encrypt can look for the challenge
&lt;&#x2F;span&gt;&lt;span&gt;        location &#x2F;.well-known&#x2F;acme-challenge&#x2F; {
&lt;&#x2F;span&gt;&lt;span&gt;                root &#x2F;var&#x2F;www&#x2F;html&#x2F;;
&lt;&#x2F;span&gt;&lt;span&gt;                default_type text&#x2F;plain;
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        # The rest of your configuration...
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;После того как мы редактировали настройки, нам потребуется перезапустить с&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;# sudo systemctl restart nginx
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Теперь у нас все готово чтобы сгенерировать сертификат. Мне нужен был
сертификат для несколько поддоменов, так что я их всех добавил в список
аргументов используя флаг -d, например&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;# certbot certonly --webroot -w &#x2F;var&#x2F;www&#x2F;html -d www.example.com -d example.com
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Certbot попросит ваш адрес электронной почти, в который будут отправляться
уведомления об истекании срока действия вашего сертификата. Однако Certbot
красавчик умеет их продлевать автоматический.&lt;&#x2F;p&gt;
&lt;p&gt;Вот и наш сертификат готов. А теперь вы можете настроить nginx чтобы он принимал
https запросы и делал редирект http запросов на https. Не забудьте добавить
правильный путь к вашему сертификату и ключу в &lt;code&gt;ssl_certificate&lt;&#x2F;code&gt; и
&lt;code&gt;ssl_certificate_key&lt;&#x2F;code&gt; соответственно.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#f8f8f2;&quot;&gt;&lt;code&gt;&lt;span&gt;server {
&lt;&#x2F;span&gt;&lt;span&gt;        listen 80;
&lt;&#x2F;span&gt;&lt;span&gt;        listen [::]:80;
&lt;&#x2F;span&gt;&lt;span&gt;        server_name www.example.com;
&lt;&#x2F;span&gt;&lt;span&gt;        return 301 https:&#x2F;&#x2F;$host$request_uri;
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;server {
&lt;&#x2F;span&gt;&lt;span&gt;        listen 443 ssl;
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        server_name www.example.com;
&lt;&#x2F;span&gt;&lt;span&gt;        ssl_certificate &#x2F;etc&#x2F;letsencrypt&#x2F;live&#x2F;www.example.com&#x2F;fullchain.pem;
&lt;&#x2F;span&gt;&lt;span&gt;        ssl_certificate_key &#x2F;path&#x2F;to&#x2F;key&#x2F;www.example.com&#x2F;privkey.pem;
&lt;&#x2F;span&gt;&lt;span&gt;        location &#x2F;static&#x2F; {
&lt;&#x2F;span&gt;&lt;span&gt;                alias &#x2F;home&#x2F;webuser&#x2F;mysite&#x2F;static&#x2F;;
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;        location &#x2F;media&#x2F; {
&lt;&#x2F;span&gt;&lt;span&gt;                alias &#x2F;home&#x2F;webuser&#x2F;mysite&#x2F;media&#x2F;;
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;        location &#x2F; {
&lt;&#x2F;span&gt;&lt;span&gt;                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
&lt;&#x2F;span&gt;&lt;span&gt;                proxy_set_header Host $http_host;
&lt;&#x2F;span&gt;&lt;span&gt;                proxy_redirect off;
&lt;&#x2F;span&gt;&lt;span&gt;                proxy_pass http:&#x2F;&#x2F;127.0.0.1:8001;
&lt;&#x2F;span&gt;&lt;span&gt;        }
&lt;&#x2F;span&gt;&lt;span&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Один минус автоматического редиректа, заключается в том что старые браузеры,
(ох уж эти старые неубиваемые версси Internet Explorer) которые не поддерживают
https, не смогут открыть ваш сайт. Но лично мне по барабану на браузера
десятилетней давности.&lt;&#x2F;p&gt;
&lt;p&gt;Вы можете найти больше информации по Certbot на этой странице (сайт на
английском):
&lt;a href=&quot;https:&#x2F;&#x2F;certbot.eff.org&#x2F;docs&#x2F;using.html&quot;&gt;https:&#x2F;&#x2F;certbot.eff.org&#x2F;docs&#x2F;using.html&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Редактировано (2018&#x2F;11&#x2F;02): Недавно в 2018 Let&#x27;s Encrypt добавили возможность
сгенерировать универсальный сертификат для всех поддоменов (например,
*.example.com).&lt;&#x2F;p&gt;
&lt;p&gt;Чтобы сгенерировать такой вид сертификата, нам понадобится скачать последнюю
версию certbot из официального репозитория гита&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; git clone https:&#x2F;&#x2F;github.com&#x2F;certbot&#x2F;certbot.git
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;После этого можем перейти в каталог certbot, и выполнить следующую комманду&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; .&#x2F;certbot-auto certonly&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt; --manual &lt;&#x2F;span&gt;&lt;span&gt;\
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span&gt;--preferred-challenges=dns \
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span&gt;--email email@example.com \
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span&gt;--server https:&#x2F;&#x2F;acme-v02.api.letsencrypt.org&#x2F;directory \
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span&gt;--agree-tos \
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span&gt;-d &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ff5e5e;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;.example.com
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Для этого нам понадобится добавить запись TXT в настройках DNS нашего домена,
посколько для таких сертификатов только доступен &quot;dns challenge&quot;. Перед тем как
нажать на клавишу ввода, убедитесь что настройки вашего домена обновлены.&lt;&#x2F;p&gt;
&lt;p&gt;Имейте ввиду что такие виды сертификатов нельзя обновлять в автоматическом режиме.&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="ru">
		<title>Как сломать pip, и как его починить</title>
		<published>2018-08-03T22:00:00+00:00</published>
		<updated>2018-08-03T22:00:00+00:00</updated>
		<link href="https://www.yaroslavps.com/ru/weblog/how-to-break-and-repair-pip/" type="text/html"/>
		<id>https://www.yaroslavps.com/ru/weblog/how-to-break-and-repair-pip/</id>
		<content type="html">&lt;p&gt;Бывает такое что программу которую мы используем предлагает нам какое-то
действие. И подумаешь, почему бы не следовать совету, ведь разработчики
красавчики сделали прекрасную работу разрабатывая эту программу, они наверно
знают о чем они говорят.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;С pip&#x27;ом походу это так не работает. Я столкнулся с этой проблемой сначала на
моем ноутбуке, а затем на своем настольном компьютере (У меня на обоих стоит
Manjaro). На своем ноутбуке я решил проблему, и когда снова с ней столкнулся на
настольном, я забыл как ее решить. Проблема заключается в том что pip
отказывается установить пакет, выдавая исключение, например
&#x27;ModuleNotFoundError&#x27;.&lt;&#x2F;p&gt;
&lt;p&gt;Сначала, я вам расскажу что НЕ надо делать чтобы избежать данную проблему.&lt;&#x2F;p&gt;
&lt;p&gt;У вас терминале может появится следующее сообщение после того как вы
пользовались pip&#x27;ом&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;You&lt;&#x2F;span&gt;&lt;span&gt; are using pip version x.x.x, however version x.x is available.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;You&lt;&#x2F;span&gt;&lt;span&gt; should consider upgrading via the &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#fbe3bf;&quot;&gt;pip install --upgrade pip&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffffff;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; command.
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Если вы видете такое, или похоже сообшение (например, тоже самое но на
русском), не обращаете на него внимание. Даже не смотрите на него. Просто
сделаете вид что его нет. Я послушался советом этого сообщения, и вот, из-за
этого а теперь я пишу запись на своем блоге о том как решить ошибку которая
возникает из-за того что следовал этим советом. По крайней мере не обращайте
внимание на это сообщение если у вас дистрибутив основан на Arch. На счет
других дистрибутивов я не знаю как следует поступать.&lt;&#x2F;p&gt;
&lt;p&gt;Однако, если вы работаете в виртуальной среде, можно и надо использовать pip
для обновления самого pip&#x27;a. Но если используем pip чтобы установить пакеты на
уровне системы, то следует пользоваться своим менеджером пакетов (pacman) для
обновления pip&#x27;a, поскольку сам менеджер пакетов обновит ваш pip вместе с
остальными пакетами системы когда этого потребуется.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;reshenie&quot;&gt;Решение&lt;&#x2F;h2&gt;
&lt;p&gt;Если вы, увы, как и я, послушались pip&#x27;a и обновили его через самого себя (то
есть обновили pip используя сам pip) то сначала потребуется удалить некоторые
файлы:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; sudo rm&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt; -rf&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;usr&#x2F;lib&#x2F;python3.6&#x2F;site-packages&#x2F;pip &#x2F;usr&#x2F;lib&#x2F;python3.6&#x2F;site-packages&#x2F;pkg_resources
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then, you should reinstall pip and setup tools:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;sh&quot; style=&quot;background-color:#191919;color:#f8f8f2;&quot; class=&quot;language-sh &quot;&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span style=&quot;color:#e9fdac;&quot;&gt;$&lt;&#x2F;span&gt;&lt;span&gt; sudo pacman&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#fc9354;&quot;&gt; -S&lt;&#x2F;span&gt;&lt;span&gt; python-setuptools python-pip
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Вот и все! Ваш pip готов к работе.&lt;&#x2F;p&gt;
&lt;p&gt;Решение проблемы я нашел на форумах arch: &lt;a href=&quot;https:&#x2F;&#x2F;bbs.archlinux.org&#x2F;viewtopic.php?id=237451&quot;&gt;https:&#x2F;&#x2F;bbs.archlinux.org&#x2F;viewtopic.php?id=237451&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</content>
	</entry>
	<entry xml:lang="ru">
		<title>Веб-журнал Ярослава де ла Пенья</title>
		<published>2018-07-21T09:06:00+00:00</published>
		<updated>2018-07-21T09:06:00+00:00</updated>
		<link href="https://www.yaroslavps.com/ru/weblog/first-post/" type="text/html"/>
		<id>https://www.yaroslavps.com/ru/weblog/first-post/</id>
		<content type="html">&lt;p&gt;Доброго времени суток, добро пожаловать в мой веб-журнал. В нем я буду
рассказывать о том чем я занимаюсь, и буду писать о том как все это делаю. Цель
данного журнала - сделать для себя такой вид электронных конспектов где для себя
описываю процесс по которому я разрабатываю софт и сайты, настраиваю линукс, и
тому подобные темы, чтобы таким образом я мог обратиться к своими же записям
когда надо будет что-то вспомнить. Я также считаю что это может пригодиться и
другим людям, и затем я записываю все жто в открытом доступе. Я не эксперт, но я
считаю что делясь знаниями и опытом, я сам лучше учусь.&lt;&#x2F;p&gt;
&lt;span id=&quot;continue-reading&quot;&gt;&lt;&#x2F;span&gt;
&lt;p&gt;В основном я буду писать на английском языке, но большинство моих записей также
будут доступны на русском и на испанском.&lt;&#x2F;p&gt;
&lt;p&gt;Возьмите себе чашку чая, или своего любимого напитка, присаживайтесь и читайте
на здоровье (или ради знания?)&lt;&#x2F;p&gt;
&lt;p&gt;В следующей записи, я напишу в кратком форматк о том как я разработал и запустил
этот сайт. Так что, если вы, как и я, интересуетесь веб-разработкой на Python (и
Django), то моя следующая запись возможно вас заинтересует. И если вы такой же
oldfag как и я, не забудьте подписаться на мою RSS ленту.&lt;&#x2F;p&gt;
&lt;p&gt;Конечно мой сайт пока не пользуется популярности, из-за этого, я решил на первое
время дать возможность оставить аноноимный комментарии. Естественно, если будет
очень большое количество спамма, я буду принужден отключить такую возможность.
Оставляйте свои комментарии дорогие читатели, буду рад всех ваших (цивильных)
комментарии и предложении.&lt;&#x2F;p&gt;
</content>
	</entry>
</feed>
