Перейти до вмісту

Модуль 0.1: Досвідчений користувач CLI (Пошук та Потоки)

Hands-On Lab Available
Ubuntu intermediate 30 min
Launch Lab ↗

Opens in Killercoda in a new tab

Складність: [QUICK] — Швидке опанування базових інструментів

Час на виконання: 45 хвилин

Передумови: «Від нуля до термінала» (Модуль 0.8)


Що ви зможете робити після цього модуля

Розділ «Що ви зможете робити після цього модуля»

Після завершення цього модуля ви зможете:

  • З’єднувати команди за допомогою пайпів, перенаправлень та підоболонок для створення потужних однорядкових конструкцій
  • Шукати файли та вміст ефективно, використовуючи find, grep та xargs
  • Обробляти текстові потоки за допомогою cut, sort, uniq, awk та sed для аналізу логів
  • Перенаправляти stdout, stderr та комбінувати потоки для скриптів і відлагодження

Чому цей модуль важливий

Розділ «Чому цей модуль важливий»

Уявіть картину: зараз 2-га година ночі, і ваш пейджер спрацьовує. Вебзастосунок повертає помилки 500. Десь у 47 лог-файлах, розкиданих по /var/log, є підказка — стек викликів (stack trace), тайм-аут або відмова у з’єднанні. Ви могли б відкривати кожен файл один за одним, прокручувати тисячі рядків втомленими очима і сподіватися помітити слово “error” до сходу сонця. Або ви могли б ввести один рядок:

Terminal window
grep -ri "error" /var/log/app/ | grep -i "database" | tail -20

Через три секунди у вас перед очима 20 останніх помилок, пов’язаних із базою даних, з усіх лог-файлів. Проблему ідентифіковано. Виправлення розгорнуто. О 2:15 ви вже знову спите.

Ось у чому різниця, яку дає цей модуль. Ви вже знаєте, як навігувати по файловій системі та запускати основні команди з курсу «Від нуля до терміналу». Тепер ви навчитеся комбінувати ці команди в потужні робочі процеси. Ви навчитеся шукати файли, шукати всередині файлів, керувати тим, куди спрямовується вивід, і з’єднувати команди, як блоки конструктора.

Це не просунуті трюки. Це повсякденні інструменти, якими професіонали Linux користуються сотні разів на день. До кінця цього модуля ви відчуєте, що маєте суперсилу — бо так воно і буде.


1. Подстановочні знаки (Wildcards): Шаблони для нетерплячих

Розділ «1. Подстановочні знаки (Wildcards): Шаблони для нетерплячих»

Введення повних імен файлів — це повільно і призводить до помилок. Подстановочні знаки (також звані “globs”) дозволяють вибирати декілька файлів за допомогою шаблонів. Оболонка (shell) розгортає їх ще до того, як команда почне виконуватися.

Зірочка * — Будь-що

Розділ «Зірочка * — Будь-що»

Зірочка * відповідає будь-якій кількості будь-яких символів (включаючи нуль).

Terminal window
# Список усіх .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-файли в директорію backup
cp *.py ~/backup/
# Список файлів, що мають "config" будь-де в назві
ls *config*
# Підходить: config.yaml, app-config.json, myconfig, config_backup.tar.gz

Знак питання ? — Рівно один символ

Розділ «Знак питання ? — Рівно один символ»

Знак ? відповідає рівно одному символу — не більше і не менше.

Terminal window
# Список файлів типу file1.txt, file2.txt, fileA.txt
ls 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

Квадратні дужки [] — Один символ із набору

Розділ «Квадратні дужки [] — Один символ із набору»

Квадратні дужки відповідають рівно одному символу, але тільки з тих, які ви вказали.

Terminal window
# Тільки вказані символи
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”), але вони постійно використовуються разом із ними.

Terminal window
# Створити декілька файлів одночасно
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 у файл. Увага: це знищує поточний вміст файлу.

Terminal window
# Зберегти список файлів у текстовий файл
ls -la /etc > etc_contents.txt
# Зберегти поточну дату та час
date > timestamp.txt
# Зберегти ім'я хоста вашої системи
hostname > server_info.txt

>> Перенаправити вивід (Додати в кінець)

Розділ «>> Перенаправити вивід (Додати в кінець)»

Додає stdout у кінець файлу. Поточний вміст файлу зберігається.

Terminal window
# Накопичувати лог-файл з часом
echo "=== Deploy started ===" >> deploy.log
echo "Version: 2.4.1" >> deploy.log
echo "=== Deploy finished ===" >> deploy.log
# Додати сьогоднішню статистику диска до щоденного звіту
df -h >> /var/log/daily_disk_report.txt

Реальний випадок — просте логування:

Terminal window
# Кожного разу при запуску скрипт додає запис із міткою часу
echo "$(date): Backup completed successfully" >> /var/log/backup.log

2> Перенаправити помилки

Розділ «2> Перенаправити помилки»

Надсилає тільки stderr (потік 2) у файл. Нормальний вивід все одно йде на екран.

Terminal window
# Спробуйте вивести список директорії, до якої немає доступу, і збережіть помилку
ls /root 2> errors.log
# Помилка "Permission denied" піде в errors.log, а не на екран
# Запустити find без спаму помилками доступу
find / -name "nginx.conf" 2> /dev/null
# /dev/null — це "чорна діра" Linux. Помилки зникають, результати на екрані.

&> Перенаправити ВСЕ

Розділ «&> Перенаправити ВСЕ»

Надсилає і stdout, і stderr в один і той самий файл.

Terminal window
# Захопити весь вивід процесу збірки
make build &> build_output.log
# Запустити скрипт і зберегти все для налагодження
./deploy.sh &> deploy_full_log.txt

< Перенаправити ввід

Розділ «< Перенаправити ввід»

Надсилає вміст файлу в stdin команди (замість введення з клавіатури).

Terminal window
# Порахувати рядки, слова та символи у файлі
wc < report.txt
# Відсортувати вміст файлу
sort < unsorted_names.txt
# Надіслати email із вмістом файлу (якщо налаштована пошта)
mail -s "Report" admin@example.com < report.txt

Комбінування перенаправлень

Розділ «Комбінування перенаправлень»

Ви можете направляти stdout і stderr у різні файли:

Terminal window
# Зберегти результати в один файл, а помилки — в інший
find / -name "*.conf" > results.txt 2> errors.txt
# Зберегти вивід у файл, а помилки викинути
grep -r "TODO" /project > todos.txt 2> /dev/null

Трюк із /dev/null: /dev/null — це спеціальний файл, який відкидає все, що в нього записують. Думайте про нього як про чорну діру. Це неймовірно корисно, коли ви хочете придушити вивід, який вам не цікавий.

Terminal window
# Запустити команду беззвучно — ні виводу, ні помилок
command_that_is_noisy > /dev/null 2>&1
# Перевірити, чи успішна команда, не зважаючи на вивід
if grep -q "ready" status.txt 2> /dev/null; then
echo "Система готова"
fi

4. Канали (Pipes): Складальна лінія

Розділ «4. Канали (Pipes): Складальна лінія»

Канали (|) — це найпотужніша концепція цього модуля. Канал бере stdout однієї команди й передає його напряму в stdin наступної команди. Жодних тимчасових файлів не потрібно.

Уявіть це як заводську конвеєрну стрічку: кожна машина (команда) робить одну маленьку роботу і передає результат наступній машині.

┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐
│ ком1 │--->│ ком2 │--->│ ком3 │--->│ ком4 │---> Фінальний результат
└──────┘ └──────┘ └──────┘ └──────┘
stdout stdout stdout stdout
стає стає стає
stdin stdin stdin

Почнемо з простого

Розділ «Почнемо з простого»
Terminal window
# Список файлів і прокрутка результату сторінка за сторінкою
ls -la /etc | less
# Порахувати, скільки файлів у директорії
ls /etc | wc -l
# Показати тільки 5 найбільших файлів
du -sh /var/log/* | sort -rh | head -5

Нарощуємо складність: канали з двох команд

Розділ «Нарощуємо складність: канали з двох команд»
Terminal window
# Знайти всі запущені процеси, що містять "nginx"
ps aux | grep nginx
# Показати використання диска, відсортоване за розміром (найбільші зверху)
du -sh /home/* | sort -rh
# Список тільки директорій у поточному місці
ls -la | grep "^d"
# Показати унікальні оболонки (shells), що використовуються в системі
cat /etc/passwd | cut -d: -f7 | sort -u

Справжня сила: ланцюжки з багатьох команд

Розділ «Справжня сила: ланцюжки з багатьох команд»

Ось де канали справді сяють. Кожен крок робить одну просту річ, але разом вони вирішують складні проблеми.

Terminal window
# Знайти 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

Порівняння «До і Після» — Чому канали змінюють усе

Розділ «Порівняння «До і Після» — Чому канали змінюють усе»

Без каналів (важкий шлях):

Terminal window
# Крок 1: Зберегти інфо про процеси в тимчасовий файл
ps aux > /tmp/all_processes.txt
# Крок 2: Шукати в цьому файлі python
grep 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

З каналами (шлях досвідченого користувача):

Terminal window
ps aux | grep python | wc -l

Один рядок. Жодних тимчасових файлів. Жодного прибирання. Той самий результат.


5. find: Пошук файлів як детектив

Розділ «5. find: Пошук файлів як детектив»

Команда find шукає у файловій системі файли та директорії, що відповідають вашим критеріям. На відміну від ls, вона за замовчуванням шукає рекурсивно в усіх піддиректоріях.

Базовий синтаксис: find [де шукати] [що шукати]

Terminal window
# Знайти файл із назвою "config.yaml", починаючи з поточної директорії
find . -name "config.yaml"
# Знайти всі YAML файли (чутливий до регістру)
find . -name "*.yaml"
# Знайти всі YAML файли (нечутливий до регістру — знайде і .YAML, і .Yaml)
find . -iname "*.yaml"
# Пошук у конкретній директорії
find /etc -name "*.conf"
Terminal window
# Тільки директорії
find . -type d
# Тільки звичайні файли (не директорії, не посилання)
find . -type f
# Тільки символічні посилання (symlinks)
find . -type l
# Усі директорії з назвою "test"
find . -type d -name "test"

Пошук за розміром — реальні сценарії

Розділ «Пошук за розміром — реальні сценарії»
Terminal window
# Знайти файли понад 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

Пошук за часом — що змінилося нещодавно?

Розділ «Пошук за часом — що змінилося нещодавно?»
Terminal window
# Файли, змінені за останні 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 може не просто виводити список, а й щось робити з файлами.

Terminal window
# Видалити всі .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 [опції] "шаблон" файл

Terminal window
# Знайти рядки з "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.

Terminal window
# Показати 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

Підрахунок та списки

Розділ «Підрахунок та списки»
Terminal window
# Порахувати кількість рядків (замість їх виводу)
grep -c "404" access.log
# Вивід: 187 (просто число)
# Показати тільки назви файлів, де є збіги (а не самі рядки)
grep -rl "TODO" /project/src/
# Вивід: список файлів, по одному в рядку
# Показати номери рядків разом зі збігами
grep -n "def main" *.py
# Вивід: main.py:42:def main():

Інверсія та точний пошук

Розділ «Інверсія та точний пошук»
Terminal window
# Показати рядки, що НЕ містять шаблон (invert)
grep -v "DEBUG" app.log
# Покаже все, крім дебаг-рядків — чудово для зменшення шуму
# Тільки цілі слова (не часткові збіги)
grep -w "error" app.log
# Знайде "error", але НЕ знайде "errors" або "error_handler"
# Пошук на початку або в кінці рядка
grep "^#" config.conf # Рядки, що починаються з # (коментарі)
grep "\.conf$" filelist # Рядки, що закінчуються на .conf

grep із каналами — найпоширеніший патерн

Розділ «grep із каналами — найпоширеніший патерн»

Ви будете використовувати grep із каналами частіше, ніж будь-яку іншу комбінацію в Linux.

Terminal window
# Знайти запущені процеси за назвою
ps aux | grep nginx
# Фільтрація історії команд
history | grep "docker"
# Знайти відкриті мережеві порти для конкретного сервісу
ss -tlnp | grep 8080
# Перевірити, чи встановлено пакет (Debian/Ubuntu)
dpkg -l | grep "nginx"
# Знайти змінні оточення, пов'язані з Java
env | grep -i java

7. Супер-комбо: find + grep + канали

Розділ «7. Супер-комбо: find + grep + канали»

Справжня магія починається при поєднанні цих інструментів. Саме так досвідчені користувачі Linux вирішують реальні задачі.

Сценарій 1: Знайти всі конфіг-файли, що містять адресу бази даних

Розділ «Сценарій 1: Знайти всі конфіг-файли, що містять адресу бази даних»
Terminal window
find /etc -name "*.conf" -exec grep -l "db.example.com" {} \;

Це знайде кожен .conf файл у /etc, перевірить кожен на наявність тексту “db.example.com” і виведе назви тільки тих файлів, де цей текст є.

Сценарій 2: Пошук визначення функції у всьому проєкті

Розділ «Сценарій 2: Пошук визначення функції у всьому проєкті»
Terminal window
find . -name "*.py" | xargs grep -n "def process_order"

Тут find дає список усіх Python-файлів, а xargs передає цей список у grep, який шукає визначення функції у кожному файлі й показує номер рядка.

Сценарій 3: Знайти великі лог-файли, змінені сьогодні

Розділ «Сценарій 3: Знайти великі лог-файли, змінені сьогодні»
Terminal window
find /var/log -name "*.log" -size +10M -mtime -1 -exec ls -lh {} \;

Знаходить лог-файли понад 10 МБ, які змінювалися за останні 24 години, і показує детальну інформацію про них.

Сценарій 4: Порахувати коментарі TODO у всьому коді

Розділ «Сценарій 4: Порахувати коментарі TODO у всьому коді»
Terminal window
find . -name "*.js" -o -name "*.ts" | xargs grep -c "TODO" | grep -v ":0$"

Знаходить усі JavaScript та TypeScript файли, рахує кількість TODO у кожному і відфільтровує файли, де TODO немає.

Сценарій 5: Знайти та “вбити” завислий процес

Розділ «Сценарій 5: Знайти та “вбити” завислий процес»
Terminal window
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 хвилин він так і не знайшов причину.

До дзвінка підключився старший інженер і ввів:

Terminal window
grep -i "payment" /var/log/app.log | grep -i "error" | tail -20

Через вісім секунд вони мали відповідь: сторонній платіжний шлюз змінив адресу свого API. Виправлення зайняло один рядок у конфігу.

Молодший інженер міг би знайти це менше ніж за хвилину за допомогою інструментів, які ви щойно вивчили. Урок не в тому, що гортати файли — це погано. А в тому, що знання своїх інструментів перетворює вас із того, хто реагує повільно, на того, хто вирішує проблеми миттєво. Саме це робить вас цінним фахівцем.


  1. Назва grep — це абревіатура. Вона означає “Global Regular Expression Print”. Це походить від команди в прадавньому текстовому редакторі ed: g/re/p. Інструмент був написаний Кеном Томпсоном у 1973 році й майже не змінився з того часу — бо він і так досконалий.

  2. Канали (pipes) винайшли під час обідньої перерви. Даг Макілрой запропонував ідею з’єднання програм у Bell Labs у 1964 році. Кену Томпсону це так сподобалося, що він додав підтримку каналів у Unix за одну ніч. Символ | був обраний, бо він рідко використовувався і нагадував фізичну трубу.

  3. /dev/null називають “найкориснішим файлом у Unix”. Усе, що туди пишеться, миттєво зникає. Він є частиною Unix з 1971 року. В інтернет-культурі “відправити щось у /dev/null” означає ігнорувати це повністю.

  4. Команда 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.txt
  • file? знайде file1, fileA, але НЕ знайде file (0 символів) або file12 (2 символи)
2. Ви хочете зберегти вивід команди у файл results.txt, не втрачаючи дані, які вже там є. Який оператор ви використаєте?

Оператор додавання в кінець >>.

Terminal window
my_command >> results.txt

Використання > перезапише файл. Використання >> додасть дані в кінець.

3. Що робить конструкція 2> /dev/null?

Вона перенаправляє потік помилок (stderr, потік 2) у пристрій /dev/null, який просто відкидає дані. Простою мовою: це приховує всі повідомлення про помилки, залишаючи на екрані тільки корисний результат.

Це часто використовується з find, щоб приховати повідомлення про відмову в доступі:

Terminal window
find / -name "config.yaml" 2> /dev/null
4. Напишіть команду для пошуку всіх файлів .log у директорії /var, які мають розмір понад 50 МБ.
Terminal window
find /var -name "*.log" -size +50M

Можна додати -type f, щоб переконатися, що це саме файли, а не директорії:

Terminal window
find /var -type f -name "*.log" -size +50M
5. Ви хочете знайти в файлі app.log слово "timeout" (незалежно від регістру) і побачити по 3 рядки тексту навколо кожного збігу. Яка команда це зробить?
Terminal window
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-адресою) в логах вебсервера:

  1. cat access.log — читає файл
  2. awk '{print $1}' — витягує тільки перше поле з кожного рядка (IP адресу)
  3. sort — сортує IP за алфавітом (необхідно для роботи uniq)
  4. uniq -c — видаляє повтори й додає кількість кожного IP
  5. sort -rn — сортує за кількістю, числово, від більшого до меншого
  6. head -10 — показує тільки перші 10 результатів
7. Що не так із цією командою: find . -name *.py?

Шаблон *.py не взято в лапки. Якщо в поточній директорії є .py файли, shell розгорне *.py у їхні імена до того, як запуститься find. Наприклад, якщо є main.py, команда перетвориться на find . -name main.py, що знайде тільки один цей файл замість усіх Python-файлів у піддиректоріях.

Виправлення: Завжди беріть шаблони у лапки:

Terminal window
find . -name "*.py"
8. Як направити нормальний вивід в один файл, а помилки — в інший?
Terminal window
command > output.txt 2> errors.txt
  • > (або 1>) направляє stdout (потік 1) у output.txt
  • 2> направляє stderr (потік 2) у errors.txt

Практична вправа: Розслідування на сервері

Розділ «Практична вправа: Розслідування на сервері»

Сценарій: Ви — молодший SRE інженер, що розслідує збій у роботі сервісу. Вам надали сервер із декількома лог-файлами. Ваше завдання — знайти релевантні помилки, витягнути їх і створити короткий звіт. Ви використаєте все, що вивчили: шаблони, перенаправлення, канали, find та grep.

Створіть тренувальне середовище:

Terminal window
# Створюємо директорію для розслідування
mkdir -p ~/investigation/logs
# Створюємо симульовані лог-файли
cat > ~/investigation/logs/web.log << 'EOF'
2024-03-15 08:01:12 INFO Request received: GET /api/users
2024-03-15 08:01:13 INFO Response sent: 200 OK
2024-03-15 08:02:44 ERROR Connection to database timed out
2024-03-15 08:02:45 ERROR Failed to process request: GET /api/orders
2024-03-15 08:03:01 WARN Retry attempt 1 for database connection
2024-03-15 08:03:02 INFO Database connection restored
2024-03-15 08:05:30 INFO Request received: GET /api/products
2024-03-15 08:07:15 ERROR OutOfMemoryError: heap space exhausted
2024-03-15 08:07:16 ERROR Service crashed - restarting
EOF
cat > ~/investigation/logs/db.log << 'EOF'
2024-03-15 08:00:00 INFO Database server started
2024-03-15 08:02:40 WARN Connection pool exhausted (max: 100)
2024-03-15 08:02:42 ERROR Too many connections - rejecting new requests
2024-03-15 08:02:43 ERROR Query timeout: SELECT * FROM orders WHERE status='pending'
2024-03-15 08:03:00 INFO Connection pool recovered
2024-03-15 08:06:00 INFO Routine backup started
2024-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 8080
2024-03-15 08:01:10 INFO Health check passed
2024-03-15 08:02:44 ERROR Upstream service unavailable: payment-gateway
2024-03-15 08:02:50 WARN Circuit breaker opened for payment-gateway
2024-03-15 08:04:00 INFO Circuit breaker closed for payment-gateway
2024-03-15 08:07:14 ERROR Memory usage exceeded threshold: 95%
2024-03-15 08:07:15 ERROR Initiating graceful shutdown
2024-03-15 08:07:16 INFO Shutdown complete
EOF
# Створимо текстові файли для вправ із find
echo "This is a config file" > ~/investigation/config.txt
echo "Important notes here" > ~/investigation/notes.txt

Виконайте кожне завдання за допомогою вивчених інструментів. Спробуйте самі перед тим, як зазирнути у відповідь.

Завдання 1: Використайте подстановочний знак, щоб вивести список ТІЛЬКИ .log файлів у ~/investigation/logs/.

Рішення
Terminal window
ls ~/investigation/logs/*.log

Завдання 2: Використайте grep, щоб знайти всі рядки з текстом “ERROR” в усіх лог-файлах. Збережіть результат у файл ~/investigation/all_errors.txt.

Рішення
Terminal window
grep "ERROR" ~/investigation/logs/*.log > ~/investigation/all_errors.txt

Завдання 3: Порахуйте, скільки рядків ERROR є у КОЖНОМУ лог-файлі (без виводу самих рядків).

Рішення
Terminal window
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 рядок тексту ДО кожного збігу.

Рішення
Terminal window
grep -i -B 1 -E "database|memory" ~/investigation/logs/*.log

Завдання 5: Використайте find, щоб знайти всі .txt файли в директорії ~/investigation.

Рішення
Terminal window
find ~/investigation -name "*.txt"

Завдання 6 (Рівень Боса): Напишіть один ланцюжок команд (pipeline), який:

  1. Читає всі лог-файли.
  2. Фільтрує тільки рядки з ERROR.
  3. Сортує їх за часом.
  4. Бере останні 5 (найсвіжіші помилки).
  5. Зберігає їх у файл ~/investigation/recent_critical.txt.
Рішення
Terminal window
cat ~/investigation/logs/*.log | grep "ERROR" | sort | tail -5 > ~/investigation/recent_critical.txt

Перевірте результат:

Terminal window
cat ~/investigation/recent_critical.txt

Ви маєте побачити 5 останніх помилок, відсортованих за часом.

Ви завершили цю вправу, якщо:

  • Файл ~/investigation/all_errors.txt існує і містить тільки рядки ERROR.
  • Ви знаєте, скільки помилок у кожному лог-файлі (Завдання 3).
  • Файл ~/investigation/recent_critical.txt містить рівно 5 відсортованих помилок.
  • Ви виконали кожне завдання за допомогою команд у терміналі (без графічних інструментів).

Далі: Модуль 0.2: Оточення та Дозволи — Дізнайтеся, як Linux знає, хто ви такий, як налаштувати свою оболонку та як система дозволів дбає про безпеку.