Не попадитесь на накрученные каналы! Узнайте, не накручивает ли канал просмотры или подписчиков Проверить канал на накрутку
Прикрепить Телеграм-аккаунт Прикрепить Телеграм-аккаунт

Телеграм канал «BashTex | Linux»

BashTex | Linux
586
92
170
8
2.5K
Авторский канал для тех, кто хочет глубже погрузиться в мир Linux.

Подойдет для разработчиков, системных администраторов и DevOps

Реклама: @dad_admin
Подписчики
Всего
2 505
Сегодня
0
Просмотров на пост
Всего
305
ER
Общий
12.19%
Суточный
8.1%
Динамика публикаций
Telemetr - сервис глубокой аналитики
телеграм-каналов
Получите подробную информацию о каждом канале
Отберите самые эффективные каналы для
рекламных размещений, по приросту подписчиков,
ER, количеству просмотров на пост и другим метрикам
Анализируйте рекламные посты
и креативы
Узнайте какие посты лучше сработали,
а какие хуже, даже если их давно удалили
Оценивайте эффективность тематики и контента
Узнайте, какую тематику лучше не рекламировать
на канале, а какая зайдет на ура
Попробовать бесплатно
Показано 7 из 586 постов
Смотреть все посты
Пост от 26.10.2026 13:20
47
0
2
hash: почему Bash запускает команду не из того каталога

Вы установили новую версию утилиты, проверили $PATH, но Bash продолжает запускать старую. При этом в другом терминале всё работает правильно.

Причина может быть во встроенном механизме hash. Bash запоминает пути к уже найденным исполняемым файлам, чтобы не искать их заново при каждом запуске.

▪️Как Bash ищет команды

Когда вы вводите:

mytool

Bash ищет подходящую команду. Если это внешняя программа, оболочка обычно проверяет каталоги из $PATH по порядку.

После первого успешного поиска путь может попасть во внутреннюю хеш-таблицу.

Посмотреть её содержимое:

hash

Или узнать сохранённый путь конкретной команды:

hash -t mytool

▪️Где возникает проблема

Допустим, утилита сначала находилась здесь:

/usr/bin/mytool

Затем вы установили новую версию в:

/usr/local/bin/mytool

Если Bash уже запомнил старый путь, он может продолжать использовать его, даже когда новая программа находится раньше в порядке поиска.
Это особенно заметно в долгоживущих сессиях.

▪️Как сбросить кеш

Удалить запись для одной команды:

hash -d mytool

Или очистить всю таблицу:

hash -r

После этого Bash заново выполнит поиск внешней команды.

Проверить все доступные варианты можно через:

type -a mytool

▪️Важный нюанс

При изменении $PATH Bash обычно сам очищает таблицу путей. Поэтому проблема чаще возникает, когда содержимое каталогов изменилось, а сама переменная осталась прежней.

Кроме того, hash не переопределяет shell-функции и встроенные команды Bash. Если имя занято функцией или alias, сначала нужно разобраться с порядком разрешения команд.

▪️Почему это важно

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

Иногда Bash уже запомнил расположение исполняемого файла, и именно поэтому две одинаковые на первый взгляд сессии запускают разные версии программы.

BashTex 📱 #bash #linux
👍 1
Пост от 23.10.2026 12:20
47
0
0
BashTex 📱 #мем
Пост от 22.10.2026 12:20
51
0
8
Процесс открыл 50 тысяч файлов: как найти причину

Приложение работает несколько дней, а потом внезапно начинает выдавать Too many open files. Перезапуск помогает, но через какое-то время ошибка возвращается.

Возможно, процесс постепенно накапливает файловые дескрипторы. Причём это не обязательно обычные файлы: FD используются для сокетов, каналов, eventfd и других объектов.

▪️Сколько дескрипторов открыто

Для начала узнаем PID процесса и посчитаем его FD:

ls -U /proc/$PID/fd | wc -l

Посмотреть установленный лимит:

grep 'Max open files' /proc/$PID/limits

Если количество FD постоянно растёт и приближается к лимиту, стоит выяснить, что именно процесс держит открытым.

▪️Смотрим, куда указывают дескрипторы

ls -l /proc/$PID/fd | head -30

В выводе могут встретиться:

15 -> /var/log/app.log
16 -> socket:[123456]
17 -> pipe:[123457]
18 -> anon_inode:[eventpoll]

Это помогает понять, что накапливается: файлы, сетевые соединения, каналы или внутренние объекты ядра.

▪️Что показывает fdinfo

Для каждого открытого дескриптора Linux хранит дополнительную информацию:

cat /proc/$PID/fdinfo/15

Например:

pos: 4096
flags: 0100002
mnt_id: 27
ino: 123456

Здесь:

• pos - текущая позиция в файле.
• flags - флаги открытия и состояния FD в восьмеричном виде.
• mnt_id - идентификатор монтирования.
• ino - номер inode.

Для некоторых объектов появляются дополнительные поля.

Например, у epoll-дескриптора можно увидеть отслеживаемые FD, а у eventfd - значение счётчика.

▪️Как найти причину утечки

Если подозреваем обычные файлы, можно посмотреть, какие пути встречаются чаще всего:

ls -l /proc/$PID/fd |
awk -F ' -> ' 'NF > 1 {print $2}' |
sort | uniq -c | sort -nr | head

Если сотни или тысячи дескрипторов указывают на один лог, файл или сокеты, это уже хорошая зацепка.

Для наблюдения за ростом:

watch -n 2 "ls -U /proc/$PID/fd | wc -l"

▪️Важный нюанс

Большое количество FD само по себе не означает утечку. Например, прокси может обслуживать десятки тысяч соединений одновременно.

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

И ещё: /proc/PID/fdinfo показывает состояние дескрипторов, но не объясняет, какая функция их открыла. Для поиска конкретного участка кода могут понадобиться strace, eBPF или профилирование приложения.

BashTex 📱 #bash #linux
👍 1
Пост от 21.10.2026 12:20
94
0
5
BASH_ENV: почему Bash-скрипт выполняет команды, которых в нём нет

Допустим, вы запускаете обычный Bash-скрипт, но перед первой строкой его кода неожиданно выполняются дополнительные команды.

При этом в самом скрипте нет ни source, ни вызовов сторонних файлов. Причина может быть в переменной окружения BASH_ENV.

▪️Как работает BASH_ENV

Когда Bash запускается в неинтерактивном режиме, он проверяет переменную BASH_ENV.

Если она задана, Bash раскрывает её значение как имя файла и выполняет его содержимое перед основным скриптом.

Например, создадим файл:

echo 'echo "Loaded from BASH_ENV"' > /tmp/bash-init

Теперь запустим:

BASH_ENV=/tmp/bash-init bash -c 'echo "Main script"'

Результат:

Loaded from BASH_ENV
Main script

Команда из /tmp/bash-init выполнилась первой, хотя в основном скрипте её вообще нет.

▪️Зачем это нужно

Механизм позволяет автоматически загружать функции, переменные и настройки для неинтерактивных запусков Bash.

Например, можно определить общую функцию логирования, которая будет доступна нескольким скриптам.

Но есть и обратная сторона: поведение программы начинает зависеть от внешнего окружения.

▪️Где возникает проблема

Предположим, скрипт запускается из CI/CD или другого автоматизированного окружения.

Если туда попала переменная:

export BASH_ENV=/some/init.sh

каждый подходящий запуск Bash может сначала выполнить этот файл.

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

▪️Как проверить

Посмотреть текущее значение:

printf '%s\n' "${BASH_ENV-}"

Запустить Bash без этой переменной:

env -u BASH_ENV bash script.sh

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

▪️Важный нюанс

BASH_ENV работает не во всех режимах запуска оболочки. Например, интерактивный Bash обычно использует ~/.bashrc, а при запуске в режиме sh действуют другие правила.

Кроме того, Bash игнорирует BASH_ENV в привилегированном режиме.

Поэтому при расследовании неожиданного поведения скрипта важно проверять не только его содержимое, но и способ запуска.

BashTex 📱 #bash #linux
Пост от 20.10.2026 12:20
17
0
0
close_range(): как Linux закрывает тысячи файловых дескрипторов одним вызовом

Когда процесс запускает дочернюю программу, вместе с ней могут оказаться открытыми файловые дескрипторы родителя: сокеты, файлы, каналы и другие ресурсы.

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

▪️Почему обычного close() недостаточно

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

Классический подход - пройтись по диапазону:

for (int fd = 3; fd < max_fd; fd++) {
close(fd);
}

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

▪️Как работает close_range()

Начиная с Linux 5.9 доступен системный вызов:

close_range(3, ~0U, 0);

Он закрывает все открытые дескрипторы начиная с номера 3.
При этом стандартные потоки остаются доступными:

0 → stdin
1 → stdout
2 → stderr

Ядро обрабатывает диапазон за один системный вызов, без необходимости вызывать close() для каждого номера отдельно.

▪️А что происходит при fork() и exec()?

Здесь есть важное различие.

После fork() дочерний процесс наследует копии дескрипторов родителя. Они ссылаются на те же открытые файловые объекты.

При execve() дескрипторы по умолчанию сохраняются, если для них не установлен флаг FD_CLOEXEC.

Поэтому случайно унаследованный FD может пережить даже запуск совершенно другой программы.

▪️Можно не закрывать, а установить CLOEXEC

У close_range() есть дополнительный режим:

close_range(3, ~0U, CLOSE_RANGE_CLOEXEC);

Он устанавливает FD_CLOEXEC для дескрипторов в диапазоне.

В результате они останутся открытыми до execve(), но будут автоматически закрыты при успешной замене образа процесса.
Это удобно, когда нужно подготовить окружение дочерней программы.

▪️Почему это важно

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

close_range() позволяет быстро закрыть целый диапазон FD или подготовить их к закрытию при execve().

Но есть нюанс: в многопоточном процессе таблица дескрипторов может быть общей для нескольких потоков. Если нужна отдельная таблица перед изменением FD, предусмотрен флаг CLOSE_RANGE_UNSHARE.

BashTex 📱 #bash #linux
👍 2
Пост от 19.10.2026 15:50
36
0
2
O_APPEND: почему несколько процессов могут писать в один файл

Допустим, два процесса одновременно записывают события в один лог. Оба открывают файл, находят его конец и добавляют новую строку.

Но что произойдёт, если они сделают это одновременно? Один процесс может перезаписать данные другого.

В Linux для таких случаев есть флаг O_APPEND.

▪️Что происходит без O_APPEND

Предположим, оба процесса выполняют:

lseek(fd, 0, SEEK_END);
write(fd, data, size);

Между этими вызовами другой процесс может изменить файл.

Получается ситуация:

Process A → lseek() → offset 100
Process B → lseek() → offset 100
Process A → write()
Process B → write()

Оба процесса начинают запись с одной позиции. Часть данных может быть перезаписана.

▪️Как работает O_APPEND

Открываем файл с дополнительным флагом:

int fd = open("app.log",
O_WRONLY | O_APPEND);

Теперь перед каждым write() ядро устанавливает позицию записи в конец файла.

Причём выбор позиции и сама запись выполняются как одна атомарная операция относительно конкурирующих записей.

Поэтому два процесса не смогут одновременно выбрать один и тот же конец файла и перезаписать друг друга из-за этой гонки.

▪️Можно проверить через Bash

Оператор >> открывает файл в режиме добавления:

echo "First event" >> app.log

Запустим несколько фоновых процессов:

for i in {1..100}; do
printf 'Event %s\n' "$i" >> app.log &
done

wait

Каждый printf открывает файл с O_APPEND, поэтому записи не должны перезаписывать друг друга из-за совпавшей позиции.

▪️Но есть ограничение

O_APPEND не превращает последовательность нескольких write() в одну атомарную транзакцию.

Если приложение записывает сообщение частями, между ними могут появиться данные другого процесса.
Кроме того, на некоторых сетевых файловых системах, например NFS, добавление в конец может реализовываться неатомарно.

▪️Почему это важно

Для логов, журналов событий и других файлов, в которые одновременно пишут несколько процессов, O_APPEND устраняет распространённую гонку между поиском конца файла и записью.

Но если требуется гарантировать целостность целого сообщения, состоящего из нескольких операций, одного O_APPEND недостаточно.

BashTex 📱 #bash #linux
Пост от 16.10.2026 12:40
62
0
1
BashTex 📱 #мем
👍 1
😁 1
Смотреть все посты