Введение в фоновые команды и задания
Стандартное выполнение команды в оболочке происходит так, что вам требуется ожидать ее завершения для дальнейшего взаимодействия с командной строкой.
Это обычно неэффективно, когда выполнение занимает время и вам не требуется общаться с утилитой через 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
Познаем brace expansion
Продолжаем серию постов по спецсимволам оболочки: (), $(), []. Сегодня говорим про расширение фигурных скобок (brace expansion).
Символы {} позволяют развернуть выражение внутри в последовательность аргументов:
Внутрь скобок может быть добавлен опциональный 3 параметр. С ним выражение {x..y..z} генерирует значения от x до y с шагом z:
Расширение {}, в отличие от команды seq, может создавать последовательность букв:
При желании, можем добавить шаг, например, чтобы выводить символ через 1 в диапазоне от A до P:
Использование перечислений
Если нам не требуется вычисление последовательности, можно поместить внутрь скобок перечисление:
Вариант практического применения данной техники - получение различий между файлами:
Прогерам бывает приходится составлять пачи по результатам команды diff и расширение тут очень кстати - не нужно дважды вводить почти идентичный путь.
Немного отойдем от общего вида паттерна, оставим 1 аргумент и создадим бэкап файла:
Если перед запятой отсутствует значение, подстановка в этом месте пропускается, но вывод, при наличии текста вне {}, выполняется:
Предупреждение: не ставьте пробелы внутри скобок иначе расширение не отработает:
Изменение формата вывода
Как можно заметить из примеров выше, вывод всегда записывается в виде одной строки, разделенной пробелами. Изменить это можно, перенаправив его другим командам, таким как tr:
Теперь можно создать псевдоним, который печатает n букву английского алфавита:
Фигурные скобки vs квадратные
Квадратные скобки — это оператор сопоставления имен файлов с шаблоном. Фигурные, в свою очередь, не имеют к файлам никакого отношения. Они просто просчитывают и возвращают последовательность значений.
К примеру, у нас в каталоге содержится 4 файла:
Используем сопоставление по шаблону в диапазоне от 1 до 9:
Все отработало без ошибок, оболочка нашла файлы, которые подходят под шаблон и передала их в качестве аргументов.
Теперь в этом же диапазоне используем расширение {}:
Оболочка без разбора подставила всю последовательность. Что-то нашлось, что-то нет.
Группировка расширений
Спокойно можно использовать группу символов {} в 1 выражении, чтобы, например, создать несколько файлов с разными расширеними:
Bash берёт каждую букву из первого набора и комбинирует её со всеми вариантами второго.
Либо еще опция - использовать вложенность. Бывает полезно при создании группы подкаталогов:
LinuxCamp
Продолжаем серию постов по спецсимволам оболочки: (), $(), []. Сегодня говорим про расширение фигурных скобок (brace expansion).
Символы {} позволяют развернуть выражение внутри в последовательность аргументов:
$ echo {1..10}
1 2 3 4 5 6 7 8 9 10
$ echo {10..1}
10 9 8 7 6 5 4 3 2 1
Внутрь скобок может быть добавлен опциональный 3 параметр. С ним выражение {x..y..z} генерирует значения от x до y с шагом z:
$ echo {1..501..100}
1 101 201 301 401 501
$ echo {501..1..100}
501 401 301 201 101 1
Расширение {}, в отличие от команды seq, может создавать последовательность букв:
$ echo {A..P}
A B C D E F G H I J K L M N O P
При желании, можем добавить шаг, например, чтобы выводить символ через 1 в диапазоне от A до P:
$ echo {A..P..2}
A C E G I K M O
Использование перечислений
Если нам не требуется вычисление последовательности, можно поместить внутрь скобок перечисление:
$ mkdir ~/Sources/{test1,test2,test3}
Вариант практического применения данной техники - получение различий между файлами:
$ diff {orig,patched}/path/to/prog.c
Прогерам бывает приходится составлять пачи по результатам команды diff и расширение тут очень кстати - не нужно дважды вводить почти идентичный путь.
Немного отойдем от общего вида паттерна, оставим 1 аргумент и создадим бэкап файла:
$ cp -p file.txt{,.bak}
$ ls
file.txt file.txt.bak
Если перед запятой отсутствует значение, подстановка в этом месте пропускается, но вывод, при наличии текста вне {}, выполняется:
$ echo file.txt{,.bak}
file.txt file.txt.bak
Предупреждение: не ставьте пробелы внутри скобок иначе расширение не отработает:
$ echo file{1.. 2}.txt
file{1.. 2}.txt
Изменение формата вывода
Как можно заметить из примеров выше, вывод всегда записывается в виде одной строки, разделенной пробелами. Изменить это можно, перенаправив его другим командам, таким как tr:
$ echo {A..P..2} | tr -d " "
ACEGIKMO
Теперь можно создать псевдоним, который печатает n букву английского алфавита:
$ alias nth="echo {A..Z} | tr -d ' ' | cut -c"
$ nth 10
J
Фигурные скобки vs квадратные
Квадратные скобки — это оператор сопоставления имен файлов с шаблоном. Фигурные, в свою очередь, не имеют к файлам никакого отношения. Они просто просчитывают и возвращают последовательность значений.
К примеру, у нас в каталоге содержится 4 файла:
$ ls
file1.txt file2.txt file3.txt file4.txt
Используем сопоставление по шаблону в диапазоне от 1 до 9:
$ ls file[1-9].txt
file1.txt file2.txt file3.txt file4.txt
Все отработало без ошибок, оболочка нашла файлы, которые подходят под шаблон и передала их в качестве аргументов.
Теперь в этом же диапазоне используем расширение {}:
$ ls file{1..9}.txt
ls: cannot access 'file5.txt': No such file or directory
ls: cannot access 'file6.txt': No such file or directory
...
file1.txt file2.txt file3.txt file4.txt
Оболочка без разбора подставила всю последовательность. Что-то нашлось, что-то нет.
Группировка расширений
Спокойно можно использовать группу символов {} в 1 выражении, чтобы, например, создать несколько файлов с разными расширеними:
$ touch {a,b,c}.{hpp,cpp}
$ ls
a.cpp a.hpp b.cpp b.hpp c.cpp c.hpp
Bash берёт каждую букву из первого набора и комбинирует её со всеми вариантами второго.
Либо еще опция - использовать вложенность. Бывает полезно при создании группы подкаталогов:
$ mkdir -p {source,help{/pages,/yelp,/images}}
$ tree
.
├── help
│ ├── images
│ ├── pages
│ └── yelp
└── source
LinuxCamp
👍55🔥23❤8👎1🤔1💘1
Копирование и вставка "по уму"
Вы наверняка умеете работать с копированием и вставкой через сочетания клавиш: Ctrl + C, Ctrl + V.
Но знаете ли вы, что можете более эффективно обрабатывать содержимое буфера обмена прямо из командной строки?
Буфер обмена — это общее название для блока памяти, в котором временно находится скопированная информация.
Большинство X11 окружений рабочего стола поддерживают два варианта буфера:
1. Системный буфер обмена (clipboard). Когда вы выполняете операции "cut/copy" через горячие клавиши, содержимое попадает в этот буфер. После вставки информация извлекается.
2. Первичный буфер обмена (primary selection). Запись происходит, когда вы мышью выделяете текст в определенных приложениях. Для извлечения используется нажатие на колесо.
Если у кого в наличии только тачпадам, следует одновременно нажать левую и правую кнопки для вставки текста.
Обычно эти буферы не связаны и хранящиеся в них данные не влияют друг на друга. Записываем что-то в clipboard, primary selection остается нетронутым.
Подключение буферов к потокам
В Linux есть команда xclip, которая соединяет X-буферы обмена с потоками stdin и stdout.
Благодаря ей можно заполнять буферы информацией либо извлекать ее через конвейер и перенаправление файла.
По умолчанию команда читает stdout и записывает его в первичный буфер:
Теперь выведем текст в stdout, перенаправим его в файл и передадим команде wc:
Очистим первичный буфер обмена, поместив в него пустую строку:
Параметр "-n" важен, так как в противном случае echo выведет в stdout символ новой строки "\n", который окажется в первичном буфере обмена.
Команда поддерживает явное указание буфера. Чтобы скопировать текст в системный буфер обмена вместо первичного, запустим xclip с параметром "-selection clipboard":
Теперь вы можете либо использовать комбинации клавиш для вывода либо просто флаг "-o".
При необходимости параметры xclip могут быть сокращены "-selection clipboard == -sel c"
Немного практики
Чтобы дополнительно облегчить себе жизнь, можно создать на xclip несколько алиасов:
Теперь, допустим, нам нужно установить определенный deb пакет, предварительно определив его среди общей массы:
Отлично, копируем название в буфер, затем выполняем вставку после целевой команды:
LinuxCamp
Вы наверняка умеете работать с копированием и вставкой через сочетания клавиш: Ctrl + C, Ctrl + V.
Но знаете ли вы, что можете более эффективно обрабатывать содержимое буфера обмена прямо из командной строки?
Буфер обмена — это общее название для блока памяти, в котором временно находится скопированная информация.
Большинство X11 окружений рабочего стола поддерживают два варианта буфера:
1. Системный буфер обмена (clipboard). Когда вы выполняете операции "cut/copy" через горячие клавиши, содержимое попадает в этот буфер. После вставки информация извлекается.
2. Первичный буфер обмена (primary selection). Запись происходит, когда вы мышью выделяете текст в определенных приложениях. Для извлечения используется нажатие на колесо.
Если у кого в наличии только тачпадам, следует одновременно нажать левую и правую кнопки для вставки текста.
Обычно эти буферы не связаны и хранящиеся в них данные не влияют друг на друга. Записываем что-то в clipboard, primary selection остается нетронутым.
Подключение буферов к потокам
В Linux есть команда xclip, которая соединяет X-буферы обмена с потоками stdin и stdout.
Благодаря ей можно заполнять буферы информацией либо извлекать ее через конвейер и перенаправление файла.
По умолчанию команда читает stdout и записывает его в первичный буфер:
$ xclip < myfile.txt
$ echo "Some cool text" | xclip
Теперь выведем текст в stdout, перенаправим его в файл и передадим команде wc:
$ xclip -o
Some cool text
$ xclip -o > file.txt
$ xclip -o | wc -w
3
Очистим первичный буфер обмена, поместив в него пустую строку:
$ echo -n | xclip
Параметр "-n" важен, так как в противном случае echo выведет в stdout символ новой строки "\n", который окажется в первичном буфере обмена.
Команда поддерживает явное указание буфера. Чтобы скопировать текст в системный буфер обмена вместо первичного, запустим xclip с параметром "-selection clipboard":
$ ls | grep scr | xclip -selection clipboard
$ xclip -selection clipboard -o
noscript.sh
Теперь вы можете либо использовать комбинации клавиш для вывода либо просто флаг "-o".
При необходимости параметры xclip могут быть сокращены "-selection clipboard == -sel c"
Немного практики
Чтобы дополнительно облегчить себе жизнь, можно создать на xclip несколько алиасов:
$ alias ccopy="xclip -sel c"
$ alias cpaste="xclip -sel c -o"
Теперь, допустим, нам нужно установить определенный deb пакет, предварительно определив его среди общей массы:
$ ls ~/Downloads | grep code
code_1.96.4-1736994636_arm64.deb
Отлично, копируем название в буфер, затем выполняем вставку после целевой команды:
$ ls ~/Downloads | grep code | ccopy
$ sudo dpkg -i ~/Downloads/$(cpaste)
LinuxCamp
👍46🔥16❤🔥3❤3🤷♂1👏1
Прокачиваемся в grep
При работе в командной строке невозможно обойтись без grep - очень полезная утилита для работы с текстом.
Сегодня мы рассмотрим несколько популярных опций, которые позволяют выполнять более продвинутую выборку.
Найти точное соответствие
Для того чтобы искать соответствия только целым словам, используйте флаг "-w":
Аналогичного результата можно добиться через регулярное выражение:
"\<" — начало слова.
"test" — искомый текст.
"\>" — конец слова.
Угловые скобки должны экранироваться, иначе они будут интерпретироваться как простые символы.
Игнорировать регистр
По умолчанию, grep чувствительна к регистру, что немного мешает поиску. Проблема решается путем добавления ключа "-i" к команде:
Вывод файлов с совпадениями
Используйте параметр "-l", чтобы вывести не сами строки, а только пути к файлам, в которых они содержатся:
Параметр "-r" отвечает за рекурсивный поиск - grep прошерстит не только 1 уровень каталога, а пойдет вглубь.
Поиск по нескольким параметрам
Для того, чтобы передать команде несколько вводных данных для определения совпадений, используется флаг "-e" перед каждым объектом поиска:
Эту команду система понимает, как "или-или" и выводит все вхождения указанных слов.
Использование регулярных выражений
Настоящая сила grep проявляется, когда вы переходите от сопоставления простых строк к сопоставлению шаблонов - регулярных выражений.
Выражения бывают 2 типов: basic и extended. Одна из особенностей второго типа заключается в том, что некоторые символы требуют экранирования для сохранности фич: ?, +, {, |, (, ), <, >.
Но можно обойтись просто добавлением флага "-E":
1. Квадратные скобки "[]" используются, чтобы провести проверку на соответствие одному из указанных символов:
Можем указать "-" для того, чтобы использовать диапазон значений:
2. Каретка "^" используется для поиска строк, которые начинаются с указанного шаблона. Давайте найдем совпадение всех строк, начинающихся с заглавной буквы:
3. Знак доллара "$" означает конец строки. В результат входят только те элементы, конец которых подходит под шаблон:
4. Точка "." обозначает любой одиночный символ, кроме новой строки. Регулярное выражение "....." обозначает любую строку, содержащую минимум 5 символов:
5. Вертикальная черта "|" выполняет роль логического оператора "ИЛИ":
В общем, регулярные выражения прекрасны и многообразны. Детальнее ознакомиться с ними можете по ссылке.
Экранирование
Иногда выражения приводят к неожиданным результатам.
Предположим, вы хотите найти в файле "myfile" только те строки, которые заканчиваются на ".sh".
Следующая команда выдаст неверный результат, поскольку точка — это регулярное выражение, означающее «любой символ»:
Чтобы обойти эту проблему, требуется экранировать спецсимвол:
Такое решение иногда становится громоздким. К счастью, можно заставить grep забыть о регулярных выражениях и искать буквально то, что мы указываем.
Для этого используется параметр (fixed) "-F":
LinuxCamp | #utils
При работе в командной строке невозможно обойтись без grep - очень полезная утилита для работы с текстом.
Сегодня мы рассмотрим несколько популярных опций, которые позволяют выполнять более продвинутую выборку.
Найти точное соответствие
Для того чтобы искать соответствия только целым словам, используйте флаг "-w":
$ ls
'test noscript.sh' test test_1 test_2
$ ls | grep -w test
test noscript.sh
test
Аналогичного результата можно добиться через регулярное выражение:
$ ls | grep "\<test\>"
test noscript.sh
test
"\<" — начало слова.
"test" — искомый текст.
"\>" — конец слова.
Угловые скобки должны экранироваться, иначе они будут интерпретироваться как простые символы.
Игнорировать регистр
По умолчанию, grep чувствительна к регистру, что немного мешает поиску. Проблема решается путем добавления ключа "-i" к команде:
ls | grep -i new
newFile
NewFile
Вывод файлов с совпадениями
Используйте параметр "-l", чтобы вывести не сами строки, а только пути к файлам, в которых они содержатся:
$ grep -r -l "libnma" /usr/share
/usr/share/doc/libnma-gtk4-0/copyright
Параметр "-r" отвечает за рекурсивный поиск - grep прошерстит не только 1 уровень каталога, а пойдет вглубь.
Поиск по нескольким параметрам
Для того, чтобы передать команде несколько вводных данных для определения совпадений, используется флаг "-e" перед каждым объектом поиска:
$ ls | grep -i -e new -e old
NewFile
newFile
oldFile
Эту команду система понимает, как "или-или" и выводит все вхождения указанных слов.
Использование регулярных выражений
Настоящая сила grep проявляется, когда вы переходите от сопоставления простых строк к сопоставлению шаблонов - регулярных выражений.
Выражения бывают 2 типов: basic и extended. Одна из особенностей второго типа заключается в том, что некоторые символы требуют экранирования для сохранности фич: ?, +, {, |, (, ), <, >.
Но можно обойтись просто добавлением флага "-E":
$ ls | grep -E "noscript|test"
1. Квадратные скобки "[]" используются, чтобы провести проверку на соответствие одному из указанных символов:
$ ls | grep "test[23]"
test2
test3
Можем указать "-" для того, чтобы использовать диапазон значений:
$ ls | grep "test[1-3]"
test2
test3
2. Каретка "^" используется для поиска строк, которые начинаются с указанного шаблона. Давайте найдем совпадение всех строк, начинающихся с заглавной буквы:
$ grep "^[A-Z]" myfile
A lot of text
Hello world
3. Знак доллара "$" означает конец строки. В результат входят только те элементы, конец которых подходит под шаблон:
$ grep "world$" myfile
Hello world
hello world
4. Точка "." обозначает любой одиночный символ, кроме новой строки. Регулярное выражение "....." обозначает любую строку, содержащую минимум 5 символов:
$ grep '.....' myfile
5. Вертикальная черта "|" выполняет роль логического оператора "ИЛИ":
$ ls | grep "noscript\|test"
noscript
test
В общем, регулярные выражения прекрасны и многообразны. Детальнее ознакомиться с ними можете по ссылке.
Экранирование
Иногда выражения приводят к неожиданным результатам.
Предположим, вы хотите найти в файле "myfile" только те строки, которые заканчиваются на ".sh".
Следующая команда выдаст неверный результат, поскольку точка — это регулярное выражение, означающее «любой символ»:
$ grep ".sh" myfile
noscript_name.sh
noscript_namesh
Чтобы обойти эту проблему, требуется экранировать спецсимвол:
$ grep "\.sh" myfile
noscript_name.sh
Такое решение иногда становится громоздким. К счастью, можно заставить grep забыть о регулярных выражениях и искать буквально то, что мы указываем.
Для этого используется параметр (fixed) "-F":
$ grep -F ".sh" myfile
noscript_name.sh
LinuxCamp | #utils
👍62🔥17❤9❤🔥3
Ничего лишнего, только head и tail
Утилиты head и tail можно назвать сестрами. Они обе позволяют просматривать только часть того, что поступило на вход: head показывает начало, а tail — конец.
Команды могут принимать входные данные либо с какого-то ресурса (файла) либо от других утилит через конвейер "|":
Если в команде head не указаны флаги, то по умолчанию выводятся первые 10 строк.
Для того, чтобы ограничить вывод и просмотреть N элементов, используем параметр "-n":
Параметр "-n" также можно использовать для того, чтобы вывести все содержимое, за исключением N последних строк. Для этого нужно использовать выражение вида "-n-N".
Если у нас всего 10 строк и требуется получить первые 3, сделаем:
Без проблем можно единовременно получить вывод с нескольких файлов. Достаточно перечислить названия через пробел:
Если вывод названий файлов и разделителей "\n" нам не нужен, используем флаг "-q":
Команда tail печатает последние строки файла — по умолчанию также 10:
Принцип использования команды tail практически аналогичен head. Если хотим ограничить вывод последними 3 строками, добавляем флаг "-n":
Если поставить перед номером знак "+", печать начнется со строки этого номера и продолжится до конца файла:
Обе команды вместе
Объединяйте head и tail, чтобы напечатать любой диапазон строк.
Например, чтобы вывести строки c 4 по 7, используем head для элементов "1-7" и tail для "7-4":
В общем, чтобы отобразить строки от M до N, извлеките первые N строк с помощью head, затем выведите последние N-M+1 строк с помощью tail.
Чуток жизненной практики
Последнее время частенько приходится работать с патчами - накладывать их на приложения через quilt и снимать.
Нужно было наложить на утилиту только 10 патчей из 20. Для того, чтобы поработать с диапазоном, использовал команду head:
1) quilt series выводит список патчей в столбец;
2) head -n 10 отображает только первые 10 строк;
3) xargs -L1 quilt push выполняет команду для каждого отдельного патча;
LinuxCamp | #utils
Утилиты head и tail можно назвать сестрами. Они обе позволяют просматривать только часть того, что поступило на вход: head показывает начало, а tail — конец.
Команды могут принимать входные данные либо с какого-то ресурса (файла) либо от других утилит через конвейер "|":
$ head test
Line 1
Line 2
Line 3
...
$ ls | head
adduser.conf
alsa
alternatives
...
Если в команде head не указаны флаги, то по умолчанию выводятся первые 10 строк.
Для того, чтобы ограничить вывод и просмотреть N элементов, используем параметр "-n":
$ head -n2 test
Line 1
Line 2
Параметр "-n" также можно использовать для того, чтобы вывести все содержимое, за исключением N последних строк. Для этого нужно использовать выражение вида "-n-N".
Если у нас всего 10 строк и требуется получить первые 3, сделаем:
$ head -n-7 test
Line 1
Line 2
Line 3
Без проблем можно единовременно получить вывод с нескольких файлов. Достаточно перечислить названия через пробел:
$ head -n2 test test2
==> test <==
Line 1
Line 2
==> test2 <==
Line 11
Line 12
Если вывод названий файлов и разделителей "\n" нам не нужен, используем флаг "-q":
$ head -n2 -q test test2
Line 1
Line 2
Line 11
Line 12
Команда tail печатает последние строки файла — по умолчанию также 10:
$ tail test
Line 1
Line 2
Line 3
...
Принцип использования команды tail практически аналогичен head. Если хотим ограничить вывод последними 3 строками, добавляем флаг "-n":
$ tail -n3 test
Line 8
Line 9
Line 10
Если поставить перед номером знак "+", печать начнется со строки этого номера и продолжится до конца файла:
$ tail -n+9 test
Line 9
Line 10
Обе команды вместе
Объединяйте head и tail, чтобы напечатать любой диапазон строк.
Например, чтобы вывести строки c 4 по 7, используем head для элементов "1-7" и tail для "7-4":
$ head -n7 test | tail -n4
Line 4
Line 5
Line 6
Line 7
В общем, чтобы отобразить строки от M до N, извлеките первые N строк с помощью head, затем выведите последние N-M+1 строк с помощью tail.
Чуток жизненной практики
Последнее время частенько приходится работать с патчами - накладывать их на приложения через quilt и снимать.
Нужно было наложить на утилиту только 10 патчей из 20. Для того, чтобы поработать с диапазоном, использовал команду head:
$ quilt series | head -n 10 | xargs -L1 quilt push
1) quilt series выводит список патчей в столбец;
2) head -n 10 отображает только первые 10 строк;
3) xargs -L1 quilt push выполняет команду для каждого отдельного патча;
LinuxCamp | #utils
👍34🔥8❤4❤🔥1
Прокачиваемся в find
Поиск файлов и каталогов через cli бывает гораздо более эффективен и гибок, нежели чем через GUI файловых менеджеров.
Команда find, как и grep, используется супер часто в командной строке. Она рекурсивно выводит пути к найденным файлам, спускаясь вглубь по иерархии.
Утилита имеет такой синтаксис:
Параметры - дополнительные опции, например, глубина поиска, фильтр по имени и т.д;
Действие - что будет выполнено с результатами поиска;
По синтаксису выше найдем пустые каталоги в tmp:
Детально ознакомиться с параметрами и прочей петрушкой можете по ссылке.
Поиск по типу файла
Флаг "-type" позволяет искать файлы по типу, среди которых:
1) f – простые файлы;
2) d – каталоги;
3) l – символические ссылки;
4) b – блочные устройства (dev);
5) c – символьные устройства (dev);
6) p – именованные каналы;
7) s – сокеты;
Перечисляем только каталоги:
Поиск по размеру файла
Флаг "-size" позволяет произвести фильтрацию по размеру.
Выведем все файлы более 1 Гб (+1G):
"+" — поиск файлов больше заданного размера;
"-" — поиск файлов меньше заданного размера;
Отсутствие знака — поиск по полному совпадению с заданным размером;
Единицы измерения файлов: c (байт), k (Кбайт), M (Мбайт), G (Гбайт).
Поиск пустых файлов и каталогов
Параметр "-empty" позволяет найти пустые ресурсы:
Не учитывать регистр при поиске
Если опция "-name" чувствительна к регистру, то "-iname" наоборот:
Несколько каталогов
Для поиска по нескольким каталогам просто используем перечисление:
Поиск по правам доступа
Команда нам позволяет искать ресурсы по определенной маске прав, например, 0664:
Вместо числового представления маски можно использовать символьное для: u (user) g (group) и o (other).
Выполним поиск файлов доступных владельцу для чтения/записи:
Чтобы немного въехать в суть прав доступа, можно просмотреть вот этот пост.
Ограничение глубины поиска
Если нам нужно указать максимальную глубину поиска, используем "-maxdepth".
Следующий запуск find пройдется только по самому верхнему уровню указанного каталога:
Операторы
Для инвертирования шаблона либо объединения можно применять операторы: and, or, not.
Флаг "-and" обычно можно опустить, т.к. он ставится по дефолту.
Найдем файлы, которые не соответствуют шаблону:
Либо найдем все файлы, начинающиеся на "test", но без расширения "php":
Можем также объединить несколько условий и найти ресурсы, которые принадлежат "xoadmin" и имеют размер "< 100 байт":
Если нужно учесть принадлежность к еще какому-нибудь пользователю, используем "or":
Действия
К команде можно добавить действия, которые будут выполнены с результатами поиска:
1) -delete: удаляет результаты поиска;
2) -ls: выводит доп информацию;
3) -print: показывает полный путь к найденным файлам (стоит по умолчанию);
4) -exec: выполняет указанную команду для найденных ресурсов;
Тут мы удаляем все пустые файлы и каталоги одним вызовом "rm -rf".
Можем через exec найти файлы и прочитать их:
Вместо {} подставляется путь к файлу. Если команда оканчивается на "\;", значит она будет выполнена для каждой строки с результатом.
LinuxCamp | #utils
Поиск файлов и каталогов через cli бывает гораздо более эффективен и гибок, нежели чем через GUI файловых менеджеров.
Команда find, как и grep, используется супер часто в командной строке. Она рекурсивно выводит пути к найденным файлам, спускаясь вглубь по иерархии.
Утилита имеет такой синтаксис:
find каталог параметры действие
Параметры - дополнительные опции, например, глубина поиска, фильтр по имени и т.д;
Действие - что будет выполнено с результатами поиска;
По синтаксису выше найдем пустые каталоги в tmp:
$ find /tmp -type d -empty -print
Детально ознакомиться с параметрами и прочей петрушкой можете по ссылке.
Поиск по типу файла
Флаг "-type" позволяет искать файлы по типу, среди которых:
1) f – простые файлы;
2) d – каталоги;
3) l – символические ссылки;
4) b – блочные устройства (dev);
5) c – символьные устройства (dev);
6) p – именованные каналы;
7) s – сокеты;
Перечисляем только каталоги:
$ find . -type d
.
./.ssh
./.cache
Поиск по размеру файла
Флаг "-size" позволяет произвести фильтрацию по размеру.
Выведем все файлы более 1 Гб (+1G):
$ find . -size +1G
./android-studio-ide-183.5692245-mac.dmg
"+" — поиск файлов больше заданного размера;
"-" — поиск файлов меньше заданного размера;
Отсутствие знака — поиск по полному совпадению с заданным размером;
Единицы измерения файлов: c (байт), k (Кбайт), M (Мбайт), G (Гбайт).
Поиск пустых файлов и каталогов
Параметр "-empty" позволяет найти пустые ресурсы:
$ find . -type d -empty
./datafiles
Не учитывать регистр при поиске
Если опция "-name" чувствительна к регистру, то "-iname" наоборот:
$ find . -name "new*"
./new test file
./newFile
$ find . -iname "new*"
./NewFile
./new test file
./newFile
Несколько каталогов
Для поиска по нескольким каталогам просто используем перечисление:
find ./dir1 ./dir2 -type f -name "*.c"
Поиск по правам доступа
Команда нам позволяет искать ресурсы по определенной маске прав, например, 0664:
$ find . -type f -perm 0664
Вместо числового представления маски можно использовать символьное для: u (user) g (group) и o (other).
Выполним поиск файлов доступных владельцу для чтения/записи:
$ find /etc -perm /u=rw
Чтобы немного въехать в суть прав доступа, можно просмотреть вот этот пост.
Ограничение глубины поиска
Если нам нужно указать максимальную глубину поиска, используем "-maxdepth".
Следующий запуск find пройдется только по самому верхнему уровню указанного каталога:
$ find /etc -maxdepth 1
Операторы
Для инвертирования шаблона либо объединения можно применять операторы: and, or, not.
Флаг "-and" обычно можно опустить, т.к. он ставится по дефолту.
Найдем файлы, которые не соответствуют шаблону:
$ find . -not -name "test*"
Либо найдем все файлы, начинающиеся на "test", но без расширения "php":
$ find . -name "test" -not -name "*.php"
Можем также объединить несколько условий и найти ресурсы, которые принадлежат "xoadmin" и имеют размер "< 100 байт":
$ find . -user xoadmin -and -size -100c -type f
Если нужно учесть принадлежность к еще какому-нибудь пользователю, используем "or":
$ find . \( -user xoadmin -or -user vasya \) -and -size -100c -type f
Действия
К команде можно добавить действия, которые будут выполнены с результатами поиска:
1) -delete: удаляет результаты поиска;
$ find . -empty -delete
2) -ls: выводит доп информацию;
3) -print: показывает полный путь к найденным файлам (стоит по умолчанию);
4) -exec: выполняет указанную команду для найденных ресурсов;
$ find . -empty -exec rm -rf {} +
Тут мы удаляем все пустые файлы и каталоги одним вызовом "rm -rf".
Можем через exec найти файлы и прочитать их:
$ find . -type f -exec cat {} \;
Вместо {} подставляется путь к файлу. Если команда оканчивается на "\;", значит она будет выполнена для каждой строки с результатом.
LinuxCamp | #utils
👍48🔥9⚡8❤🔥4❤1👏1
Прокачиваемся в cp
У вас хоть одна пользовательская сессия проходит без копирования файлов?) В общем-то для этого мы и используем команду cp, в которой немало полезных опций.
Начнем с простого. Для копирования файлов команда имеет 2 типа синтаксиса:
1) с сохранением названия - с указанием каталога;
2) без сохранения - с указанием нового имени файла;
Сразу же скину ссылку на полную информацию о команде. Далее мы рассмотрим основные кейсы.
Копирование каталога
Для копирования каталогов нужно использовать опцию "-r":
Тут ме переносим весь каталог вместе с его наполнением.
Если нет полной уверенности в том, что каталог "dest" существует, можно добавить флаг "-t" для вывода предупреждения:
Копирование в этом случае выполнено не будет и каталог не будет создан.
Копирование содержимого каталога
Для того, чтобы перенести только содержимое директории, а не ее саму, используем:
Но есть нюансик... Это так работает только, если no_dest ранее не существовал. Если каталог назначения существует, то в нем будет создан src.
Для того чтобы избежать такого поведения можно использовать опцию "-T":
Как вариант, еще можно решить задачу использованием шаблона поиска:
Однако в этом случае скрытые файлы скопированы не будут. Ну и это не проблема особо:
Обработка существующих файлов
По умолчанию, если файл каталоге назначения уже существует, он будет перезаписан. Если вы хотите, чтобы утилита спросила вас, стоит ли его перезаписывать, используйте флаг "-i":
С помощью опции "-n" можно отключить перезапись существующих ресурсов:
Создание бэкапов
Для существующих файлов можно cделать резервную копию с помощью опции "-b". Если использовать этот флаг, то в конце названия файла резервной копии будет добавлен символ тильды "~":
При использовании параметра "--backup" можно настроить имя резервной копии. Вот доступные варианты:
1) none - резервная копия не делается;
2) numbered - к имени файла будет добавляться номер;
3) simple - в конец файла будет добавлен знак "~";
4) existing - если в целевой директории уже есть бэкапы, то будет использоваться аналогичный им тип нейминга;
Чтобы использовать номер в имени бэкапа используйте:
Ещё один вариант обработки существующих файлов - заменять только, если изначальный новее.
Для этого нужно использовать опцию "-u":
Копирование ссылок
По умолчанию жесткие и символические ссылки копируются как обычные файлы, сохраняя содержимое ресурса, к которому были подвязаны:
Если вы хотите, чтобы символические ссылки копировались, сохраняя свой тип, нужно использовать опцию "-P":
Ток, пожалуйста, не забывайте проверять путь к оригиналу на корректность - в примере выше ссылка поломана.
Для жестких ссылок существует другой подход. Если вы хотите, чтобы она осталась собой после копирования, нужно использовать опцию "-l":
Сохранение атрибутов
По умолчанию cp обновляет временные метки и атрибуты прав доступа файлов при копировании.
Иногда может возникнуть необходимость их сохранить. Для этого используем "--preserve":
LinuxCamp | #utils
У вас хоть одна пользовательская сессия проходит без копирования файлов?) В общем-то для этого мы и используем команду cp, в которой немало полезных опций.
Начнем с простого. Для копирования файлов команда имеет 2 типа синтаксиса:
1) с сохранением названия - с указанием каталога;
$ cp ./src/file ./dest/
2) без сохранения - с указанием нового имени файла;
$ cp ./src/file ./dest/file_backup
Сразу же скину ссылку на полную информацию о команде. Далее мы рассмотрим основные кейсы.
Копирование каталога
Для копирования каталогов нужно использовать опцию "-r":
$ cp -r source destination
$ ls destination
source
Тут ме переносим весь каталог вместе с его наполнением.
Если нет полной уверенности в том, что каталог "dest" существует, можно добавить флаг "-t" для вывода предупреждения:
$ cp -rt src dest3
cp: cannot stat 'dest3': No such file or directory
Копирование в этом случае выполнено не будет и каталог не будет создан.
Копирование содержимого каталога
Для того, чтобы перенести только содержимое директории, а не ее саму, используем:
$ cp -r src no_dest
$ ls no_dest
file1 file2 file3
Но есть нюансик... Это так работает только, если no_dest ранее не существовал. Если каталог назначения существует, то в нем будет создан src.
Для того чтобы избежать такого поведения можно использовать опцию "-T":
$ cp -rT src yes_dest
ls yes_dest
file1 file2 file3
Как вариант, еще можно решить задачу использованием шаблона поиска:
$ cp src/* dest
Однако в этом случае скрытые файлы скопированы не будут. Ну и это не проблема особо:
$ cp src/* src/.* dest
Обработка существующих файлов
По умолчанию, если файл каталоге назначения уже существует, он будет перезаписан. Если вы хотите, чтобы утилита спросила вас, стоит ли его перезаписывать, используйте флаг "-i":
$ cp -i src/* dest
cp: overwrite 'dest/file1'? y
cp: overwrite 'dest/file2'? y
С помощью опции "-n" можно отключить перезапись существующих ресурсов:
$ cp -n file1 dest
Создание бэкапов
Для существующих файлов можно cделать резервную копию с помощью опции "-b". Если использовать этот флаг, то в конце названия файла резервной копии будет добавлен символ тильды "~":
$ cp -b file1 dest
$ ls dest
file1~
При использовании параметра "--backup" можно настроить имя резервной копии. Вот доступные варианты:
1) none - резервная копия не делается;
2) numbered - к имени файла будет добавляться номер;
3) simple - в конец файла будет добавлен знак "~";
4) existing - если в целевой директории уже есть бэкапы, то будет использоваться аналогичный им тип нейминга;
Чтобы использовать номер в имени бэкапа используйте:
$ cp --backup=numbered file1 dest
$ ls dest
file1.~1~
Ещё один вариант обработки существующих файлов - заменять только, если изначальный новее.
Для этого нужно использовать опцию "-u":
$ cp -u file1 dest
Копирование ссылок
По умолчанию жесткие и символические ссылки копируются как обычные файлы, сохраняя содержимое ресурса, к которому были подвязаны:
$ cp test_link links
$ ls -l links
-rw-rw-r-- 1 ... test_link
Если вы хотите, чтобы символические ссылки копировались, сохраняя свой тип, нужно использовать опцию "-P":
$ cp test_link links
$ ls -l links
lrwxrwxrwx 1 ... test2_link -> test2
Ток, пожалуйста, не забывайте проверять путь к оригиналу на корректность - в примере выше ссылка поломана.
Для жестких ссылок существует другой подход. Если вы хотите, чтобы она осталась собой после копирования, нужно использовать опцию "-l":
$ cp -l hlink hlink1
$ ls -l
-rw-rw-r-- 3 ... file
-rw-rw-r-- 3 ... hlink
-rw-rw-r-- 3 ... hlink1
Сохранение атрибутов
По умолчанию cp обновляет временные метки и атрибуты прав доступа файлов при копировании.
Иногда может возникнуть необходимость их сохранить. Для этого используем "--preserve":
$ cp --preserve=all file dest
LinuxCamp | #utils
👍40🔥18❤6