Операторы перенаправления ввода-вывода [3]
Я же уверен, что 80% из вас когда-то использовали оператор "|". Он невероятно полезен - позволяет подключить стандартный вывод (STDOUT) одной команды к стандартному вводу (STDIN) другой, чтобы первая смогла передать свои выходные данные во вторую.
Вертикальная черта "|" между командами — это символ канала (pipe), который реализовывает механизм конвейера (pipeline).
Посмотрим на самый узнаваемый сценарий работы конвейера - отфильтровать вывод по шаблону:
В результате мы видим не все содержимое директории, а только то, с чем grep нашел пересечение по шаблону.
Команды обычно и не знают, что являются частью конвейера: ls считает, что выводит данные на дисплей, хотя на самом деле ее вывод был перенаправлен на grep, который верит, что читает данные с клавиатуры, когда на самом деле получает вывод ls:
Тут уже оболочка, на своем уровне, выполняет всю магию и использует системный вызов "pipe()" для перенаправления:
Важно понимать, что любая утилита, которая читает стандартный ввод или записывает вывод, может участвовать в создании конвейера и быть полезна для решения комплексной задачи.
Допустим, мы хотим узнать, сколько подкаталогов находится в "/usr/lib". Нет простой команды для получения ответа, поэтому создадим конвейер.
Начнем с простого вывода содержимого директории. Обратите внимание, что команда "ls –l" помечает каталоги буквой "d" в начале строки:
Используем cut, чтобы вывести первый столбец:
Затем используем grep, чтобы оставить только строки, содержащие букву "d":
Наконец, подсчитаем строки с помощью команды wc и получим ответ, созданный конвейером из четырех команд:
Результат: директория "/usr/lib" содержит 145 подкаталогов.
Что мы сделали? Превратили небольшую горстку команд в набор комбинируемых инструментов. Как говорится, целое всегда есть нечто большее, чем сумма его частей.
LinuxCamp
Я же уверен, что 80% из вас когда-то использовали оператор "|". Он невероятно полезен - позволяет подключить стандартный вывод (STDOUT) одной команды к стандартному вводу (STDIN) другой, чтобы первая смогла передать свои выходные данные во вторую.
Вертикальная черта "|" между командами — это символ канала (pipe), который реализовывает механизм конвейера (pipeline).
Посмотрим на самый узнаваемый сценарий работы конвейера - отфильтровать вывод по шаблону:
$ ls /usr/lib | grep nma
libnma.so.0
libnma.so.0.0.0
В результате мы видим не все содержимое директории, а только то, с чем grep нашел пересечение по шаблону.
Команды обычно и не знают, что являются частью конвейера: ls считает, что выводит данные на дисплей, хотя на самом деле ее вывод был перенаправлен на grep, который верит, что читает данные с клавиатуры, когда на самом деле получает вывод ls:
ls (STDOUT) -> grep (STDIN) -> grep (STDOUT)
Тут уже оболочка, на своем уровне, выполняет всю магию и использует системный вызов "pipe()" для перенаправления:
#include <unistd.h>
int pipe(int pipefd[2]);
Важно понимать, что любая утилита, которая читает стандартный ввод или записывает вывод, может участвовать в создании конвейера и быть полезна для решения комплексной задачи.
Допустим, мы хотим узнать, сколько подкаталогов находится в "/usr/lib". Нет простой команды для получения ответа, поэтому создадим конвейер.
Начнем с простого вывода содержимого директории. Обратите внимание, что команда "ls –l" помечает каталоги буквой "d" в начале строки:
$ ls -l /usr/lib
drwxrwxr-x ... 4kstogram
drwxr-xr-x ... NetworkManager
Используем cut, чтобы вывести первый столбец:
$ ls -l /usr/lib | cut -c1
d
d
d
-
-
-
Затем используем grep, чтобы оставить только строки, содержащие букву "d":
$ ls -l /usr/lib | cut -c1 | grep d
d
d
d
Наконец, подсчитаем строки с помощью команды wc и получим ответ, созданный конвейером из четырех команд:
$ ls -l /usr/lib | cut -c1 | grep d | wc -l
145
Результат: директория "/usr/lib" содержит 145 подкаталогов.
Что мы сделали? Превратили небольшую горстку команд в набор комбинируемых инструментов. Как говорится, целое всегда есть нечто большее, чем сумма его частей.
LinuxCamp
👍54🔥12❤🔥4
Набираем обороты с pattern matching
Чтобы повысить продуктивность, оболочка предусматривает ряд спецсимволов для оптимизации работы и выполнения ряда задач.
Концепция работы с символами: *, ?, [], называется сопоставлением с шаблоном (pattern matching).
И так, команда может включать в себя символ групповых операций * для одновременной ссылки на несколько файлов:
Этот символ обрабатывается командной оболочкой, а не программой ls. Оболочка заменяет выражение "*.py" списком имен подходящих файлов еще до запуска программы ls.
Иными словами, ls не увидит символ групповой операции. С точки зрения утилиты, вы ввели команду следующего вида:
Символ * соответствует любой последовательности из символов в путях к файлам или каталогам.
Например, гораздо проще и быстрее, вместо прямого перечисления:
Использовать базовый шаблон:
Остается за кадром, как командная оболочка (не программа grep) преобразует шаблон "chapter*" в список подходящих имен файлов. И только после этого оболочка запускает grep.
Если шаблон не соответствует ни одному файлу, оболочка передает его в качестве аргумента команды:
Еще бывает полезно использовать знак ?, который соответствует любому единичному символу. Например, вы можете выполнить поиск слова Linux в главах с 1 по 9, используя ? для поиска совпадений:
Для поиска в главах с 10 по 99 придется использовать "??":
Менее известно использование скобок [] для запроса у оболочки соответствия одному из символов набора. Например, вы можете искать только в первых 3 главах:
Любые символы, не только цифры, могут быть помещены в квадратные скобки для сопоставления.
Например, следующая команда заставит оболочку искать имена файлов, начинающиеся с заглавной буквы, содержащие символ _ и заканчивающиеся символом @:
LinuxCamp
Чтобы повысить продуктивность, оболочка предусматривает ряд спецсимволов для оптимизации работы и выполнения ряда задач.
Концепция работы с символами: *, ?, [], называется сопоставлением с шаблоном (pattern matching).
Если вы все еще путаетесь в том, что такое оболочка, предлагаю обратиться к моей последней сводке постов.
И так, команда может включать в себя символ групповых операций * для одновременной ссылки на несколько файлов:
$ ls *.py
data.py main.py user_interface.py
Этот символ обрабатывается командной оболочкой, а не программой ls. Оболочка заменяет выражение "*.py" списком имен подходящих файлов еще до запуска программы ls.
Иными словами, ls не увидит символ групповой операции. С точки зрения утилиты, вы ввели команду следующего вида:
$ ls data.py main.py user_interface.py
Символ * соответствует любой последовательности из символов в путях к файлам или каталогам.
Например, гораздо проще и быстрее, вместо прямого перечисления:
$ grep Linux chapter1 chapter2 chapter3 chapter4 chapter5...
Использовать базовый шаблон:
$ grep Linux chapter*
Остается за кадром, как командная оболочка (не программа grep) преобразует шаблон "chapter*" в список подходящих имен файлов. И только после этого оболочка запускает grep.
Если шаблон не соответствует ни одному файлу, оболочка передает его в качестве аргумента команды:
$ grep Linux chapter*
grep: chapter*: No such file or directory
Еще бывает полезно использовать знак ?, который соответствует любому единичному символу. Например, вы можете выполнить поиск слова Linux в главах с 1 по 9, используя ? для поиска совпадений:
$ grep Linux chapter?
Для поиска в главах с 10 по 99 придется использовать "??":
$ grep Linux chapter??
Менее известно использование скобок [] для запроса у оболочки соответствия одному из символов набора. Например, вы можете искать только в первых 3 главах:
$ grep Linux chapter[123]
$ grep Linux chapter[1-3]
Любые символы, не только цифры, могут быть помещены в квадратные скобки для сопоставления.
Например, следующая команда заставит оболочку искать имена файлов, начинающиеся с заглавной буквы, содержащие символ _ и заканчивающиеся символом @:
$ ls [A-Z]*_*@
LinuxCamp
👍38🔥15❤🔥3
Вычисление переменных и развеивание заблуждений
Мы с вами уже как-то говорили про суть переменных оболочки и окружения. Сегодня рассмотрим оператор $, который позволяет определить значение переменной.
Когда командная оболочка вычисляет переменную, определяет ее значение и подставляет его вместо имени. Чтобы выполнить задачу, нужно просто поставить знак $ перед именем.
Самый простой способ увидеть, как оболочка обрабатывает символ — запустить команду echo, которая выводит свои аргументы (после того, как оболочка завершит их вычисление):
Когда вы выводите на экран значение переменной с помощью команды echo, вы можете подумать, что сама команда проверяет переменную и выводит ее значение.
На самом деле это не так, команда ничего не знает о переменных. Она просто выводит на экран любые аргументы, которые вы ей передаете. Значения для HOME и USER вычисляет оболочка перед запуском команды.
Вы можете определить или изменить переменную в любое время, используя следующий синтаксис:
Например, если вы часто работаете с каталогом "Projects" внутри домашней директории, вы можете присвоить его имя переменной:
И использовать его как удобное сокращение при работе с cd:
Вы можете передавать $work любой команде, ожидающей имя каталога, в качестве аргумента:
Вообще, этот принцип важно понять: оболочка вычисляет переменные, шаблоны и другие конструкции перед выполнением команды.
Шаблоны vs переменные
Предположим, вы хотите перенести ряд файлов с расширением ".txt" из одного каталога в другой.
Вот два способа сделать это, но один работает, а другой нет:
Метод 1 работает, потому что шаблон соответствует всему пути к файлу — имя каталога dir1 является частью совпадений:
Таким образом, метод 1 работает так, как если бы вы набрали следующую команду:
В методе 2 используются переменные, имеющие только свои буквальные значения, и нет специального инструмента для вычисления путей к файлам:
Следовательно, метод 2 работает так, как если бы вы набрали следующую команду:
LinuxCamp
Мы с вами уже как-то говорили про суть переменных оболочки и окружения. Сегодня рассмотрим оператор $, который позволяет определить значение переменной.
Когда командная оболочка вычисляет переменную, определяет ее значение и подставляет его вместо имени. Чтобы выполнить задачу, нужно просто поставить знак $ перед именем.
Самый простой способ увидеть, как оболочка обрабатывает символ — запустить команду echo, которая выводит свои аргументы (после того, как оболочка завершит их вычисление):
$ echo My name is $USER and my files are in $HOME
My name is xoadmin and my files are in /home/xoadmin
$ echo ch*ter9
chapter9
Когда вы выводите на экран значение переменной с помощью команды echo, вы можете подумать, что сама команда проверяет переменную и выводит ее значение.
На самом деле это не так, команда ничего не знает о переменных. Она просто выводит на экран любые аргументы, которые вы ей передаете. Значения для HOME и USER вычисляет оболочка перед запуском команды.
Вы можете определить или изменить переменную в любое время, используя следующий синтаксис:
name=value
Например, если вы часто работаете с каталогом "Projects" внутри домашней директории, вы можете присвоить его имя переменной:
$ work=$HOME/Projects
И использовать его как удобное сокращение при работе с cd:
$ cd $work
$ pwd
/home/xoadmin/Projects
Вы можете передавать $work любой команде, ожидающей имя каталога, в качестве аргумента:
$ cp myfile $work
$ ls $work
Myfile
Вообще, этот принцип важно понять: оболочка вычисляет переменные, шаблоны и другие конструкции перед выполнением команды.
Шаблоны vs переменные
Предположим, вы хотите перенести ряд файлов с расширением ".txt" из одного каталога в другой.
Вот два способа сделать это, но один работает, а другой нет:
# Метод 1
$ mv dir1/*.txt dir2
# Метод 2
$ FILES="file1.txt file1.txt"
$ mv dir1/$FILES dir2
Метод 1 работает, потому что шаблон соответствует всему пути к файлу — имя каталога dir1 является частью совпадений:
$ echo dir1/*.txt
dir1/file1.txt dir1/file2.txt
Таким образом, метод 1 работает так, как если бы вы набрали следующую команду:
$ mv dir1/file1.txt dir1/file2.txt dir2
В методе 2 используются переменные, имеющие только свои буквальные значения, и нет специального инструмента для вычисления путей к файлам:
$ echo dir1/$FILES
dir1/file1.txt file2.txt
Следовательно, метод 2 работает так, как если бы вы набрали следующую команду:
$ mv dir1/file1.txt file2.txt dir2
/bin/mv: cannot stat 'file2.txt': No such file or directory
LinuxCamp
👍36🔥23❤🔥4
Выполняй только то, что нужно! Условные списки Bash
Скорее всего, вы каждый день запускаете команды, которые зависят от выполнения предыдущих.
Механизм списков позволяет не только разом выполнить группу команд, но и выстроить условную последовательность через операторы "&& (И)" и "|| (ИЛИ)".
Условные списки
Предположим, вы хотите создать файл new.txt в каталоге dir. Типичная последовательность может быть следующей:
Запуск второй команды зависит от успешного выполнения первой. Если каталог не существует, то нет смысла и команду запускать.
Оболочка позволяет сделать эту зависимость явной, объединив команды оператором && (И):
Если вы используете систему контроля версий Git, то, вероятно, знакомы со следующей последовательностью команд фиксации и внесения изменений:
Если какая-либо из команд завершится ошибкой, остальные вы не запустите. Поэтому эта цепочка хорошо работает в формате условного списка.
Так же, как оператор && запускает вторую команду только в случае успеха первой, оператор || (ИЛИ) запускает вторую команду только в случае сбоя первой.
Например, следующая команда пытается войти в каталог и, если это не удается, создает его:
Вы часто будете видеть этот оператор в сценариях оболочки. В частности, для выхода в случае возникновения ошибки:
Операторы && и || можно использовать вместе, чтобы настраивать более сложные действия:
Последовательность предполагает попытку войти в каталог dir, если это не удается, создать каталог и войти в него, а если и это не удается, вывести ошибку.
Безусловные списки
Команды в списке не обязательно должны зависеть друг от друга. Если вы разделяете команды точкой с запятой, они просто выполняются по порядку.
Вот пример команды, которая спит течение двух часов, а затем создает резервную копию важных файлов:
Безусловные списки дают те же результаты, что и ввод команд по отдельности.
Единственное существенное различие - коды возврата. В таком списке коды отдельных команд отбрасываются, кроме последней.
Только код возврата последней команды в списке присваивается переменной оболочки "?":
LinuxCamp
Скорее всего, вы каждый день запускаете команды, которые зависят от выполнения предыдущих.
Механизм списков позволяет не только разом выполнить группу команд, но и выстроить условную последовательность через операторы "&& (И)" и "|| (ИЛИ)".
Условные списки
Предположим, вы хотите создать файл new.txt в каталоге dir. Типичная последовательность может быть следующей:
$ cd dir
$ touch new.txt
Запуск второй команды зависит от успешного выполнения первой. Если каталог не существует, то нет смысла и команду запускать.
Оболочка позволяет сделать эту зависимость явной, объединив команды оператором && (И):
$ cd dir && touch new.txt
Если вы используете систему контроля версий Git, то, вероятно, знакомы со следующей последовательностью команд фиксации и внесения изменений:
$ git add . && git commit -m"fixed a bug" && git push
Если какая-либо из команд завершится ошибкой, остальные вы не запустите. Поэтому эта цепочка хорошо работает в формате условного списка.
Так же, как оператор && запускает вторую команду только в случае успеха первой, оператор || (ИЛИ) запускает вторую команду только в случае сбоя первой.
Например, следующая команда пытается войти в каталог и, если это не удается, создает его:
$ cd dir || mkdir dir
Вы часто будете видеть этот оператор в сценариях оболочки. В частности, для выхода в случае возникновения ошибки:
cd dir || exit 1
Операторы && и || можно использовать вместе, чтобы настраивать более сложные действия:
$ cd dir || mkdir dir && cd dir || echo "I failed"
Последовательность предполагает попытку войти в каталог dir, если это не удается, создать каталог и войти в него, а если и это не удается, вывести ошибку.
Безусловные списки
Команды в списке не обязательно должны зависеть друг от друга. Если вы разделяете команды точкой с запятой, они просто выполняются по порядку.
Вот пример команды, которая спит течение двух часов, а затем создает резервную копию важных файлов:
$ sleep 7200; cp -a ~/files /mnt/backup_drive
Безусловные списки дают те же результаты, что и ввод команд по отдельности.
Единственное существенное различие - коды возврата. В таком списке коды отдельных команд отбрасываются, кроме последней.
Только код возврата последней команды в списке присваивается переменной оболочки "?":
$ mv file1 file2; mv file2 file3; mv file3 file4
# Код возврата команды «mv file3 file4»
$ echo $?
0
LinuxCamp
👍40🔥10❤🔥7❤1
Что за праздник на пороге?) Новый год 🔴
Ну вот, пишу завершающий пост в 2024 году, давайте подведем небольшие итоги и чуть побеседуем.
Много было проделано работы, мы набрали больше 7к человек, среди которых как устоявшиеся спецы, так и новички, которым только предстоит окунуться в мир разработки и администрирования.
Представляете, 7к! Я, честно говоря, думал, и до 5 с трудом доковыляем. Но как-то все пошло-поехало и получилось зафиксировать хороший результат. Очень рад, что в этом году все-таки получилось начать движение в сторону публичной деятельности. Мы держим в уме - все только начинается!
Хочу каждому выразить огромную благодарность за то, что остаетесь на связи, читаете и комментируете публикации. Радует, что держатся и олды, которые на канале с самого его зачатия. Они помнят те бесконечные посты про динамические библиотеки))
Вам хочу пожелать крепкого здоровья, профессиональной реализации, огня в глазах, успехов в достижении поставленных целей и положительных перемен. Все у вас получится!
Также искренне желаю, чтобы вас окружали правильные люди, которые будут помогать держать верный курс. Наше окружение оказывает значительное влияние на то, кто мы есть и кем будем. Работайте над ним, иногда рефлексируйте и, при необходимости, вносите коррективы)
На этом прощаюсь, с наступающим праздником!
Ну вот, пишу завершающий пост в 2024 году, давайте подведем небольшие итоги и чуть побеседуем.
Много было проделано работы, мы набрали больше 7к человек, среди которых как устоявшиеся спецы, так и новички, которым только предстоит окунуться в мир разработки и администрирования.
Представляете, 7к! Я, честно говоря, думал, и до 5 с трудом доковыляем. Но как-то все пошло-поехало и получилось зафиксировать хороший результат. Очень рад, что в этом году все-таки получилось начать движение в сторону публичной деятельности. Мы держим в уме - все только начинается!
Хочу каждому выразить огромную благодарность за то, что остаетесь на связи, читаете и комментируете публикации. Радует, что держатся и олды, которые на канале с самого его зачатия. Они помнят те бесконечные посты про динамические библиотеки))
Вам хочу пожелать крепкого здоровья, профессиональной реализации, огня в глазах, успехов в достижении поставленных целей и положительных перемен. Все у вас получится!
Также искренне желаю, чтобы вас окружали правильные люди, которые будут помогать держать верный курс. Наше окружение оказывает значительное влияние на то, кто мы есть и кем будем. Работайте над ним, иногда рефлексируйте и, при необходимости, вносите коррективы)
На этом прощаюсь, с наступающим праздником!
Please open Telegram to view this post
VIEW IN TELEGRAM
🎉64🎄11🔥7👍5❤🔥3☃2🍾2❤1🍓1
Подстановка вывода команды: $()
Оператор, который мы сегодня рассмотрим является супер полезной фичей оболочки. Мы буквально можем подставить вывод команды либо целой цепочки посреди выражения.
Предположим, у вас есть несколько тысяч текстовых файлов c песнями. Каждый файл содержит название песни, ее текст и имя исполнителя:
Стоит задача распределить файлы в подкаталоги по исполнителям. Ну, для начала, можно найти все файлы песен исполнителя с помощью grep:
Затем переместить каждый файл в необходимый каталог:
Чет неудобно, так? Было бы неплохо сказать оболочке: «Перемести все файлы, содержащие строку Лепс, в каталог leps».
Для этого нужно забрать то, что нам выдала команда "grep -l" и передать результат в качестве списка аргументов для mv:
Синтаксис "$(команда)" выполняет выражение в круглых скобках и заменяет вставку его выводом.
Таким образом, "grep -l" подменяется, подходящими под условие именнами файлов. Результат использования $() в примере выше аналогичен:
В сценариях оболочки подстановка бывает полезна для сохранения вывода команды в переменной:
Например, напишем простенький скрипт, который поможет нам узнать, содержит ли текущая директория файлы:
Выдаем права на выполнение, запускаем и проверяем:
Для чего бывает полезно брать "$()" в кавычки?
Есть несколько основных кейсов, когда следует использовать "$()" вместо $().
Во-первых, если вывод команды содержит пробелы, он будет разбит на отдельные слова.
Представим, что стоит задача определить для текущей директории специальные права.
Есть момент - имя каталога состоит из нескольких слов, разделенных пробелами "photo and video":
После подстановки оболочка интерпретирует это как попытку применить chmod к трём разным объектам: "/home/xoadmin/photo", "and", и "video". Это, вероятно, приведёт к ошибке:
Чтобы вывод pwd воспринимался, как единое целое, следует заключить оператор в кавычки:
Во-вторых, без кавычек, символы перевода строки могут быть удалены при выводе через echo:
Если требуется сохранить четкую структуру текста, содержащего спец символы, следует использовать "$()":
LinuxCamp
Оператор, который мы сегодня рассмотрим является супер полезной фичей оболочки. Мы буквально можем подставить вывод команды либо целой цепочки посреди выражения.
Предположим, у вас есть несколько тысяч текстовых файлов c песнями. Каждый файл содержит название песни, ее текст и имя исполнителя:
Название: Зеркала
Исполнитель: Лепс
Острые углы, нервы, суета
Стоит задача распределить файлы в подкаталоги по исполнителям. Ну, для начала, можно найти все файлы песен исполнителя с помощью grep:
$ grep -l "Лепс" *.txt
song1.txt
song2.txt
Затем переместить каждый файл в необходимый каталог:
$ mkdir leps
$ mv song1.txt leps
$ mv song2.txt leps
Чет неудобно, так? Было бы неплохо сказать оболочке: «Перемести все файлы, содержащие строку Лепс, в каталог leps».
Для этого нужно забрать то, что нам выдала команда "grep -l" и передать результат в качестве списка аргументов для mv:
$ mv $(grep -l "Лепс" *.txt) leps
Синтаксис "$(команда)" выполняет выражение в круглых скобках и заменяет вставку его выводом.
Таким образом, "grep -l" подменяется, подходящими под условие именнами файлов. Результат использования $() в примере выше аналогичен:
$ mv song1.txt song2.txt leps
В сценариях оболочки подстановка бывает полезна для сохранения вывода команды в переменной:
переменная=$(команда)
Например, напишем простенький скрипт, который поможет нам узнать, содержит ли текущая директория файлы:
status=$(ls ./ 2>/dev/null | wc -l)
if [ "$status" -gt 0 ]; then
echo "В директории есть $status файлов"
else
echo "Директория пуста или не существует"
fi
Выдаем права на выполнение, запускаем и проверяем:
$ chmod +x noscript.sh
$ ./noscript.sh
В директории есть 66 файлов
Для чего бывает полезно брать "$()" в кавычки?
Есть несколько основных кейсов, когда следует использовать "$()" вместо $().
Во-первых, если вывод команды содержит пробелы, он будет разбит на отдельные слова.
Представим, что стоит задача определить для текущей директории специальные права.
Есть момент - имя каталога состоит из нескольких слов, разделенных пробелами "photo and video":
$ pwd
$ /home/xoadmin/photo and video
$ chmod 777 $(pwd)
После подстановки оболочка интерпретирует это как попытку применить chmod к трём разным объектам: "/home/xoadmin/photo", "and", и "video". Это, вероятно, приведёт к ошибке:
chmod: cannot access '/home/xoadmin/photo': No such file or directory
chmod: cannot access 'and': No such file or directory
chmod: cannot access 'video': No such file or directory
Чтобы вывод pwd воспринимался, как единое целое, следует заключить оператор в кавычки:
$ chmod 777 "$(pwd)"
Во-вторых, без кавычек, символы перевода строки могут быть удалены при выводе через echo:
$ echo $(ls)
adduser.conf alsa alternatives apache2 apg.conf apparmor
Если требуется сохранить четкую структуру текста, содержащего спец символы, следует использовать "$()":
$ echo "$(ls)"
adduser.conf
alsa
alternatives
LinuxCamp
👍39🔥16❤7🎄4❤🔥2
Введение в фоновые команды и задания
Стандартное выполнение команды в оболочке происходит так, что вам требуется ожидать ее завершения для дальнейшего взаимодействия с командной строкой.
Это обычно неэффективно, когда выполнение занимает время и вам не требуется общаться с утилитой через CLI либо отлаживать ее логи.
Не беда, вы можете запускать команды особым образом, чтобы они исчезали из поля зрения, но продолжали выполняться, освобождая текущую оболочку.
Этот метод называется фоновым выполнением команды (backgrounding).
Если же команда занимает оболочку, ее называют командой переднего плана (foreground).
Запуск команды в фоновом режиме
Чтобы запуститься в фоновом режиме, просто добавьте амперсанд "&" после команды:
[1] - номер, под которым закрепилось задание (job);
74931 - PID процесса;
Если команда завершится успешно, оболочка выведет сообщение:
Если где-то произошла ошибка и команда завершилась аварийно, вы увидите сообщение о выходе с кодом возврата:
Амперсанд "&" является оператором списка - вы можете вывести в фон сразу ряд команд:
Чем является задание?
Вы можете подумать, что под заданием подразумевается 1 процесс - немного не так.
Задание — это единица работы оболочки. Простые команды, конвейеры и условные списки — примеры заданий, которые можно запускать из командной строки.
Задание — это больше, чем просто процесс Linux. Задание может состоять из одного или нескольких процессов:
Например, конвейер из шести программ представляет собой одно задание, включающее 6 процессов:
В оболочке может быть запущено одновременно несколько заданий, каждый экземпляр имеет свой ID.
LinuxCamp
Стандартное выполнение команды в оболочке происходит так, что вам требуется ожидать ее завершения для дальнейшего взаимодействия с командной строкой.
Это обычно неэффективно, когда выполнение занимает время и вам не требуется общаться с утилитой через CLI либо отлаживать ее логи.
Не беда, вы можете запускать команды особым образом, чтобы они исчезали из поля зрения, но продолжали выполняться, освобождая текущую оболочку.
Этот метод называется фоновым выполнением команды (backgrounding).
Если же команда занимает оболочку, ее называют командой переднего плана (foreground).
Запуск команды в фоновом режиме
Чтобы запуститься в фоновом режиме, просто добавьте амперсанд "&" после команды:
$ wc -c file.txt &
[1] 74931
$
[1] - номер, под которым закрепилось задание (job);
74931 - PID процесса;
Если команда завершится успешно, оболочка выведет сообщение:
[1]+ Done wc -c file.txt
Если где-то произошла ошибка и команда завершилась аварийно, вы увидите сообщение о выходе с кодом возврата:
[1]+ Exit 1 wc -c file.txt
Амперсанд "&" является оператором списка - вы можете вывести в фон сразу ряд команд:
$ nm-applet & wc -c file.txt &
[1] 28839
[2] 28840
Чем является задание?
Вы можете подумать, что под заданием подразумевается 1 процесс - немного не так.
Задание — это единица работы оболочки. Простые команды, конвейеры и условные списки — примеры заданий, которые можно запускать из командной строки.
Задание — это больше, чем просто процесс Linux. Задание может состоять из одного или нескольких процессов:
[4]+ Running nm-applet && wc -c file.txt &
Например, конвейер из шести программ представляет собой одно задание, включающее 6 процессов:
$ cat file.txt | grep "word" | sort | uniq | tr 'a-z' 'A-Z' | wc -l > result.txt &
[5]+ Running cat file.txt | grep --color=auto "word" ... &
В оболочке может быть запущено одновременно несколько заданий, каждый экземпляр имеет свой ID.
LinuxCamp
👍39🔥11❤🔥3
Команды управления заданиями
В прошлый раз мы узнали о фоновом выполнении команд и дали определение термину "задание".
Сегодня рассмотрим, встроенные в оболочку средства, которые позволяют управлять заданиями: bg, fg, jobs, kill.
Давайте для начала запустим в фоне несколько команд sleep, которые ничего не будет делать в течение заданного времени:
Чтобы выяснить, за какими заданиями следит оболочка, используется команда jobs:
[1] - номер задания, который используется для идентификации. Полезен, когда необходимо "ткнуть пальцем" в определенный элемент, используя: fg, bg, kill;
"" (отсутствие знака) - обозначает то, что задание не является ни текущим ни предыдущим, но находится в списке.
"+" указывает на текущее задание, по отношению к которому будут выполнены команды, если не указывать номер. "-" указывает на предыдущее задание;
Running - статус задачи. Также возможны: Stopped, Done, Terminated, Killed. Статусы могут меняться в ответ на отправленный сигнал (SIGKILL, SIGSTOP и т.д.);
Теперь выведем второе задание на передний план. Для этого будем использовать команду fg с указанием номера:
Если в параметры ничего не вносить, команда выполнится для последнего задания (со знаком +).
Для того, чтобы перенести выполнение в фон и не блокировать терминал, используется bg.
Для примера запустим задание переднего плана, остановим его выполнение "Ctrl + Z" и отправим его в фоновый режим:
К целевому заданию также можно обратиться по номеру:
С заданиями "kill %n" можно использовать для принудительного завершения:
По умолчанию отправляется сигнал SIGTERM, при желании, можно указать любой другой:
LinuxCamp
В прошлый раз мы узнали о фоновом выполнении команд и дали определение термину "задание".
Сегодня рассмотрим, встроенные в оболочку средства, которые позволяют управлять заданиями: bg, fg, jobs, kill.
Давайте для начала запустим в фоне несколько команд sleep, которые ничего не будет делать в течение заданного времени:
$ sleep 10 & sleep 20 & sleep 30 &
Чтобы выяснить, за какими заданиями следит оболочка, используется команда jobs:
$ jobs
[1] Running sleep 10 &
[2]- Running sleep 20 &
[3]+ Running sleep 30 &
[1] - номер задания, который используется для идентификации. Полезен, когда необходимо "ткнуть пальцем" в определенный элемент, используя: fg, bg, kill;
"" (отсутствие знака) - обозначает то, что задание не является ни текущим ни предыдущим, но находится в списке.
"+" указывает на текущее задание, по отношению к которому будут выполнены команды, если не указывать номер. "-" указывает на предыдущее задание;
Running - статус задачи. Также возможны: Stopped, Done, Terminated, Killed. Статусы могут меняться в ответ на отправленный сигнал (SIGKILL, SIGSTOP и т.д.);
Теперь выведем второе задание на передний план. Для этого будем использовать команду fg с указанием номера:
$ fg %2
sleep 20
Если в параметры ничего не вносить, команда выполнится для последнего задания (со знаком +).
Для того, чтобы перенести выполнение в фон и не блокировать терминал, используется bg.
Для примера запустим задание переднего плана, остановим его выполнение "Ctrl + Z" и отправим его в фоновый режим:
$ nm-applet
^Z
[1]+ Stopped nm-applet
$ bg
[1]+ nm-applet &
$ jobs
[1]+ Running nm-applet
К целевому заданию также можно обратиться по номеру:
$ jobs
[1]- Stopped sleep 200
[2]+ Running sleep 100 &
$ bg %1
[1]+ sleep 200 &
С заданиями "kill %n" можно использовать для принудительного завершения:
$ kill %1
[1]+ Terminated sleep 200
По умолчанию отправляется сигнал SIGTERM, при желании, можно указать любой другой:
$ kill -9 %1
[1]+ Killed sleep 200
LinuxCamp
🔥30👍21❤🔥3⚡3🥰1
Выбираем название канала
Для лучшего поиска нужно добавить 1 слово, которое бы выделяло канал. Если есть идеи, обязательно пишите в комменты)
Для лучшего поиска нужно добавить 1 слово, которое бы выделяло канал. Если есть идеи, обязательно пишите в комменты)
Final Results
20%
Baza Linux++
12%
DevHub Linux++
5%
Crazy Linux++
26%
GNU/Linux++
34%
Pro Linux++
4%
BrainBar Linux++
3%
Mania Linux++
22%
Все не то
✍14👍7⚡3❤🔥1🤔1
Проблема с вводом-выводом в фоновом выполнении
Фоновая команда может использовать стандартный вывод, когда это совершенно не к месту)
Что будет, если вы, например, отсортируете немалый файл и запросите вывод двух первых строк в фоновом режиме?
Вначале оболочка напечатает номер задания (1), идентификатор процесса (81089) и приглашение к вводу:
На данном этапе происходит сортировка данных и подготовка вывода. Когда первая часть задания завершится, отработает команда "head -n2" и выведутся две строки (где бы курсор не находился):
Вывод на экран при выполнении фонового задания может появиться в любое время. Ладно, если там пару строк, а вдруг данные выводятся регулярно и в большом объеме...
Совет: чтобы избежать беспорядка, перенаправьте stdout в файл, а затем просмотрите его, когда вам будет удобно:
Неожиданности случаются и тогда, когда фоновое задание пытается читать со стандартного ввода. Оболочка приостанавливает задание, печатает сообщение Stopped и ожидает ввода. Запустив команду cat в фоновом режиме без аргументов, чтобы она читала STDIN:
Задания не могут читать ввод в фоновом режиме, поэтому сначала переведем его на передний план с помощью fg, а затем введем данные:
После ввода можно уже либо завершить задачу "Ctrl + C", либо вернуть ее в фон через "Ctrl + Z" и bg.
LinuxCamp
Фоновая команда может использовать стандартный вывод, когда это совершенно не к месту)
Что будет, если вы, например, отсортируете немалый файл и запросите вывод двух первых строк в фоновом режиме?
Вначале оболочка напечатает номер задания (1), идентификатор процесса (81089) и приглашение к вводу:
$ sort /usr/share/dict/words | head -n2 &
[1] 81089
$
На данном этапе происходит сортировка данных и подготовка вывода. Когда первая часть задания завершится, отработает команда "head -n2" и выведутся две строки (где бы курсор не находился):
$ sort /usr/share/dict/words | head -n2 &
[1] 81089
$A
A's
Вывод на экран при выполнении фонового задания может появиться в любое время. Ладно, если там пару строк, а вдруг данные выводятся регулярно и в большом объеме...
Совет: чтобы избежать беспорядка, перенаправьте stdout в файл, а затем просмотрите его, когда вам будет удобно:
$ sort /usr/share/dict/words | head -n2 > /tmp/results &
$ cat /tmp/results
A
A's
Неожиданности случаются и тогда, когда фоновое задание пытается читать со стандартного ввода. Оболочка приостанавливает задание, печатает сообщение Stopped и ожидает ввода. Запустив команду cat в фоновом режиме без аргументов, чтобы она читала STDIN:
$ cat &
[1] 82455
[1]+ Stopped cat
Задания не могут читать ввод в фоновом режиме, поэтому сначала переведем его на передний план с помощью fg, а затем введем данные:
$ fg
cat
Hello world!
Hello world!
После ввода можно уже либо завершить задачу "Ctrl + C", либо вернуть ее в фон через "Ctrl + Z" и bg.
LinuxCamp
👍25🔥6❤🔥3
Передача команды в качестве bash аргумента
bash — это обычная программка, такая же, как и любая другая, поэтому вы можете запускать ее по имени в командной строке.
По умолчанию bash запускает интерактивную оболочку для ввода и выполнения команд.
Кроме того, можно передать команду в bash в виде строки с помощью параметра "-c".
Тогда bash запустит эту строку как команду, а после выполнения завершит работу:
Почему это бывает полезно?
Потому что новый процесс будет дочерним со своим собственным окружением, включая текущий каталог, переменные и их значения.
Любые изменения в дочерней оболочке не повлияют на текущую:
Пример выше запускает доп. оболочку только для того, чтобы поменяет каталог на tmp и удалить файл, а затем завершает работу.
Однако наиболее показательно и полезно использование "bash -c" вместе с sudo и перенаправлением ввода/вывода. Тогда-то эта фича является ключом к успеху.
Предположим, вы хотите создать файл журнала в системном каталоге "/var/log", недоступном для записи обычным пользователям.
Вы добавляете sudo, чтобы получить привилегии и создать файл журнала, но команда загадочным образом не исполняется:
Минуту, команда sudo должна дать разрешение на создание любого файла в любом месте. Как что-то может пойти не так?
Почему sudo даже не запрашивает пароль? Ответ: потому что sudo вообще не запускалась.
Вы применили sudo к команде echo, но не к перенаправлению вывода, которое запустилось первым и провалилось.
Опишем процесс пошагово:
1) вы нажали клавишу Enter;
2) оболочка начала вычислять всю команду, включая перенаправление;
3) оболочка попыталась создать файл custom.log в защищенном каталоге "/var/log";
У нас не было разрешения на запись в "/var/log", поэтому оболочка сообщила, что в доступе отказано (Permission denied).
Чтобы решить эту проблему, нужно сообщить оболочке:
«Выполни всю команду, включая перенаправление вывода, от имени суперпользователя».
Это именно та ситуация, которую так хорошо решает "bash -c".
Создайте команду, которую вы хотите запустить, в виде строки и передайте ее в качестве аргумента для "sudo bash -c":
На этот раз мы запустили от имени суперпользователя bash, а не просто echo.
По итогу, bash выполнит всю строку как команду. Перенаправление проходит успешно.
Помните о "bash -c", когда sudo сочетается с перенаправлением.
LinuxCamp
bash — это обычная программка, такая же, как и любая другая, поэтому вы можете запускать ее по имени в командной строке.
По умолчанию bash запускает интерактивную оболочку для ввода и выполнения команд.
Кроме того, можно передать команду в bash в виде строки с помощью параметра "-c".
Тогда bash запустит эту строку как команду, а после выполнения завершит работу:
$ bash -c "ls -l"
-rw-r--r-- 1 smith smith 325 Jul 3 17:44 animals.txt
Почему это бывает полезно?
Потому что новый процесс будет дочерним со своим собственным окружением, включая текущий каталог, переменные и их значения.
Любые изменения в дочерней оболочке не повлияют на текущую:
$ pwd
/home/smith
$ touch /tmp/badfile
$ bash -c "cd /tmp && rm badfile"
$ pwd
/home/smith
Пример выше запускает доп. оболочку только для того, чтобы поменяет каталог на tmp и удалить файл, а затем завершает работу.
Однако наиболее показательно и полезно использование "bash -c" вместе с sudo и перенаправлением ввода/вывода. Тогда-то эта фича является ключом к успеху.
Предположим, вы хотите создать файл журнала в системном каталоге "/var/log", недоступном для записи обычным пользователям.
Вы добавляете sudo, чтобы получить привилегии и создать файл журнала, но команда загадочным образом не исполняется:
$ sudo echo "New log file" > /var/log/custom.log
bash: /var/log/custom.log: Permission denied
Минуту, команда sudo должна дать разрешение на создание любого файла в любом месте. Как что-то может пойти не так?
Почему sudo даже не запрашивает пароль? Ответ: потому что sudo вообще не запускалась.
Вы применили sudo к команде echo, но не к перенаправлению вывода, которое запустилось первым и провалилось.
Опишем процесс пошагово:
1) вы нажали клавишу Enter;
2) оболочка начала вычислять всю команду, включая перенаправление;
3) оболочка попыталась создать файл custom.log в защищенном каталоге "/var/log";
У нас не было разрешения на запись в "/var/log", поэтому оболочка сообщила, что в доступе отказано (Permission denied).
Чтобы решить эту проблему, нужно сообщить оболочке:
«Выполни всю команду, включая перенаправление вывода, от имени суперпользователя».
Это именно та ситуация, которую так хорошо решает "bash -c".
Создайте команду, которую вы хотите запустить, в виде строки и передайте ее в качестве аргумента для "sudo bash -c":
$ sudo bash -c 'echo "New log file" > /var/log/custom.log'
[sudo] password for smith: xxxxxxxx
$ cat /var/log/custom.log
New log file
На этот раз мы запустили от имени суперпользователя bash, а не просто echo.
По итогу, bash выполнит всю строку как команду. Перенаправление проходит успешно.
Помните о "bash -c", когда sudo сочетается с перенаправлением.
LinuxCamp
👍45🔥16⚡3❤🔥1❤1😁1
Явные подоболочки
Подоболочка - копия родительской оболочки, со всеми ее локальными алиасами, функциями, переменными и т.д.
С дочерними оболочками так не работает - тот же алиас мы должны определить в конфиге, иначе она его не сможет использовать.
Подстановка команд, которую мы рассматривали, отрабатывает в подоболочке и возвращает вывод.
Бывают случаи, когда нам передавать вывод никуда не требуется, но и текущую оболочку трогать не хочется. Вот тут-то и можно явно создать подоболочку и в ней выполнить, что надо.
Для этого просто заключим команду в круглые скобки:
Как видим, первая команда выполнилась в подоболочке и не поменяла текущую рабочую директорию => нам не нужно повторно вызывать cd.
Заключать в скобки можно и часть комбинированной команды. Типичным примером является конвейер.
Предположим, нам нужно через команду tar извлечь файлы из архива в определенный каталог. Можно выполнить задачу несколькими способами:
1) изи - использовать флаг "-С" c указанием путь:
2) хардкор - передать tar-данные в подоболочку, которая зайдет в нужный каталог и выполнит архивирование из стандартного вывода (STDOUT):
Сам я базово использую подоболочку, когда нужно, не меняя рабочий каталог, собрать бинарные пакеты и посмотреть на их список:
Раньше приходилось держать доп. терминал, по сути, для 1 примитивной задачи)
LinuxCamp
Подоболочка - копия родительской оболочки, со всеми ее локальными алиасами, функциями, переменными и т.д.
С дочерними оболочками так не работает - тот же алиас мы должны определить в конфиге, иначе она его не сможет использовать.
Подстановка команд, которую мы рассматривали, отрабатывает в подоболочке и возвращает вывод.
Бывают случаи, когда нам передавать вывод никуда не требуется, но и текущую оболочку трогать не хочется. Вот тут-то и можно явно создать подоболочку и в ней выполнить, что надо.
Для этого просто заключим команду в круглые скобки:
$ (cd /usr/local && ls)
bin etc games lib man sbin share
$ pwd
/home/smith
Как видим, первая команда выполнилась в подоболочке и не поменяла текущую рабочую директорию => нам не нужно повторно вызывать cd.
Заключать в скобки можно и часть комбинированной команды. Типичным примером является конвейер.
Предположим, нам нужно через команду tar извлечь файлы из архива в определенный каталог. Можно выполнить задачу несколькими способами:
1) изи - использовать флаг "-С" c указанием путь:
$ tar -xzf package.tar.gz -C ./extr
2) хардкор - передать tar-данные в подоболочку, которая зайдет в нужный каталог и выполнит архивирование из стандартного вывода (STDOUT):
cat package.tar.gz | (cd ./extr && tar xzvf -)
Сам я базово использую подоболочку, когда нужно, не меняя рабочий каталог, собрать бинарные пакеты и посмотреть на их список:
$ dpkg-buildpackage -b -us -uc && (cd ..; ls -l)
Раньше приходилось держать доп. терминал, по сути, для 1 примитивной задачи)
LinuxCamp
👍28🔥16❤🔥3
Запускаем чат LinuxCamp
Нас уже немало набежало и пришло время укреплять комьюнити)
Чат - место, где мы будем вести оживленное общение, помогать друг другу решать задачи по администрированию/разработке, отвечать на вопросы и делиться интересными новостями.
Если вы хотите окружить себя единомышленниками, перенимать опыт и делиться им, welcome в LinuxCamp | Chat.
Нас уже немало набежало и пришло время укреплять комьюнити)
Чат - место, где мы будем вести оживленное общение, помогать друг другу решать задачи по администрированию/разработке, отвечать на вопросы и делиться интересными новостями.
Если вы хотите окружить себя единомышленниками, перенимать опыт и делиться им, welcome в LinuxCamp | Chat.
👍17❤🔥13✍4👎1
1000 & 1 способ: задача
Данная рубрика отражает возможность в Linux выполнить одну и ту же задачу "1000 & 1" изощренным способом.
Суть следующая: я даю задачку на подумать, вы пишите свои варианты решения в комменты, после чего я демонстрирую и объясняю способ, с которым сам работал.
Задача: наиболее интересно, используя команду/команды Bash, создать в одном каталоге 10 файлов "file1.txt, file2.txt ..." и заполнить их текстом названия:
LinuxCamp
Данная рубрика отражает возможность в Linux выполнить одну и ту же задачу "1000 & 1" изощренным способом.
Суть следующая: я даю задачку на подумать, вы пишите свои варианты решения в комменты, после чего я демонстрирую и объясняю способ, с которым сам работал.
Задача: наиболее интересно, используя команду/команды Bash, создать в одном каталоге 10 файлов "file1.txt, file2.txt ..." и заполнить их текстом названия:
$ ls
file10.txt file1.txt file2.txt file3.txt file4.txt file5.txt file6.txt file7.txt file8.txt file9.txt
$ cat file9.txt
file9.txt
LinuxCamp
❤🔥16👍8🔥7✍4❤1
1000 & 1 способ: решение
И так, было интересно посмотреть на ваши варианты, один из них даже пробил то, о чем пойдет речь.
Возможно, способ не самый минималистичный, но мне понравился используемый стек)
Сразу не пугайтесь, все разберем:
1) seq 1 10 - генерирует последовательность чисел 1-10. Каждое число будет выведено в новой строке:
2) конвейер '|' - используется для того, чтобы команда xargs получила на вход (STDIN) вывод (STDOUT) предыдущей команды seq.
В результате xargs будет работать с последовательностью 1-10;
3) "xargs -I{}" - утилита xargs позволяет выполнять произвольную команду для одного либо нескольких входных значений. В данном случае входные значения передаются через конвейер.
Мы детально ее разберем отдельно. Пока вам нужно знать только то, что xargs выполнит "bash -c" для каждого элемента от 1 до 10.
"-I{}" позволяет определить место входных данных в сгенерированной команде. По умолчанию они идут в конец. Вместо "{}" может быть что угодно. Это, своего рода, шаблон.
В результате каждый элемент 1-10 будет подставлен в нужное нам место внутри команды:
4) "bash -c" - ну тут-то вы уже подкованы).
Если коротко, таким образом мы запускаем дочернюю оболочку и выполняем в ней команду.
Без доп. оболочки тут обойтись не получится, т.к. для перенаправления xargs не выполнит подстановку по шаблону.
Вернее, '>' вообще не будет частью xargs и отработает в первую очередь, еще до самой команды:
5) "echo \"file{}.txt\" > file{}.txt" - строка, которую bash выполнит для каждого значения от 1 до 10 ({}).
"echo \"file{}.txt\" > file{}.txt" - записывает текст fileX.txt в файл fileX.txt. Сам файл создается при перенаправлении вывода, которое мы разбирали тут.
\"\" - экранирование символов, которое необходимо, чтобы избежать разрыва, т.к. строка команды также находится внутри двойных кавычек.
Обратный слэш сообщает bash, что кавычки - это часть текста, а не завершающий символ;
LinuxCamp
И так, было интересно посмотреть на ваши варианты, один из них даже пробил то, о чем пойдет речь.
Возможно, способ не самый минималистичный, но мне понравился используемый стек)
Сразу не пугайтесь, все разберем:
$ seq 1 10 | xargs -I{} bash -c "echo \"file{}.txt\" > file{}.txt"
1) seq 1 10 - генерирует последовательность чисел 1-10. Каждое число будет выведено в новой строке:
$ seq 1 10
1
2
3
...
2) конвейер '|' - используется для того, чтобы команда xargs получила на вход (STDIN) вывод (STDOUT) предыдущей команды seq.
В результате xargs будет работать с последовательностью 1-10;
3) "xargs -I{}" - утилита xargs позволяет выполнять произвольную команду для одного либо нескольких входных значений. В данном случае входные значения передаются через конвейер.
Мы детально ее разберем отдельно. Пока вам нужно знать только то, что xargs выполнит "bash -c" для каждого элемента от 1 до 10.
"-I{}" позволяет определить место входных данных в сгенерированной команде. По умолчанию они идут в конец. Вместо "{}" может быть что угодно. Это, своего рода, шаблон.
В результате каждый элемент 1-10 будет подставлен в нужное нам место внутри команды:
$ seq 1 10 | xargs -I{} echo "file{}.txt"
file1.txt
file2.txt
file3.txt
4) "bash -c" - ну тут-то вы уже подкованы).
Если коротко, таким образом мы запускаем дочернюю оболочку и выполняем в ней команду.
Без доп. оболочки тут обойтись не получится, т.к. для перенаправления xargs не выполнит подстановку по шаблону.
Вернее, '>' вообще не будет частью xargs и отработает в первую очередь, еще до самой команды:
$ seq 10 | xargs -I{} echoo file{}.txt > file{}.txt
xargs: echoo: No such file or directory
$ ls
file{}.txt
5) "echo \"file{}.txt\" > file{}.txt" - строка, которую bash выполнит для каждого значения от 1 до 10 ({}).
"echo \"file{}.txt\" > file{}.txt" - записывает текст fileX.txt в файл fileX.txt. Сам файл создается при перенаправлении вывода, которое мы разбирали тут.
\"\" - экранирование символов, которое необходимо, чтобы избежать разрыва, т.к. строка команды также находится внутри двойных кавычек.
Обратный слэш сообщает bash, что кавычки - это часть текста, а не завершающий символ;
LinuxCamp
👍36🔥15❤7❤🔥1
Автоматизация задач с xargs
Многие пользователи Linux никогда не слышали о команде xargs, хотя это мощный инструмент для автоматизации задач и запуска команд с разными аргументами.
Утилита обрабатывает входные данные из стандартного потока ввода (STDIN). Они могут туда поступать либо напрямую от пользователя либо от сторонних команд через конвейер '|'.
Рассмотрим простой пример. Предположим, вы находитесь в каталоге с тремя файлами:
Передадим данный список в xargs, чтобы он служил входными данными, и "wc -l" в качестве шаблона команды:
В результате xargs применил шаблон команды "wc -l" к каждому файлу для подсчета строк.
Недостаток примера заключается в том, что xargs тут-то и не требуется, можно обойтись сопоставлением файлов с шаблоном:
Зачем тогда использовать xargs?
Ее мощь становится очевидной, когда входные строки немного сложнее.
Предположим, вы хотите обойти дерево каталогов и посчитать количество строк во всех python скриптах с именами, оканчивающимися на ".py".
Такой список путей к файлам легко создать с помощью команды find:
Теперь xargs может применить шаблон команды к каждому файлу:
Комбинируя find и xargs, можно дать возможность любой команде выполняться с обходом всей файловой системы, затрагивая только те ресурсы, которые соответствуют критериям.
Команда xargs имеет множество опций. Рассмотрим наиболее интересные "-n", "-I" и "-0".
1. Параметр "-n" указывает то количество аргументов, которое будет передано на 1 выполнение команды:
Во втором случае, команда echo выполнится 2 раза - по вызову на аргумент.
2. Параметр "-I" определяет место входных строк в команде. По умолчанию они добавляются в конец, но вы можете настроить их отображение в другом месте.
После "-I" введите любую строку, и она станет прототипом, указывающим, куда следует вставлять аргументы:
Обратите внимание, что "-I" ограничивает xargs одной входной строкой на команду.
Это значит, что если входной поток передается "сплошняком", его нужно разбить на строки, чтобы подстановка отработала для каждого элемента, иначе весь поток будет служить аргументом.
3. Параметр "-0" использует символ "\0" в качестве разделителя данных, вместо "\n" или пробела.
Часто используется при объединении find и xargs, т.к., обычно xargs ожидает, что строки будут разделены пробелами.
А если отдельные элементы в строках содержат дополнительные пробелы, например имена файлов?
По умолчанию команда будет рассматривать их как разделители ввода и, в результате, передавать неполные строки команде в качестве аргументов.
Например, если входные данные включают "file num 1.txt", xargs обработает все по отдельности и, вероятно, выведет ошибку:
Как разделить входные строки нулями вместо символов новой строки? К счастью, у команды find есть возможность сделать это с помощью флага "-print0":
Теперь xargs будет искать разделитель "\0" и по нему сформирует корректный список аргументов для "wc -l":
LinuxCamp
Многие пользователи Linux никогда не слышали о команде xargs, хотя это мощный инструмент для автоматизации задач и запуска команд с разными аргументами.
Утилита обрабатывает входные данные из стандартного потока ввода (STDIN). Они могут туда поступать либо напрямую от пользователя либо от сторонних команд через конвейер '|'.
Рассмотрим простой пример. Предположим, вы находитесь в каталоге с тремя файлами:
$ ls -1
file1.txt
file2.txt
file3.txt
Передадим данный список в xargs, чтобы он служил входными данными, и "wc -l" в качестве шаблона команды:
$ ls -1 | xargs wc -l
3 file1.txt
4 file2.txt
1 file3.txt
8 total
В результате xargs применил шаблон команды "wc -l" к каждому файлу для подсчета строк.
Недостаток примера заключается в том, что xargs тут-то и не требуется, можно обойтись сопоставлением файлов с шаблоном:
$ wc -l *
3 file1.txt
4 file2.txt
...
Зачем тогда использовать xargs?
Ее мощь становится очевидной, когда входные строки немного сложнее.
Предположим, вы хотите обойти дерево каталогов и посчитать количество строк во всех python скриптах с именами, оканчивающимися на ".py".
Такой список путей к файлам легко создать с помощью команды find:
$ find . -type f -name \*.py -print
/usr/lib/bup/bup/options.py
/usr/lib/bup/bup/xstat.py
...
Теперь xargs может применить шаблон команды к каждому файлу:
$ find / -type f -name \*.py -print | xargs wc -l
292 /usr/lib/bup/bup/options.py
112 /usr/lib/bup/bup/xstat.py
...
Комбинируя find и xargs, можно дать возможность любой команде выполняться с обходом всей файловой системы, затрагивая только те ресурсы, которые соответствуют критериям.
Команда xargs имеет множество опций. Рассмотрим наиболее интересные "-n", "-I" и "-0".
1. Параметр "-n" указывает то количество аргументов, которое будет передано на 1 выполнение команды:
$ ls | xargs echo
file1.txt file2.txt
$ ls | xargs -n1 echo
file1.txt
file2.txt
Во втором случае, команда echo выполнится 2 раза - по вызову на аргумент.
2. Параметр "-I" определяет место входных строк в команде. По умолчанию они добавляются в конец, но вы можете настроить их отображение в другом месте.
После "-I" введите любую строку, и она станет прототипом, указывающим, куда следует вставлять аргументы:
$ ls | xargs -I XYZ echo XYZ is OK
file1.txt is OK
file2.txt is OK
Обратите внимание, что "-I" ограничивает xargs одной входной строкой на команду.
Это значит, что если входной поток передается "сплошняком", его нужно разбить на строки, чтобы подстановка отработала для каждого элемента, иначе весь поток будет служить аргументом.
3. Параметр "-0" использует символ "\0" в качестве разделителя данных, вместо "\n" или пробела.
Часто используется при объединении find и xargs, т.к., обычно xargs ожидает, что строки будут разделены пробелами.
А если отдельные элементы в строках содержат дополнительные пробелы, например имена файлов?
По умолчанию команда будет рассматривать их как разделители ввода и, в результате, передавать неполные строки команде в качестве аргументов.
Например, если входные данные включают "file num 1.txt", xargs обработает все по отдельности и, вероятно, выведет ошибку:
$ find ./ -type f -name \*.txt -print | xargs wc -l
wc: ./file: No such file or directory
wc: num: No such file or directory
wc: 1.txt: No such file or directory
Как разделить входные строки нулями вместо символов новой строки? К счастью, у команды find есть возможность сделать это с помощью флага "-print0":
$ find ./ -name \*.txt -print0
./file1.txt./file num 1.txt
Теперь xargs будет искать разделитель "\0" и по нему сформирует корректный список аргументов для "wc -l":
$ find ./ -name \*.txt -print0 | xargs -0 wc -l
0 ./file1.txt
0 ./file num 1.txt
0 total
LinuxCamp
👍52🔥14❤🔥6
Xargs и флаги: -L, -t
Прошлый пост в общих чертах рассказал нам об утилите xargs и ее возможностях. Сегодня уделим дополнительное внимание 2 ее флагам, которые вполне могут пригодиться.
1. И так, начнем с "-t". Флаг позволяет нам наглядно увидеть то, как xargs вызывает команду и какие аргументы ей передает.
Его полезно использовать для лучшего понимания принципа работы утилиты.
В следующем примере мы найдем все файлы с расширением .txt, разобьем список аргументов по разделителю "\0" и подсчитаем количество строк для каждого элемента:
Сразу после выполнения нам выведется строка с общим видом выполняемой команды:
Можем убедиться в том, что "wc -l" выполнился 1 раз с вот таким длинным списком аргументов. Далее будем использовать "-t" для просмотра и разбора вызовов.
2. Переходим к "-L". Эта вещь позволяет нам указать, сколько строк будет передано на каждый вызов команды.
Тут уточню, что указывается количество строк, а не аргументов. В 1 строке может быть несколько разделённых параметров:
Тогда все просто - xargs передаст команда столько аргументов, сколько найдет в каждой строке:
Полезный пример, матайте на ус. Используется, когда нужно, например, поменять расширение для нескольких файлов:
Давайте разберем по частям:
Вывод команды ls передается на вход для sed, после чего тот печатает изначальные строки и те, в которых изменено расширение.
В следующей части вывод sed передается команде xargs, которая выполняет mv по 1 разу для каждых 2 строк. Внедрим параметр "-t" для наглядности:
Хммм, а если у нас есть файлы, имена которых состоят из нескольких слов, разделенных пробелами... Решается по щелчку:
Команда 'tr "\n" "\0"' заменяет символы, а флаг "-0" теперь воспринимает за разделитель только символ "\0".
LinuxCamp
Прошлый пост в общих чертах рассказал нам об утилите xargs и ее возможностях. Сегодня уделим дополнительное внимание 2 ее флагам, которые вполне могут пригодиться.
1. И так, начнем с "-t". Флаг позволяет нам наглядно увидеть то, как xargs вызывает команду и какие аргументы ей передает.
Его полезно использовать для лучшего понимания принципа работы утилиты.
В следующем примере мы найдем все файлы с расширением .txt, разобьем список аргументов по разделителю "\0" и подсчитаем количество строк для каждого элемента:
$ find ./ -name \*.txt -print0 | xargs -0 -t wc -l
Сразу после выполнения нам выведется строка с общим видом выполняемой команды:
wc -l ./file1.txt ./file2.txt './test document.txt'
3 ./file1.txt
10 ./file2.txt
15 ./test document.txt
Можем убедиться в том, что "wc -l" выполнился 1 раз с вот таким длинным списком аргументов. Далее будем использовать "-t" для просмотра и разбора вызовов.
2. Переходим к "-L". Эта вещь позволяет нам указать, сколько строк будет передано на каждый вызов команды.
Тут уточню, что указывается количество строк, а не аргументов. В 1 строке может быть несколько разделённых параметров:
$ ls | paste - -
file1.sh file2sh
file3.sh file4.sh
Тогда все просто - xargs передаст команда столько аргументов, сколько найдет в каждой строке:
$ ls | paste - - | xargs -t -L1 wc -l
wc -l file1.sh file2.sh
...
wc -l file3.sh file4.sh
Полезный пример, матайте на ус. Используется, когда нужно, например, поменять расширение для нескольких файлов:
$ ls | sed -e "p;s/.txt$/.sh/" | xargs -L2 mv
Давайте разберем по частям:
$ ls | sed -e "p;s/.txt$/.sh/"
file1.txt
file1.sh
file2.txt
file2.sh
Вывод команды ls передается на вход для sed, после чего тот печатает изначальные строки и те, в которых изменено расширение.
В следующей части вывод sed передается команде xargs, которая выполняет mv по 1 разу для каждых 2 строк. Внедрим параметр "-t" для наглядности:
$ ... | xargs -L2 -t mv
mv file1.txt file1.sh
mv file2.txt file2.sh
Хммм, а если у нас есть файлы, имена которых состоят из нескольких слов, разделенных пробелами... Решается по щелчку:
$ ls | sed -e "p;s/.txt$/.sh/" | tr "\n" "\0" | xargs -L2 -t -0 mv
Команда 'tr "\n" "\0"' заменяет символы, а флаг "-0" теперь воспринимает за разделитель только символ "\0".
LinuxCamp
🔥21👍10✍7
Xargs в действии
Прошлые 2 поста дали нам достаточно информации про утилиту xargs, рассмотрим-ка несколько практических примеров.
Удаление файлов [1]
Одна из самых частых ситуаций использования xargs — удаление группы файлов, найденных при помощи find:
Как можете заметить, тут мы обработали кейс, когда в именах содеражатся пробелы: мы через -print0 указали "\0" разделитель для строк, сформированных командой find и определили "\0" разделитель, по которому xargs будет формировать аргументы.
Удаление файлов [2]
Также можно удалить все файлы, кроме тех, которые подходят под определенный шаблон:
Тут мы рекурсивно удаляем все файлы, кроме ".sh" скриптов.
Переименование файлов
С помощью xargs можно осуществлять массовое переименование файлов.
Представим себе, что у нас есть группа файлов с расширением ".txt", и нам нужно произвести замену на ".sql".
Выполнить задачу можно при помощи xargs и потокового текстового редактора sed:
Можно еще одним интересным способом поменять расширение файлам, используя cut:
Изменение прав
С помощью xargs можно ускорить процесс смены прав на файлы и каталоги для пользователя/группы:
Удаление старых файлов
Вот так, например, можно удалить временные файлы, созданные более 7 дней назад:
Архивация файлов
Иногда может потребоваться вычленить группу файлов по "первичному признаку" и запихнуть все в архив. Следующий пример работает с ".png" файлами:
Форматирование вывода
Если необходимо для дальнейшего оперирования данными отформатировать вывод в строку, можно использовать xargs. Например, выведем список всех пользователей системы:
Команда sort выведет все в столбик, xargs, без параметров, передаст весь вывод команде echo, которая отобразит данные с пробелом, в качестве разделителя:
LinuxCamp
Прошлые 2 поста дали нам достаточно информации про утилиту xargs, рассмотрим-ка несколько практических примеров.
Удаление файлов [1]
Одна из самых частых ситуаций использования xargs — удаление группы файлов, найденных при помощи find:
$ find . -type f -name "*.sh" -print0 | xargs -0 rm -rf
Как можете заметить, тут мы обработали кейс, когда в именах содеражатся пробелы: мы через -print0 указали "\0" разделитель для строк, сформированных командой find и определили "\0" разделитель, по которому xargs будет формировать аргументы.
Удаление файлов [2]
Также можно удалить все файлы, кроме тех, которые подходят под определенный шаблон:
$ find . -type f -not -name '*.sh' -print0 | xargs -0 rm -rf
Тут мы рекурсивно удаляем все файлы, кроме ".sh" скриптов.
Переименование файлов
С помощью xargs можно осуществлять массовое переименование файлов.
Представим себе, что у нас есть группа файлов с расширением ".txt", и нам нужно произвести замену на ".sql".
Выполнить задачу можно при помощи xargs и потокового текстового редактора sed:
$ ls | sed -e "p;s/.txt$/.sql/" | xargs -L2 mv
Можно еще одним интересным способом поменять расширение файлам, используя cut:
ls | cut -d. -f1 | xargs -I{} mv {}.txt {}.sh
Изменение прав
С помощью xargs можно ускорить процесс смены прав на файлы и каталоги для пользователя/группы:
$ sudo bash -c "find ./ -group root -print | xargs chgrp xoadmin"
Удаление старых файлов
Вот так, например, можно удалить временные файлы, созданные более 7 дней назад:
$ find /tmp -type f -name '*' -mtime +7 -print0 | xargs -0 rm -f
Архивация файлов
Иногда может потребоваться вычленить группу файлов по "первичному признаку" и запихнуть все в архив. Следующий пример работает с ".png" файлами:
$ find ./ -name "*.png" -type f -print0 | xargs -0 tar -cvzf images.tar.gz
Форматирование вывода
Если необходимо для дальнейшего оперирования данными отформатировать вывод в строку, можно использовать xargs. Например, выведем список всех пользователей системы:
$ cut -d: -f1 < /etc/passwd | sort | xargs
Команда sort выведет все в столбик, xargs, без параметров, передаст весь вывод команде echo, которая отобразит данные с пробелом, в качестве разделителя:
xoadmin backup bin ...
LinuxCamp
👍26✍7❤🔥6❤4
Раскрываем завесу тайн над устройствами
Для многих пользователей Linux долгое время может быть неясна суть устройств, каталогов dev/sys и различий между ними. Хорошо бы в этом немного разбираться, т.к. иногда приходится работать с дисками, разделами, tty, pty.
Что еще за dev?
В каталоге dev находятся файлы, которые являются интерфейсом взаимодействия ядра с физическими (принтер, камера, SSD и т.д.) и виртуальными (null, urandom, tty и т.д.) устройствами, подключенными к системе и готовыми к работе.
Сами файлы драйверами не являются, при работе с ними ядро отказывается от своих обычных файловых операций и использует необходимые драйвера.
Устройства бывают разных типов:
Обратите внимание на первый символ каждой строки. Если он входит в перечисление: b (block), c (character), p (pipe) или s (socket), то файл является устройством.
Сейчас кратко рассмотрим типы, без излишнего углубления, т.к. знать тут все на начальных порах необязательно.
Блочные устройства
Доступ к данным блочного устройства происходит фиксированными частями определенного размера. Устройство sda1 в приведенном примере - это дисковое устройство, которое является типом блочного устройства.
Обычно устройства данного типа характеризуются возможностью хостить файловую систему: HDD, SSD, USB накопители.
Символьные устройства
К символьным устройствам можно обращаться как к потокам данных. Чтение и запись происходит посимвольно либо небольшими блоками за раз. Примерами устройств являются: принтер, мышь, клавиатура, tty, null.
Именованный конвейер
По структуре такой же, как символьное устройство, но с другим процессом на конце потока ввода-вывода вместо драйвера ядра.
Фактически - это обыкновенный pipe |, у которого есть имя, которое можно указывать всюду, где требуется файл.
Сокет
Специальный интерфейс для межпроцессной связи. Они позволяют обмениваться данными через сетевые соединения или внутри одного компьютера (с помощью Unix-сокетов).
Номера major и minor
К блочным и символьным устройствам применимы специальные номера major и minor, которые ядро использует для идентификации:
Major (8) говорит о том, какой драйвер использовать, minor (1) - описывает номер устройства, для которого используется драйвер, подвязанный к номеру major.
Скажем, HDD может быть разбит на несколько разделов, каждый из которых будет иметь отдельный номер minor и единый major, т.к. один и тот же драйвер используется для каждого раздела.
Файлы в каталоге dev не являются постоянными, они создаются либо в момент старта системы либо при подключении и определении устройства. Создаются демонами: udevd или mdevd. Как раз эти программы отвечают за определение устройства и подгрузку соответсвующих драйверов.
Драйвер - программа, которая позволяет нашей ОС общаться с оборудованием. Представлен он может быть, например, динамически подгружаемым модулем ядра либо его статической частью. Подключили мышку, нужен драйвер, который позволить с ней работать.
LinuxCamp
Для многих пользователей Linux долгое время может быть неясна суть устройств, каталогов dev/sys и различий между ними. Хорошо бы в этом немного разбираться, т.к. иногда приходится работать с дисками, разделами, tty, pty.
Что еще за dev?
В каталоге dev находятся файлы, которые являются интерфейсом взаимодействия ядра с физическими (принтер, камера, SSD и т.д.) и виртуальными (null, urandom, tty и т.д.) устройствами, подключенными к системе и готовыми к работе.
Сами файлы драйверами не являются, при работе с ними ядро отказывается от своих обычных файловых операций и использует необходимые драйвера.
Устройства бывают разных типов:
$ ls -l
brw-rw---- 1 root disk 8, 1 Sep 6 08:37 sda1
crw-rw-rw- 1 root root 1, 3 Sep 6 08:37 null
prw-r--r-- 1 root root 0 Mar 3 19:17 fdata
srw-rw-rw- 1 root root 0 Dec 18 07:43 log
Обратите внимание на первый символ каждой строки. Если он входит в перечисление: b (block), c (character), p (pipe) или s (socket), то файл является устройством.
Сейчас кратко рассмотрим типы, без излишнего углубления, т.к. знать тут все на начальных порах необязательно.
Блочные устройства
Доступ к данным блочного устройства происходит фиксированными частями определенного размера. Устройство sda1 в приведенном примере - это дисковое устройство, которое является типом блочного устройства.
Обычно устройства данного типа характеризуются возможностью хостить файловую систему: HDD, SSD, USB накопители.
Символьные устройства
К символьным устройствам можно обращаться как к потокам данных. Чтение и запись происходит посимвольно либо небольшими блоками за раз. Примерами устройств являются: принтер, мышь, клавиатура, tty, null.
Именованный конвейер
По структуре такой же, как символьное устройство, но с другим процессом на конце потока ввода-вывода вместо драйвера ядра.
Фактически - это обыкновенный pipe |, у которого есть имя, которое можно указывать всюду, где требуется файл.
Сокет
Специальный интерфейс для межпроцессной связи. Они позволяют обмениваться данными через сетевые соединения или внутри одного компьютера (с помощью Unix-сокетов).
Номера major и minor
К блочным и символьным устройствам применимы специальные номера major и minor, которые ядро использует для идентификации:
8, 1 Sep 6 08:37 sda1
Major (8) говорит о том, какой драйвер использовать, minor (1) - описывает номер устройства, для которого используется драйвер, подвязанный к номеру major.
Скажем, HDD может быть разбит на несколько разделов, каждый из которых будет иметь отдельный номер minor и единый major, т.к. один и тот же драйвер используется для каждого раздела.
Файлы в каталоге dev не являются постоянными, они создаются либо в момент старта системы либо при подключении и определении устройства. Создаются демонами: udevd или mdevd. Как раз эти программы отвечают за определение устройства и подгрузку соответсвующих драйверов.
Драйвер - программа, которая позволяет нашей ОС общаться с оборудованием. Представлен он может быть, например, динамически подгружаемым модулем ядра либо его статической частью. Подключили мышку, нужен драйвер, который позволить с ней работать.
LinuxCamp
1👍47🔥13❤🔥3❤2
Не самый стандартный способ использовать syslog
Расскажу историю о том, как очередная хотелка заказчика заставила меня немного под другим углом взглянуть на syslog. И так, какой самый привычный вам способ обращаться к файлу /var/log/syslog?
Если вы штатный пользователь, то, вероятно, хотите провести мониторинг логов и выяснить, где что-то пошло не так. Для этого вы пойдете искать сообщения от "подозреваемого" сервиса.
Если вы разработчик, то можете захотеть направлять туда отладочную информацию. А-ля, подключение к VPN прошло успешно, сертификат принят и т.д. Если вы пишите демон, за которым не может быть закреплен терминал, то вариант с syslog - вынужденная мера.
Так вот, пришел заказчик и говорит: "Нашим пользователям абсолютно неясна причина, по которой подключение к VPN было отклонено. То ли это ошибка в конфигах, то ли сертификат просрочен. Хочется, чтобы на рабочий стол выводилось уведомление с подробным описанием ошибки".
Принято, сделаем. Первое, что пришло в голову - использовать libnotify. Библиотека позволяет через код собирать уведомления и направлять их специальному демону (зависит от окружения) для вывода. Утилита "notify-send" демонстрирует работу API:
Выяснить, какой процесс выступает в роли демона для уведомлений, можно следующим образом:
Короче говоря, подход этот оказался нерабочим, т.к. коды ошибок формировал демон вне пользовательской сессии, а libnotify требовал в окружении процесса переменную DBUS_SESSION_BUS_ADDRESS, которая отсутствовала...
Частично о проблеме можно почитать тут.
Дальше либо добавлять новые коды ошибок, патчить 3 утилиты "strongswan -> network manager -> nm-applet" и выводить сообщения через nm-applet, либо использовать сторонний ПОЛЬЗОВАТЕЛЬСКИЙ сервис, который бы отслеживал логи и по ним собирал уведомления.
Благо, в дистрах обычно присутствуем подсистема событий, которая работает совместно с демоном syslog-ng и позволяет реагировать на определенные логи.
В результате, задача решилась следующим образом:
1) проработан ряд конфигов, по которым производился парсинг сообщений syslog и настройка уведомлений;
2) в код strongswan добавлен вывод отладочной информации (в централизованном формате) в файл /var/log/syslog:
3) в правила "роспакоуки" deb пакета добавлены инструкции установки конфигов в системные директории;
С высоты текущего полета не сказал бы, что решение супер гибкое и легко масштабируемое, но правки оказались минимальными и безопасными, что особенно важно при работе с таким софтом, как strongswan.
LinuxCamp
Расскажу историю о том, как очередная хотелка заказчика заставила меня немного под другим углом взглянуть на syslog. И так, какой самый привычный вам способ обращаться к файлу /var/log/syslog?
Если вы штатный пользователь, то, вероятно, хотите провести мониторинг логов и выяснить, где что-то пошло не так. Для этого вы пойдете искать сообщения от "подозреваемого" сервиса.
Если вы разработчик, то можете захотеть направлять туда отладочную информацию. А-ля, подключение к VPN прошло успешно, сертификат принят и т.д. Если вы пишите демон, за которым не может быть закреплен терминал, то вариант с syslog - вынужденная мера.
Так вот, пришел заказчик и говорит: "Нашим пользователям абсолютно неясна причина, по которой подключение к VPN было отклонено. То ли это ошибка в конфигах, то ли сертификат просрочен. Хочется, чтобы на рабочий стол выводилось уведомление с подробным описанием ошибки".
Принято, сделаем. Первое, что пришло в голову - использовать libnotify. Библиотека позволяет через код собирать уведомления и направлять их специальному демону (зависит от окружения) для вывода. Утилита "notify-send" демонстрирует работу API:
$ notify-send header body
Выяснить, какой процесс выступает в роли демона для уведомлений, можно следующим образом:
$ NOTIFD_ID=$(qdbus org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.GetConnectionUnixProcessID org.freedesktop.Notifications)
$ ps aux | grep $NOTIFD_ID
Короче говоря, подход этот оказался нерабочим, т.к. коды ошибок формировал демон вне пользовательской сессии, а libnotify требовал в окружении процесса переменную DBUS_SESSION_BUS_ADDRESS, которая отсутствовала...
Частично о проблеме можно почитать тут.
Дальше либо добавлять новые коды ошибок, патчить 3 утилиты "strongswan -> network manager -> nm-applet" и выводить сообщения через nm-applet, либо использовать сторонний ПОЛЬЗОВАТЕЛЬСКИЙ сервис, который бы отслеживал логи и по ним собирал уведомления.
Благо, в дистрах обычно присутствуем подсистема событий, которая работает совместно с демоном syslog-ng и позволяет реагировать на определенные логи.
В результате, задача решилась следующим образом:
1) проработан ряд конфигов, по которым производился парсинг сообщений syslog и настройка уведомлений;
2) в код strongswan добавлен вывод отладочной информации (в централизованном формате) в файл /var/log/syslog:
DBG1(DBG_CFG, "type=STRONGSWAN action='CONNECTION ERROR REPORT' body='%s'", "Не удалось загрузить сертификат клиента");
3) в правила "роспакоуки" deb пакета добавлены инструкции установки конфигов в системные директории;
С высоты текущего полета не сказал бы, что решение супер гибкое и легко масштабируемое, но правки оказались минимальными и безопасными, что особенно важно при работе с таким софтом, как strongswan.
LinuxCamp
🔥24👍13❤🔥3🤔3
Что такое /dev/null и почему туда направляют данные?
Если вы активно работаете в командной строке, то, вероятно, использовали файл /dev/null для следующих целей:
1) убрать из вывода всю ненужную инфу (предупреждения, ошибки и т.д.):
2) передать утилите пустой ресурс в качестве аргумента. Делаться это может с целью исключения пользовательских и системных конфигов и применения дефолтных настроек на стороне программы:
3) полностью очистить файл:
Окей, принято, а чем является этот самый /dev/null?
В сущности - это cимвольное псевдо-устройство, которое создается на этапе запуска системы и работает с потоками данных:
О типе устройства говорит первый бит режима файла "c (character)".
Ресурс удаляет все записанное в него и возвращает при чтении EOF (End of File). Когда мы взаимодействуем с /dev/null, неявно отрабатывает специальный драйвер ядра, в который и зашита логика.
Если интересно, можно порыться в исходниках с реализацией: drivers/char/mem.c. Код имеет отношение не только к /dev/null, но и к другим символьным устройствам.
Развернем более подробную информацию:
Этот вывод показывает, что файл имеет размер 0 байт, для него выделено 0 блоков на диске, дата создания = дата запуска системы:
Права доступа установлены таким образом, что любой может читать и записывать в него, но никто не может его выполнять:
Поскольку файл не исполняемый, мы не можем использовать конвейер |. Единственный способ — использовать перенаправление файлов ">, >>".
Думаю, этих знаний вам пока будет достаточно для того, чтобы комфортно пользоваться "трюками" этого устройства. До встречи)
LinuxCamp
Если вы активно работаете в командной строке, то, вероятно, использовали файл /dev/null для следующих целей:
1) убрать из вывода всю ненужную инфу (предупреждения, ошибки и т.д.):
$ find / -name "*.conf" 2>/dev/null
2) передать утилите пустой ресурс в качестве аргумента. Делаться это может с целью исключения пользовательских и системных конфигов и применения дефолтных настроек на стороне программы:
$ picom --config /dev/null
3) полностью очистить файл:
$ cat /dev/null > bigfile
Окей, принято, а чем является этот самый /dev/null?
В сущности - это cимвольное псевдо-устройство, которое создается на этапе запуска системы и работает с потоками данных:
$ ls -l
crw-rw-rw- 1 root root 1, 3 Sep 6 08:37 null
О типе устройства говорит первый бит режима файла "c (character)".
Ресурс удаляет все записанное в него и возвращает при чтении EOF (End of File). Когда мы взаимодействуем с /dev/null, неявно отрабатывает специальный драйвер ядра, в который и зашита логика.
Если интересно, можно порыться в исходниках с реализацией: drivers/char/mem.c. Код имеет отношение не только к /dev/null, но и к другим символьным устройствам.
Развернем более подробную информацию:
$ stat /dev/null
File: /dev/null
Size: 0 Blocks: 0 IO Block: 4096 character special file
Access: (0666/crw-rw-rw-) Uid: (0/ root) Gid: (0/ root)
Access: 2025-01-25 14:42:20.101000002 +0300
...
Этот вывод показывает, что файл имеет размер 0 байт, для него выделено 0 блоков на диске, дата создания = дата запуска системы:
$ who -b
system boot 2025-01-25 14:42
Права доступа установлены таким образом, что любой может читать и записывать в него, но никто не может его выполнять:
$ echo hello | /dev/null
-bash2: /dev/null: Permission denied
Поскольку файл не исполняемый, мы не можем использовать конвейер |. Единственный способ — использовать перенаправление файлов ">, >>".
Думаю, этих знаний вам пока будет достаточно для того, чтобы комфортно пользоваться "трюками" этого устройства. До встречи)
LinuxCamp
👍42🔥11❤🔥3❤2