Представьте: ваше приложение не может достучаться до соседнего API. Вы лезете в контейнер, чтобы проверить сетевую связанность.
А там голый образ. Ни
curl, ни nc, ни telnet, и поставить нельзя — пользователь непривилегированный, да и интернета нет.И как теперь быть?
А вот так:
exec 3<>/dev/tcp/10.244.1.15/8000
Но что тут вообще происходит?
Это старый трюк bash, о котором знают немногие — разберём по частям.
1️⃣
/dev/tcp/<IP>/<port> — не файлКажется, что это обычный путь. Но стоит проверить:
~$ ls /dev/tcp
ls: cannot access '/dev/tcp': No such file or directory
Файла нет и не было.
Это специальный путь, который перехватывает bash: вместо того чтобы открыть файл на диске, он открывает TCP-соединение. Есть и брат-близнец
/dev/udp/... — для UDP.2️⃣
3<> — а это что за тройка с ромбиком?Это файловый дескриптор — неотрицательное число, через которое процесс обращается к чему-то открытому: файлу, сокету, пайпу.
Базовые три всегда заняты:
0 → stdin (ввод)
1 → stdout (вывод)
2 → stderr (ошибки)
А дальше номера свободны — можно открывать свои.
Запись
3<> означает «открой на чтение и запись и привяжи к дескриптору 3». Так наш TCP-сокет получает номер 3.Команда
exec закрепляет дескриптор за текущим процессом bash, а не за дочерним — поэтому сокет остаётся открытым для следующих команд.3️⃣ Пусть номер выберет система
При ручном выборе дескриптора можно словить конфликт — занял 3, а он уже где-то используется. Поэтому отдадим выбор bash:
exec {fd}<>/dev/tcp/10.244.1.15/8000
echo "$fd" # bash сам выдал свободный номер, например 10
Вместо фиксированной цифры пишем
{fd} — bash сам найдёт свободный дескриптор и положит его номер в переменную.📌 Как понять, что проверка сработала?
Сам по себе
exec 3<>/dev/tcp/... ничего не выводит — просто пытается открыть сокет. А если порт фильтруется (пакеты молча отбрасываются), команда зависнет. Поэтому оборачиваем в
timeout и явно говорим, что считать успехом:timeout 3 bash -c 'exec 3<>/dev/tcp/10.244.1.15/8000' && echo CONNECTED || echo FAILED
Если соединение установилось за 3 секунды —
CONNECTED. Иначе — FAILED: порт закрыт, недоступен или не ответил за таймаут.👨💻 Код в Прод