Всем привет. Опять решил поделиться опытом своих провалов.
🔤 🔤 🔥 🔤 🔤 🔤 🔤
Вобщем, как-то раз я решил написать самоучитель по bash.
По традиции все учебники либо в html, либо в pdf. Я решил остановиться на pdf. Я начал писать в libreoffice, там есть экспорт в pdf. Пока писал - познакомился с markdown. И вдруг подумалось, markdown - такой классный, напрямик можно в гитхаб запихнуть. И в pdf конвертнуть с помощью pandoc можно. Вобщем, решил верстать в markdown.
ㅤ
Для начала познакомился с редакторами, которые умеют подсвечивать markdown (pluma, mousepad, geany) Вобщем, жить можно, но подсвечивается не всё.
После этого попробовал Apostrophe. Он уже умеет дополнительно показывать результат. Но работает медленно. Особенно на больших документах.
В общем - перепопробовал, - не нравится. Решил писать в mousepad, а потом конвертить с помощью pandoc.
Написал скрипт для удобства пользования - меняется дата файла - автоматом резервная копия версии и конвертация в фоне.
Начал работать и тут вскрылась куча недостатков markdown;
1. Нет нормального форматирования (заголовок нельзя центрировать)
2. Нет нормальных таблиц, один ущерб какой-то.
3. Проблема с кирилицей (решаемая), но с помощью дополнительного tex-файла настроек.
4. Нет возможности печатать некоторые символы UTF.
5. некоторые символы приходится маскировать, чтобы они не понимались, как управляющие.
Единственный плюс - подсветка синтаксиса bash.
В общем, после 19 главы я понял, что моего терпения не хватит закончить работу. Вернулся к libreoffice. За два дня освоил работу со стилями, и все пошло как по маслу. Кстати, экспорт в pdf тоже быстрее, на мой взгляд.
Может и не все получилось, сами знаете - первый блин комом.
Замечания и комментарии приветствуются.
С результатом можно ознакомиться здесь 👇
🅰️ 🅰️
➡️ https://github.com/tagd-tagd/self-instruction
🅰️ 🅰️
🛠 #bash #linux #utilites #markdown
—
✅ @bashdays / @linuxfactory / @blog
Вобщем, как-то раз я решил написать самоучитель по bash.
По традиции все учебники либо в html, либо в pdf. Я решил остановиться на pdf. Я начал писать в libreoffice, там есть экспорт в pdf. Пока писал - познакомился с markdown. И вдруг подумалось, markdown - такой классный, напрямик можно в гитхаб запихнуть. И в pdf конвертнуть с помощью pandoc можно. Вобщем, решил верстать в markdown.
ㅤ
Для начала познакомился с редакторами, которые умеют подсвечивать markdown (pluma, mousepad, geany) Вобщем, жить можно, но подсвечивается не всё.
После этого попробовал Apostrophe. Он уже умеет дополнительно показывать результат. Но работает медленно. Особенно на больших документах.
В общем - перепопробовал, - не нравится. Решил писать в mousepad, а потом конвертить с помощью pandoc.
Написал скрипт для удобства пользования - меняется дата файла - автоматом резервная копия версии и конвертация в фоне.
Начал работать и тут вскрылась куча недостатков markdown;
1. Нет нормального форматирования (заголовок нельзя центрировать)
2. Нет нормальных таблиц, один ущерб какой-то.
3. Проблема с кирилицей (решаемая), но с помощью дополнительного tex-файла настроек.
\usepackage{longtable}\setlength{\LTleft}{2em}
\setmainfont{Liberation Serif}
\setsansfont{Liberation Sans}
\setmonofont{Liberation Mono}
\newfontfamily\cyrillicfont{Liberation Sans}
\defaultfontfeatures{Scale=MatchLowercase, Mapping=tex-text}
\usepackage{polyglossia}
\setmainlanguage{russian}
\setotherlanguage{english}4. Нет возможности печатать некоторые символы UTF.
5. некоторые символы приходится маскировать, чтобы они не понимались, как управляющие.
Единственный плюс - подсветка синтаксиса bash.
В общем, после 19 главы я понял, что моего терпения не хватит закончить работу. Вернулся к libreoffice. За два дня освоил работу со стилями, и все пошло как по маслу. Кстати, экспорт в pdf тоже быстрее, на мой взгляд.
Может и не все получилось, сами знаете - первый блин комом.
Замечания и комментарии приветствуются.
С результатом можно ознакомиться здесь 👇
—
Please open Telegram to view this post
VIEW IN TELEGRAM
3 95
Сегодня будем убивать неугодные сервисы. Нет, тут будет не про
Короче в юните можно указать параметр
ㅤ
Удобно применять для сервисов, которые не должны жить вечно. Нет ничего вечного! Например, временные задачи, вспомогательные демоны, скрипты и т.п.
А что будет если время вышло?
Как и написал выше — будет песда!
Этот сервис будет убит через 60 секунд после запуска — даже если скрипт ещё не завершился.
Если
Ждём до 10 секунд → если не завершился →
Частый паттерн
Сервис работает максимум 5 минут, и если завис —
А нахуя тут Restart=on-failure?
Оно говорит — «если сервис завершился аварийно — перезапусти его» А завершение по
Если не указать
Важный нюанс!
Если в юните используется
Такие дела, изучай!
🛠 #linux #tricks #debug #systemd #bash
—
✅ @bashdays / @linuxfactory / @blog
kill и т.п. а будет все тот же systemd.Короче в юните можно указать параметр
RuntimeMaxSec, в нем задаём время жизни сервиса. Если сервис работает дольше указанного времени, то ему песда. Systemd принудительно завершит его.ㅤ
Удобно применять для сервисов, которые не должны жить вечно. Нет ничего вечного! Например, временные задачи, вспомогательные демоны, скрипты и т.п.
[Service]
RuntimeMaxSec=30s
0s, 5min, 1h, 2d — интервалыinfinity — отключение лимитаА что будет если время вышло?
Как и написал выше — будет песда!
Systemd пошлет SIGTERM. А если сервис сука живучий и не завершился, то в ход пойдет тяжелая артиллерия через TimeoutStopSec, тут уже будет послан SIGKILL. Но его нужно предварительно прописать.TimeoutStopSec= — это время ожидания корректного завершения сервиса после того, как systemd послал ему сигнал SIGTERM.[Service]
ExecStart=/usr/bin/python3 /opt/scripts/bashdays-task.py
RuntimeMaxSec=60
Этот сервис будет убит через 60 секунд после запуска — даже если скрипт ещё не завершился.
[Service]
ExecStart=/usr/bin/bashdays-daemon
RuntimeMaxSec=60
TimeoutStopSec=10
Если
bashdays-daemon работает дольше 60 секунд → SIGTERMЖдём до 10 секунд → если не завершился →
SIGKILLЧастый паттерн
RuntimeMaxSec=300
TimeoutStopSec=5
Restart=on-failure
Сервис работает максимум 5 минут, и если завис —
systemd подождёт 5 секунд на аккуратное завершение, а потом прибьёт его нахуй.А нахуя тут Restart=on-failure?
Оно говорит — «если сервис завершился аварийно — перезапусти его» А завершение по
SIGKILL из-за превышения времени жизни это и есть failure.Если не указать
TimeoutStopSec, будет использоваться значение по умолчанию: 90 секунд — порой это дохуя, поэтому предпочтительнее задать его руками.Важный нюанс!
Если в юните используется
Restart=always, то после убийства, сервис будет перезапущен и возможно сразу «помрёт» если не изменит своё поведение.Такие дела, изучай!
—
Please open Telegram to view this post
VIEW IN TELEGRAM
6 61
Имена файлов удаляются с помощью системных вызовов
ㅤ
Ну дак вот. Когда счетчик ссылок (имен) становится равен нулю — файл удаляется.
Физическое удаление (блоки маркируются свободными) происходит когда больше никто не удерживает файл. То есть процесс закрыл последний дескриптор ассоциированный с файлом.
Давай попробуем поймать (открыть файл) до того, как запустится вызов
Создаем искусственный временный файл:
Создаем и запускаем скрипт:
Что тут происходит?
Итоги:
Эта фишка демонстрирует, что можно удалить файл, но продолжить его использовать если он был открыт на момент удаления.
Это классическая Unix-модель: имя файла — не сам файл, а просто ссылка.
А тут как-то рассказывал, как восстанавливать удаленные файлы, в том числе и запущенные.
Чтиво почитать:
man 2 unlink
man 2 unlinkat
🛠 #linux #bash
—
✅ @bashdays / @linuxfactory / @blog
unlink, unlinkat.ㅤ
Ну дак вот. Когда счетчик ссылок (имен) становится равен нулю — файл удаляется.
Физическое удаление (блоки маркируются свободными) происходит когда больше никто не удерживает файл. То есть процесс закрыл последний дескриптор ассоциированный с файлом.
Давай попробуем поймать (открыть файл) до того, как запустится вызов
unlink.Создаем искусственный временный файл:
printf '%s\n' {a..z} > /tmp/sh-thd-bashdaysСоздаем и запускаем скрипт:
#!/bin/bash
file=/tmp/sh-thd-bashdays
exec 3< "$file"
rm -vf "$file" # Имени уже нет
read -N 4096 -ru 3 # Но мы читаем
printf '%s' $REPLY # Выводим
exec 3>&-
exit
Что тут происходит?
exec 3< - файл открывается на чтение, привязывается к дескриптору 3 и с этого момента файл начинает жить в «памяти» в open file table ядра, даже если мы его ёбнем удалим. Дескриптор 3 теперь указывает на открытый файл, независимо от имени.rm -vf - файл удаляется из файловой системы, имени больше нет, НО, его содержимое еще доступно, потому что он открыт.read -N 4096 - читаем до 4096 байт из открытого файла через дескриптор 3.exec 3>& - закрываем дескриптор 3 и после этого файл окончательно исчезнет, если его больше никто не держит, а ядро высвобождает ресурсы.Итоги:
Эта фишка демонстрирует, что можно удалить файл, но продолжить его использовать если он был открыт на момент удаления.
Это классическая Unix-модель: имя файла — не сам файл, а просто ссылка.
Если держишь дескриптор — файл всё ещё существует.
А тут как-то рассказывал, как восстанавливать удаленные файлы, в том числе и запущенные.
Чтиво почитать:
man 2 unlink
man 2 unlinkat
—
Please open Telegram to view this post
VIEW IN TELEGRAM
Напозырить и ужаснуться
50 GNU Commands VS 50 PowerShell Commands
ㅤ
🛠 #bash #powershell
—
✅ @bashdays / @linuxfactory / @blog
50 GNU Commands VS 50 PowerShell Commands
ㅤ
—
Please open Telegram to view this post
VIEW IN TELEGRAM
2 38
CRON в первый рабочий день месяца
ㅤ
Да, ключевой момент тут именно в «рабочий день».
Задачка вроде не тривиальная, но как оказалось
Мы с тобой не пальцем деланы, изобретем свой велосипед!
Чтобы реализовать желаемое, я изобрел такую кишку:
Выглядит монструозно, но блядь... Можно в сам скрипт проверку забить, но это еще один костыль.
Что тут происходит?
Короче…
То есть АПИха возвращает
Тут еще бы для
Всегда старайся указывать полные пути до программ и утилит. Это распространенный кейс, крон вроде отрабатывает, но ничего не работает. А оно просто не знает откуда запускать, то что ты ему прописал.
Если знаешь еще какие-то способы, велком в комментарии.
UPD: более корректные алгоритмы решения этой задачи смотрим в комментах, всем спасибо!
🛠 #bash #linux
—
✅ @bashdays ✅ @linuxfactory ✅ @blog
ㅤ
Да, ключевой момент тут именно в «рабочий день».
Задачка вроде не тривиальная, но как оказалось
cron нихуя не умеет определять рабочий сегодня день или нет. И systemd timer тоже не умеет. Никто ничо блядь не умеет.Мы с тобой не пальцем деланы, изобретем свой велосипед!
Чтобы реализовать желаемое, я изобрел такую кишку:
0 8 1-3 * * [ "$(date +\%u)" -lt 6 ] && [ "$(curl -s https://isdayoff.ru/$(date +\%Y\%m\%d))" = "0" ] && /usr/local/sbin/bashdays.sh
Выглядит монструозно, но блядь... Можно в сам скрипт проверку забить, но это еще один костыль.
Что тут происходит?
Короче…
0 8 1-3 * * — Запуск 1–3 числа месяца в 08:00. Потому что первый рабочий день месяца может выпасть на 1-е число, если это будний день. 2-е число, если 1-е — выходной. 3-е число, если 1-е и 2-е — выходные (например, сб + вс).[ "$(date +%u)" -lt 6 ] — Проверяем, что сегодня будний день (1–5 = Пн–Пт). Пусть тебя здесь 6ка не смущает. Она означает: день меньше 6, т.е. 1, 2, 3, 4, 5 — это будни (Пн – Пт).curl ... = "0" — Проверка, что сегодня рабочий день по календарю РФ, выполняется через АПИху производственного календаря.&& /opt/scripts/first-workday.sh — Выполняем только если сошлись оба условия.То есть АПИха возвращает
0 если сегодня будни. Если выходной, то оно вернет что-то другое.Тут еще бы для
curl и date указать что-то вроде CURL=$(which curl), а то крон частенько залупается и не знает откуда запускать эти команды. Всегда старайся указывать полные пути до программ и утилит. Это распространенный кейс, крон вроде отрабатывает, но ничего не работает. А оно просто не знает откуда запускать, то что ты ему прописал.
Да, есть зависимость от внешнего API и порой это пиздец хуёва. Отвалилась АПИха, скрипт не получил данные. Поэтому рекомендую сделать себе собственный микросервис с АПИхой и ни от кого не зависеть. Тем более если сервер в оффлайне, запрос на внешнюю АПИху он сделать не сможет.
Если знаешь еще какие-то способы, велком в комментарии.
UPD: более корректные алгоритмы решения этой задачи смотрим в комментах, всем спасибо!
—
Please open Telegram to view this post
VIEW IN TELEGRAM
6 60
Сопроцессы. Теория. Часть первая.
🔤 🔤 🔥 🔤 🔤 🔤 🔤
Надеюсь все знают, что в bash можно запустить любую программу в фоновом режиме. Для этого после команды достаточно указать &. Например: sleep &
ㅤ
В этом случае программа начинает жить своей жизнью а переменная $! получает PID последнего запущенного процесса, чтобы можно было отследить завершение фонового процесса, а при крайней необходимости сказать знаменитую фразу Тараса Бульбы.
Для контроля и управления фоновыми заданиями служат команды jobs bg fg .
Если будет интересно - напишите комменты - рассмотрю их подробнее. Сейчас не об этом. В bash, начиная с четвертой версии появились сопроцессы (coproc). Иногда их называют копроцессы, но мне слово не нравится. Чем то оно попахивает.
С помощью этой команды можно запустить любой процесс в фоновом режиме, но в отличие от обычного фонового режима, процесс запущенный через coproc связывается через дескрипторы с основной оболочной и с ним можно взаимодействовать.
Форма запуска:
NAME - имя индексного массива, в котором содержатся дескрипторы command. Если NAME не задано, по-умолчанию используется COPROC .
COPROC[0] связан с stdout command , COPROC[1] - с stdin. И с помощью этих дескрипторов мы сможем взаимодействовать с command, не смотря на то, что программа работает в фоновом режиме.
Сразу хочу обратить внимание. Если задано NAME - вместо command необходимо использовать группировку, даже из одной команды:
Иначе coproc поймет NAME - как команду, а command как ее параметры. И да, при группировке пробелы и точка с запятой очень важны. Добро пожаловать в bash. :-)
Пока все не так просто, как хочется, но практика все расставит по местам, а заодно научимся принимать почту от POP3 сервера с ssl.
🛠 #bash
—
✅ @bashdays ✅ @linuxfactory ✅ @blog
Надеюсь все знают, что в bash можно запустить любую программу в фоновом режиме. Для этого после команды достаточно указать &. Например: sleep &
ㅤ
В этом случае программа начинает жить своей жизнью а переменная $! получает PID последнего запущенного процесса, чтобы можно было отследить завершение фонового процесса, а при крайней необходимости сказать знаменитую фразу Тараса Бульбы.
Для контроля и управления фоновыми заданиями служат команды jobs bg fg .
Если будет интересно - напишите комменты - рассмотрю их подробнее. Сейчас не об этом. В bash, начиная с четвертой версии появились сопроцессы (coproc). Иногда их называют копроцессы, но мне слово не нравится. Чем то оно попахивает.
С помощью этой команды можно запустить любой процесс в фоновом режиме, но в отличие от обычного фонового режима, процесс запущенный через coproc связывается через дескрипторы с основной оболочной и с ним можно взаимодействовать.
Форма запуска:
coproc [NAME] command [redirections]
NAME - имя индексного массива, в котором содержатся дескрипторы command. Если NAME не задано, по-умолчанию используется COPROC .
COPROC[0] связан с stdout command , COPROC[1] - с stdin. И с помощью этих дескрипторов мы сможем взаимодействовать с command, не смотря на то, что программа работает в фоновом режиме.
Сразу хочу обратить внимание. Если задано NAME - вместо command необходимо использовать группировку, даже из одной команды:
coproc [NAME] { command [redirections];}Иначе coproc поймет NAME - как команду, а command как ее параметры. И да, при группировке пробелы и точка с запятой очень важны. Добро пожаловать в bash. :-)
Пока все не так просто, как хочется, но практика все расставит по местам, а заодно научимся принимать почту от POP3 сервера с ssl.
—
Please open Telegram to view this post
VIEW IN TELEGRAM
2 43
Сопроцессы. Практика. Часть Вторая.
🔤 🔤 🔥 🔤 🔤 🔤 🔤
coproc хорошо подходит для общения в клиент-серверном режиме. Для примера попробуем подключиться к POP3 серверу с шифрованием ssl прямо из bash-скрипта.
ㅤ
Сам ssl несколько сложноват для bash, поэтому в качестве посредника будем использовать openssl s_client.
Протокол и команды POP3 лучше посмотреть на википедии.
1. Cоздим сопроцесс. Для этого запустим openssl в режиме s_client. При этом из дескриптора POP3_CONN[0] можно читать данные от сопроцесса.
В дескриптор POP3_CONN[1] можно писать для сопроцесса.
При записи используем перенаправление >&${POP3_CONN[1] . При чтении тоже можно использовать перенаправление, но поскольку у команды read есть ключ -u красивее воспользоваться им.
2. Аутентифицируемся
3. Закроем сессию и дескрипторы.
Задержки 0.3 секунды при отправке нужны для того, чтобы сервер успел сформировать ответ.
Ошибки -ERR не обрабатывал. В случае чего команда read завершится по таймауту в 2 сек. (-t 2)
${REC//$'\r'/} конструкция удаляет cr, потому что POP3 сервер отвечает c lfcr.
help coproc
help read
man openssl
вики POP3
🛠 #bash #linux
—
✅ @bashdays ✅ @linuxfactory ✅ @blog
coproc хорошо подходит для общения в клиент-серверном режиме. Для примера попробуем подключиться к POP3 серверу с шифрованием ssl прямо из bash-скрипта.
ㅤ
Сам ssl несколько сложноват для bash, поэтому в качестве посредника будем использовать openssl s_client.
Протокол и команды POP3 лучше посмотреть на википедии.
1. Cоздим сопроцесс. Для этого запустим openssl в режиме s_client. При этом из дескриптора POP3_CONN[0] можно читать данные от сопроцесса.
В дескриптор POP3_CONN[1] можно писать для сопроцесса.
При записи используем перенаправление >&${POP3_CONN[1] . При чтении тоже можно использовать перенаправление, но поскольку у команды read есть ключ -u красивее воспользоваться им.
2. Аутентифицируемся
3. Закроем сессию и дескрипторы.
# Функция для отправки команд серверу
function SEND_CMD() {
sleep 0.3
echo "$@" >&${POP3_CONN[1]}
sleep 0.3
}
# аутентификация. Обычный логин
function POP3_LOGIN() {
declare REC
declare -a AREC
# проверка соединения
read -ert 2 -u ${POP3_CONN[0]} REC
read -ra AREC <<<${REC//$'\r'/}
if [[ "${AREC[0]}" == "+OK" ]];then
# Отправляем логин
SEND_CMD "USER $USER"
read -ert 2 -u ${POP3_CONN[0]} REC
read -ra AREC <<<${REC//$'\r'/}
if [[ "${AREC[0]}" == "+OK" ]];then
# Отправляем пароль
SEND_CMD "PASS $PASS"
read -ert 2 -u "${POP3_CONN[0]}" REC
read -ra AREC <<<${REC//$'\r'/}
if [[ "${AREC[0]}" == "+OK" ]];then
return 0 # аутентификация успешна
else
return 3 # не правильный пароль
fi
else
return 2 #не правильный login
fi
else
return 1 # ошибка соединения с сервером
fi
}
#Выход и закрытие дескрипторов.
function POP3_QUIT(){
SEND_CMD "QUIT"
# Закрываем coproc
exec ${POP3_CONN[0]}<&-
exec ${POP3_CONN[1]}>&-
}
Задержки 0.3 секунды при отправке нужны для того, чтобы сервер успел сформировать ответ.
Ошибки -ERR не обрабатывал. В случае чего команда read завершится по таймауту в 2 сек. (-t 2)
${REC//$'\r'/} конструкция удаляет cr, потому что POP3 сервер отвечает c lfcr.
#!/bin/bash
SERVER="server"
PORT=995
USER="user@server"
PASS="StrongPass"
# создаем сопроцесс и соединяемся с сервером pop3
coproc POP3_CONN { openssl s_client -connect "${SERVER}:${PORT}" -quiet 2>/dev/null;}
POP3_LOGIN
POP3_QUIT
help coproc
help read
man openssl
вики POP3
—
Please open Telegram to view this post
VIEW IN TELEGRAM
2 21
Сопроцессы. Практика. Часть Третья.
🔤 🔤 🔥 🔤 🔤 🔤 🔤
Это уже больше не сопроцессы, а про то, как принять почту в скрипте bash.
ㅤ
Соединение с POP3 сервером есть. Аутентификация тоже. Осталось написать что-нибудь полезное.
Финальный код
help coproc
help read
man openssl
🛠 #bash #linux
—
✅ @bashdays ✅ @linuxfactory ✅ @blog
Это уже больше не сопроцессы, а про то, как принять почту в скрипте bash.
ㅤ
Соединение с POP3 сервером есть. Аутентификация тоже. Осталось написать что-нибудь полезное.
# возвращает число писем в ящике
function POP3_STAT(){
declare -a AREC
declare REC
SEND_CMD "STAT"
read -ert 2 -u ${POP3_CONN[0]} REC
read -ra AREC <<<${REC//$'\r'/}
if [[ ${AREC[0]} == "+OK" ]];then
echo ${AREC[1]} # число сообщений
return 0
else
echo 0
return 1
fi
}
#Помечает к удалению указанное письмо
function POP3_DELE(){
declare -i MSG_NUM=${1:-1} # по умолчанию первое
declare -a AREC
declare REC
SEND_CMD "DELE $MSG_NUM" #удаляем указанное сообщение
read -ert 2 -u ${POP3_CONN[0]} REC
read -ra AREC <<<${REC//$'\r'/}
if [[ ${AREC[0]} == "+OK" ]];then
return 0
else
return 1
fi
}
# читает письмо с заголовками
function POP3_RETR(){
declare -i MSG_NUM=${1:-1} # по умолчанию первое
declare -a AREC
declare REC
SEND_CMD "RETR $MSG_NUM" #читаем указанное сообщение
read -ert 2 -u ${POP3_CONN[0]} REC
read -ra AREC <<<${REC//$'\r'/}
if [[ ${AREC[0]} == "+OK" ]];then
while read -r -t 2 -u ${POP3_CONN[0]} REC ; do
REC=${REC//$'\r'/}
echo "$REC"
if [[ "$REC" == "." ]];then
return 0 # msg end
fi
done
else
return 1
fi
}
# читает указанное число строк письма
function POP3_TOP(){
declare -i MSG_NUM=${1:-1} # по умолчанию первое
declare -i STR_NUM=${2:-1} # по умолчанию одна строка
declare -a AREC
declare REC
#читаем указанное сообщение
SEND_CMD "TOP $MSG_NUM $STR_NUM"
read -ert 2 -u ${POP3_CONN[0]} REC
read -ra AREC <<<${REC//$'\r'/}
if [[ ${AREC[0]} == "+OK" ]];then
while read -ert 2 -u ${POP3_CONN[0]} REC ; do
REC=${REC//$'\r'/}
echo "$REC"
if [[ "$REC" == "." ]];then
return 0
fi
done
else
return 1
fi
}
Финальный код
#!/bin/bash
SERVER="server"
PORT=995
USER="user@server"
PASS="StrongPass"
coproc POP3_CONN { openssl s_client -connect "${SERVER}:${PORT}" -quiet 2>/dev/null;}
POP3_LOGIN && echo POP3_LOGIN OK
MSG_NUM=$(POP3_STAT)
#цикл перебора сообщений
while ((MSG_NUM));do
POP3_TOP $MSG_NUM 1 # Заголовки + 1 строку сообщения
# POP3_RETR $MSG_NUM # сообщения целиком
# POP3_DELE $MSG_NUM # помечаем к удалению.
((--MSG_NUM))
done
POP3_QUIT
help coproc
help read
man openssl
—
Please open Telegram to view this post
VIEW IN TELEGRAM
Хочешь устроить себе челлендж на знание командной строки? Да пожалуйста, лови тренажер по Linux-терминалу. Правда он на английском, но мы с тобой тоже не пальцем деланные.
Я даж успешно прошел первую задачку, правда по-олдскульному и затронул все бед-практики, которые только существуют.
ㅤ
Установка простая:
Здесь я использовал
Что прикольно, если совсем тупой, то можно получить подсказку, будет показано несколько решений. Подсказка открывается по
Сможешь выбить все 77 вопросов без подсказок?
Исходники этого тренажера лежат тут, а видосик с работой можешь посмотреть тут.
🛠 #linux #bash
—
✅ @bashdays ✅ @linuxfactory ✅ @blog
Тренажер содержит 77 вопросов. Вполне достаточно чтобы заебаться.
Я даж успешно прошел первую задачку, правда по-олдскульному и затронул все бед-практики, которые только существуют.
ㅤ
Установка простая:
cd /tmp
python3 -m venv textual_apps
cd textual_apps
source bin/activate
pip install cliexercises
cliexercises
Здесь я использовал
tmp папку и venv, чтобы систему всяким гавно не засорять, а чисто поиграться.Что прикольно, если совсем тупой, то можно получить подсказку, будет показано несколько решений. Подсказка открывается по
CTRL+S.Сможешь выбить все 77 вопросов без подсказок?
Исходники этого тренажера лежат тут, а видосик с работой можешь посмотреть тут.
—
Please open Telegram to view this post
VIEW IN TELEGRAM
3 64
Мне прилетела интересная задача.
🔤 🔤 🔥 🔤 🔤 🔤 🔤
ТЗ: Сервер без GUI, к нему подключают usb-диск с NTFS и начинается автоматическое архивирование. Логин не требуется, сообщения выдаются на tty1.
Использовать будем штатные средства
1. Подключаем диск, и запоминаем UUID.
здесь FLASH - метка диска
ㅤ
создадим каталог для монтирования:
Дальше создаем 4 файла. Чтобы было проще, в каждом файле в начале коммент с названием файла.
После создания:
Как это работает:
При подключении диска usb-диска срабатывает UDEV правило
Сама
Если все условия совпадают,
Если используется архивирование с чередованием дисков - просто сделайте у дисков одинаковые метки:
👆 Если в mount не указать опцию
👆 Запустить скрипт через UDEV даже в фоне не получится, поскольку система вырубит его через 5 сек.
🛠 #linux #bash
—
✅ @bashdays ✅ @linuxfactory ✅ @blog
ТЗ: Сервер без GUI, к нему подключают usb-диск с NTFS и начинается автоматическое архивирование. Логин не требуется, сообщения выдаются на tty1.
sudo apt install ntfs-3g # для монтирования ntfs
Использовать будем штатные средства
udev + systemd .1. Подключаем диск, и запоминаем UUID.
lsblk -f
sdc
└─sdc1
ntfs FLASH
1234567890ABCDEF
здесь FLASH - метка диска
1234567890ABCDEF - UUIDㅤ
создадим каталог для монтирования:
mkdir -p /media/usb_ntfs; chmod 777 /media/usb_ntfs
Дальше создаем 4 файла. Чтобы было проще, в каждом файле в начале коммент с названием файла.
После создания:
sudo systemctl daemon-reload
Как это работает:
При подключении диска usb-диска срабатывает UDEV правило
99-usb-mount.rules и пытается запустить службу autousbbackup.serviceautousbbackup.service пытается запустить media-usb_ntfs.mount, поскольку жестко он нее зависит.Сама
media-usb_ntfs.mount запустится только в том случае, если UUID диска будет 1234567890ABCDEF.Если все условия совпадают,
autousbbackup.service запустит скрипт autousbbackup.sh, внутри которого Вы напишите копирование или синхронизацию данных в каталог /media/usb_ntfs.Если используется архивирование с чередованием дисков - просто сделайте у дисков одинаковые метки:
sudo umount /dev/sdXN # где /dev/sdXN имя вашего NTFS-раздела.
sudo ntfslabel --new-serial=1234567890ABCDEF /dev/sdXN #задайте UUID
👆 Если в mount не указать опцию
nofail система будет тормозить при загрузке.👆 Запустить скрипт через UDEV даже в фоне не получится, поскольку система вырубит его через 5 сек.
#/etc/udev/rules.d/99-usb-mount.rules
SUBSYSTEM=="block", KERNEL=="sd*", ACTION=="add", TAG+="systemd", ENV{SYSTEMD_WANTS}="autousbbackup.service"
#/etc/systemd/system/media-usb_ntfs.mount
[Unit]
Description=Mount USB NTFS by UUID
[Mount]
What=/dev/disk/by-uuid/1234567890ABCDEF
Where=/media/usb_ntfs
Type=ntfs-3g
Options=defaults,big_writes,nofail,uid=1000,gid=1000
[Install]
WantedBy=multi-user.target
#/etc/systemd/system/autousbbackup.service
[Unit]
Description=Simple service autousbbackup
Requires=media-usb_ntfs.mount
After=media-usb_ntfs.mount
[Service]
Type=simple
ExecStart=/root/work/autousbbackup/autousbbackup.sh
[Install]
WantedBy=multi-user.target
#!/bin/bash
#/root/work/autousbbackup/autousbbackup.sh
declare -x PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
declare MOUNT_POINT=/media/usb_ntfs
declare TTY=/dev/tty1
declare DF='%(%Y%m%d-%H%M%S)T' #date format
declare LOG="$0.log"
exec &>"$LOG" # only one backup log
#exec &>>"$LOG" # all backups log
printf "$DF %s\n" -1 "START BACKUP"|tee "$TTY"
##############################################
sleep 3 # backup emulation
##############################################linux
printf "$DF %s\n" -1 "END BACKUP"|tee "$TTY"
#suicide, because service require mount point
systemd-mount --umount "$MOUNT_POINT"
—
Please open Telegram to view this post
VIEW IN TELEGRAM
6 77
Смотри какая лялька: ExplainShell
ㅤ
Сервис помогает понять, что делает shell команда и все её параметры и ключи. Вставляешь например команду из прошлого поста:
И получаешь по ней полный разбор.
Работает достаточно просто, под капотом овер-дохуя ≈30к-man страниц. Штука оупенсорцная и лежит тут.
Логика работы:
1. Ман-страницы (разделы 1 и 8) загружаются и преобразуются в HTML.
2. Параграфы классифицируются – разделяются те, где описаны опции/флаги, и те, где нет.
3. Из отобранных параграфов извлекаются конкретные параметры и их описания.
4. Когда ты вводишь команду, она разбирается на синтаксическое дерево (AST) с помощью библиотеки
5. Компоненты команды («узлы» AST) сопоставляются с параметрами, найденными в ман-страницах.
6. Отображаем на фронте.
Вообще штука довольно бесполезная, но в образовательных целях очень даже вменяемая. Как раз для персонажей которые нихуя не понимают как ориентироваться в man страницах.
Ладно, глядишь сгодиться в хозяйстве.
🛠 #services #bash
—
✅ @bashdays ✅ @linuxfactory ✅ @blog
ㅤ
Сервис помогает понять, что делает shell команда и все её параметры и ключи. Вставляешь например команду из прошлого поста:
strace -s 200 -f -e trace=network,recvfrom task sync
И получаешь по ней полный разбор.
Работает достаточно просто, под капотом овер-дохуя ≈30к-man страниц. Штука оупенсорцная и лежит тут.
Логика работы:
1. Ман-страницы (разделы 1 и 8) загружаются и преобразуются в HTML.
2. Параграфы классифицируются – разделяются те, где описаны опции/флаги, и те, где нет.
3. Из отобранных параграфов извлекаются конкретные параметры и их описания.
4. Когда ты вводишь команду, она разбирается на синтаксическое дерево (AST) с помощью библиотеки
bashlex.5. Компоненты команды («узлы» AST) сопоставляются с параметрами, найденными в ман-страницах.
6. Отображаем на фронте.
Вообще штука довольно бесполезная, но в образовательных целях очень даже вменяемая. Как раз для персонажей которые нихуя не понимают как ориентироваться в man страницах.
Хотя, кого я обманываю, сейчас каждый первый загоняет непонятную команду в GPT и оно тебе всё по полочкам раскладывает. Да еще и на русском языке.
Ладно, глядишь сгодиться в хозяйстве.
—
Please open Telegram to view this post
VIEW IN TELEGRAM
2 69
Довольно часто нужно быстро загрузить файл построчно в массив.
Как делает мальчик:
Как делает мужчина:
В первом варианте много кода, НО, работает везде. Во втором варианте, работает только в bash ≥4.0, но кода в разы меньше и не жрет CPU.
Либо расширь второй вариант и укажи:
Это гарантирует, что твой скрипт выполнится именно через bash, а не через системный
Ну и прицепом можешь добавить:
Это включение «строгого режима» в баше:
По итогу:
- Скрипт точно запустится под bash
- Ошибки не будут замалчиваться
- Сразу ловишь косяки
Удобно в CI/CD, где всё должно падать быстро и без хуйни.
Такие дела, изучай.
🛠 #bash
—
✅ @bashdays ✅ @linuxfactory ✅ @blog
Как делает мальчик:
lines=()
while IFS= read -r line; do
lines+=("$line")
done < file.txt
echo "Первая строка: ${lines[0]}"
echo "Всего строк: ${#lines[@]}"
Как делает мужчина:
mapfile -t lines < file.txt
echo "Первая строка: ${lines[0]}"
echo "Всего строк: ${#lines[@]}"
В первом варианте много кода, НО, работает везде. Во втором варианте, работает только в bash ≥4.0, но кода в разы меньше и не жрет CPU.
Совет: если пишешь скрипт под bash — всегда используй mapfile. Если нужен кросс-шелл (sh,dash,ash) — оставайся на цикле.
Либо расширь второй вариант и укажи:
#!/usr/bin/env bash
Это гарантирует, что твой скрипт выполнится именно через bash, а не через системный
sh (который может быть dash, ash, ksh и т.п.).env ищет bash в $PATH, так что это более переносимо, чем жёстко указывать #!/bin/bashНу и прицепом можешь добавить:
set -euo pipefailЭто включение «строгого режима» в баше:
-e — выход из скрипта при любой ошибке (не игнорировать exit code ≠ 0).-u — ошибка при обращении к неинициализированной переменной (не будет пустых значений «по-тихому»).-o pipefail — пайплайны возвращают код ошибки первой упавшей команды, а не последней.По итогу:
- Скрипт точно запустится под bash
- Ошибки не будут замалчиваться
- Сразу ловишь косяки
Удобно в CI/CD, где всё должно падать быстро и без хуйни.
grep foo file.txt | wc -l
echo $? # 0, даже если grep ничего не нашёл
set -o pipefail
grep foo file.txt | wc -l
echo $? # 1, потому что grep ушел по пизде
Такие дела, изучай.
—
Please open Telegram to view this post
VIEW IN TELEGRAM
1 69