Bash Days | Linux | DevOps
Авторский блог от действующего девопса Самобытно про разработку, devops, linux, скрипты, сисадминство, техдирство и за айтишную жизу. Автор: Роман Шубин Реклама: @maxgrue MAX: https://max.ru/bashdays Курс: @tormozilla_bot Блог: https://bashdays.ru
显示更多📈 Telegram 频道 Bash Days | Linux | DevOps 的分析概览
频道 Bash Days | Linux | DevOps (@bashdays) 俄语 语言赛道中的 是活跃参与者。目前社区聚集了 23 788 名订阅者,在 技术与应用 类别中位列第 5 702,并在 俄罗斯 地区排名第 28 099 位。
📊 受众指标与增长动态
自 невідомо 创建以来,项目保持高速增长,吸引了 23 788 名订阅者。
根据 19 六月, 2026 的最新数据,频道保持稳定运转。过去 30 天订阅人数变化为 -226,过去 24 小时变化为 1,整体触达仍然可观。
- 认证状态: 未认证
- 互动率 (ER): 平均受众互动率为 23.40%。内容发布后 24 小时内通常能获得 13.11% 的反应,占订阅者总量。
- 帖子覆盖: 每篇帖子平均可获得 5 567 次浏览,首日通常累积 3 119 次浏览。
- 互动与反馈: 受众积极参与,单帖平均反应数为 22。
- 主题关注点: 内容集中在 bashdays, linux, bash, docker, скрипт 等核心主题上。
📝 描述与内容策略
作者将该频道定位为表达主观观点的平台:
“Авторский блог от действующего девопса
Самобытно про разработку, devops, linux, скрипты, сисадминство, техдирство и за айтишную жизу.
Автор: Роман Шубин
Реклама: @maxgrue
MAX: https://max.ru/bashdays
Курс: @tormozilla_bot
Блог: https://bashdays.r...”
凭借高频更新(最新数据采集于 20 六月, 2026),频道始终保持新鲜度与高覆盖。分析显示受众积极互动,使其成为 技术与应用 类别中的关键影响点。
printf '%s\n' {a..d} > /tmp/test.txt
либо так:
echo {a..d} > /tmp/test.txt
После создания файла, нужно запустить команду sync, но можно и не запускать, спустя несколько секунд linux сам всё нужное сделает. Я запускаю, потому что мне важна чистота эксперимента.
sync — утилита Unix, предназначенная для обновления файловых систем и для синхронизации данных на диске с данными в памяти. При этом выполняется системный вызов sync, который вызывает запись всех буферизованных изменений метаданных файлов и данных в базовые файловые системы. Он гарантирует, что все, что хранилось в памяти, будет записано на диск, предотвращая потерю данных, хранящихся в кеше, при аварийном завершении работы.
Так, файл успешно создан, давай посмотрим что внутри:
cat /tmp/test.txt abcdОк. Теперь давай узнаем физическое расположение файла на диске, для этого запускай команду:
filefrag -b512 -v /tmp/test.txtПрограмма filefrag (из пакета e2fsprogs) показывает насколько сильно фрагментирован файл. После выполнения команды, смотрим результат. Нам важна колонка: physical_offset в моём случае я получил такие значения:
4612136..4612143Отлично. Теперь я знаю точное расположение файла на жестком диске. А давай прочитаем его прям с диска! Для этого стартуем:
sudo dd if=/dev/sda1 skip=4612136 status=none count=8Важно правильно указать свой диск /dev/sdX. Ну и в параметр skip подставить первое значение из колонки physical_offset По итогу запуска, я получаю туже картину. Только без применения сторонних утилит вроде cat и т.п..
abcdНу и вишенка. Если я удалю файл
rm /tmp/test.txt и затем выполню предыдущую команду:
sudo dd if=/dev/sda1 skip=4612136 status=none count=8То получу тот же вывод «abcd», потому что файл на диске продолжает лежать и занимать место. Это визуально он исчез, чтобы тебе глаза не мозолить. Но зная его physical_offset вполне можно до него дотянутся и восстановить при желании. Полезно? Полезно! Для чего это можно применить? Нууу не знаю, коллега к примеру таким образом восстанавливал базу данных, которую в пятницу вечером решили случайно удалить. А бэкапы съели мыши.🐁 Кстати успешно восстановил. Ну это уже лирика… Очередную порцию полезных знаний я тебе выдал, ставь лайк, изучай. Увидимся! 😻 tags: #linux #bash — 🟢 Подпишись: @bashdays
/usr/local/sbin/cheat_shit.sh чмодим chmod +x cheat_shit.sh чтобы он в экзешник превратился.
#!/bin/bash tput civis tput smcup tput cup 0 0 trap 'tput rmcup;tput cvvis' EXIT echo 'Hello,this is Cheat-Shit' echo '------------------------' echo 'а тут можешь написать всё, что захочешь' echo '------------------------' echo 'source: https://t.me/bashdays' read -srn1 -t 0.7 while read -srn1 -t 0.1 do : done exitОЧЕНЬ СТРАШНО! Держу пари мало кто про такое вообще слышал и тем более видел. Но такое в bash вполне реализуемо и в школе такому не научат. Кратенько:
tput civis = скрываем курсор
tput smcup = переходим на альтернативный экран
tput cup 0 0 = переводим курсор в начало строки
trap 'tput…' = после выхода зачищаем весь мусор
Далее прописываем бинд в ~/.bashrc и вешаем вызов скрипта на CTRL+h
bind -x '"\C-h":"/usr/local/sbin/cheat_shit.sh"'Перезапускаем сессию. Теперь при нажатии CTRL+h у меня поверх рабочей консоли открывается попап с нужным мне текстом. В тексте может быть шпаргалка либо котик 😑 либо что-то еще полезное. Как повторить для zsh, ХЗ, я не разбирался. Если будут наработки, скидывайте в бота, сделаю отдельный пост. Ну и для гиков, кто хочет покопаться поглубже, можешь зама́нить и захелпить:
man 3 readline man bash (раздел readline) man tput man stty help trap help read help bind man 5 terminfoПомимо шпаргалки по хоткею, ты можешь запустить вообще любой скрипт. Тут уже зависит от полета фантазии. Больше не смею тебя отвлекать, спасибо за внимание. Давай пять и погнали дальше отдыхать! ✅ ВИДЕО КАК ЭТО РАБОТАЕТ tags: #bash — 🟢 Подпишись: @bashdays
#!/bin/bash
COUNT_Q=$(ssh user@bashdayz-d1 rabbitmqctl list_queues | grep 'email.send.mass'|awk '{print $2}')
if [ $COUNT_Q -gt 500 ]
then
su - amqp-daemon -c "cd ~/daemon && daemon.pl stop"
su - amqp-daemon -c "cd ~/daemon && daemon.pl start"
fi
Разбор скрипта:
Скрипт работает в кроне на сервере рядом с микросервисом. Запускается каждые полчаса. После запуска, он подключается по ssh к серверу с очередями RabbitMQ. Проверяет общее количество писем в очереди email.send.mass. Если писем скопилось более 500, то значит ПРИПЛЫЛИ!
Оператор -gt в bash означает: Больше
А конструкция su - amqp-daemon -c означает, что запускаем команды от пользователя amqp-daemon
Ну а далее срабатывает логика перезапуска микросервиса, остановка и запуск.
Профит. Клиент доволен как слон, а мы при деньгах. 💰
Не забывыем прописать ssh public ключи, чтобы скрипт мог ходить на другие сервера без пароля. Ну про это ты должен знать. Если не знаешь, то обязательно погугли как работают ssh ключи, это база.
Также можно сюда прикрутить логирование, оповещения, экспортер в prometheus и на графиках в grafana все красиво вывести. Когда чо упало, когда перезапустилось, пустая ли очередь и т.п.
Переработав этот скрипт под свои нужды, можно получать вообще любые данные с любых серверов, не используя экспортеры. Ну и в дальнейшем строить логику в скрипте на этих данных. А самое главное это быстро реализуемо. Костыльно? Конечно! Но клиент всегда прав, а богатый клиент прав в двойне. Рабочие будни 😎
С пятницей ребят! Всем хороших предстоящих выходных и самое главное — берегите себя.
tags: #bash
—
🟢 Подпишись: @bashdays/mnt/storage:
sshfs -o compression=no,allow_other,reconnect storage@bashdayz.ru:/storage /mnt/storage
compression - не использовать компрессию
allow_other - разрешить доступ к шаре
reconnect - нативный реконект если шара отвалилась
Из плюсов: на baremetal сервере не надо устанавливать никакой дополнительный софт, все работает по протоколу ssh.
Но есть нюансы. Допустим если ноду перезагрузить, то всё отвалится. Либо придут сетевые ножницы и оно тоже отвалится.
Запихать в fstab не вариант. Так как на этапе маунта еще нет сети и загрузка сервера просто остановится в попытках примонтировать шару. А ключик reconnect работает как ему захочется, даже если выставить таймауты проверок.
Решение простое, создаем три юнита в systemd.
✅ Первый юнит (АААААРРРРРР!!!!! В пост не влазиет, да и форматирование тут убогое, публикую в телеграфе)
After=network.target - запускать маунт только после того, как на хосте поднимется сеть
What=storage@bashdayz.ru:/storage - что монтируем
Where=/mnt/storage - куда монтируем
Важно! Файл юнита должен называться в соответствии с путем куда монтируем. Узнать имя можно командой:
systemd-escape -p /mnt/storageПервый юнит сохраняем сюда:
/etc/systemd/system/mnt-storage.mount
Теперь нужно сделать юнит проверки, если шара отвалилась. Для начала создаем юнит с таймером:
✅ Второй юнит
After=mnt-storage.mount - обеспечит запуск таймера после загрузки сервера, но только после того, как маунт юнит будет запущен, то есть после того, как удалённая ФС смонтируется.
Unit=mnt-storage.service - какой юнит будем запускать при срабатывании таймера. О нём чуть ниже.
OnCalendar=*-*-* *:*:00 - это означает каждую минуту.
Юнит-файл таймера можно называть как угодно. Но чтобы было понятнее, будем называть также, как и маунт-юнит. Итак, сохраняем в /etc/systemd/system/mnt-storage.timer
Теперь нужно создать юнит, который будет заниматься проверкой маунта и его перезапуском при необходимости:
✅ Третий юнит
Здесь всё просто. Bash строка в ExecStart это bash’евый однострочник, проверяющий наличие маркерного файла mount.yes, при отсутствии которого будет перезапущен маунт-юнит. В более новой версии systemd можно было бы это всё сделать иначе, но зато такой вариант более универсален.
Cохраняем в /etc/systemd/system/mnt-storage.service
Релодим и активируем
systemctl daemon-reload systemctl enable mnt-storage.mount systemctl enable mnt-storage.timerТретий юнит mnt-storage.service при загрузке сервера активировать не нужно, поскольку этот юнит вызывается таймером mnt-storage.timer. Он будет всегда Active: inactive (dead), это нормально. Ну и в финале запускаем таймер:
systemctl start mnt-storage.timerВот и все! Наша шара успешно взята под контроль, подключена. А в случае отвала по любым причинам, она сама перемонтируется без лишних вопросов. Ну и после перезагрузки ноды, тоже все поднимется из коробки. Способ рабочий, полет стабильный более трёх лет. Можешь приспособить к своим каким-то изобретениям и использовать уже юниты, а не закроненные bash скрипты. А шары монтировать через sshfs, а не через вонючий, разваливающийся gluster. Фак еее! 🐄 tags: #linux — 🟢 Подпишись: @bashdays
Out of Memory: Killed process 2256 (mysql) score 907 or sacrifice childА это уже не шутки. Если к тебе стал приходить OOM Killer, значит в какой-то момент на сервере, что-то
cat /proc/<PID>/oom_scoreГде PID это идентификатор процесса, узнать можешь командой ps ax|grep postfix В результатах ты увидишь число, к примеру: 826, это и есть очки негодности. Если интересно как начисляются очки негодности, я вынес это в отдельный пост в телеграф, чтобы не валить тебя скучной теорией. Почитать можешь тут: ✅ Как вычисляются очки негодности? TL;DR Если подытожить, то OOM Killer убьет самый «жирный» процесс, который наименее активен в системе и имеет самое короткое время жизни. Как обуздать OOM Killer? 🔪 Можно вообще его отключить! Но по понятным причинам, это все равно что отключить жизненно важный орган у человека. Какое-то время он еще проживет, но потом обязательно сдохнет в kernel panic. Отключается командой:
sudo echo 1 > /proc/sys/vm/panic_on_oomПо умолчанию 0 (то есть включено). Я ни разу не встречал, чтобы кто-то отключил этот функционал, но достаточно много раз сталкивался с забиваем костылей в сами процессы. Можно повысить или понизить репутацию для процесса, добавив в файл oom_adj значение от -17 до +15. Для повышения репутации выполняем команду:
sudo echo -6 > /proc/<PID>/oom_adjНе забываем подставить в PID, идентификатор нужного процесса. Для отключения OOM Killer для определенного процесса, выставляем репутацию -17. Теперь этот процесс в «домике» и его никакая собака не посмеет тронуть.
sudo echo -17 > /proc/<PID>/oom_adjНо если ты рестартанешь процесс, у него изменится PID. А репутация, которую ты ему уже накрутил, может примениться к совсем другому процессу таким же PID. Так же можно динамически определять PID процесса и менять ему репутацию. Закинуть это в крон и прыгать от счастья:
pgrep -f "/usr/sbin/sshd" | while read PID; do echo -17 > /proc/$PID/oom_adj; doneНо правильнее задать очки в самом systemd, в юните для сервиса, этот параметр:
[Service] OOMScoreAdjust=-500Собственно это база. По опыту скажу так — если к тебе пришел OOM Killer, сервак можно смело перезагружать. Нихрена там уже не работает, несмотря на всякие очки и коэффициенты. Перезагрузиться будет намного эффективнее, чем пытаться поднять что-то. Поднял, а потом уже по горячим следам и логам, дебаж. Поздравляю, ты только что прокачался еще на один уровень. Хорошего тебе понедельника, да и лёгкой рабочей недели! Увидимся! 🐾 tags: #linux — 🟢 Подпишись: @bashdays
$EDITOR. Ты снова скажешь — да CTRL+x+e (а в osx кнопка CTRL со значком ^).
Как нажать CTRL+x+e и не сломать пальцы? Сначала зажимаешь и удерживаешь CTRL, следом жмешь x и не отпуская CTRL жмешь e.
📺 Тырым-Пырым и перед тобой уже твой любимый vim/mcedit/nano/другойshit
Если получил ошибку: External editor requested but $VISUAL or $EDITOR not set. Не расстраивайся, выполни эти команды и у тебя все заработает. Вместо nano подставь своё.
EDITOR=$(which nano) export EDITOR=$EDITORЛибо на постоянку добавь в
~/.bashrc или ~/.zshrc и не забудь перечитать эти файлы: source ~/.bashrc && source ~/.zshrc
which — команда используется для определения местоположения данного исполняемого файла, который выполняется при вводе имени исполняемого файла (команды) в строке терминала. Команда ищет исполняемый файл, указанный в качестве аргумента, в каталогах, перечисленных в переменной среды PATH.
Есть еще команда select-editor, но не везде присутствует, она сразу список всех редакторов выведет в читабельном виде, тебе останется лишь выбрать циферку. Редактор установится глобально в системе без правки .bashrc/zshrc.
Так, ушли от темы, короче вызвал ты свой любимый редактор и не сломал пальцы. А дальше? А дальше накидываешь в нем скрипт или команды, которые тебе нужно выполнить в оболочке bash/zsh.
Размеренно, удобно, с подсветкой синтаксиса и хоткеев, а если у тебя прокаченный vim, так вообще полноценная IDE получается.
Накидал? Сохраняешь! Сохраняется по умолчанию во временную папку: /tmp/bash-fc.GpOzlI
И после закрытия, все команды из файла автоматически выполняются, а временный файл удаляется. Все введенные команды и выхлоп по ним продублируются в консоли. Так что не переживай, ничего не CTRL+x+e, вставляю туда свою портянку, сохраняю и иду в кроватку принимать горизонтальные процедуры.
А еще если ввел какую-то длинную команду в консоли и хочешь ее сохранить отдельным скриптом, жмешь хоткей ctrl+x+e и вуаля, открывается редактор и в нем уже вставлена эта команда. Сохраняешь в папке ~/Downloads и забываешь про этот файл навсегда.
Почему не ansible? Хм, можешь и плейбуки написать. Хозяин барин. Но у нас тут про комфортную работу в консоли. Про ansible тоже посты будут, но попозже.
Практично, удобно, всё работает из коробки. А мы с тобой такое любим. Вот такие пироги! Ну и с пятницей друзья, всем хороших предстоящих выходных, берегите себя.
PS: Кстати выйти из vi/vim можно командой :q! Это тебе бонус на всякий случай 👋
tags: #bash #linux
—
🟢 Подпишись: @bashdaysexport HISTTIMEFORMAT="%d/%m/%y %T "И вывод будет примерно таким:
369 20/07/23 15:46:54 flask run 370 20/07/23 15:46:54 /usr/bin/python3 371 20/07/23 15:46:54 python --version 372 20/07/23 15:46:54 python3 --version 373 20/07/23 15:46:54 ps ax|grep python 374 20/07/23 15:46:54 sudo kill -9 30049 375 20/07/23 15:46:54 brew install pyenvЛибо можешь прописать это в
~/.bashrc чтобы export выполнялся автоматически:
echo "export HISTTIMEFORMAT=\"%d/%m/%y %T \"" >> ~/.bashrcПрекрасно, теперь намного нагляднее. Идем дальше. Давай перекрасим временные маркеры в синий цвет, чтобы более лаконично выглядело.
export MY_BASH_BLUE="\033[0;34m"
export MY_BASH_NOCOLOR="\033[0m"
export HISTTIMEFORMAT=`echo -e ${MY_BASH_BLUE}[%F %T $MY_BASH_NOCOLOR `
Эти экспорты можешь так же закинуть в ~/.bashrc и затем выполнить команду source ~/.bashrc чтобы не перезагружать сессию и применить настройки в моменте.
Окей, но как же быть с оболочкой zsh? Сейчас и в ней сделаем нечто подобное.
Из коробки zsh, ты можешь воспользоваться командой:
history -Eвывод будет таким:
9481 9.5.2023 16:04 export FLASK_RUN_PORT=8888 9482 9.5.2023 16:04 export FLASK_APP=index.py 9483 9.5.2023 16:04 flask run 9484 9.5.2023 16:08 export TGS_API_KEY=12345 9485 9.5.2023 16:08 flask runУже более менее информативно, а если так:
history -iопа-опа-опапа:
9481 2023-05-09 16:04 export FLASK_RUN_PORT=8888 9482 2023-05-09 16:04 export FLASK_APP=index.py 9483 2023-05-09 16:04 flask run 9484 2023-05-09 16:08 export TGS_API_KEY=12345 9485 2023-05-09 16:08 flask runВидим другой формат даты. Вообще ключей для форматирования даты достаточно много, можешь почитать на досуге если интересно:
man zshoptions man zshbuiltinsНу а чтобы каждый раз не вводить ключи, сделай нужный тебе alias в
~/.zshrc
alias history="history -i"А еще есть такая утилита как «fc», я думаю большинство про нее вообще ничего не слышали. fc — unix-утилита, служащая для редактирования списка ранее введенных команд, а также их выполнения. Вот тебе команда на основе fc, которая выведет историю, сразу же с временными маркерами:
fc -li 100Больше уж и сказать нечего, основное разобрали, внедряй. Еще есть и другие оболочки типа fish, но так как я ими не пользуюсь ежедневно, то и рассказывать вам про них сегодня не буду. А завтра снова пятница, неделя прям в трубу вылетела. Давайте, увидимся. 🐱 tags: #bash #linux — 🟢 Подпишись: @bashdays
stat -c'%z' /proc/self/statВременные метки [atime, mtime, ctime] будут равны времени создания [inode] для этого «файла». В данном случае это время обращения к данному файлу. Вообще proc сама по себе интересная штука. Почти для каждого файла есть свой набор функций для стандартных операций [read, write, open и т.п.].
2023-07-18 11:42:22.592640126 +0000А еще получить желаемое можно с помощью утилиты «ps»
ps --no-headers -o lstart -C psВремя и дата равны времени запуска процесса ps
Tue Jul 18 11:44:07 2023Следом идет команда «printf»
printf '%(%c)T\n'Это встроенная команда в оболочку Bash. Выводится дата и время в соответствии с установленной локалью.
Tue Jul 18 11:44:53 2023А еще можно так:
( T='\t' ; echo ${T@P} )
( T='\T' ; echo ${T@P} )
( T='\@' ; echo ${T@P} )
( T='\A' ; echo ${T@P} )
( T='\D{%X%t%x}'; echo ${T@P} )
${parameter@P} начиная с версии bash 4.4
16:16:22 04:16:26 04:16 PM 16:16 16:16:39 07/18/23Ну и фаталити на закусочку, выведем unixtime тремя разными способами. Эквивалентно команде:
date '+%s'
printf '%s\n' "$EPOCHREALTIME" printf '%s\n' "$EPOCHSECONDS" printf '%(%s)T\n' 1689686418.954954 1689686418 1689686418Вообще редко такое может пригодиться, но пару раз на собесах какие-то упоротые техдиры задавали подобный вопрос. Не знаю откуда они такое берут, но факт остается фактом. Разнообразь свои скрипты такими замысловатыми конструкциями и ни один девопс (кроме тебя естественно) нихрена не поймёт. Создашь басфактор и будешь самым незаменимым в коллективе 😠 пам пам пам Всем добра котики! tags: #bash #linux — 🟢 Подпишись: @bashdays
HUY.txt, давай создадим его командой:
echo '12345' > HUY.txtОпыты проводим над утилитой
sed. Исследовать будем команду:
sed -i.tmp 's/1/2/' HUY.txtКлюч
-i означает редактирование файла на месте, принимает необязательный суффикс tmp. Если суффикс задан, то будет создана копия файла с предыдущим содержанием.
Команда s/// это команда замены, одного на другое. То есть в примере мы меняем (1) на (2) в файле HUY.txt
Погнали изучать кишки
strace -ye '/^open',read,write,rename,close sed -i.tmp 's/1/2/' HUY.txtВыведет
1. openat(AT_FDCWD, "HUY.txt", O_RDONLY) = 3</tmp/HUY.txt>
2. openat(AT_FDCWD, "./sedvKFsXv", O_RDWR|O_CREAT|O_EXCL, 0600) = 4 </tmp/sedvKFsXv>
3. read(3</tmp/HUY.txt>, "12345\n", 4096) = 6
4. read(3</tmp/HUY.txt>, "", 4096) = 0
5. close(3</tmp/HUY.txt>) = 0
6. write(4</tmp/sedvKFsXv>, "22345\n", 6) = 6
7. close(4</tmp/sedvKFsXv>) = 0
8. rename("HUY.txt", "HUY.txt.tmp") = 0
9. rename("./sedvKFsXv", "HUY.txt") = 0
10. close(1</dev/pts/0>) = 0
Теперь разберем построчно, что же произошло:
1. Открывается файл HUY.txt
2. Открывается временный файл sedvKFsXv
3. Из файла HUY.txt читаются 6 байт 12345\n
4. Пробует прочитать еще раз HUY.txt, вернулось 0 байт, найден конец строки
5. Закрывается файл HUY.txt
6. Записывается 6 байт 22345\n во временный файл sedvKFsXv
7. Закрывается временный файл sedvKFsXv
8. Переименовывается файл HUY.txt в HUY.txt.tmp
9. Переименовывается временный файл sedvKFsXv в HUY.txt
10. Что-то там где-то опять закрывается
Если подытожить получилось такое:
- Считывается исходный файл HUY.txt
- Во временный файл sedvKFsXv записывается обработанный текст
- Исходный файл HUY.txt становится резервной копией HUY.txt.tmp
- Временный файл sedvKFsXv становится текущим HUY.txt
Что нам дал этот эксперимент?
А дал он нам то, что всё работает. И теперь у нас есть понятие как это работает.
Допустим столкнулся ты с проблемой, что sed не смог что-то записать и ты не понимаешь почему. Запускаешь strace и смотришь почему:
write(4</tmp/sedvKFsXv>, "strace: exec: Permission denied\n", 6) = 6Опа, а прав на запись в папку
/tmp нет, возможно какой-то лось дырявый запретил туда запись. Отдебажили, фиксим: выставляем 3 топора (chmod 777) на папку /tmp и радуемся какие мы молодцы.
Этот способ отладки ты можешь применить не только для sed, но и для своих скриптов, программ, сервисов и т.п. Как нибудь в будущем поэкспериментируем с php и Битриксом 🤡
Как-то так. Ничего же сложного? Ну вот и я про тоже. Главное не боятся и знать куда смотреть. Ну а я тебе покажу куда смотреть и проведу тебя протоптанными дорожками.
Ладно, пойду пельмени жарить, всем хорошего понедельника! 💗
tags: #debug
—
🟢 Подпишись: @bashdays1. grep -wc '^processor' /proc/cpuinfo 2. getconf _NPROCESSORS_ONLN 3. nproc --allЭто не единственные способы заполучить желаемое, но самые релевантные. Кстати
getconf актуален и для макаводов (osx).
Для чего нам знать количество ядер? Вопрос хороший, каждый для себя сам решает. Всё зависит от задач.
К примеру заскейлил ты тачку в Selectel, через их веб панельку, но nginx продолжает работать на старом конфиге. После этого очень желательно сразу переопределить в nginx.conf параметр worker_processes.
Если Nginx выполняет работу нагружающую процессор (например SSL или gzipping), то оптимально установить эту директиву в значение, равное количеству ядер процессора.
Также, директива worker_processes, умноженная на worker_connections из секции event, даст максимально возможное количество клиентов.
Конечно же справедливо всё это ансиблом (ansible) или террой (terraform) раскатать, но это дополнительный геморрой, который никому не нужен. По крайней мере, когда это нужно было еще вчера и нет возможности писать лапшу из плейбуков.
Проще уж из скрипта узнать количество ядер, все посчитать и тем же sed’ом зареврайтить нужный тебе конфиг. Вешаешь его на крон, а оно следит за твоими ядрами и в нужный момент делает всё автоматически, хоть там каждую минуту горизонтальным масштабированием занимайся.
Прототип без ифов, так, для наглядности:
#!/bin/bash CPU_CORES=$(grep -wc '^processor' /proc/cpuinfo) sed -i "s/worker_processes.*/worker_processes $CPU_CORES;/" /etc/nginx/nginx.conf systemctl reload nginxБери на вооружение, пригодится. 😮💨 Ну а я желаю тебе хороших предстоящих выходных и береги себя! Мож чо на выходные еще закину интересного почитать. tags: #linux #nginx — 🟢 Подпишись: @bashdays
echo $(tr -dc 0-9A-Za-z < /dev/urandom | head -c 16)На выходе получаем нечто подобное из 19ти символов:
IioP0zmnPTBOuHqI xhqohdWb0r94w7di yMVEHwU0DCTYaGCq KbLwMB7Iqb28Ud4TТы в праве поменять
0-9A-Za-z и оставить к примеру только цифры 0-9, ну и соотвественно указать длину получаемой строки -c 16.
Короче, запрашиваем у устройства /dev/urandom данные (16 случайных символов), скармливаем их tr, приводим в должный вид и получаем ожидаемый результат. Красота!
Ну и кому интересно, маленько теории по tr и urandom
Команда tr (translate) используется в Linux в основном для преобразования и удаления символов. Она часто находит применение в скриптах обработки текста. Ее можно использовать для преобразования верхнего регистра в нижний, сжатия повторяющихся символов и удаления символов.
Устройство /dev/urandom это генератор псевдослучайных чисел. Псевдослучайность urandom зависит от системы. Во многих случаях random и urandom генерируют символы по одному и тому же алгоритму.
Чтение данных устройства /dev/urandom возвратит столько байтов, сколько было запрошено.
Ну и по ключам tr которые использовались.
-c - удалить все символы, кроме тех, что в первом наборе
-d - удалить символы из первого набора
Чтобы это ни значило, это работает. Просто используй 😊!
tags: #linux #bash
—
🟢 Подпишись: @bashdayssed, то скорость извлечения нужного слова из файла — ну совсем никакая, сидишь как баран ждешь, пока этот сыщик Коломбо, что-то откроет-отроет. Но в век высокий технологий, скорость как-никак в приоритете.
SED – это потоковый редактор текста (от stream editor), c помощью которого можно выполнять с файлами множество операций вроде поиска и замены, вставки или удаления. При этом чаще всего он используется именно для поиска и замены.
Давай разгонять этого ленивца «Блиц, скорость без границ»
Каков план:
1. Отсортировать содержимое txt файла по алфавиту
2. Проиндексировать данные
Так как файл у меня содержит слова (не цифры и т.п.), то индексами я сделаю диапазоны строк начинающихся на определенную букву.
sort -o data.txt data.txtЭта команда отсортирует содержимое файла data.txt по алфавиту и перезапишет его в нужном мне формате. Пишем код Проверяем первый аргумент переданный в скрипт. Если передать что-то кроме букв, то экзитим:
[[ $1 =~ ^[a-z]+$ ]] || exitБерем первую букву из первого аргумента и присваиваем её переменной.
INDEX=${1:0:1}
Инициализируем переменную SEARCH значением первого аргумента, чтобы нам было удобнее в будущем. Это будет искомым словом по нашей базе.
SEARCH=$1Далее объявляем переменную DATA. В которой будет указываться путь до нашего файла. Который мы заранее отсортировали по алфавиту.
DATA=data.txtОбъявляем и инициализируем hash ассоциативный массив. Будет работать начиная с bash 4.0, это важно.
declare -A HASH=(['a']=1,1001 ['b']=1002,2002 ['c']=2003,3003
)
Тут я сократил, ниже скрипт полностью.
Здесь можешь ручками заполнить этот хэш, а можешь еще один скрипт написать, чтобы автоматом заполнился. Но проще ручками, чтобы не sed -n "${HASH[$INDEX]}p" | sed -n "/^${SEARCH}$/{p;q}"
Весь скрипт будет выглядеть так:
#!/bin/sh
[[ $1 =~ ^[a-z]+$ ]] || exit
INDEX=${1:0:1}
SEARCH=$1
DATA=path
declare -A HASH=(
['a']=1,1001 ['b']=1002,2002 ['c']=2003,3003
['d']=3004,4004 ['e']=4005,5005 ['f']=5006,6006
['g']=6007,7007 ['h']=7008,8008 ['i']=8009,9009
['j']=9010,10010 ['k']=10011,11011 ['l']=11012,12012
['m']=12013,13013 ['n']=13014,14014 ['o']=14015,15015
['p']=15016,16016 ['q']=16017,17017 ['r']=17018,18018
['s']=18019,19019 ['t']=19020,20020 ['u']=20021,21021
['v']=21022,22022 ['w']=22023,23023 ['x']=23024,24024
['y']=24025,25025 ['z']=25026,26026 )
sed -n "${HASH[$INDEX]}p" "$DATA" | sed -n "/^${SEARCH}$/{p;q}"
Ничего сложного, а самое главное мы используем инструменты, которые поставляются из коробки с Linux. Ну и конечно же в несколько тысяч раз повысили и оптимизировали скорость чтения данных из огромного текстового файла.
Не нужно стрелять из пушки по воробьям используя какие-то мастодонтные решения. С помощью гвоздя и палки, можно творить настоящие чудеса.
Надеюсь коллеги вам было интересно, продолжим завтра!
Show must go on ☺️
tags: #linux #bash
—
🟢 Подпишись: @bashdaysJul 11 00:00:01 bashdays CRON[123456]: (user) CMD (/var/www/htdocs/bin/console export:users)Пожалуй очень информативно, правда? Ну запустился, а что произошло внутри,
>> /var/log/cronlogs/www-console.log
тип того:
* */1 * * * php /var/www/htdocs/bin/console export:users >> /var/log/cronlogs/www-console.logТеперь весь выхлоп с команды
console export:users будет аккуратненько логироваться в файл www-console.log. По итогу в файле получаем красоту:
Папку только не забудь создать в /var/log, а то оно дурное и не додумается само.
[2023-07-11 10:04:20] service.stats.INFO: Processing users [2023-07-11 10:04:20] service.stats.INFO: Updating local stats [2023-07-11 10:04:20] service.stats.INFO: Updating count users [2023-07-11 10:04:26] service.stats.INFO: Updating total stats [2023-07-11 10:04:26] service.stats.INFO: Export SuccessПо желанию грепаем нужное нам, ну и всегда остаемся в курсе событий, зная что же происходит под капотом. Кстати отлично помогает при дебаге. То что кроновская задача выполнилась, еще ни о чем не говорит, внутри может быть злобный эксепшен 😡 Да и не забываем накинуть logrotate, чтобы место на диске не сжирало бигдатой, а лучше сразу перенаправляй это дело в какой-нибудь агрегатор логов типа ELK или LOKI. Бонусом лови конфиг для logrotate, чтоб в гугле не лопатить:
/var/log/cronlogs/www-console.log {
su root root
daily
missingok
rotate 14
compress
notifempty
sharedscripts
}
Есть ли другие способы мониторинга для подобных ситуаций? Конечно есть! Но способ который я описал выше, используется практически всеми. По крайней мере я на него натыкаюсь постоянно у ребят в различных компаниях.
Потому что люди не любят усложнять и предпочитают быстренько наговнокодить, получить желаемый результат и дальше смотреть свои любимые сериальчики и наши мемчики тут и тут.
О других способах я обязательно напишу отдельный пост, пусть это будет интригой, ну а может ты сам загуглишь и нам потом расскажешь.
В общем адью, албибэк, увидимся! 😎
tags: #linux
—
🟢 Подпишись: @bashdays /usr/local/sbin/config-agent.sh делаем ему chmod +x (чтобы он был исполняемым) и ставим его в крон */1 * * * *
#!/bin/bash
DIR=/tmp/nginx-configs
if [ ! -d "$DIR" ];
then
git clone git@git.bashdays.ru:dev/nginx-configs.git /tmp/nginx-configs
fi
cd /tmp/nginx-configs && git pull --quiet
RSYNC=$(rsync -aizh /tmp/nginx-configs/ /etc/nginx)
if [ $? -eq 0 ]; then
if [ -n "${RSYNC}" ]; then
systemctl reload nginx
fi
else
exit 0
fi
Давай смотреть что тут происходит:
1. Создаем отдельную папку если ее нет в /tmp
2. Клонируем в нее эталонные конфиги с git репозитория
3. Переходим в папку и забираем последние изменения
4. С помощью rsync, синкаем эталон в папку /etc/nginx
5. Если файлы заменились в /etc/nginx то делаем reload
Всё!
Знак $? используется для поиска возвращаемого значения последней выполненной команды.
Теперь у нас есть полный контроль от кривых рук. Ну а чтобы изменить какой-то конфиг, нужно заморочиться и сделать это через git репу со всеми вытекающими кодревью и т.п.
Как говорится - на bash’ке моей горшок, а в кармане пирожок!
Всем хорошего понедельника коллеги![===>xxxxxxxx] 20%Пошли тыкать:
pv /var/log/php/php-fpm.log | gzip > php-fpm.gz
33MiB 0:00:03 [ 114MiB/s] [==========> ] 32% ETA 0:00:06
Наглядно видно, что через пайп за 3 секунды прошло 33Мб — это 32% от всего объема, операция займет еще 6 секунд. cat, её возможности намного шире, тут уже зависит на сколько ты будешь оригинален в своих скриптах и велосипедах.
Утилита укомплектована внушительной кучей различных ключей для запуска. Но я не привередливый и пользуюсь ей исключительно функционалом из коробки. Если есть время, кури --help или можешь глянуть на доисторической официальной страничке, а при желании и скомпилировать.
Из клёвых ключей, есть:
-l строчный режим, pv может ограничивать скорость и просто в байтах -L 100 – необходимое ограничениеДопустим у тебя есть база данных, которая не толерантна к большому объёму INSERT-ов и UPDATE-ов. Но у тебя также есть большой дамп с кучей таких операций. Как безопасно импортировать дамп в базу и не убить её
# скорость ограничена 100 тысячами строк в секунду pv -L 100k -l dump.sql | mysql -u root -p # скорость ограничена 100 строками в секунду pv -L 100 -l dump.sql | mysql -u root -pНу и на закусочку, баянище:
pv /dev/urandom > /dev/null
23MB 0:00:05 [ 12,9MB/s] [...<=>..........]
Не болей и береги себя. Всем хороших предстоящих выходных. Тут еще столько всего неизвестного и полезного ожидает тебя, мама не горюй )))
Увидимся в понедельник! 💛
tags: #utils
—
🟢 Подпишись: @bashdays
现已上线!2025 年 Telegram 研究 — 年度关键洞察 
