Модуль 0.1: Досвідчений користувач CLI (Пошук та Потоки)
Складність:
[QUICK]— Швидке опанування базових інструментівЧас на виконання: 45 хвилин
Передумови: «Від нуля до термінала» (Модуль 0.8)
Що ви зможете робити після цього модуля
Розділ «Що ви зможете робити після цього модуля»Після завершення цього модуля ви зможете:
- З’єднувати команди за допомогою пайпів, перенаправлень та підоболонок для створення потужних однорядкових конструкцій
- Шукати файли та вміст ефективно, використовуючи find, grep та xargs
- Обробляти текстові потоки за допомогою cut, sort, uniq, awk та sed для аналізу логів
- Перенаправляти stdout, stderr та комбінувати потоки для скриптів і відлагодження
Чому цей модуль важливий
Розділ «Чому цей модуль важливий»Уявіть картину: зараз 2-га година ночі, і ваш пейджер спрацьовує. Вебзастосунок повертає помилки 500. Десь у 47 лог-файлах, розкиданих по /var/log, є підказка — стек викликів (stack trace), тайм-аут або відмова у з’єднанні. Ви могли б відкривати кожен файл один за одним, прокручувати тисячі рядків втомленими очима і сподіватися помітити слово “error” до сходу сонця. Або ви могли б ввести один рядок:
grep -ri "error" /var/log/app/ | grep -i "database" | tail -20Через три секунди у вас перед очима 20 останніх помилок, пов’язаних із базою даних, з усіх лог-файлів. Проблему ідентифіковано. Виправлення розгорнуто. О 2:15 ви вже знову спите.
Ось у чому різниця, яку дає цей модуль. Ви вже знаєте, як навігувати по файловій системі та запускати основні команди з курсу «Від нуля до терміналу». Тепер ви навчитеся комбінувати ці команди в потужні робочі процеси. Ви навчитеся шукати файли, шукати всередині файлів, керувати тим, куди спрямовується вивід, і з’єднувати команди, як блоки конструктора.
Це не просунуті трюки. Це повсякденні інструменти, якими професіонали Linux користуються сотні разів на день. До кінця цього модуля ви відчуєте, що маєте суперсилу — бо так воно і буде.
1. Подстановочні знаки (Wildcards): Шаблони для нетерплячих
Розділ «1. Подстановочні знаки (Wildcards): Шаблони для нетерплячих»Введення повних імен файлів — це повільно і призводить до помилок. Подстановочні знаки (також звані “globs”) дозволяють вибирати декілька файлів за допомогою шаблонів. Оболонка (shell) розгортає їх ще до того, як команда почне виконуватися.
Зірочка * — Будь-що
Розділ «Зірочка * — Будь-що»Зірочка * відповідає будь-якій кількості будь-яких символів (включаючи нуль).
# Список усіх .txt файлів у поточній директоріїls *.txt# Підходить: notes.txt, readme.txt, a.txt# НЕ підходить: notes.txt.bak (не закінчується на .txt)
# Список усіх файлів, що починаються на "report"ls report*# Підходить: report.pdf, report_2024.csv, report-final.docx, reports/
# Видалити всі JPEG зображенняrm *.jpg# Підходить: photo.jpg, screenshot.jpg, a.jpg
# Скопіювати всі Python-файли в директорію backupcp *.py ~/backup/
# Список файлів, що мають "config" будь-де в назвіls *config*# Підходить: config.yaml, app-config.json, myconfig, config_backup.tar.gzЗнак питання ? — Рівно один символ
Розділ «Знак питання ? — Рівно один символ»Знак ? відповідає рівно одному символу — не більше і не менше.
# Список файлів типу file1.txt, file2.txt, fileA.txtls file?.txt# Підходить: file1.txt, fileA.txt, filex.txt# НЕ підходить: file12.txt (два символи там, де очікується один)# НЕ підходить: file.txt (нуль символів там, де очікується один)
# Файли з розширенням із двох символівls *.??# Підходить: archive.gz, image.py, data.js# НЕ підходить: readme.txt (розширення з трьох символів)
# Лог-файли з одноцифровим номером ротаціїls app.log.?# Підходить: app.log.1, app.log.2, app.log.9# НЕ підходить: app.log.10Квадратні дужки [] — Один символ із набору
Розділ «Квадратні дужки [] — Один символ із набору»Квадратні дужки відповідають рівно одному символу, але тільки з тих, які ви вказали.
# Тільки вказані символиls file[abc].txt# Підходить: filea.txt, fileb.txt, filec.txt# НЕ підходить: filed.txt
# Діапазон символівls data[0-9].csv# Підходить: data0.csv, data1.csv, ... data9.csv
# Великі літериls report[A-Z].pdf# Підходить: reportA.pdf, reportB.pdf, ... reportZ.pdf
# Комбінація діапазонівls log[0-9a-f].txt# Підходить: log0.txt, loga.txt, logf.txt# НЕ підходить: logg.txt (літера 'g' поза межами діапазону)
# Заперечення через ! або ^ — будь-що, КРІМ вказаногоls file[!0-9].txt# Підходить: filea.txt, fileZ.txt# НЕ підходить: file1.txt, file9.txtФігурні дужки {} — Генерація декількох рядків
Розділ «Фігурні дужки {} — Генерація декількох рядків»Фігурні дужки технічно не є подстановочними знаками (це функція Bash під назвою “brace expansion”), але вони постійно використовуються разом із ними.
# Створити декілька файлів одночасноtouch report_{jan,feb,mar}.txt# Створить: report_jan.txt, report_feb.txt, report_mar.txt
# Створити бекап файлу з новим розширеннямcp config.yaml{,.bak}# Перетвориться на: cp config.yaml config.yaml.bak
# Створити структуру директорійmkdir -p project/{src,tests,docs}# Створить три піддиректорії всередині project/Головна думка: Shell розгортає шаблони до того, як команда їх побачить. Коли ви вводите
ls *.txt, shell перетворює це на щось на кшталтls notes.txt readme.txt todo.txtі тільки потім запускаєlsіз цими трьома аргументами. Сама командаlsніколи не бачить символу*.
2. Потоки: Як дані течуть через команди
Розділ «2. Потоки: Як дані течуть через команди»Кожна команда в Linux працює з трьома невидимими каналами даних. Розуміння цих каналів — це фундамент для всього іншого в цьому модулі.
┌─────────────────────┐ Клавіатура ------->│ │--------> Екран (stdin) │ Ваша команда │ (stdout) Потік 0 │ (напр. grep) │ Потік 1 │ │ │ │--------> Екран └─────────────────────┘ (stderr) Потік 2- stdin (потік 0): Звідки команда читає вхідні дані. За замовчуванням це ваша клавіатура. Але це може бути файл або вивід іншої команди.
- stdout (потік 1): Куди команда надсилає нормальні результати. За замовчуванням це ваш екран.
- stderr (потік 2): Куди команда надсилає повідомлення про помилки. Також йде на екран за замовчуванням, але це окремий потік від stdout.
Чому stdout і stderr розділені? Тому що ви часто хочете обробляти їх по-різному. Ви можете захотіти зберегти нормальний вивід у файл, але при цьому бачити помилки на екрані. Або ви захочете приховати помилки, залишивши тільки корисні дані. Розділення дає вам цей контроль.
3. Перенаправлення: Керування куди йде вивід
Розділ «3. Перенаправлення: Керування куди йде вивід»Перенаправлення дозволяє змінювати маршрути цих трьох потоків — надсилати вивід у файли замість екрана або читати вхідні дані з файлів замість клавіатури.
> Перенаправити вивід (Перезаписати)
Розділ «> Перенаправити вивід (Перезаписати)»Надсилає stdout у файл. Увага: це знищує поточний вміст файлу.
# Зберегти список файлів у текстовий файлls -la /etc > etc_contents.txt
# Зберегти поточну дату та часdate > timestamp.txt
# Зберегти ім'я хоста вашої системиhostname > server_info.txt>> Перенаправити вивід (Додати в кінець)
Розділ «>> Перенаправити вивід (Додати в кінець)»Додає stdout у кінець файлу. Поточний вміст файлу зберігається.
# Накопичувати лог-файл з часомecho "=== Deploy started ===" >> deploy.logecho "Version: 2.4.1" >> deploy.logecho "=== Deploy finished ===" >> deploy.log
# Додати сьогоднішню статистику диска до щоденного звітуdf -h >> /var/log/daily_disk_report.txtРеальний випадок — просте логування:
# Кожного разу при запуску скрипт додає запис із міткою часуecho "$(date): Backup completed successfully" >> /var/log/backup.log2> Перенаправити помилки
Розділ «2> Перенаправити помилки»Надсилає тільки stderr (потік 2) у файл. Нормальний вивід все одно йде на екран.
# Спробуйте вивести список директорії, до якої немає доступу, і збережіть помилкуls /root 2> errors.log# Помилка "Permission denied" піде в errors.log, а не на екран
# Запустити find без спаму помилками доступуfind / -name "nginx.conf" 2> /dev/null# /dev/null — це "чорна діра" Linux. Помилки зникають, результати на екрані.&> Перенаправити ВСЕ
Розділ «&> Перенаправити ВСЕ»Надсилає і stdout, і stderr в один і той самий файл.
# Захопити весь вивід процесу збіркиmake build &> build_output.log
# Запустити скрипт і зберегти все для налагодження./deploy.sh &> deploy_full_log.txt< Перенаправити ввід
Розділ «< Перенаправити ввід»Надсилає вміст файлу в stdin команди (замість введення з клавіатури).
# Порахувати рядки, слова та символи у файліwc < report.txt
# Відсортувати вміст файлуsort < unsorted_names.txt
# Надіслати email із вмістом файлу (якщо налаштована пошта)mail -s "Report" admin@example.com < report.txtКомбінування перенаправлень
Розділ «Комбінування перенаправлень»Ви можете направляти stdout і stderr у різні файли:
# Зберегти результати в один файл, а помилки — в іншийfind / -name "*.conf" > results.txt 2> errors.txt
# Зберегти вивід у файл, а помилки викинутиgrep -r "TODO" /project > todos.txt 2> /dev/nullТрюк із /dev/null: /dev/null — це спеціальний файл, який відкидає все, що в нього записують. Думайте про нього як про чорну діру. Це неймовірно корисно, коли ви хочете придушити вивід, який вам не цікавий.
# Запустити команду беззвучно — ні виводу, ні помилокcommand_that_is_noisy > /dev/null 2>&1
# Перевірити, чи успішна команда, не зважаючи на вивідif grep -q "ready" status.txt 2> /dev/null; then echo "Система готова"fi4. Канали (Pipes): Складальна лінія
Розділ «4. Канали (Pipes): Складальна лінія»Канали (|) — це найпотужніша концепція цього модуля. Канал бере stdout однієї команди й передає його напряму в stdin наступної команди. Жодних тимчасових файлів не потрібно.
Уявіть це як заводську конвеєрну стрічку: кожна машина (команда) робить одну маленьку роботу і передає результат наступній машині.
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐│ ком1 │--->│ ком2 │--->│ ком3 │--->│ ком4 │---> Фінальний результат└──────┘ └──────┘ └──────┘ └──────┘ stdout stdout stdout stdout стає стає стає stdin stdin stdinПочнемо з простого
Розділ «Почнемо з простого»# Список файлів і прокрутка результату сторінка за сторінкоюls -la /etc | less
# Порахувати, скільки файлів у директоріїls /etc | wc -l
# Показати тільки 5 найбільших файлівdu -sh /var/log/* | sort -rh | head -5Нарощуємо складність: канали з двох команд
Розділ «Нарощуємо складність: канали з двох команд»# Знайти всі запущені процеси, що містять "nginx"ps aux | grep nginx
# Показати використання диска, відсортоване за розміром (найбільші зверху)du -sh /home/* | sort -rh
# Список тільки директорій у поточному місціls -la | grep "^d"
# Показати унікальні оболонки (shells), що використовуються в системіcat /etc/passwd | cut -d: -f7 | sort -uСправжня сила: ланцюжки з багатьох команд
Розділ «Справжня сила: ланцюжки з багатьох команд»Ось де канали справді сяють. Кожен крок робить одну просту річ, але разом вони вирішують складні проблеми.
# Знайти 5 IP-адрес, які найчастіше звертаються до вашого вебсервераcat /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -5# Крок за кроком:# 1. cat: читає лог-файл# 2. awk '{print $1}': витягує перше поле (IP-адресу) з кожного рядка# 3. sort: сортує IP за алфавітом (необхідно для роботи uniq)# 4. uniq -c: рахує кількість повторюваних рядків, що йдуть підряд# 5. sort -rn: сортує за кількістю, числово, у зворотному порядку (найбільші зверху)# 6. head -5: показує тільки топ-5 результатів
# Знайти процеси, що споживають найбільше пам'ятіps aux | sort -k4 -rn | head -10 | awk '{print $4"% "$11}'# Покаже: відсоток пам'яті та назву команди для топ-10 процесів
# Порахувати, скільки разів кожен HTTP статус-код зустрічається в логахcat access.log | awk '{print $9}' | sort | uniq -c | sort -rn# Вивід може виглядати так:# 15234 200# 2341 304# 187 404# 23 500Порівняння «До і Після» — Чому канали змінюють усе
Розділ «Порівняння «До і Після» — Чому канали змінюють усе»Без каналів (важкий шлях):
# Крок 1: Зберегти інфо про процеси в тимчасовий файлps aux > /tmp/all_processes.txt# Крок 2: Шукати в цьому файлі pythongrep python /tmp/all_processes.txt > /tmp/python_processes.txt# Крок 3: Порахувати рядкиwc -l /tmp/python_processes.txt# Крок 4: Видалити тимчасові файлиrm /tmp/all_processes.txt /tmp/python_processes.txtЗ каналами (шлях досвідченого користувача):
ps aux | grep python | wc -lОдин рядок. Жодних тимчасових файлів. Жодного прибирання. Той самий результат.
5. find: Пошук файлів як детектив
Розділ «5. find: Пошук файлів як детектив»Команда find шукає у файловій системі файли та директорії, що відповідають вашим критеріям. На відміну від ls, вона за замовчуванням шукає рекурсивно в усіх піддиректоріях.
Базовий синтаксис: find [де шукати] [що шукати]
Пошук за назвою
Розділ «Пошук за назвою»# Знайти файл із назвою "config.yaml", починаючи з поточної директоріїfind . -name "config.yaml"
# Знайти всі YAML файли (чутливий до регістру)find . -name "*.yaml"
# Знайти всі YAML файли (нечутливий до регістру — знайде і .YAML, і .Yaml)find . -iname "*.yaml"
# Пошук у конкретній директоріїfind /etc -name "*.conf"Пошук за типом
Розділ «Пошук за типом»# Тільки директоріїfind . -type d
# Тільки звичайні файли (не директорії, не посилання)find . -type f
# Тільки символічні посилання (symlinks)find . -type l
# Усі директорії з назвою "test"find . -type d -name "test"Пошук за розміром — реальні сценарії
Розділ «Пошук за розміром — реальні сценарії»# Знайти файли понад 100 МБ (пошук тих, хто "з'їв" місце на диску)find /var -type f -size +100M
# Знайти файли понад 1 ГБ (ігноруємо помилки доступу)find / -type f -size +1G 2> /dev/null
# Знайти маленькі файли (менше за 1 КБ) — можливе сміттяfind . -type f -size -1k
# Знайти абсолютно порожні файли (0 байт)find . -type f -emptyПошук за часом — що змінилося нещодавно?
Розділ «Пошук за часом — що змінилося нещодавно?»# Файли, змінені за останні 24 годиниfind /var/log -type f -mtime -1
# Файли, змінені за останні 30 хвилинfind . -type f -mmin -30
# Файли, які НЕ змінювалися останні 90 днів (застарілі)find /home -type f -mtime +90
# Файли, до яких зверталися за останню годинуfind . -type f -amin -60Пошук із діями
Розділ «Пошук із діями»find може не просто виводити список, а й щось робити з файлами.
# Видалити всі .tmp файли (ОБЕРЕЖНО — без можливості скасування!)find /tmp -name "*.tmp" -delete
# Виконати команду для кожного знайденого файлу (-exec)find . -name "*.log" -exec wc -l {} \;# {} замінюється на кожне знайдене ім'я файлу# \; позначає кінець команди -exec
# Змінити дозволи на всіх скриптах оболонкиfind . -name "*.sh" -exec chmod +x {} \;
# Вивести результати з деталями (як ls -l)find . -name "*.conf" -lsПорада: Завжди беріть шаблони у лапки в команді
find. Якщо ви напишетеfind . -name *.txtбез лапок і в поточній директорії є .txt файли, shell розгорне*.txtще до запускуfind, і ви отримаєте неочікувані результати. Завжди використовуйтеfind . -name "*.txt".
6. grep: Пошук ВСЕРЕДИНІ файлів
Розділ «6. grep: Пошук ВСЕРЕДИНІ файлів»Якщо find шукає файли за назвою або розміром, то grep шукає всередині файлів текст, що відповідає шаблону. Він виводить кожен рядок, де знайдено збіг.
Базовий синтаксис: grep [опції] "шаблон" файл
Базовий пошук
Розділ «Базовий пошук»# Знайти рядки з "error" у лог-файліgrep "error" /var/log/syslog
# Нечутливий до регістру пошук (знайде і Error, і ERROR, і error)grep -i "error" /var/log/syslog
# Пошук у декількох файлах одночасноgrep "timeout" server1.log server2.log server3.log
# Рекурсивний пошук у всіх файлах директоріїgrep -r "password" /etc/# УВАГА: це може показати конфіденційні дані — будьте відповідальніКонтекст — показати сусідні рядки
Розділ «Контекст — показати сусідні рядки»Коли ви знайшли збіг, часто потрібно побачити, що відбувалося навколо нього. Для цього є -A, -B та -C.
# Показати 3 рядки ПІСЛЯ кожного збігу (A = After)grep -A 3 "Exception" app.log# Чудово для перегляду стек-трейсів, що йдуть після помилки
# Показати 2 рядки ДО кожного збігу (B = Before)grep -B 2 "failed" deploy.log# Допомагає побачити, яка команда призвела до збою
# Показати 3 рядки до І після збігу (C = Context)grep -C 3 "timeout" app.log# Повна картина навколо кожного збігу
# Поєднання з ігноруванням регіструgrep -i -C 5 "critical" /var/log/syslogПідрахунок та списки
Розділ «Підрахунок та списки»# Порахувати кількість рядків (замість їх виводу)grep -c "404" access.log# Вивід: 187 (просто число)
# Показати тільки назви файлів, де є збіги (а не самі рядки)grep -rl "TODO" /project/src/# Вивід: список файлів, по одному в рядку
# Показати номери рядків разом зі збігамиgrep -n "def main" *.py# Вивід: main.py:42:def main():Інверсія та точний пошук
Розділ «Інверсія та точний пошук»# Показати рядки, що НЕ містять шаблон (invert)grep -v "DEBUG" app.log# Покаже все, крім дебаг-рядків — чудово для зменшення шуму
# Тільки цілі слова (не часткові збіги)grep -w "error" app.log# Знайде "error", але НЕ знайде "errors" або "error_handler"
# Пошук на початку або в кінці рядкаgrep "^#" config.conf # Рядки, що починаються з # (коментарі)grep "\.conf$" filelist # Рядки, що закінчуються на .confgrep із каналами — найпоширеніший патерн
Розділ «grep із каналами — найпоширеніший патерн»Ви будете використовувати grep із каналами частіше, ніж будь-яку іншу комбінацію в Linux.
# Знайти запущені процеси за назвоюps aux | grep nginx
# Фільтрація історії командhistory | grep "docker"
# Знайти відкриті мережеві порти для конкретного сервісуss -tlnp | grep 8080
# Перевірити, чи встановлено пакет (Debian/Ubuntu)dpkg -l | grep "nginx"
# Знайти змінні оточення, пов'язані з Javaenv | grep -i java7. Супер-комбо: find + grep + канали
Розділ «7. Супер-комбо: find + grep + канали»Справжня магія починається при поєднанні цих інструментів. Саме так досвідчені користувачі Linux вирішують реальні задачі.
Сценарій 1: Знайти всі конфіг-файли, що містять адресу бази даних
Розділ «Сценарій 1: Знайти всі конфіг-файли, що містять адресу бази даних»find /etc -name "*.conf" -exec grep -l "db.example.com" {} \;Це знайде кожен .conf файл у /etc, перевірить кожен на наявність тексту “db.example.com” і виведе назви тільки тих файлів, де цей текст є.
Сценарій 2: Пошук визначення функції у всьому проєкті
Розділ «Сценарій 2: Пошук визначення функції у всьому проєкті»find . -name "*.py" | xargs grep -n "def process_order"Тут find дає список усіх Python-файлів, а xargs передає цей список у grep, який шукає визначення функції у кожному файлі й показує номер рядка.
Сценарій 3: Знайти великі лог-файли, змінені сьогодні
Розділ «Сценарій 3: Знайти великі лог-файли, змінені сьогодні»find /var/log -name "*.log" -size +10M -mtime -1 -exec ls -lh {} \;Знаходить лог-файли понад 10 МБ, які змінювалися за останні 24 години, і показує детальну інформацію про них.
Сценарій 4: Порахувати коментарі TODO у всьому коді
Розділ «Сценарій 4: Порахувати коментарі TODO у всьому коді»find . -name "*.js" -o -name "*.ts" | xargs grep -c "TODO" | grep -v ":0$"Знаходить усі JavaScript та TypeScript файли, рахує кількість TODO у кожному і відфільтровує файли, де TODO немає.
Сценарій 5: Знайти та “вбити” завислий процес
Розділ «Сценарій 5: Знайти та “вбити” завислий процес»ps aux | grep "[r]unaway_script" | awk '{print $2}' | xargs killТрюк із [r] запобігає тому, щоб grep знаходив сам себе у списку процесів. awk витягує PID (друга колонка), а xargs передає його команді kill.
Повчальна історія: Нічне полювання за логами
Розділ «Повчальна історія: Нічне полювання за логами»Кілька років тому молодший інженер отримав сповіщення: обробка платежів у компанії зламалася. Він зайшов на сервер через SSH, відкрив /var/log/app.log у редакторі nano і почав гортати. Файл важив 2 ГБ. Nano завис. Він спробував vi. Той завантажився повільно, і інженер почав шукати вручну. Через 45 хвилин він так і не знайшов причину.
До дзвінка підключився старший інженер і ввів:
grep -i "payment" /var/log/app.log | grep -i "error" | tail -20Через вісім секунд вони мали відповідь: сторонній платіжний шлюз змінив адресу свого API. Виправлення зайняло один рядок у конфігу.
Молодший інженер міг би знайти це менше ніж за хвилину за допомогою інструментів, які ви щойно вивчили. Урок не в тому, що гортати файли — це погано. А в тому, що знання своїх інструментів перетворює вас із того, хто реагує повільно, на того, хто вирішує проблеми миттєво. Саме це робить вас цінним фахівцем.
Чи знали ви?
Розділ «Чи знали ви?»-
Назва
grep— це абревіатура. Вона означає “Global Regular Expression Print”. Це походить від команди в прадавньому текстовому редакторіed:g/re/p. Інструмент був написаний Кеном Томпсоном у 1973 році й майже не змінився з того часу — бо він і так досконалий. -
Канали (pipes) винайшли під час обідньої перерви. Даг Макілрой запропонував ідею з’єднання програм у Bell Labs у 1964 році. Кену Томпсону це так сподобалося, що він додав підтримку каналів у Unix за одну ніч. Символ
|був обраний, бо він рідко використовувався і нагадував фізичну трубу. -
/dev/nullназивають “найкориснішим файлом у Unix”. Усе, що туди пишеться, миттєво зникає. Він є частиною Unix з 1971 року. В інтернет-культурі “відправити щось у /dev/null” означає ігнорувати це повністю. -
Команда
findможе замінити десятки кліків у GUI. Задача на кшталт “знайти всі PDF-файли, змінені за останній тиждень, розміром понад 5 МБ” зайняла б хвилини клацання по папках у графічному менеджері. Зfindце один рядок:find . -name "*.pdf" -mtime -7 -size +5M.
Типові помилки
Розділ «Типові помилки»| Помилка | Чому це стається | Як виправити |
|---|---|---|
Використання > замість >> | Ви хотіли додати запис у лог, але випадково перезаписали файл, знищивши всі попередні записи. | Зробіть паузу і подумайте: “Я хочу замінити чи додати?” Якщо сумніваєтеся, використовуйте >>. |
Забули лапки навколо шаблонів у find | Написали find . -name *.txt без лапок. Якщо в поточній папці є .txt файли, shell розгорне їх у список імен до запуску find, що призведе до дивних помилок. | Завжди беріть у лапки: find . -name "*.txt". |
| Передача виводу через pipe у команди, що ігнорують stdin | Команди як ls, cd, rm не читають дані зі stdin. echo "/etc" | ls не зробить нічого корисного. | Використовуйте xargs для перетворення stdin в аргументи: echo "/etc" | xargs ls. |
Пошук від / без придушення помилок | Запуск find / -name "myfile" затопить ваш екран помилками “Permission denied” з папок, до яких у вас немає доступу. | Додайте 2> /dev/null, щоб сховати помилки: find / -name "myfile" 2> /dev/null. |
Використання grep без -r для папок | Ви написали grep "error" /var/log/ очікуючи пошуку по всіх файлах, але grep шукає тільки у файлах, які ви назвали явно. | Додайте -r для рекурсивного пошуку: grep -r "error" /var/log/. |
Плутанина між find -name та find -path | Ви очікували, що find . -name "src/config.yaml" знайде шлях, але -name шукає тільки по частині з іменем файлу. | Використовуйте -path для пошуку за повним шляхом: find . -path "*/src/config.yaml". |
grep "pattern" без вказання файлу “зависає” | Ви ввели grep "hello" і термінал ніби замерз. Насправді він чекає, поки ви почнете вводити текст із клавіатури (stdin). | Натисніть Ctrl+C для скасування. Вкажіть файл (grep "hello" file.txt) або передайте дані через pipe. |
Тест
Розділ «Тест»Перевірте свої знання. Спробуйте відповісти перед тим, як відкрити рішення.
1. Яка різниця між подстановочними знаками * та ??
* відповідає будь-якій кількості (0 або більше) будь-яких символів. ? відповідає рівно одному символу.
file*знайдеfile,file1,file_backup,filename.txtfile?знайдеfile1,fileA, але НЕ знайдеfile(0 символів) абоfile12(2 символи)
2. Ви хочете зберегти вивід команди у файл results.txt, не втрачаючи дані, які вже там є. Який оператор ви використаєте?
Оператор додавання в кінець >>.
my_command >> results.txtВикористання > перезапише файл. Використання >> додасть дані в кінець.
3. Що робить конструкція 2> /dev/null?
Вона перенаправляє потік помилок (stderr, потік 2) у пристрій /dev/null, який просто відкидає дані. Простою мовою: це приховує всі повідомлення про помилки, залишаючи на екрані тільки корисний результат.
Це часто використовується з find, щоб приховати повідомлення про відмову в доступі:
find / -name "config.yaml" 2> /dev/null4. Напишіть команду для пошуку всіх файлів .log у директорії /var, які мають розмір понад 50 МБ.
find /var -name "*.log" -size +50MМожна додати -type f, щоб переконатися, що це саме файли, а не директорії:
find /var -type f -name "*.log" -size +50M5. Ви хочете знайти в файлі app.log слово "timeout" (незалежно від регістру) і побачити по 3 рядки тексту навколо кожного збігу. Яка команда це зробить?
grep -i -C 3 "timeout" app.log-iробить пошук нечутливим до регістру-C 3показує по 3 рядки до і після кожного збігу
6. Поясніть, що робить цей ланцюжок команд: cat access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10
Він знаходить топ-10 найактивніших відвідувачів (за IP-адресою) в логах вебсервера:
cat access.log— читає файлawk '{print $1}'— витягує тільки перше поле з кожного рядка (IP адресу)sort— сортує IP за алфавітом (необхідно для роботи uniq)uniq -c— видаляє повтори й додає кількість кожного IPsort -rn— сортує за кількістю, числово, від більшого до меншогоhead -10— показує тільки перші 10 результатів
7. Що не так із цією командою: find . -name *.py?
Шаблон *.py не взято в лапки. Якщо в поточній директорії є .py файли, shell розгорне *.py у їхні імена до того, як запуститься find. Наприклад, якщо є main.py, команда перетвориться на find . -name main.py, що знайде тільки один цей файл замість усіх Python-файлів у піддиректоріях.
Виправлення: Завжди беріть шаблони у лапки:
find . -name "*.py"8. Як направити нормальний вивід в один файл, а помилки — в інший?
command > output.txt 2> errors.txt>(або1>) направляє stdout (потік 1) уoutput.txt2>направляє stderr (потік 2) уerrors.txt
Практична вправа: Розслідування на сервері
Розділ «Практична вправа: Розслідування на сервері»Сценарій: Ви — молодший SRE інженер, що розслідує збій у роботі сервісу. Вам надали сервер із декількома лог-файлами. Ваше завдання — знайти релевантні помилки, витягнути їх і створити короткий звіт. Ви використаєте все, що вивчили: шаблони, перенаправлення, канали, find та grep.
Підготовка
Розділ «Підготовка»Створіть тренувальне середовище:
# Створюємо директорію для розслідуванняmkdir -p ~/investigation/logs
# Створюємо симульовані лог-файлиcat > ~/investigation/logs/web.log << 'EOF'2024-03-15 08:01:12 INFO Request received: GET /api/users2024-03-15 08:01:13 INFO Response sent: 200 OK2024-03-15 08:02:44 ERROR Connection to database timed out2024-03-15 08:02:45 ERROR Failed to process request: GET /api/orders2024-03-15 08:03:01 WARN Retry attempt 1 for database connection2024-03-15 08:03:02 INFO Database connection restored2024-03-15 08:05:30 INFO Request received: GET /api/products2024-03-15 08:07:15 ERROR OutOfMemoryError: heap space exhausted2024-03-15 08:07:16 ERROR Service crashed - restartingEOF
cat > ~/investigation/logs/db.log << 'EOF'2024-03-15 08:00:00 INFO Database server started2024-03-15 08:02:40 WARN Connection pool exhausted (max: 100)2024-03-15 08:02:42 ERROR Too many connections - rejecting new requests2024-03-15 08:02:43 ERROR Query timeout: SELECT * FROM orders WHERE status='pending'2024-03-15 08:03:00 INFO Connection pool recovered2024-03-15 08:06:00 INFO Routine backup started2024-03-15 08:07:10 ERROR Disk space critical: /var/lib/mysql at 98%EOF
cat > ~/investigation/logs/app.log << 'EOF'2024-03-15 08:00:05 INFO Application started on port 80802024-03-15 08:01:10 INFO Health check passed2024-03-15 08:02:44 ERROR Upstream service unavailable: payment-gateway2024-03-15 08:02:50 WARN Circuit breaker opened for payment-gateway2024-03-15 08:04:00 INFO Circuit breaker closed for payment-gateway2024-03-15 08:07:14 ERROR Memory usage exceeded threshold: 95%2024-03-15 08:07:15 ERROR Initiating graceful shutdown2024-03-15 08:07:16 INFO Shutdown completeEOF
# Створимо текстові файли для вправ із findecho "This is a config file" > ~/investigation/config.txtecho "Important notes here" > ~/investigation/notes.txtЗавдання
Розділ «Завдання»Виконайте кожне завдання за допомогою вивчених інструментів. Спробуйте самі перед тим, як зазирнути у відповідь.
Завдання 1: Використайте подстановочний знак, щоб вивести список ТІЛЬКИ .log файлів у ~/investigation/logs/.
Рішення
ls ~/investigation/logs/*.logЗавдання 2: Використайте grep, щоб знайти всі рядки з текстом “ERROR” в усіх лог-файлах. Збережіть результат у файл ~/investigation/all_errors.txt.
Рішення
grep "ERROR" ~/investigation/logs/*.log > ~/investigation/all_errors.txtЗавдання 3: Порахуйте, скільки рядків ERROR є у КОЖНОМУ лог-файлі (без виводу самих рядків).
Рішення
grep -c "ERROR" ~/investigation/logs/*.logОчікуваний вивід:
/home/user/investigation/logs/app.log:3/home/user/investigation/logs/db.log:3/home/user/investigation/logs/web.log:4Завдання 4: Знайдіть усі помилки, пов’язані з “database” або “memory” (незалежно від регістру), показуючи 1 рядок тексту ДО кожного збігу.
Рішення
grep -i -B 1 -E "database|memory" ~/investigation/logs/*.logЗавдання 5: Використайте find, щоб знайти всі .txt файли в директорії ~/investigation.
Рішення
find ~/investigation -name "*.txt"Завдання 6 (Рівень Боса): Напишіть один ланцюжок команд (pipeline), який:
- Читає всі лог-файли.
- Фільтрує тільки рядки з ERROR.
- Сортує їх за часом.
- Бере останні 5 (найсвіжіші помилки).
- Зберігає їх у файл
~/investigation/recent_critical.txt.
Рішення
cat ~/investigation/logs/*.log | grep "ERROR" | sort | tail -5 > ~/investigation/recent_critical.txtПеревірте результат:
cat ~/investigation/recent_critical.txtВи маєте побачити 5 останніх помилок, відсортованих за часом.
Критерії успіху
Розділ «Критерії успіху»Ви завершили цю вправу, якщо:
- Файл
~/investigation/all_errors.txtіснує і містить тільки рядки ERROR. - Ви знаєте, скільки помилок у кожному лог-файлі (Завдання 3).
- Файл
~/investigation/recent_critical.txtмістить рівно 5 відсортованих помилок. - Ви виконали кожне завдання за допомогою команд у терміналі (без графічних інструментів).
Далі: Модуль 0.2: Оточення та Дозволи — Дізнайтеся, як Linux знає, хто ви такий, як налаштувати свою оболонку та як система дозволів дбає про безпеку.