Файлы, права и окружение

Что это такое

Всё, с чем работает оболочка, лежит где-то в одном дереве файловой системы и несёт набор битов прав, которые говорят, кому позволено это читать, писать или исполнять; при старте процесс наследует ещё и окружение из переменных. Три идеи — местоположение, права и окружение — объясняют большинство ошибок, которые вам встретятся: «команда не найдена», «доступ запрещён», скрипт, который работает в вашем терминале, но падает в задании cron. Разобраться в них — значит превратить каждую такую ошибку из загадки в быструю проверку.

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

Продакшн — место, где такие детали перестают быть мелочами. Скрипт развёртывания падает, потому что файл не исполняемый; служба не может прочитать свою конфигурацию, потому что работает под другим пользователем; плановая задача работает везде, кроме автоматического раннера, потому что окружение отличается. Ни одна из этих проблем не глубока. Зато каждая может съесть полдня, когда модели нет. Знание, где живут файлы, как читаются биты прав и как процесс находит своё окружение, делает их однострочными диагнозами.

Ключевые идеи

Одно дерево с условностями, которые важны

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

/etc      конфигурация
/var      переменные данные (журналы, очереди, кэши)
/usr/bin  программы, установленные для всех
/home/you ваши файлы и ваши собственные dotfiles

Права отвечают на три вопроса

У каждого файла есть владелец, группа и набор битов для каждого из них: чтение, запись и исполнение. Бит исполнения у каталога означает «можно пройти сквозь», поэтому читаемый каталог без него нельзя перечислить, и поэтому же права на пути важны не меньше, чем на самом файле. Сделать что-то доступным на запись для всех, чтобы обойти ошибку прав, лечит симптом и создаёт дыру в безопасности.

-rwxr-xr--  владелец: rwx, группа: r-x, остальные: r--
chmod +x deploy.sh      # сделать скрипт запускаемым
umask                   # биты, которых не получат новые файлы

Переменные окружения — канал конфигурации

Каждый процесс стартует с переменными «ключ-значение», унаследованными от родителя. Так оболочка находит программы, так служба узнаёт свой порт и так скрипт понимает, в каком окружении находится. Важнее всего путь поиска: «команда не найдена» обычно означает, что её каталога нет в пути, а не что программы нет вообще.

echo "$PATH"            # каталоги, где ищется короткое имя команды
export API_BASE=api.example.test   # видна дочерним процессам

У оболочек есть конфигурация, и грузится она условно

Личные настройки живут в dot-файлах в домашнем каталоге, и то, какие из них читаются, зависит от интерактивности оболочки и от того, является ли она login-оболочкой. Из-за такого условного чтения псевдоним работает в вашем терминале и не работает в скрипте, и из-за него же плановая задача будто теряет ваш путь. Когда что-то ведёт себя иначе в автоматизации, подозревайте окружение в первую очередь.

интерактивная оболочка  -> читает ваши псевдонимы
cron / CI                -> нет; он стартует с минимальным окружением

Подстановка шаблонов и поиск

Шаблоны вроде wildcard оболочка раскрывает в список подходящих путей ещё до того, как команда их увидит, поэтому шаблон, ни с чем не совпавший, передаётся буквально. За пределами простых шаблонов используйте команду поиска, которая обходит дерево с условиями и действиями. Понимание, чем из двух вы пользуетесь, объясняет большинство неожиданностей насчёт того, какие файлы получила команда.

rm *.tmp                      # оболочка раскрывает шаблон первой
find . -name '*.log' -mtime +7 -delete   # обойти, отфильтровать, подействовать

Практика

Разберите «не найдено» и «доступ запрещён»

Сделайте обе ошибки сами: запустите программу из каталога, которого нет в вашем пути, и скрипт, у которого нет права на исполнение. После этого исправьте и то и другое.

Готово, когда: обе команды запускаются, а вы можете точно сказать, что именно изменили и почему это помогло.

Сравните интерактивное и минимальное окружение

Выведите окружение внутри интерактивной оболочки, а потом — из процесса, который стартовал без вашей конфигурации оболочки.

Готово, когда: вы называете три переменные, которые есть в одном окружении и отсутствуют в другом, и объясняете, почему для скрипта эта разница важна.

Частые ошибки

  • Файл, доступный на запись всем, ради исправления ошибки прав — команда работает, но система становится небезопасной; исправить: смените владельца или группу либо выдайте только то право, которое нужно задаче.
  • Добавление каталога в путь только в интерактивном файле — автоматизация этого файла не читает, и команда не находится; исправить: задавайте путь там, где его увидит неинтерактивный процесс.
  • Уверенность, что у плановой задачи ваше окружение — запускается она с минимальным набором переменных и с другим рабочим каталогом; исправить: задайте всё нужное явно в самой задаче.
  • Удаление с wildcard без кавычек — оболочка раскрывает его, и удаляется более широкое совпадение, чем вы задумали; исправить: сначала запустите команду с показанным шаблоном, а потом заключите его в кавычки.
  • Путаница симлинка с его целью — права и пути ведут себя по-разному в зависимости от того, какой из двух используется, а битая ссылка выглядит как файл, которого нет; исправить: когда путь ведёт себя неожиданно, осмотрите саму ссылку.

Что читать дальше