Pull to refresh

«примеры эффективного использования GNU утилит в Linux»

Reading time 3 min
Views 25K
Привет всему сообществу Хабра.
Это мой первый пост и, надеюсь, не последний. Поэтому неизбежны всяческие недочеты, баги и некоторая водянистость текста, так что прошу строго не судить :)
К написанию этого поста меня сподвиг топик «Консоль для новичка.» habrahabr.ru/blog/linux/46610.html, где ISVir поднял острую, на мой взгляд, тему — как доступным языком рассказать новичкам о консоли, не отпугнув их мнимой сверх-сложностью.

Не собираюсь отбирать у ISVir паритет, лишь расскажу о практическом использовании нескольких самых основных утилит «на каждый день», без которых работа в консоли для меня невозможна.

Итак, что мы имеем:

find — поиск файлов. позволяет искать файлы, каталоги, симлинки и другие файловые объекты. find Позволяет задать множество опций поиска таких как:
  • поиск по маске (в имени )
  • контроль глубины вложенности поиска
  • поиск определенных типов файлов(каталог, симлинки, сокеты)
  • поиск по времени создания/модификации файла
  • можно задать размер (от и до в диапазоне) файла
  • выполнение действий с каждым найденным файлом
в мане к find можно прочесть об остальных опциях и параметрах.

итак, с места в карьер — поиск всех файлов в каталоге /etc/, измененных за последние сутки:

$find /etc/ -type f -mtime -1

разберем, что мы написали:

первым параметром всегда указывается начальный каталог для поиска.
опция -type с параметром f говорит find, что нужно искать только обыкновенные файлы.
опция -mtime с параметром -1 указывает find, что нужно найти файлы, изменившиеся за последние сутки.
"-"перед 1 задает верхнюю границу диапазона, т.е. «все, что изменилось за последние 24 часа»

если бы мы указали "+" перед 1, то find нашел бы всех файлы, изменившиеся от 01.01.1970 до вчерашнего дня (более суток назад)
так же можно указать точную дату поставив число без модификатора.

выполнение действий с найденными файлами.
опция -exec принимает строку с командой, которая будет выполнятся для каждого найденного файла
параметр передающийся команде обозначается через {}
строка должна заканчиваться символами " \; "

рассмотрим пример:
* найти в каталоге /tmp все файлы, изменившиеся за последний месяц и скопировать их в каталог
/tmp/backup/
$find /tmp -type f -mtime -30 -exec cp {} /tmp/backup \;

* удалить все каталоги(рекурсивно) с именем logs, изменившиеся за последний день в каталоге
/var/www
$find /var/www -type d -mtime 0 -name logs -exec sudo rm -fr {} \;

параметр d в опции -type указывает на поиск только каталогов
опция -name задает поиск по имени.
здесь стоит добавить, что удалять таким образом файлы не оптимально(медленно).
для удаления у find есть встроенная опция -delete, которая отрабатывает на порядок быстрее.

еще не устали? идем дальше :)

рассмотрим утилиту awk.
awk — это язык программирования, предназначенный для обработки файлов. Цель его
разработки — облегчить постановку и решение многих задач, связанных с переработкой текстовой информации. По сути, awk — это утилита, доступная из консоли.
Я по понятным причинам не буду здесь рассматривать приемы написания awk кода — расскажу только про один важный для нас прием.

во первых, awk может получать данные из STDIN: $echo «test»|awk ...
во вторых, awk эффективен при написании однострочников в консоли, т.к. выполняет код, данные ему как параметр:
$echo «test»|awk " ..."

awk разделяет входной поток на поля и помещает эти поля в переменные вида $1,$2,..$N
по умолчанию, разделитель полей — пробел, но с помощью опции -F"_разделитель_" это можно переопределить:
$head -4 /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh

$cat /etc/passwd|awk -F":" '{print $1}'
root
daemon
bin



например, у нас в каталоге /var/www есть несколько сайтов. для каждого сайта существует каталог logs, куда пишутся логи апача (для этого сайта).и вот мы хотим узнать суммарный обьем этих логов, а так же найти все логи больше 100Mb.

here we go:

1.поиск больших логов:

$find /var/www -type f -name «access.log*» -size +100M
/var/www/site1/logs/access.log
/var/www/site2/logs/access.log.1.gz

2.подсчитаем суммарный обьем логов:

find /var/www/ -type f -name «access.log*» -exec du -k {} \;|awk '{s+=$1}END{print s}'
5071604

так, не пугаться — щас все обьясню :)

find ищет все файлы по маске (access.log*) и для каждого запускает команду du.
команда du печатает размер файла. опция -k делает вывод в килобайтах.
дальше запускается процессор awk, просто суммирует первое поле строк (числа) в переменную s и выводит значение переменной на экран.

еще примерчик: найдем в системе все файлы и каталоги принадлежищие юзеру test1 и подсчитаем суммарный обьем.
#find / -user test1 -exec du -sm {} \;|awk '{s+=$1}END{print s}'

т.е. здесь с помощью опции -user find ищет файлы, принадлежашие юзеру test1 и для каждого файла/каталога подсчитываем его размер (команда du)
дальше через конвеер эти данные принимает awk и, как мы делали выше, считает их сумму в Kb.

ок. думаю, на сегодня хватит.
пост вышел довольно большим, видимо с непривычки :)

сразу хочу сказать — я не ставил цель просто рассказать об использовании find и awk, а привести примеры именно практического применения в реальных ситуациях.
если статья понравится — продолжу писать в данном направлении.

спасибо, что уделили время.
Tags:
Hubs:
+1
Comments 55
Comments Comments 55

Articles