← КурсСамостоятельный просмотрПульт

Пара 3 / октябрь

Shell, структура каталогов и текстовые утилиты

Безопасно создавать, читать, копировать и искать файлы; понимать кавычки.

Контекст

Shell превращает командную строку в запуск с аргументами и окружением.

Безопасно создавать, читать, копировать и искать файлы; понимать кавычки.

Команда — имя и аргументы

Shell разделяет слова до запуска программы.

01Строка команды
02Разбор Bash
03Аргументы
04Запуск программы

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

Сначала осмотр, затем изменение

pwd и ls снижают риск работы не в той папке.

01pwd / ls
02Проверка цели
03cp / mv
04Сравнение результата

Аналогия: прежде чем переносить коробки, проверьте номер склада.

Поиск и чтение

Ищем имя отдельно от текста внутри файла.

01find: имя
02grep: текст
03less: чтение
04wc: количество

Имена и содержимое — разные пространства поиска.

Terminal, shell и утилиты — три разных слоя

Shell превращает командную строку в запуск с аргументами и окружением.

Terminal показывает ввод/вывод, shell разбирает команду, утилита выполняет работуTerminal / PTYОкно и поток вводаBash / zsh / fishРазбор и запускgrep / sed / PythonОтдельные процессыЯдроПроцессы, файлы, I/OBuiltins: cd, export, readМеняют состояние самого shellВнешние команды: grep, lsДочерняя программа получает argv / envsh — интерфейс/имя shell, а не всегда Bash. Fish не является POSIX shell.

Кавычки, expansion и разбиение argv происходят до исполнения утилиты. На Mac интерактивный zsh и системный старый Bash — разные среды.

Файл .env скрыт только от обычного списка

В Linux точка — соглашение об имени, а не особый секретный тип файла.

Точка в начале имени влияет на обычный показ, а не на права доступаКаталогreport.csv, .env, .config/lsОбычный списокreport.csv — имена с точкой обычно опущеныls -aПолный списокreport.csv, .env, .config/, . и ..Скрытие имени не шифрует данные и не запрещает cat .env. chmod и секреты — отдельные механизмы.

ls -a показывает скрытые имена; ls -A опускает специальные записи . и .. Hidden не означает encrypted или unreadable.

/etc, /var, /usr, /tmp: роли каталогов

По роли данных можно выбрать место хранения и область диагностики.

Роли основных каталогов Linux/Корень/etcКонфигурация хоста/varЛоги, cache, spool, state/homeЛичные данные/usrПрограммы и данные системы/runRuntime state текущей загрузки/tmpВременные файлы/proc и /sysИнтерфейсы сведений ядра/devУстройства и специальные объекты

Настройки, код, runtime state и пользовательские данные имеют разные сроки жизни и требования к резервному копированию.

grep, sed и awk решают разные задачи

Текстовый поток можно отобрать, преобразовать и разобрать без изменения оригинала.

grep выбирает строки, sed преобразует поток, awk работает с полямиevents.logINFO 200  /healthzgrep -F ERRORСтроки с буквальным ERRORИсходный текстstatus=failedsed 's/failed/retry/'Преобразованный stdout; исходный файл не изменёнsed -i меняет файл и различается между GNU/BSD. Для знакомства сначала выводим результат отдельно.

Фильтрацию и преобразование сначала выводим в новый файл; sed -i используется после проверки и с учётом различий GNU/BSD.

Наблюдение механизмов

mkdir -p ~/devops-course/text-demo
cd ~/devops-course/text-demo
printf "INFO status=ok\nERROR status=failed\n" > events.log
printf "local-setting\n" > .settings
ls
ls -a
grep -n -F ERROR events.log
sed 's/failed/retry/' events.log
awk '{print $1}' events.log
command -v sh bash grep sed
Полный разбор команд в конспекте →

Команды и наблюдения

Ubuntu / Bash

mkdir -p ~/devops-course/sandbox
cd ~/devops-course/sandbox
printf "OK run=1
ERROR run=2
OK run=3
" > "run log.txt"
cp -- "run log.txt" backup.txt
grep -n -F ERROR "run log.txt"
find . -type f -name "*.txt"
wc -l "run log.txt"
cmp "run log.txt" backup.txt

Разбор результата

grep находит строку 2; wc показывает 3; cmp молчит и возвращает 0.

Кавычки делают run log.txt одним аргументом; шаблон find заключён в кавычки, чтобы его обработал find, а не shell.

На macOS

mkdir, cp, grep, find, head, tail, less, wc и cmp доступны. Linux find -maxdepth не считайте переносимым; для поиска по всему учебному дереву достаточно команды выше. BSD и GNU-флаги могут различаться. Проверяйте man на своей системе.

mkdir -p ~/devops-course/sandbox
cp -- "run log.txt" backup.txt
grep -n -F ERROR "run log.txt"
find . -type f -name "*.txt"
wc -l "run log.txt"

Архив экспериментальных запусков

  1. Создайте три файла, один с пробелом в имени.
  2. Скопируйте их в отдельную папку backup без изменения оригиналов.
  3. Найдите строки ERROR и посчитайте файлы через find.
  4. Переименуйте один файл и удалите только специально созданную копию с rm -i.

Что должно получиться

history-команды без секретов и найденные строки с номерами.

Оригиналы сохранены; все пути с пробелами обработаны корректно.

Ошибка для диагностики

Неэкранированный пробел разбил имя на два аргумента.

Симптом→Гипотеза→Проверка

Основные выводы

  1. Обычно в shell до запуска команды, если шаблон не заключён в кавычки.
  2. Ищет буквальную строку без интерпретации регулярного выражения.

После пары

Создать шпаргалку из восьми команд: цель, пример, риск неправильного применения.

Конспект, команды и разбор →

Конвейер: порядок операций имеет значение

A
B
A
A
B
Выберите порядок обработки

Пара 4 / октябрь

VFS, библиотеки, память и конвейеры

Соединять команды, проверять код возврата и писать небольшой повторяемый скрипт.

Контекст

Одинаковые open/read работают поверх разных файловых систем.

Соединять команды, проверять код возврата и писать небольшой повторяемый скрипт.

Три стандартных потока

stdin — вход; stdout — результат; stderr — диагностика.

01stdin → процесс
02stdout → данные
03stderr → ошибки

Аналогия: готовые блюда и сообщения о поломке кухни идут по разным каналам.

Конвейер обработки

Каждый инструмент выполняет небольшой понятный шаг.

01grep
02cut
03sort
04uniq -c

Аналогия: конвейер сортировки посылок; плохой шаг загрязняет весь результат.

Код возврата и повторяемость

Успех команды — обычно код 0, а не отсутствие текста.

01Вход
02Проверки
03Обработка
04Код возврата

Успешно напечатать пустой результат и успешно решить задачу — не всегда одно и то же.

Куда на самом деле пишет stdout

Shell настраивает дескрипторы перед запуском программы.

Перенаправление связывает файловые дескрипторы процесса с объектами ядраПроцесс: pythonТаблица дескрипторов0 stdin1 stdout2 stderrТерминалВвод пользователяout.log> out.logerr.log2> err.logДескриптор — целое число в процессе, не имя файла. Возможны pipe, socket, device.

Нет. Она пишет в stdout; shell уже настроил дескриптор.

Конвейер создаёт два процесса и канал

Pipe передаёт байты и заставляет ждать при пустом или полном буфере.

Два процесса соединены буфером pipe в ядреprintfstdout: FD 1wc -lstdin: FD 0pipe в ядреБайты: запись → чтениеShell создаёт pipe и процессыdup2 настраивает 1 и 0 перед execEOF после закрытия всех writersЧитатель не знает смысл данныхКонвейер передаёт поток байтов; stdout не обязан вести на экран.

Когда все записывающие концы pipe закрыты и чтение возвращает EOF.

VFS даёт общий файловый интерфейс

Одинаковые open/read работают поверх разных файловых систем.

VFS связывает путь и открытый файл с реализацией файловой системыopen("/data/x")Запрос процессаdentry + inodeИмя и объектfile descriptionОткрытие, flags, offsetfile operationsРеализация FSext4 / XFSФайлы на носителеtmpfs / procfsПамять или данные ядраNFS / другиеДругой источник данныхИмя, inode и открытый файловый объект — разные сущности; расширение не определяет формат.

Путь и inode не тождественны. Разные имена могут указывать на один объект, а одно имя со временем — на разные объекты.

Удаление имени и освобождение данных — не один момент

Открытый файл может продолжать существовать после rm.

Удаление имени не обязательно сразу освобождает открытый файлИмя events.logЗапись каталогаinode / содержимоеОбъект файловой системыFD процессаФайл ещё открытunlink / rmИмя убрано из каталогаМесто освобождается позжеКогда не осталось hard links и удерживающих открытийПричина случая «rm большой лог, но df не изменился»: процесс продолжает держать открытый файл.

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

Shared library загружает динамический linker

Библиотека содержит код; ABI задаёт правила связи с программой.

ELF и динамический загрузчик связывают программу с shared librariesexec: ELFКод и ELF metadataPT_INTERPДинамический loaderЗависимости .soПроверка ABI, поискmmap и relocationsОбраз процессаОбщие read-only страницы кодаМогут физически разделяться процессамиИзменяемые данныеНе становятся автоматически общимиLinux .so, macOS .dylib/frameworks, Windows DLL. Совпадение имени не гарантирует совместимый ABI.

Ubuntu: file /usr/bin/ls; readelf -l /usr/bin/ls; readelf -d /usr/bin/ls. Mac: file /bin/ls; otool -L /bin/ls.

RAM нужна для исполнения, но не всё копируется заранее

Виртуальная память отображает нужные страницы по мере обращения.

Адресное пространство не равно заранее занятой физической RAMВиртуальные адресаКод, библиотеки, heap, stackТаблицы страницСвязь виртуальных адресов и физических страницPage faultНужная страница ещё не доступнаВыделить / прочитать страницуDemand paging; доступ проверяет ядроCPU исполняет доступные страницы через память; приложение не обязано загружать весь файл целиком.

Исполняются доступные отображённые страницы. Большой файл модели может читаться постепенно или через mmap, а не обязательно целиком до старта.

Swap помогает вытеснять страницы, но не заменяет RAM

Cache, anonymous memory и swap участвуют в разных решениях reclaim.

Page cache и swap сохраняют разные виды страниц при дефиците памятиФизическая RAMКод, данные, cachereclaimЧистая file-backed страницаМожно отбросить и позже перечитать файлswap outAnonymous / изменённые данныеМогут быть выгружены в swap; затем swap infree: available важнее одного free. Swappiness — политика стоимости I/O, не процент занятой RAM.

Ubuntu: free -h; swapon --show; vmstat 1 3. Mac: vm_stat; sysctl vm.swapusage; Activity Monitor показывает другую модель учёта.

/tmp — назначение каталога, tmpfs — тип хранения

Временное имя не гарантирует RAM и конкретный срок очистки.

Временные данные различаются по времени жизни и расположению/tmpВременная работа программы/var/tmpДольше между загрузками/runRuntime state после boottmpfs — тип файловой системыДанные в памяти; возможен swap, зависит от настроек/tmp ≠ всегда tmpfsПроверить findmntОчистку определяет политика дистрибутива. /tmp не место для единственной копии результата.

findmnt -T /tmp показывает реальное хранение. tmpfs может обмениваться страницами со swap; после reboot данные не являются постоянным архивом.

Наблюдение механизмов

printf "A\nB\n" | wc -l
python3 -c 'import sys; print("result"); print("diagnostic", file=sys.stderr)' >out.log 2>err.log
cat out.log
cat err.log
file /usr/bin/ls
# Optional when binutils is installed
readelf -l /usr/bin/ls | grep -F interpreter
readelf -d /usr/bin/ls | grep -F NEEDED
free -h
swapon --show
Полный разбор команд в конспекте →

Команды и наблюдения

Ubuntu / Bash

cd ~/devops-course/sandbox
printf "ERROR api
OK worker
ERROR api
ERROR db
" > events.log
grep -F ERROR events.log | cut -d " " -f 2 | sort | uniq -c
ls missing-file > result.txt 2> error.txt
printf "exit=%s
" "$?"
cat error.txt

Разбор результата

api встречается дважды, db один раз; ls возвращает ненулевой код, диагностика находится в error.txt.

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

На macOS

Стандартные потоки и конвейеры переносимы. Пользовательский shell macOS часто zsh; скрипт курса запускайте явно через bash. Системный Bash на macOS может быть старее Linux-версии; не переносите новые возможности Bash без проверки bash --version.

bash summary.sh "run log.txt"
grep -F ERROR events.log | cut -d " " -f 2 | sort | uniq -c

Скрипт сводки

  1. Создайте summary.sh с #!/usr/bin/env bash и set -o pipefail.
  2. Примите путь первым аргументом; при отсутствии файла напечатайте понятную ошибку в stderr и завершитесь с кодом 2.
  3. Выведите число строк и число ERROR; отсутствие ошибок должно давать 0, а не падение.
  4. Запустите на нормальном журнале, журнале без ERROR и несуществующем файле.

Что должно получиться

summary.sh и результаты трёх запусков.

Все три случая предсказуемы; пути с пробелами работают.

Ошибка для диагностики

grep без совпадений ошибочно считается аварией скрипта.

Симптом→Гипотеза→Проверка

Основные выводы

  1. uniq сравнивает соседние строки.
  2. Перезаписывает существующее содержимое файла.

После пары

Улучшить скрипт: различать отсутствие совпадений и ошибку чтения; объяснить проверку кода возврата.

Конспект, команды и разбор →