← Назад к вопросам

Что такое файловый дескриптор в Linux?

2.2 Middle🔥 181 комментариев
#Linux и администрирование

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Файловый дескриптор в Linux

Файловый дескриптор (File Descriptor, FD) - это фундаментальная концепция Unix/Linux. Это числовой идентификатор для open файла или I/O ресурса.

Определение

File Descriptor - это целое число которое операционная система использует для:

  • Отслеживания открытых файлов
  • Сокетов (network)
  • Трубок (pipes)
  • Устройств (devices)

Каждый процесс имеет свою таблицу file descriptors.

Стандартные file descriptors

0 - stdin (Standard Input)
   Откуда читаются данные (обычно клавиатура)
   
1 - stdout (Standard Output)
   Куда пишутся результаты (обычно экран)
   
2 - stderr (Standard Error)
   Куда пишутся ошибки (обычно экран)
   
Примеры:
```bash
echo "Hello" >&1   # Пишет в stdout (1)
echo "Error" >&2   # Пишет в stderr (2)
read var < file    # Читает из stdin (0)

3+ - пользовательские file descriptors

Открытие файла автоматически присваивает FD
Первый открытый файл получит FD=3
Второй файл: FD=4
И так далее...

Как работают file descriptors

Процесс (PID=1234)
┌─────────────────────────────────┐
│  File Descriptor Table          │
│  ┌─────────────────────────────┐│
│  │ FD 0 → /dev/tty (stdin)    ││
│  │ FD 1 → /dev/tty (stdout)   ││
│  │ FD 2 → /dev/tty (stderr)   ││
│  │ FD 3 → /var/log/app.log    ││
│  │ FD 4 → /etc/config.conf    ││
│  │ FD 5 → socket (network)    ││
│  └─────────────────────────────┘│
└────────────────────┬────────────┘
                 │
          ┌──────┼──────┐
          ▼      ▼      ▼
       File   File   Socket
      System Kernel  Handler

Практическое использование

Bash - перенаправление I/O

Стандартное перенаправление

command > output.txt        # stdout → file (FD 1)
command 2> error.txt        # stderr → file (FD 2)
command < input.txt         # stdin ← file (FD 0)

Перенаправить оба потока

command > output.txt 2>&1   # stderr в stdout

Открыть для читания

read var < <(echo "data")

Открыть для записи

echo "data" > fd.txt

Перенаправить произвольный FD

echo "test" >&3              # Write to FD 3
exec 3> output.txt          # Open FD 3 for writing
exec 3< input.txt           # Open FD 3 for reading
exec 3>&-                   # Close FD 3

Python - работа с file descriptors

import os

Открыть файл и получить FD

fd = os.open('/var/log/app.log', os.O_WRONLY | os.O_CREAT)

fd = 3

Писать в FD

os.write(fd, b'Hello\n')

Читать из FD

data = os.read(fd, 1024)

Закрыть FD

os.close(fd)

Работа с стандартными FD'ами

os.write(1, b'stdout\n')   # Пишем в stdout (FD 1)
os.write(2, b'stderr\n')   # Пишем в stderr (FD 2)

Проверка file descriptors процесса

Посмотреть какие FD открыты у процесса

ls -la /proc/[PID]/fd/

Пример вывода

lrwx------. user user 0 Nov 26 10:15 0 -> /dev/pts/0
lrwx------. user user 0 Nov 26 10:15 1 -> /dev/pts/0
lrwx------. user user 0 Nov 26 10:15 2 -> /dev/pts/0
lrwx------. user user 0 Nov 26 10:15 3 -> /var/log/app.log
lrwx------. user user 0 Nov 26 10:15 4 -> socket:[12345]

Максимальное количество FD'ов для процесса

ulimit -n

Результат: 1024 (можно открыть 1024 файла одновременно)

Увеличить лимит

ulimit -n 65536

Постоянно (в /etc/security/limits.conf)

username soft nofile 65536
username hard nofile 65536

File descriptor leak (утечка)

Плохо - файл не закрывается

for i in range(1000): f = open('file.txt') # FD не закрывается # File remains open!

Хорошо - использовать контекстный менеджер

for i in range(1000): with open('file.txt') as f: # Автоматически закрывается

Обнаружить утечку

lsof -p [PID] | wc -l  # Количество открытых FD'ов

Мониторить

watch -n 1 'lsof -p [PID] | wc -l'

Пределы file descriptors

Система wide лимит

cat /proc/sys/fs/file-max

Пример: 9223372036854775807

Per-process лимит

ulimit -n

Пример: 1024

Увеличить system лимит (временно)

sysctl -w fs.file-max=2000000

Постоянно (/etc/sysctl.conf)

fs.file-max = 2000000

Применить

sysctl -p

lsof - List Open Files

Какие файлы открыл процесс

lsof -p [PID]

Все процессы обращающиеся к файлу

lsof /var/log/app.log

Все network сокеты

lsof -i

Все файлы на определённом порту

lsof -i :8080

Файлы в определённой директории

lsof +D /var/log

Какие FD'ы открыты

lsof | grep -E '^java' | wc -l

В контексте DevOps

1. Мониторинг в production

Проверить что нет утечек

for pid in $(pgrep java); do echo "PID $pid: $(lsof -p $pid | wc -l) FD'ов"

done

Alert если много FD'ов

if [ $(lsof -p $pid | wc -l) -gt 3000 ]; then send_alert "High FD count for $pid"

fi

2. Container limits (Docker/Kubernetes)

Docker

docker run --ulimit nofile=65536:65536 image:tag

Kubernetes

apiVersion: v1
kind: Pod
metadata:
  name: app
spec:
  containers:
  - name: app
image: app:1.0
securityContext:
  runAsUser: 1000
resources:
  limits:
    memory: "1Gi"

3. Performance tuning

Если приложение получает "Too many open files"

Шаги:

1. Проверить лимит

ulimit -n

2. Проверить текущее использование

lsof -p [PID] | wc -l

3. Если близко к лимиту - увеличить

ulimit -n 65536

4. Проверить код на утечки

Убедиться что все файлы закрываются

Выводы

File Descriptor:

✅ Это numerical identifier для I/O ресурсов ✅ 0, 1, 2 - это stdin, stdout, stderr ✅ Каждый процесс имеет лимит (обычно 1024) ✅ Утечка FD'ов может привести к проблемам ✅ Мониторить для production систем ✅ Увеличивать лимит для high-load приложений

Правило: всегда закрывать FD'ы когда больше они не нужны!