Bash Days | Linux | DevOps
23.2K subscribers
127 photos
22 videos
600 links
Авторский канал от действующего девопса

Самобытно про разработку, devops, linux, скрипты, тестирование, сисадминство, техдирство, пиэмство и за айтишную жизу.

Автор: Роман Шубин
Реклама: @maxgrue

Курс: @tormozilla_bot

РКН: https://two.su/bashdays
Download Telegram
Очередные грабли. При клонировании Linux машин, клонированные машины получают по DHCP тот же IP адрес, что и донор. Возникает конфликт интересов.

Проблема распространенная, лечится довольно просто.

1. Меняем MAC адреса на клонах
2. Меняем machine-id на клонах

В первом случае всё просто, делается через морду VBox, либо через консольные команды:

ip link
sudo ip link set dev eth0 down
sudo ip link set dev eth0 address 00:11:22:33:44:55
sudo ip link set dev eth0 up


Новый MAC адрес можешь сгенерить такой командой:

printf '02:%02x:%02x:%02x:%02x:%02x\n' $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256))


Во втором случае это файл /etc/machine-id, в нем хранится уникальный идентификатор машины.

ed76c4f179044828b51028aadf9f4981


Удаляем и генерим новый machine-id:

sudo rm /etc/machine-id sudo systemd-machine-id-setup


Перезапускаем виртуальную машину. DHCP выдаёт этой машине новый IP адрес, который не будет конфликтовать с донором.

Вот и вся наука. Пользуйся.

🛠 #linux #linuxfactory

@bashdays / @linuxfactory / @blog
Please open Telegram to view this post
VIEW IN TELEGRAM
86
Продолжаем тыкать SelectOS

На этот раз, я покажу как раскатать ОС в облаке из ISO образ (не из коробки).

Наступлю на несколько граблей, задебажу, пофиксю и пообщаюсь с саппортом. Короче будет интересно, го 👇

🦖 Ставим SelectOS в облако

Предыдущие посты:

- Пробуем SelectOS
- SelectOS в деле

🛠 #linux #review

@bashdays / @linuxfactory / @blog
Please open Telegram to view this post
VIEW IN TELEGRAM
230
Решил поделиться своим опытом использования Samba.

🔤🔤🔥🔤🔤🔤🔤

Ну, не то, чтобы прям Samba, но всякими smb-комбайнами.

Я сопровождаю небольшие конторки от 5 до 100 компов. Покупать виндовые серверы для такого количества — просто излишество. Если для маленьких конторок, для 10 машин, еще можно расшарить папку на win-pro, то дальше нужно думать.

Начал я с FreeNas, потом Nas4free, TrueNas, OMV, и когда поднабрался опыта, остановился на Samba без всяких web-интерфейсов.

Но я не об этом. Тем, кто думает, что можно легко заменить win-server на Samba Посвящается.

Основное отличие виндового и линуксового сервера — права доступа. У винды права реализованы лучше и гибче. Сейчас мне в комментах напишут про ACL, особенно те, кто их не использует.

Винда, устанавливает права на папку, и в зависимости от прав на папку — выставляются права на файл. При перемещении файла из папки в папку — права могут меняться. На линуксе файл получает права при создании, и потом с ними живет.

Большинство проблем, связанных с правами на Samba, связаны именно с ACL.

Ситуация следующая, два пользователя U1, U2, три папки D1, D2, D3. U1 имеет доступ D1, D2, U2 к D2, D3. На винде, если U1, создаст файл в D1, а потом перенесет в D2 - пользователь U2 будет иметь к нему доступ, а на линуксе нет.

Для некоторых папок приходится делать cron-скрипт для сброса прав. Может у кого-то есть опыт использования inotify для этого, поделитесь.

Не знаю, как Вы, а я для себя решил отказаться от ACL. Потому что использовать getacl setfacl не удобно.

Рекомендую для маленьких контор использовать разрешения на шАры и обычные линуксовые права. Просто в этом случае расшаренных папок много.

Ну, про то, что таблицы символов для файловых систем не совпадают — я уже как-то писал. Проблема возникает, если в конторе часть пользователей на винде, часть на linux.

В общем, на мой взгляд пока нет полноценной замены для Win-сервера в качестве файлопомойки, для контор среднего и большого размера.

🛠 #windows #linux

@bashdays / @linuxfactory / @blog
Please open Telegram to view this post
VIEW IN TELEGRAM
36
Я тут недавно игрушку написал. Ну, как написал, реализовал.

🔤🔤🔥🔤🔤🔤🔤

Вариант 2048, оптимизированный по занимаемому экранному пространству.

➡️ Ознакомиться с игрушкой можно здесь.


Но у нас тут люди серьезные, поэтому рассмотрим проблемы, возникающие при реализации вывода скриптов.

Простой пример:

for i in {1..100};do
printf "#"
sleep .3
done


Код просто выводит символы #, примерно 3 штуки в секунду. Все работает нормально, пока пользователь не начинает что-то набирать на клавиатуре.

И тогда получаем:

######sb#sf#bg#sfbg#wfgb#wg#fg#b###^[[A#^[[B#^[[D#^[[A#^[[B##


Убрать эхо вывода на терминал просто:

stty -echo


Классная команда. После ее выполнения нажатые клавиши не отображаются.

Все работает, команды выполняются, результат отображается, а набранная команда — нет. Как при наборе пароля.

Вернуть все просто:

stty echo


Но в скриптах желательно обрабатывать прерывания:

trap 'exit' INT HUP TERM
trap 'stty echo;tput cnorm' EXIT
# stop terminal echo
stty -echo
#hide cursor
tput civis


Применять исключительно для причинения добра.

man stty
man tput
help trap


🛠 #bash #linux #games

@bashdays / @linuxfactory / @blog
Please open Telegram to view this post
VIEW IN TELEGRAM
50
Если тебе необходимо изменить файл сервиса в Linux, не нужно пиздовать ручками в папку /etc/systemd искать и править его.

Постоянно вижу этот кейс, чёто там ищут по папкам, ебутся. Правят оригинальный файл и все к хуям ломают.


А бест-практика уже заложена в systemctl!

Достаточно выполнить команду:

sudo systemctl edit nginx


Откроется редактор с нужным сервисом. НО, редактировать ты будешь не корневой юнит, а override. То есть прокладку, которая переопределит параметры основного юнита.

В моём случае с nginx будет открыт файл:

/etc/systemd/system/nginx.service.d/override.conf

В нем я переопределяю нужные параметры для сервиса и НЕ трогаю основной файл юнита.

А если я хочу править корневой?

Да похуй, вот тебе команда:

sudo systemctl edit --full nginx


Теперь будет открыт основной файл сервиса, можешь лезть в него своими шаловливыми ручонками и создавать проблемы.

1. Копирует оригинальный юнит-файл из /lib/systemd/system/nginx.service в /etc/systemd/system/nginx.service

2. Открывает его в редакторе.

3. После сохранения — systemd использует именно эту копию в /etc/.

Это безопасный способ редактировать полные юниты, без риска перезаписи при обновлении пакетов.

Есть еще ключ --force, но про него погугли сам.


Как проверить валидность файла юнита?

systemd-analyze verify /etc/systemd/system/nginx.service


В ответ получишь:

/etc/systemd/system/nginx.service:31: Missing '=', ignoring line.


Ага, ошибочка, правим и только после этого можно делать:

sudo systemctl daemon-reload
sudo systemctl restart nginx


Короче учись работать правильно и всё у тебя будет хорошо!

С пятницей! Хороших тебе предстоящих выходных и береги себя!

🛠 #linux #tricks #debug #systemd

@bashdays / @linuxfactory / @blog
Please open Telegram to view this post
VIEW IN TELEGRAM
7204
Сегодня будем профилировать Linux сервисы.

В прошлый раз мы с тобой посмотрели, как без хуйни обращаться с юнитами.

Сегодня же посмотрим, как определить какие юниты дольше всего грузятся при старте системы.

Это достаточно пиздатый хак, особенно при отладке медленного запуска системы. Ну и изобретать нам ничего не придется, всё уже придумали за нас.


Запускаем и смотрим:

systemd-analyze blame


По итогу получаем список юнитов и их время запуска.

17.084s docker.service
10.961s systemd-journal-flush.service
7.595s containerd.service
7.496s cloud-final.service
7.189s cloud-init-local.service
3.260s apt-daily-upgrade.service
2.522s cloud-init.service
2.095s dpkg-db-backup.service
1.991s networkd-dispatcher.service
1.963s chrony.service


В моём примере дольше всего грузится служба с докером.

Отрубаем службу и радуемся приросту в 17 секунд. Но НЕТ! На самом деле тут всё немного сложнее.

Иногда сам юнит стартует достаточно быстро, но сука ждет другой юнит, который «Блиц — скорость без границ».

Смотрим цепочку зависимостей:

systemd-analyze critical-chain


└─docker.socket @13.269s +8ms
└─sysinit.target @13.261s
└─cloud-init.service @10.735s +2.522s
└─systemd-networkd-online.service @12.806s +31ms
└─systemd-networkd.service @12.741s +59ms


Ага, то есть дело тут не только в юните докера, юнит ждет другой юнит, в нашем случае докер ждет пока на сервере поднимется сетка.

То есть docker.service зависит от systemd-networkd-wait-online.service, ну и дальше пошли по цепочке.

Почему так?

Docker по умолчанию может иметь After=network-online.target, а при использовании systemd-networkd это приводит к ожиданию systemd-networkd-wait-online.service.

А чё делать?

Выйти из айти, купить яхту и поехать ловить крабов.

Если тебе нужно, чтобы Docker НЕ ждал сеть, поменяй юнит:

sudo systemctl edit docker.service


[Unit]
After=network.target
Wants=network.target


Ну или вообще убрать After=network-online.target, если нет зависимости от сети на старте.

После этого снова смотрим выхлоп через blame:

4.739s cloud-init-local.service
4.041s containerd.service
2.329s dev-sda1.device


Всё блядь! Теперь докер не тормозит загрузку, но после загрузки системы докер исправно работает.

Вот такими хитрыми манипуляциями можно профилировать это говнище. Не скажу что часто этим пользуюсь, но всегда держу на вооружении.

Забирай в копилку, для дебага маст-хев!

🛠 #linux #tricks #debug #systemd

@bashdays / @linuxfactory / @blog
Please open Telegram to view this post
VIEW IN TELEGRAM
3126
Как безопасно тестировать юниты

Так, мы уже знаем как безопасно переопределять юниты, как их дебажить и ну и так по мелочи.

Но не знаем как всё это дело тестировать. А для тестирования тебе пригодится ключик --runtime.

Ключ --runtime — создаёт временное переопределение, которое исчезнет после перезагрузки.


Идеально подходит, если ты тестишь, не уверен или не хочешь ничего портить.

А вот и сама команда:

SYSTEMD_EDITOR=vim systemctl edit --runtime nginx


Как ты мог заметить, зачастую по умолчанию открывается nano редактор, но у многих с ним проблемы. Поэтому в команде сразу втыкаем нужный редактор, например mcedit или vim.


Всё! Теперь правим юнит, тестируем. Временный файл с override будет создан тут /run/systemd/.

И самое главное — все изменения сохранятся только до следующей перезагрузки системы.

А какая в этом польза?

1. Для временного изменения конфигурации systemd без затрагивания оригинального файла.

2. Для тестов или отладки (например, сменить ExecStart для nginx только на время текущей сессии).

3. Чтобы не создавать перманентные изменения, которые могут повлиять на стабильность после перезагрузки.

Пример с nginx

Хочу временно запустить nginx с другим конфигом! Создаю рантайм.

[Service]
ExecStart=
ExecStart=/usr/sbin/nginx -c /home/user/nginx-bashdays.conf


Перезапускаю nginx и радуюсь результату, теперь nginx запущен с другим конфигом.

А почему ExecStart идет дважды?

Хе брат, это очередная приколюха systemd. Оно очищает предыдущее значение ExecStart из основного юнита. А следующая строка задаёт новое значение.

Без этой хуйни systemd бы просто добавил вторую команду, не заменив первую.

Думаю на этом можно закончить. Я неочевидную базу выдал, а ты стал еще сильнее. Изучай и ничего не бойся!

🛠 #linux #tricks #debug #systemd

@bashdays / @linuxfactory / @blog
Please open Telegram to view this post
VIEW IN TELEGRAM
154
Как разгребать гавно в юнитах

Ладно, не гавно, а override файлы, которых может быть нихуя не одна штука. Причем несколько для одного юнита.

Не знаю нахуя так делают, но временами такое встречается. Особенно на каких-то легаси серверах, которые работают со времен фидонета.

Короче, все что нам нужно это команда:

sudo systemctl revert nginx


Эта команда отменяет все локальные изменения юнита nginx и возвращает его к состоянию по умолчанию, заданному в оригинальных unit-файлах, поставляемых системой или пакетом.

Короче достаточно прикольная штука, когда нахуевертил, но не знаешь как откатиться.

Команда удаляем override-файлы в:

/etc/systemd/system/nginx.service.d/
/etc/systemd/system/nginx.service


И следом будет использован оригинальный unit-файл, который обычно расположен в /lib/systemd/system/nginx.service.

Когда это полезно?

Если ты вносил изменения через systemctl edit, вручную правил nginx.service, или добавлял drop-in'ы — и хочешь откатиться к дефолтной конфигурации, revert делает это безопасно.

Наглядные примеры приводить не буду, думаю и так все понятно, что было и что будет.

Ну а ты носи в это в голове и никогда не бойся экспериментировать. Любой факап — твой опыт.

Предыдущие посты на тему systemd ищи по тегу #systemd


🛠 #linux #tricks #debug #systemd

@bashdays / @linuxfactory / @blog
Please open Telegram to view this post
VIEW IN TELEGRAM
462
Почему в юнитах не работает Environment.

Сразу пример:

[Service]
Environment="FOO=bar"
ExecStart=/bin/bash /usr/local/sbin/bashdays.sh


Сделал юнит, но в скрипт bashdays.sh не передаётся переменная FOO. Хотя логически всё правильно.

Тут снова приколы.

➡️ 1. Скрипт запускается не напрямую, а через интерпретатор.

Если в ExecStart указан скрипт с shebang’ом (#!/bin/bash), systemd запускает его как отдельный процесс, и переменные окружения передаются.

Но если ты укажешь в ExecStart сам интерпретатор, вот так:

ExecStart=/bin/bash /usr/local/sbin/bashdays.sh


То переменная FOO, заданная через Environment=, не попадёт в подскрипт, потому что ExecStart запускает bash, а уже bash запускает — скрипт, и переменные окружения само собой нихуя не передаются.

Как правильно?

Вот так:

[Service]
Environment="FOO=bar"
ExecStart=/usr/local/sbin/bashdays.sh


А сам скрипт:

#!/bin/bash

echo "FOO is $FOO"


Всё! Теперь переменная из юнита будет корректно передаваться в скрипт.

➡️ 2. Использовать EnvironmentFile=

Если у тебя дохуя переменных, то выносим их в отдельный файл, например сюда /etc/bashdays-service.env.

FOO=bar
BAZ=qux


А в самом юните прописываем:

[Service]
EnvironmentFile=/etc/bashdays-service.env
ExecStart=/usr/local/sbin/bashdays.sh


Всё! Теперь переменные считываются из файла и скрипт их видит.

➡️ 3. Передавать переменные прямо в ExecStart

[Service]
ExecStart=/bin/bash -c 'FOO=bar exec /usr/local/sbin/bashdays.sh'


Тут особо и комментировать нечего, всё очевидно.

Как отладить и задебажить?

А вот так:

systemctl show nginx


Вместо nginx подставляешь свой сервис и наблюдаешь все переменные которые передались. В наших примерах увидишь Environment=FOO=bar.

Справедливо не только для собственных юнитов, но и для других, например для того же nginx или docker.

Как вариант, можешь добавить в скрипт такую хуйню:

env > /tmp/env.log


И смотришь, какие переменные реально передаются в твой скрипт.

Еще одна база выдана, вроде очевидные вещи, но так глубоко в это никто не лезет. Пользуйся.

🛠 #linux #tricks #debug #systemd #bash

@bashdays / @linuxfactory / @blog
Please open Telegram to view this post
VIEW IN TELEGRAM
783
Три скрытых героя systemd

А вот и сами герои: timer, path и socket

Это невидимые юниты systemd, которые могут заменить cron, inotify`и даже `xinetd.

➡️ 1. Timer

Про timer ты наверняка слышал. Это альтернатива crontab. Позволяет запускать сервис по расписанию. Вместо того чтобы писать крон-джобы, ты создаёшь .service и .timer.

Пример:

/etc/systemd/system/backup.service

[Unit]
Description=Backup job

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/backup.sh


/etc/systemd/system/backup.timer

[Unit]
Description=Run backup daily

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target


Активируем:

sudo systemctl enable --now backup.timer


Persistent=true гарантирует запуск пропущенной задачи, если система была выключена.

Всё! Никаких тебе легаси кронтабов, все работает на юнитах, запускается бэкапилка, тикает таймер.

➡️ 2. Path

Работает как inotifywait или File Watcher: следит за файлами/папками и запускает сервис при изменении.

Пример:

/etc/systemd/system/upload.path

[Unit]
Description=Watch upload folder

[Path]
PathModified=/var/www/bashdays/upload
Unit=process-upload.service

[Install]
WantedBy=multi-user.target


/etc/systemd/system/process-upload.service

[Unit]
Description=Process uploaded files

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/process-upload.sh


Теперь каждый раз когда в папке /var/www/bashdays/upload что-то меняется, автоматически запускается скрипт process-upload.sh.

Тут уже от твоих предпочтений зависит, как и с чем это скрещивать, но кейсов можно придумать довольно дохуя. Например, проверка антивирусом, или запуск какого-нибудь ffmpeg.


➡️ 3. Socket

Заменяет ручной systemctl start, активируя сервис при первом подключении к сокету. Аналог inetd/xinetd

Нихуя не понятно, но на примере сейчас всё прояснится.

Пример:

/etc/systemd/system/echo.socket

[Unit]
Description=Echo socket

[Socket]
ListenStream=12345
Accept=yes

[Install]
WantedBy=sockets.target


/etc/systemd/system/echo@.service

[Unit]
Description=Echo service

[Service]
ExecStart=/usr/bin/nc -l -p 12345 -e /bin/cat
StandardInput=socket


В примере, сервис НЕ работает постоянно, он стартует, только когда кто-то подключается к порту 12345.

Когда ты используешь .socket с Accept=yes, systemd открывает сокет сам и ждёт подключения. А когда подключение приходит — создаёт новый экземпляр сервиса, подставляя туда данные об этом соединении. После завершения — сервис умирает. Всё очень экономно и прозрачно.

Как понять, какой экземпляр стартует?

systemd запускает echo@<ID>.service, где <ID> — уникальный идентификатор подключения (например, PID или номер сокета).

journalctl -u echo@*


Зачем нужны скрытые юниты?

1. Не нужен cron, всё централизовано в systemd.
2. Не нужен inotify-tools.
3. Сервисы не висят без дела, запускаются только когда нужно
4. Журналирование через journalctl

Вот такие пироги. В повседневной работе я применяю timer и path, с сокетами как-то сильно не приходилось париться.

Ну а ты попробуй хотя бы перетащить свои кронджобы в timer и порадоваться бест-практикам.

🛠 #linux #tricks #debug #systemd #bash

@bashdays / @linuxfactory / @blog
Please open Telegram to view this post
VIEW IN TELEGRAM
9103