Основна частина роботи у командному рядку ведеться з файлами. У цьому розділі ми розглянемо, як переглядати і фільтрувати вміст файлів, видобувати з файлів потрібну інформацію за допомогою однієї команди і сортувати вміст файла.
Ці команди мають майже однаковий синтаксис: ім'я_команди [опції] [файл(и)], і можуть бути використані в каналах. Всі вони використовуються для виведення частини файла відповідно до певних критеріїв.
Утиліта cat об'єднує файли і виводить результат на стандартний вихід, яким зазвичай є екран вашого комп'ютера. Це одна з найчастіше використовуваних команд. Наприклад, ви можете скористатися:
# cat /var/log/mail/info
для виведення вмісту файла журналу поштового демона на стандартний вихід[23]. Команда cat має дуже корисну опцію (-n
), яка дозволяє вам виводити номери рядків.
Деякі файли, на зразок журналів демонів (якщо вони запущені), зазвичай мають досить великий розмір[24] і повне їх виведення на екран буде не дуже корисним. Взагалі, вам потрібні лише кілька рядків з файла. Для цього ви можете скористатися командою tail. Наступна команда виведе (за умовчанням) останні 10 рядків з файла /var/log/mail/ info
:
# tail /var/log/mail/info
Файлы на зразок журналів зазвичай динамічно змінюються, бо демони постійно додають в них звіти про скоєні дії чи події. Для спостереження за змінами в лог-файлі в режимі реального часу ви можете скористатися перевагами опції -f
:
# tail -f /var/log/mail/info
В цьому випадку всі зміни у файлі /var/log/mail/info
будуть негайно виводитися на екран. Використання команди tail з опцією -f
дуже корисно, коли потрібно знати, як працює ваша система. Наприклад, спостерігаючи за файлом журналу /var/ log/messages
, ви зможете завжди отримувати оновлену інформацію про системні повідомлення і демонів.
Якщо ви використовуєте tail для кількох файлів, вона буде виводити в окремому рядку імена цих файлів перед виведенням їх вмісту. Робота з опцією -f
при цьому також можлива, що є цінним доповненням для спостереження за взаємодією різних частин системи.
Ви можете використовувати опцію -n
для виведення останніх n рядків файла. Наприклад, для виведення останніх 2-х рядків наберіть:
# tail -n2 /var/log/mail/info
Як і для інших команд, ви можете одночасно використовувати різні опції. Наприклад, при одночасному використанні опцій -n2
і -f
ви почнете з двох останніх рядків файла і продовжуватимете спостерігати появу нових рядків у міру додавання їх у файл журналу.
Команда head схожа на tail, але вона виводить перші рядки файла. Наступна команда виведе (за умовчанням) перші 10 рядків файла /var/log/mail/info
:
# head /var/log/mail/info
Як і у випадку з tail ви можете скористатися опцією -n
для вказівки кількості рядків для виведення. Наприклад, для виведення перших 2-х наберіть:
# head -n2 /var/log/mail/info
Також ви можете використовувати ці дві команди спільно. Наприклад, якщо ви хочете побачити лише рядки 9 і 10, ви можете скористатися командою, у якій head вибере перші 10 рядків з файла і передасть їх по каналу до команди tail.
# head /var/log/mail/info | tail -n2
При цьому остання команда візьме останні 2 рядки і виведе їх на екран. Таким же чином ви можете вибрати 20-й від кінця файла рядок:
# tail -n20 /var/log/mail/info |head -n1
У цьому прикладі ми говоримо команді tail взяти останні 20 рядків й передати їх по каналу в head. Потім команда head виводить на екран перший рядок з отриманих даних.
Давайте припустимо, що нам потрібно вивести на екран результат останнього прикладу і зберегти його у файл results.txt
. Нам може допомогти утиліта tee. Її синтаксис:
tee [опції] [файл]
Тепер ми можемо змінити попередню команду так:
# tail -n20 /var/log/mail/info |head -n1|tee results.txt
Давайте розглянемо ще один приклад. Нам потрібно вибрати останні 20 рядків, зберегти їх у файлі results.txt
, а на екран вивести лише перший з них. Тоді ми повинні запровадити наступне:
# tail -n20 /var/log/mail/info |tee results.txt |head -n1
У команди tee є корисна опція (-a
), яка дозволяє вам дописати дані в кінець існуючого файла.
У наступному розділі ми побачимо, як ми можемо використовувати команду grep як фільтр для відділення повідомлень Postfix від повідомлень інших служб.
Ні ім'я команди, ні її абревіатура (“General Regular Expression Parser” - синтаксичний аналізатор загальних регулярних виразів) не є інтуїтивними, проте її дія і використання досить прості: grep шукає в одному кількох файлах шаблон, який задано в якості аргументу. Її синтаксис:
grep [опції] <шаблон> [один чи кілька файлів]
Якщо зазначено кілька файлів, в результаті їхні імена вводитимуться перед кожним знайденим рядком. Ви можете використовувати опцію -h
для запобігання виведення цих імен чи ви можете скористатися опцією -l
для виведення лише імен файлів зі знайденими збігами. Шаблон - це регулярний вираз, хоча в більшості випадків він складається з одного єдиного слова. Найчастіше використовуються опції:
Отже, давайте тепер повернемося до аналізу лог-файла поштового демона. Нам необхідно знайти всі рядки у файлі /var/log/mail/info
, що містять шаблон “postfix”. Для цього ми вводимо таку команду:
# grep postfix /var/log/mail/info
Якщо нам потрібно знайти всі рядки, що НЕ містять шаблону postfix
, нам необхідно скористатися опцією -v
:
# grep -v postfix /var/log/mail/info
Команду grep можна використовувати в каналах.
Припустимо, що нам потрібно знайти всі повідомлення про успішно відправлені листи. У цьому разі ми повинні відфільтрувати всі рядки, додані поштовим демоном в файл журналу (ті, що містять шаблон postfix
), і вони повинні утримувати повідомлення про успішну відправку (status=sent
)[25]:
# grep postfix /var/log/mail/info |grep status=sent
У цьому разі команда grep використана двічі. Це дозволяється, але виглядає не зовсім гарно. Той самий результат може бути отримано за допомогою утиліти fgrep. По суті fgrep - це простіший спосіб для виклику grep -F. Спочатку нам потрібно створити файл, який містить шаблони, записані кожен в окремому рядку. Такий файл може бути створено так (ми використовуємо patterns.txt
як ім'я файлу):
# echo -e 'status=sent\npostfix' >./patterns.txt
Перевірте результат командою cat. \n
- це спеціальний шаблон, означає “новий рядок”.
Потім ми викликаємо наступну команду, у якій ми використовуємо файл patterns.txt
і утиліту fgrep замість “подвійного виклику” команди grep:
# fgrep -f ./patterns.txt /var/log/mail/info
Файл ./patterns.txt
може містити скільки завгодно шаблонів. Наприклад, для вибору повідомлень про листи, успішно відправлених на адресу peter@mandriva.com
, достатньо буде додати цю електронну адресу в наш файл ./patterns.txt
, виконавши таку команду:
# echo 'peter@mandriva.com' >>./patterns.txt
Ясна річ, що ви можете комбінувати команду grep з tail і head. Якщо нам потрібно знайти повідомлення про передостанній електронний лист, що відправлений на адресу peter@mandriva.com
, ми використовуємо:
# fgrep -f ./patterns.txt /var/log/mail/info | tail -n2 | head -n1
Тут ми застосували описаний вище фільтр і відправили результат через канал в команди tail і head. Вони вибрали з даних передостаннє значення.
З допомогою grep ми обмежені шаблонами і фіксованими даними. Як нам знайти всі електронні листи, відправлені кожному працівнику “ABC Company”? Пошук у переліку їхніх електронних адрес буде не таким вже й простим завданням, бо ми можемо пропустити когось з них, або нам доведеться вручну копирсатися у файлі журналу.
Як і у випадку зі fgrep, grep має скорочений виклик для команди grep -E: egrep. egrep використовує регулярні вирази замість шаблонів, надаючи нам потужніший інтерфейс для “grep'ання” тексту.
Що ж до того, що згадувалось у розділі Параграф 3, “Шаблони підстановки в командному процесорі” при розгляді шаблонів підстановки, ось кілька додаткових регулярних виразів:
[:alnum:]
, [:alpha:]
і [:digit:]
можуть бути використані замість визначення класів самих символів і уявляють, відповідно: літери плюс всі цифри, літери (верхній і нижній регістри) і всі цифри. У них є додаткові переваги - вони вони передбачають міжнародні символи і враховують регіональне налаштування системи.
[:print:]
представляє всі символи, які можуть бути виведені на екран.
[:lower:]
і [:upper:]
представляють усі літери верхнього і нижнього регістрів відповідно.
Існує багато інших доступних класів і ви можете переглянути їх у egrep(1). Перелічені вище класи є найчастіше використовуваними.
Після регулярних виразів можуть слідувати один чи кілька різних операторів, що повторюються:
Якщо ви візьмете регулярний вираз в квадратні дужки, пізніше ви зможете відновити його. Припустимо, що ви зазначили вираз [:alpha:]+
. Це може бути слово. Якщо ви хочете визначити двічі повторювані слова, ви можете помістити це словосполучення в дужки і повторно використовувати його за допомогою \1
, якщо це перша група. У вас може бути до 9 таких “записів”.
$ echo -e "abc def\nabc abc def\nabc1 abc1\nabcdef\nabcdabcd\nabcdef abcef" > testfile $ egrep "([[:alpha:]]+) \1" testfile abc abc def $
Єдиним рядком, якого повернуто, буде рядок, що відповідає виключно двом групам літер, розділених пробілом. Ніяка інша група не є входженням регулярного виразу.
Також ви можете використовувати символ |
, який визначає входження для виразу зліва від знака |
або для виразу праворуч від цього знака. Цей оператор об'єднує ці вирази. Використовуючи створений раніше файл testfile
, ви можете спробувати пошукати вирази, що містять лише слова, що дублюються, або містять слова, що дублюються, з числами:
$ egrep "([[:alpha:]]+) \1|([[:alpha:][:digit:]]+) \2" testfile abc abc def abc1 abc1 $
Зверніть увагу, що для другої групи, що використовує дужки, ми повинні використовувати \2
, у протилежному випадку висловлення не буде відповідати тому, що нам потрібно. Більш ефективним виразом в окремо взятому разі буде:
$ egrep "([[:alnum:]]+) \1" testfile abc abc def abc1 abc1 $
І, на закінчення, для використання певних символів ви повинні їх “заекранувати”, поставивши перед ними зворотну скісну риску. Ось ці символи: ?
, +
, {
, |
, (
, )
і, звісно ж \
. Для використання їх у своїх висловлюваннях ви повинні писати: \?
, \+
, \{
, \|
, \(
\)
і \\
.
Ця маленька хитрість може допомогти уникнути повторення набраних слів у “вашому вашому” тексті.
Регулярні вирази в усіх утилітах повинні дотримуватися цих (або дуже схожих) правил. Витративши якийсь час на їхнє розуміння, ви багато в чому допоможете собі при роботі з іншими утилітами, такими як sed. sed - це утиліта, яка серед іншого може обробляти текст шляхом його зміни з використанням регулярних виразів як правил.
Команда wc (Word Count - підрахунок слів) використовується для підрахунку кількості рядків, і символів в файлах. Також вона корисна для обчислення самого довгого рядку. Її синтаксис:
wc [опції] [файл(и)]
За умовчанням команда wc виводить кількість рядків і символів. Ось кілька прикладів використання:
Якщо нам потрібно визначити кількість користувачів у нашій системі, ми можемо запровадити:
$ wc -l /etc/passwd
Якщо нам потрібно дізнатися кількість CPU у нашій системі, ми пишемо:
$ grep "model name" /proc/cpuinfo |wc -l
У попередньому розділі ми отримали список повідомлень про успішно відправлені листи на адреси, перелічені в нашому файлі ./patterns.txt
. Якщо нам потрібно дізнатися кількість цих повідомлень, ми можемо перенаправити наш відфільтрований результат через канал у команду wc:
# fgrep -f ./patterns.txt /var/log/mail/info | wc -l
Нижче представлений синтаксис цієї потужної утиліти для сортування[26]:
sort [опції] [файл(и)]
Давайте відсортуємо частину файла /etc/passwd
. Як бачите, цей файл не відсортований:
$ cat /etc/passwd
Якщо нам потрібно відсортувати його за полем login
, ми набираємо:
$ sort /etc/passwd
За умовчанням команда sort сортує інформацію за першим полем в порядку зростання (в нашому разі за полем login
). Щоб відсортувати дані у порядку спаду, використовуйте опцію -r
:
$ sort -r /etc/passwd
Для кожного користувача є свій власний UID
, записаний у файлі /etc/passwd
. Наступна команда сортує файл в порядку зростання за полем UID
:
$ sort /etc/passwd -t":" -k3 -n
Тут ми використовуємо такі опції sort:
Те ж може бути виконано у зворотному порядку:
$ sort /etc/passwd -t":" -k3 -n -r
Зверніть увагу, що sort має дві важливі опції:
І, нарешті, якщо ми хочемо знайти користувача з максимальним UID
, ми можемо скористатися наступної командою:
$ sort /etc/passwd -t":" -k3 -n |tail -n1
де ми сортуємо файл /etc/passwd
в порядку зростання по колонці UID
і перенаправляємо результат по каналу у команду tail. Далі виводиться перше значення відсортованого списку.
[23] Деякі приклади в цьому розділі ґрунтуються на реальній роботі з файлами журналів деяких серверів (служб, демонів). Переконайтеся, що у вас запущено syslogd (дозволяє журналювати дії демонів) і відповідний демон (в нашому разі Postfix), і що ви в працюєте під root
'ом. Звичайно ж ви завжди можете застосовувати наші приклади до інших файлів.
[24] Наприклад, файл /var/log/mail/info
містить інформацію про всі відправлені листи, повідомлення про вибирання пошти користувачами по протоколу POP
і т.п.
[25] Хоча можна виконати фільтрацію просто за шаблоном стану, будь ласка, дозвольте нам показати вам цьому прикладі нову команду.
[26] Тут ми тільки коротенько розглянемо sort. Про її можливості можна написати цілу книжку.