Основна частина роботи у командному рядку ведеться з файлами. У цьому розділі ми розглянемо, як переглядати і фільтрувати вміст файлів, видобувати з файлів потрібну інформацію за допомогою однієї команди і сортувати вміст файла.
Ці команди мають майже однаковий синтаксис: ім'я_команди [опції] [файл(и)], і можуть бути використані в каналах. Всі вони використовуються для виведення частини файла відповідно до певних критеріїв.
Утиліта 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. Про її можливості можна написати цілу книжку.