LinuxSkill - Сводки с прода и Шпаргалки
10.7K subscribers
68 photos
102 videos
12 files
531 links
Следим за новостями Linux, DevOps и ИБ, чтобы быть готовым к любым факапам.
Бонусом — плотные шпаргалки и чеклисты для ежедневной работы в терминале.

📩 По всем вопросам: @chorapov

Зеркало в MAX: https://max.ru/LinuxSkill

РКН https://vk.cc/cMUwm4
Download Telegram
🧨 Ты ищешь в strace open() — а его там нет

Полез за выжимкой по strace в свою базу конспектов, получил бодрый совет: фильтруй по -e trace=open,openat, увидишь, где программа ищет конфиг. Решил проверить перед постом. Ubuntu 24.04, strace 6.8. Не увидел ничего.

Подопытный — скрипт, который проверяет конфиг через test -f:


# фильтр из конспекта
strace -f -e trace=open,openat ./finder.sh \
| grep myapp
# пусто

# весь файловый класс
strace -f -e trace=%file ./finder.sh | grep myapp
# newfstatat(AT_FDCWD, "/etc/myapp/config.ini",
# 0x7ffc0f32bee0, 0) = -1 ENOENT


Программе незачем открывать файл, чтобы понять, что его нет. Она зовёт newfstatat, и фильтр по open его срезает. Фильтр отрезает ровно то, ради чего ты запускал strace.

Заодно: open( в выводе cat — 0 вхождений, openat( — 3. glibc на x86_64 давно ходит через openat. Искать в трейсе open() бессмысленно.

Рабочий вариант


# -Z печатает только вызовы, вернувшие ошибку
strace -f -Z -e trace=%file \
-o /tmp/t.log ./myapp

grep -E 'ENOENT|EACCES' /tmp/t.log


-o тут не для красоты. Без него 2>&1 | grep смешает трейс с выводом самого приложения, у меня в грепнутый поток прилетело cat: /nonexistent: No such file от подопытного.

Если процесс уже крутится


PID=$(systemctl show -p MainPID --value nginx)
sudo strace -f -Z -e trace=%file -p $PID


Честно: эту связку я проверял только по документации, systemd-хоста под рукой не было. Синтаксис --value живёт с systemd 230.

Что читать в ошибках

▪️ ENOENT — такого пути нет
▪️ EACCES — нет прав на файл или каталог
▪️ ENOTDIR — в середине пути не каталог
▪️ ELOOP — symlink закольцевался

Половина «config not found» в проде — это EACCES, а не отсутствие файла.

Грабли: -Z появился в strace 5.2 от 12 июля 2019. На старом RHEL 7 со strace 4.12 его нет, там остаётся grep по ENOENT. В контейнере нужен --cap-add=SYS_PTRACE. И трейс тормозит процесс в разы — на живом сервисе цепляйся коротко.

А вы чем ловите такие вещи — strace, ltrace или сразу lsof -p?

#Linux #strace #DevOps #Debug #SRE
👍6
Ходовой набор для отладки bash-скрипта известен всем: set -euo pipefail сверху, set -x вокруг мутного места и ловушка DEBUG с read, чтобы останавливаться перед каждой командой. Прогнал этот набор на Ubuntu 24.04, bash 5.2. Три вещи из него ведут себя не так, как ожидаешь.

Сначала то, что работает без оговорок:


# падаем на ошибке, пустой переменной и в пайпах
set -euo pipefail


pipefail не декорация: false | true без него даёт код 0, с ним 1. А set -u ловит то, до чего не доберётся проверка синтаксиса:


echo "путь: /${UNSET_VAR}/data"
# bash: UNSET_VAR: unbound variable


Но `set -e` замолкает в условиях. Вызвал функцию через if — код возврата внутри перестал что-либо значить:


check() { false; echo "функция продолжила"; }
if check; then :; fi
# echo выполнился, rc=0


Трассировка. Обычно пишут просто set -x, но дефолтный PS4 печатает голый плюс — в скрипте на 300 строк не поймёшь, где ты:


PS4='+ ${BASH_SOURCE}:${LINENO}: '
set -x
do_something_risky
set +x


Теперь в каждой строке трассировки видно файл и номер:


+ g.sh:4: mkdir -p /tmp/zz


Пошаговый режим. Типовой рецепт — функция с read и ловушка DEBUG:


dbg() { read -p "$BASH_SOURCE:$LINENO? " _; }
trap 'dbg' DEBUG


В нём три поломки, и каждая тихая.

Первая: $LINENO и $BASH_SOURCE внутри функции указывают на саму функцию. На всех командах печаталось line=3 — строка, где стоит read. Реальные 6 и 7 не появились ни разу. Координаты надо передавать аргументами:


dbg() { read -r -p "[$1:$2] $3? " _; }
trap 'dbg "$BASH_SOURCE" "$LINENO" "$BASH_COMMAND"' DEBUG


Вторая: ловушка не заходит внутрь функций. Без set -T виден только вызов work, а команды в её теле пропадают — как раз там, где обычно и прячется баг.


set -T


Третья самая злая. read в ловушке читает тот же stdin, что и скрипт. Подал в цикл три строки — дошла одна:


printf 'alpha\nbeta\ngamma\n' | bash f.sh
получил: beta


Две строки съела отладка — отладчик изменил поведение отлаживаемого. Плюс при неинтерактивном stdin приглашение read -p не печатается вовсе, и скрипт молча проносится мимо пауз. Лечится перенаправлением:


dbg() { read -r -p "$1? " _ < /dev/tty; }


С ним прошли все три строки, паузы работали даже при stdin из /dev/null.

И про bash -n, который советуют как «проверку перед запуском». Он про синтаксис и только: незакрытый if поймал с кодом 2, а несуществующую команду и rm -rf /$UNSET_VAR/data пропустил с кодом 0.

Прогонял на двух машинах, bash 5.2.21 и 5.2.37 — поведение одинаковое.

А вы set -T вообще используете или обходитесь set -x?

#Linux #Bash #Debug #DevOps #Автоматизация
👀2👍1
Посмотреть, какие интерфейсы подняты, и не принять погасший порт за живой

Краткий статус интерфейсов


ip -4 -br address show up


Нюанс: up фильтрует по состоянию линка, а не по наличию адреса. Погасил eth0 — с ключом он пропал из вывода совсем, без ключа виден как DOWN со всеми адресами на месте. Пустая строка тут не значит «адреса нет».

Второй адрес без алиасов вида eth0:1


ip address add 10.0.0.50/24 dev eth0
ip address del 10.0.0.50/24 dev eth0


Второй адрес встаёт рядом с первым, при удалении линк не дёргается.

Узнать, куда реально пойдёт пакет


ip route get 8.8.8.8
# 8.8.8.8 via 192.0.2.1 dev eth0 src 192.0.2.2


Не читает таблицу, а спрашивает у ядра готовое решение вместе с исходящим адресом. Для локального ответит local 192.0.2.2 dev lo.

Увидеть все таблицы маршрутизации


ip route show table all


Обычный show дал одну строку, table all — шесть, включая local с broadcast и host-маршрутами. С VPN и контейнерами разница уходит в десятки строк.

Посмотреть, кто есть в сети рядом


ip -4 neigh show
ip -6 neigh show


Нюанс: ip neigh — не ARP-таблица, как пишут в шпаргалках, а таблица соседей: ARP плюс IPv6 NDP. Без ключа -4 или -6 получишь обе вперемешку. arp -n показывал только первую, отсюда и путаница.

Сбросить кэш соседей


ip -s -s neigh flush dev eth0


Нюанс: без -s -s команда молчит и отдаёт код 0 — не отличишь «очистил десять записей» от «там было пусто». С ключом печатает удалённые записи и итог *** Round 1, deleting 1 entries ***.

Дать интерфейсу второе имя без даунтайма


ip link property add dev eth0 altname eno2


altname eno2 появляется в ip link show eth0, и по новому имени интерфейс находится: ip address show dev eno2 отдаёт eth0. Есть с ядра 5.8 и iproute2 5.8, на RHEL 7 синтаксис не разберётся.

Всё, что пишет, требует CAP_NET_ADMIN — в контейнере без --cap-add=NET_ADMIN упадёт.

А вы ip route get в отладке применяете или сразу лезете в show?

#Linux #iproute2 #Networking #DevOps #Debug
👍8🔥1