Learning Platform
Глоссарий Troubleshooting
Урок 06.01 · 15 мин
Начальный
mkdirtouchmktempFile Creation

Создание файлов и директорий

В прошлых модулях мы научились ориентироваться в файловой системе. Теперь — создавать в ней файлы и папки. На первый взгляд тривиально, но есть нюансы: mkdir -p, touch с правильным mtime, mktemp для безопасных временных файлов. Это рутинные операции DE, которые лучше делать правильно с самого начала.


mkdir: создание директорий

Базовое использование:

$ mkdir new-folder
$ ls
new-folder/

# Ошибка, если уже существует
$ mkdir new-folder
mkdir: cannot create directory 'new-folder': File exists

Опции:

mkdir — главные опции
-pParents. Создать все недостающие parent-папки. Без ошибки, если папка уже существует. КРИТИЧНО для скриптов
-m MODEУстановить права при создании. -m 0755 — стандартные права для папок. По умолчанию — определяется umask
-vVerbose. Печатает, что создано. Полезно при -p для диагностики

mkdir -p — это самая используемая опция:

$ mkdir -p ~/projects/airflow/dags/etl
# Создаст все 4 уровня: projects, airflow, dags, etl

# Если что-то уже есть — не ошибётся
$ mkdir -p ~/projects/airflow/dags/etl
# (молча: всё уже существует)

Без -p пришлось бы делать:

$ mkdir ~/projects
$ mkdir ~/projects/airflow
$ mkdir ~/projects/airflow/dags
$ mkdir ~/projects/airflow/dags/etl

В скриптах всегда используйте -p. Это idempotent — можно запускать N раз, состояние одно.

С правами при создании:

$ mkdir -m 0700 ~/.ssh
# Создаст с правами 0700 (только владелец может)

$ mkdir -m 0755 -p /var/data/raw/2026
# Стандартные права для общедоступных папок

Подробнее про права (0700, 0755 и так далее) — в модуле 6.


touch: пустые файлы и mtime

touch имеет два применения:

  1. Создать пустой файл (если не существует).
  2. Обновить modification time существующего файла на текущее.
# Создать пустой файл
$ touch newfile.txt
$ ls -la newfile.txt
-rw-r--r-- 1 user user 0 May 13 14:00 newfile.txt
# Размер 0, mtime = сейчас

# Обновить mtime уже существующего
$ ls -l existing.txt
-rw-r--r-- 1 user user 1024 May 10 10:00 existing.txt
$ touch existing.txt
$ ls -l existing.txt
-rw-r--r-- 1 user user 1024 May 13 14:00 existing.txt
# Размер тот же, mtime теперь сейчас

Опции touch:

# Установить конкретное время
$ touch -t 202605131200 file.txt    # 2026-05-13 12:00
$ touch -d "2026-01-01 00:00" file.txt
$ touch -d "yesterday" file.txt
$ touch -d "2 hours ago" file.txt

# Не создавать новый, только обновить (если существует)
$ touch -c file.txt

# Установить только atime / только mtime
$ touch -a file.txt   # только access time
$ touch -m file.txt   # только modification time

В DE-практике touch используется:

  1. Создать marker-файлы: touch /var/lock/etl.lock — для логики «уже запущен».
  2. Обновить mtime для cache invalidation: некоторые инструменты пересчитывают, если mtime изменился.
  3. Создать пустые placeholder-файлы.
# Marker-файл для уведомления о завершении ETL
$ touch /var/data/2026-05-13/_SUCCESS
# Многие big data tools используют такой паттерн

mktemp: безопасные временные файлы

В скриптах часто нужны временные файлы. Простое решение «использовать /tmp/myfile.txt» имеет проблемы:

  1. Race condition: два скрипта могут создать одно имя одновременно.
  2. Безопасность: предсказуемое имя позволяет attacks (symlink attack).
  3. Чистка: легко забыть удалить.

Правильное решение — mktemp:

$ mktemp
/tmp/tmp.XJZ9aB2c4q
# Создал файл с уникальным именем, вернул путь

# С префиксом и шаблоном
$ mktemp /tmp/etl-XXXXXX.csv
/tmp/etl-aZ9bX1.csv
# XXXXXX заменяется на 6 случайных символов

# Создать директорию вместо файла
$ mktemp -d
/tmp/tmp.XJZ9aB2c4q

В скриптах паттерн такой:

#!/usr/bin/env bash
set -euo pipefail

TMPDIR=$(mktemp -d /tmp/myapp.XXXXXX)
trap "rm -rf $TMPDIR" EXIT     # автоудаление при выходе

# Работаем в TMPDIR
curl https://api.example.com/data > "$TMPDIR/raw.json"
jq '.data[]' "$TMPDIR/raw.json" > "$TMPDIR/processed.json"
mv "$TMPDIR/processed.json" /var/data/result.json

# При exit (любом — успех, ошибка, Ctrl-C) trap чистит

Подробнее про trap и cleanup-паттерны — в модуле 18.

Volumes в Docker — аналог mktemp для контейнеров
WARNING

Никогда не используйте предсказуемые имена в /tmp. /tmp/my-script-output.txt — это уязвимость. Атакующий может заранее создать symlink /tmp/my-script-output.txt -> /etc/passwd, и ваш скрипт перезапишет /etc/passwd. Всегда mktemp.


Куда mktemp кладёт файлы

По умолчанию mktemp использует:

  1. Переменную $TMPDIR, если установлена.
  2. /tmp, если $TMPDIR не установлена.
$ export TMPDIR=~/my-temp
$ mkdir -p ~/my-temp
$ mktemp
/home/user/my-temp/tmp.aB9X1c2d3e

Это полезно, когда:

  • Скрипт обрабатывает большие файлы, и /tmp слишком маленький (tmpfs в RAM, ~7GB).
  • Хочется хранить tmp на отдельном диске.
# Явный путь для большого временного файла
$ TMP_BIG=$(mktemp /data/scratch/etl-XXXXXX.csv)

Команды для типичных задач

Создание daily-папок в data lake:

$ today=$(date +%Y-%m-%d)
$ mkdir -p /var/data/raw/"$today"/
$ mkdir -p /var/data/processed/"$today"/
$ mkdir -p /var/data/archived/"$today"/

Подготовка структуры нового проекта:

$ mkdir -p new-project/{src,tests,docs,data,scripts}
$ touch new-project/{README.md,.gitignore,requirements.txt}
$ ls new-project
data/  docs/  README.md  requirements.txt  scripts/  src/  tests/  .gitignore

Заметьте brace expansion {src,tests,docs} — bash раскрывает в несколько аргументов. Это работает с mkdir, touch, cp и любой командой.

Создание временной копии в pipeline:

$ TMP=$(mktemp -d)
$ cp -r /var/data/important "$TMP/working-copy"
$ # делаем что-то с копией
$ rm -rf "$TMP"

Brace expansion: создание массивами

Bash brace expansion — это мощный синтаксис для создания нескольких имён одной командой:

# Несколько папок
$ mkdir -p project/{src,tests,docs}
# Создаёт project/src, project/tests, project/docs

# Нумерованные
$ mkdir batch-{01..10}
$ ls
batch-01/  batch-02/  ...  batch-10/

# Декартово произведение
$ mkdir {dev,staging,prod}-{api,db,cache}
$ ls
dev-api/  dev-cache/  dev-db/  staging-api/  staging-cache/  ...

# Touch с разными расширениями
$ touch report.{csv,json,yaml,md}
$ ls
report.csv  report.json  report.md  report.yaml

# Числовая последовательность
$ touch day-{2026-05-{01..31}}.csv
# day-2026-05-01.csv ... day-2026-05-31.csv

Это типично для DE: создание daily-партиций, серий тестовых файлов, структуры окружений.


Создание файлов через перенаправление

Альтернатива touch — записать пустоту в файл через >:

$ : > newfile.txt
# Или
$ > newfile.txt
$ echo -n > newfile.txt

Все три создают пустой файл (или очищают существующий). Подробнее про перенаправления — в модуле 9.

Для создания файла с содержимым:

# Heredoc — многострочный текст
$ cat > config.yaml <<'EOF'
database:
  host: localhost
  port: 5432
EOF

$ cat config.yaml
database:
  host: localhost
  port: 5432

Heredoc (<<'EOF') — это шаблон создания файла в скриптах. Подробнее в модуле 9.


Попробуй сам

$ mkdir -p ~/linux-sandbox/lesson-create
$ cd ~/linux-sandbox/lesson-create

# Базовое создание
$ mkdir simple-dir
$ touch simple-file.txt

# Brace expansion — структура нового DE-проекта
$ mkdir -p new-etl/{src/{api,db,utils},tests/{unit,integration},docs,scripts}
$ tree new-etl
new-etl
├── docs
├── scripts
├── src
   ├── api
   ├── db
   └── utils
└── tests
    ├── integration
    └── unit

# Daily-партиции
$ mkdir -p data/raw/2026-05-{01..31}
$ ls data/raw | head -5
2026-05-01  2026-05-02  2026-05-03  2026-05-04  2026-05-05

# mktemp
$ TMP=$(mktemp -d)
$ echo "$TMP"
/tmp/tmp.aB9X1c2d3e

$ echo "test data" > "$TMP/data.txt"
$ ls "$TMP"
data.txt

# Удалить после использования
$ rm -rf "$TMP"

Heredoc для создания конфига:

$ cat > config.yaml <<'EOF'
service:
  name: etl-pipeline
  version: 1.0.0
schedule:
  cron: "0 */6 * * *"
EOF

$ cat config.yaml
service:
  name: etl-pipeline
  version: 1.0.0
schedule:
  cron: "0 */6 * * *"

Проверка знанийKnowledge check
Junior пишет в скрипте: cat > /tmp/myapp-output.txt. Скрипт работает локально. На production-сервере DevOps добавляет в audit лог: «Возможная уязвимость symlink-attack — переписан /etc/cron.d/myjob». Что произошло и как починить?
ОтветAnswer
Это классическая symlink attack. На многопользовательской системе атакующий мог заранее создать /tmp/myapp-output.txt как symlink на /etc/cron.d/myjob (или любой другой важный файл). Когда ваш скрипт запускается с правами, превышающими атакующего (например, под root через cron), cat > /tmp/myapp-output.txt следует symlink и перезаписывает /etc/cron.d/myjob — что даёт атакующему возможность выполнить произвольный код. Решение: использовать mktemp вместо предсказуемых имён. TMPFILE=$(mktemp /tmp/myapp.XXXXXX); cat > "$TMPFILE"; trap 'rm -f "$TMPFILE"' EXIT. mktemp создаёт файл атомарно, с уникальным непредсказуемым именем, с правами 600 (только владелец). После завершения trap чистит. Это базовая безопасность shell-скриптов на многопользовательских системах. Дополнительно: некоторые системы монтируют /tmp с опцией nosymfollow или используют /tmp как private namespace для systemd-сервисов.

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 5. Что делает `mkdir -p path/to/nested`?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 5