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

    Привет всему сообществу Хабра.
    Это мой первый пост и, надеюсь, не последний. Поэтому неизбежны всяческие недочеты, баги и некоторая водянистость текста, так что прошу строго не судить :)
    К написанию этого поста меня сподвиг топик «Консоль для новичка.» 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, а привести примеры именно практического применения в реальных ситуациях.
    если статья понравится — продолжу писать в данном направлении.

    спасибо, что уделили время.

    Similar posts

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 55

      0
      Cтатья понравилась, в манах такого не встретишь.
      мне как новичку в линуксе полезно было прочесть - в закладки !
      поставил бы плюсег, если бы мог
      • UFO just landed and posted this here
          +1
          да, про sed обязательно будет, в связке с awk, find и т.д.
          0
          Оч. понравилось, жду продолжения.
            +2
            Довольно популярный способ распространения троянов это вставки на сайты iframe блока указывающего на “вражеский сервер” с самим трояном. Перелопатить несколько тысяч страниц вручную, задача из разряда фантастических.

            Еще полезная команда (чистка кода сайта от iframe вставок):
            find ./ -type f -name \*.php -exec sed -i ’s/^.*iframe bla bla bla.*$//g’ {} \;
              +1
              да, в следующий раз об этом как раз собираюсь рассказать
              ваш пример очень показателен.
                –4
                Написал бы тоже статейку, но где бы взять карму
              0
              тоже часто приходится чистить сайты от троянских iframе-ов
              типа ( <script...>..ndfc() {.... ),
              мой вариант делает почти тоже самое, находит и удаляет строчку ndfc() плюс еще 6 строк ниже:
              find ./ -type f -print0 | xargs -0 -I'{}' sed -i '/ndfc()/,+6 d' '{}'
              +1
              Часто пользуюсь следующей связкой
              find -type d -exec chmod 755 {} \;
              find -type f -exec chmod 644 {} \;
                0
                chmod -R 755 dirname
                  0
                  и ты сделаешь все внутри 755.

                  Показаный выше пример, папкам ставит 755, а файлам 644
                    +1
                    делать chmod -R в данном случае неверно, т.к. права изменяться и на файлы и на каталоги, а если нужно, как писал посмотреть профиль Pokoinik изменить права только на файлы, тогда
                    find ./ -type f -exec chmod 644 {} \;
                • UFO just landed and posted this here
                    +2
                    find — далеко не самый лучший "поисковик", если использовать его именно как поисковик. locate с этим делом справляется быстрее, индекс, все-таки.

                    А find удобен именно для того, чтобы перебирать файлы из конкретного участка дерева и с ними что-нибудь делать.
                      0
                      Если файлы часто обновляются, делать updatedb постоянно не лучший вариант. А так конечно намного быстрее.
                        0
                        верно, locate/slocate на несколько порядков быстрее (т.к.поиск по созданной базе)
                        но на боевых серверах файлы обновляются часто и запускать индексирование чаще, чем раз в сутки, имхо накладно
                        к тому же, я делаю упор не на сам поиск, а на выполнение действий с найденным.
                        как пример : -exec в find + поиск по заданным критериям.
                        конечно, с locate такое тоже частично можно делать:

                        locate some_dir|xargs rm -fr
                        locate named.conf|xargs grep some_zone -A 20

                        но например вы удалили какой-то каталог, и чтобы у вас уже неверный индекс, его нужно перестраивать, чтобы данные были актуальны.

                        вобщем, тема для еще одной статьи ))
                          –1
                          всегда думал, что locate для блондинок, не знающих, что у них на компе находится.
                          никогда не использовал, и не вижу надобности.
                            0
                            а вот смотрите:
                            есть у вас два десятка серверов (или даже просто неизвестный сервер)
                            и вам нужно поправить httpd.conf например - и совсем не факт, что он будет лежать в /etc/httpd/conf/httpd.conf
                            где вы будете его искать ? делать find / ?

                            а locate httpd.conf вам в этом случае сразу все покажет.
                            *httpd.conf редко перемещают с места на места, так что инфа будет актуальной.
                              0
                              у меня есть "неизвестный" сервер? Откуда? Что мне делать на неизвестном мне сервере?
                              а на известных мне серверах, я знаю, где какие конфиги лежат
                              0
                              Если вы не видите надобности, это еще не значит, что ее нет. Если бы locate был совсем не нужен, его бы не написали в далеком 83 году.

                              Я, вроде бы, не блондинка, но таки не знаю что где именно находится из 678000 файлов на моем домашнем компьютере.
                            +1
                            ИМХО: образцовая статья про использование консоли.
                            Спасибо!
                              0
                              аригато, гозаимаста ))
                              0
                              наконец то кто-то понял что нужно писать в статьях для новичков линукса. спасибо.
                                0
                                спасибо за отзыв, значит дальше буду двигаться в данном стиле.
                                +1
                                я бы не советовал начинать работать в консоли с этой статьи.
                                Может для начало надо было обьяснить новечку что вообще такое консоль?
                                Что такое STDIN, STDOUT, STDERR. Философию Unix в отношении консоли. Рассказать подробнее про pipe, про bg, fg. Также использование подстановочных символов, шаблонов. О том, что консоль рассматривается как файл.
                                  +2
                                  ну я тоже не советую эту статью, как первую или вторую
                                  здесь наверно будет уместным еще раз сослаться на статью "Консоль для новичка.", написанную посмотреть профиль ISVir.
                                  я же предполагаю, что человек уже изучил подобные вещи, но не совсем понимает что с ними делать ...как-то так.
                                  0
                                  Вот прекрасная , на мой взгляд лучше не написать
                                    0
                                    несколько комментариев.
                                    1. -exec есть зло, ибо выполняет действие отдельно над каждой строкой. xargs работает процентов на 30 быстрее.
                                    2. >> find /var/www/ -type f -name "access.log*" -exec du -k {} \;|awk '{s+=$1}END{print s}'
                                    с точки зрения производительности и читабельности ИМХО не самое лучшее решение. Предлагаю свой вариант:
                                    find /usr/local/apache/logs/ -type f -name "*_log"|xargs du -csh
                                    0 /usr/local/apache/logs/modsec_debug_log
                                    2.2M /usr/local/apache/logs/access_log
                                    1.0K /usr/local/apache/logs/audit_log
                                    875K /usr/local/apache/logs/error_log
                                    96K /usr/local/apache/logs/ssl_engine_log
                                    3.1M total

                                    где:
                                    -c - "Итого"
                                    -s - "display only a total for each argument"
                                    -h - human-readable. Кому как, но лично мне не очень удобно переводить в уме кило в мега.

                                    3. awk
                                    >>по умолчанию, разделитель полей - пробел, но с помощью опции -F" " это можно переопределить
                                    кавычки для агрумента -F не нужны - они слишком "въедаются" в мозг, и это приводит к некоторым неудобствам: тот же -F ":" не на всех системах корректно отрабатывает.
                                    но это так, мелкая придирка :)
                                    вообще, всю конструкцию
                                    >>cat /etc/passwd|awk -F":" '{print $1}'

                                    я бы заменил более короткой
                                    cat /etc/passwd|cut -d : -f 1


                                    В любом случае, успехов вам. Ждем продолжения про sed :)
                                      0
                                      1. верно, но не вспоминать про жту опцию тоже было бы плохо, не так ли?
                                      2.дело в том, что мой вариант более гибкий и я бы хотел, чтобы человек научился прежду всего именно ему.
                                      3.опять вы правы, но как-то я побоялся втискивать в рамки статьи еще и cut, а про awk сказать хотелось.

                                      вобщем, все это будет во второй части
                                        0
                                        2. Согласен, но -h можно было и упомянуть :)

                                        Вы молодец, завидую по-доброму: я вот не умею писать статьи такого уровня, чтобы доходчиво о простых вещах; как-то "серьезные" мануалы лучше получаются :)
                                          +1
                                          2. ну для моего контекста она скорее мешала, поэтому и не описал.
                                          почему мешала?
                                          просто вывод du обрабатывается потом awk и мне там совсем ни к чему символы K,M,G и запятые ..
                                          подумайте сами, как бы вы распарсили (с уклоном для новичка) вывод
                                          du -sh|awk "??"
                                          а du -k дает нам однозначные цифры, без "грязи"
                                            0
                                            Логично :) Не подумал как-то про этот момент. Мои извинения.
                                              0
                                              ничего, все ок ))
                                              почему бы вам тоже не написать что-то более веское ? - знания, вижу у вас есть...
                                                0
                                                Я молчать не умею, карма страдает хроническим минусом :)
                                                И придумать тему не получается такую, чтобы и полезно, и многим :)
                                                  0
                                                  ну карму мы вам поправим :), надеюсь, не только я...
                                                  а тем очень много - надо просто взглянуть на свою работу со стороны - попробуйте.
                                                    0
                                                    Спасибо, но... Работа администратора j2ee серверов приложений вряд ли интересна хабраюзерам. Попробую прикинуть, что из моего фрилансерского опыта может быть полезным широким массам. Спасибо за доверие.
                                                      0
                                                      а я бы с удовольствием прочел про администрирование J2ee серверов и приложений. серьезно.
                                                      ну и по фрилансу, думаю, всем интересно будт почитать
                                                        0
                                                        вы меня почти уговорили :)
                                                        попробую написать что-нибудь, если самому понравится - стукнусь вам за кармой :) не против?
                                            0
                                            и спасибо за поддержку - этого в таких вещах всегда не хватает...
                                            более серьезные вещи тоже обязательно будут, не все сразу :)
                                          0
                                          >кавычки для агрумента -F не нужны

                                          для новичка - это более наглядно, вы согласны?
                                          0
                                          Отлично :) Статья понравилась, и очень полезна не только для новичком, но и для обычным пользователей, который мало сталкивались с консолью лицом к лицу.
                                            0

                                            Еще очень рекомендую xargs. Возможно вам стоит упомянуть про perl (подавляющее число однострочников я пишу на нем).

                                              0
                                              Доступно и с примерами.
                                              Спасибо за статью, в деле пригодится!
                                                0
                                                Есть хорошая, на мой взгляд, книга - Unix Power Tools - Shelley Powers, Jerry Peek, Tim O'Reilly, Mike Loukides. Будет полезна новичкам и не только.
                                                  0
                                                  Где-то слышал фразу: если бы люди умели пользоваться find, sed, awk и grep, то миллионы программ никогда не были бы написаны.
                                                    0
                                                    отлично сказано!
                                                    помню, в начале освоения линукса, уже администрируя несколько веб серверов, писал простыни на перле, хотя с помощью sed+find задача решалась в одну строку.
                                                    с другой стороны, это дало мне опыт программинга на перле :)
                                                    0
                                                    Спасибо за развитие темы.
                                                    Есть один общий вопрос касательно поиска ответов для начинающих пользователей, или КАК КУДА и Почему обращаться "по уму"
                                                    Суть вопроса в описании web-ресурсов и некоторых правил общения, гарантирующих адекватную реакцию на обращение за помощью.
                                                    В идеале хотелось бы иметь свои "желтые страницы" рунета по opensource.
                                                    Просто зачастую пара нерешенных вопросов заставляет многих возвращаться к окнам. У меня, к примеру, так и не работает сканер Canon Lide 90 и дровишек к нему пока не предвидется :(
                                                    и извиняйте за невольный офтоп
                                                      0
                                                      а как такое сделать %)
                                                      каждый из 10 файлов в папке переместить в 10 создаваемых папкок названных как эти 10 файлов причем из названия файлов и папок убирать некую последовательность символов :)

                                                      получится такое 1 командой?
                                                        +1
                                                        $ls
                                                        . .. 10.log 1.log 2.log 3.log 4.log 5.log 6.log 7.log 8.log 9.log

                                                        $for i in *;do m=`echo $i|sed "s/\.log//"`;mkdir $m ;mv $i $m/$m;done

                                                        $ls -l
                                                        drwxr-xr-x 2 test1 test1 4096 Июл 18 03:17 1
                                                        drwxr-xr-x 2 test1 test1 4096 Июл 18 03:17 10
                                                        drwxr-xr-x 2 test1 test1 4096 Июл 18 03:17 2
                                                        drwxr-xr-x 2 test1 test1 4096 Июл 18 03:17 3
                                                        drwxr-xr-x 2 test1 test1 4096 Июл 18 03:17 4
                                                        drwxr-xr-x 2 test1 test1 4096 Июл 18 03:17 5
                                                        drwxr-xr-x 2 test1 test1 4096 Июл 18 03:17 6
                                                        drwxr-xr-x 2 test1 test1 4096 Июл 18 03:17 7
                                                        drwxr-xr-x 2 test1 test1 4096 Июл 18 03:17 8
                                                        drwxr-xr-x 2 test1 test1 4096 Июл 18 03:17 9
                                                        drwxr-xr-x 12 test1 test1 4096 Июл 18 03:17 .
                                                        drwxrwxrwx 11 root root 20480 Июл 18 03:13 ..

                                                        $ls -l 1

                                                        -rw-r--r-- 1 test1 test1 0 Июл 18 03:14 1
                                                        drwxr-xr-x 2 test1 test1 4096 Июл 18 03:17 .
                                                        drwxr-xr-x 12 test1 test1 4096 Июл 18 03:17 ..
                                                        $ls -l 6

                                                        -rw-r--r-- 1 test1 test1 0 Июл 18 03:14 6
                                                        drwxr-xr-x 2 test1 test1 4096 Июл 18 03:17 .
                                                        drwxr-xr-x 12 test1 test1 4096 Июл 18 03:17 ..
                                                          0
                                                          спасибо, консоль рулит!
                                                        0
                                                        history|awk ‘{a[$2]++} END{for(i in a){printf “%5d\t%s\n”,a[i],i}}’|sort -rn|head
                                                          0
                                                          Как мне сделать поиск тех файлов в которых есть троян, с параметром в котором задан пример «вредного» текста, но без замены (удаления) такового?
                                                            0
                                                            просто grep:

                                                            $cd www_site_path
                                                            $grep -ri «some malware code» ./

                                                          Only users with full accounts can post comments. Log in, please.