LXF78:Мощные инструменты командной строки

Материал из Linuxformat.

Перейти к: навигация, поиск

Срубите GUI, вышвырните мышь из дома и дайте вашей графической супер-карте отдохнуть – «реальные пацаны» используют командную строку, утверждает Пол Хадсон.

Содержание


Это четвёртый из наших уроков серии Hardcore Linux, и если вы досюда добрались, то вам почти пора наниматься в Linux Format. Заметьте, только почти, потому что ваши испытания на самом деле только начинаются. Вот как побываете под брюхом овцы, ослепите циклопа горящим бревном, перехитрите Цирцею и напишете собственный драйвер, тогда и будете готовы присоединиться к суперэлитной команде LXF.

А пока – сидите на коленях мастеров и учитесь, и в этом месяце вам откроются тайны командной строки. Причина, по которой храбрецы вроде нас овладевают командной строкой, та же самая, из-за которой Эдмунд Хиллари [новозеландец, впервые покоривший Эверест, в паре с проводником-шерпом Тенсингом Норгеем, – прим. перев.], по его словам, совершил восхождение на Эверест. Нет, не ради свежего горного воздуха, а просто потому, что Эверест есть.

Я хотел бы стать вашим Тенсингом Норгеем и помочь вам в восхождении к знаниям. Но, к сожалению, возможность слияния разумов исключается, ибо профанам Башни LXF недоступны, а Древнейшее Таинство Приобщения осложнено тем, что Mountain Dew в ближайшем универсаме на всех не хватит. Придется обойтись прозаическими бумагой и чернилами.

Шаг 1 – Секреты Bash

Стивен Борн (Stephen Bourne) написал первоначальный вариант командной оболочки Bourne для 7-й версии Unix в далёких семидесятых, и увидел Бог, что это хорошо. Но в 1987 году ее заменили улучшенной версией, названной Bourne-again Shell и большинству известной как Bash. Этот терминал уже много лет используется по умолчанию чуть ли не в каждом дистрибутиве Linux, так что новички даже не догадываются, что бывают и другие оболочки. Команда ls -l /bin/sh докажет вам, что самая основная оболочка на вашей системе – на самом деле просто ссылка на Bash, поскольку Bash – расширение sh, добавляющее новые функции, не нарушая работоспособность скриптов.

Bash еще функциональнее, чем можно вообразить. Всем нам доводилось пользоваться встроенными командами типа cd и export, а как насчёт time, alias, for и волшебного обратного апострофа? Даже управление заданиями, считавшееся абсолютно необходимым во времена больших компьютеров, – это вымирающее искусство. Ладно, я несколько отклонился от темы, дальше отклоняться не буду: настало время воскресить старые методы и поведать молодёжи, почему псевдонимы столь важны, сохраняя традиции наших Unix-предков. И первый шаг в этой революции – освоить Bash.

  • Меняем псевдонимы

Используемый по умолчанию набор команд в Unix довольно ограничен, но его можно обогатить с помощью различных параметров, передаваемых командам для модификации их работы. Кому нравится набирать команды, загибающиеся на три строки, поднимите руку! Конечно, это подвох – немногие люди, которые и вправду любят подобные вещи, вероятно, из-за артроза кистей рук поднять их не смогут.

Псевдонимы (aliases) – это простой способ создавать укороченные команды в Linux. Например, можно определить псевдоним la, который запускал бы ls -a. На самом деле многие дистрибутивы поставляются именно с таким псевдонимом, установленным по умолчанию – если вы введёте alias в командной строке, то увидите список всех готовых псевдонимов. Чтобы создать собственный, введите

alias la=’ls -a’

По идее, нужно вводить этот (и другие ваши псевдонимы) каждый раз после перезагрузки, но чтобы не увеличивать ваши ежедневные заботы, Bash позволит вам раз навсегда занести ваши псевдонимы в файл ~/.Bash_aliases, да сам их и загрузит.

  • Условный ответ

Bash – мощная система разработки скриптов, способная проверять условия в операторах if и циклах не хуже других языков программирования. Скриптов я касаться не буду, но условные операторы могут очень пригодиться при использовании в псевдонимах.

Вот общий пример условного оператора:

if uname -a | grep «GNU/Linux» > /dev/null; then echo «Вы работаете в Linux»; fi

Работает он следующим образом: сперва исполняет uname -a, для получения информации о системе, а затем просеивает эту информацию через grep, пытаясь обнаружить строку «GNU/Linux». Заметьте, что вывод команды перенаправлен в /dev/null, чтобы результат grep не выводился на экран. Если grep найдёт строку, значит, наше условие истинно (true), и Bash выведет: «Вы работаете в Linux». Обратите внимание на использование точки с запятой: после условия и действия, но не после fi (if наоборот; по сути, то же, что и endif).

Мы можем усложнить оператор, добавив блок else – действие, которое будет выполнено, если условие вернёт значение «ложь» (false).

Расширим предыдущий пример:

if uname -a | grep «GNU/Hurd» > /dev/null; then echo «Вы работаете в Hurd»; else echo «Вы  работаете не в Hurd»; fi

Само условие может быть любой сложности. Попробуем, например, проверить, запущен ли Firefox, выполнив ps aux и перенаправив вывод на grep для поиска процесса firefox.

Однако, grep сам является программой, а значит, появится в выводе ps. И поскольку строка «firefox» содержится в «grep firefox», то окажется, что Firefox якобы запущен, хотя на самом деле мы всего лишь запустили поиск такой строки. Чтобы обойти эту проблему, применим grep дважды: сперва для проверки наличия Firefox, а затем, с ключом -v, для инвертирования условия, чтобы исключить из результата строку с grep. Итак:

if ps aux | grep firefox | grep -v grep > /dev/null; then echo «Firefox запущен»; fi

Совершенно неудобоваримо, так что заготовим псевдоним...

alias isff=’if ps aux | grep firefox | grep -v grep > /dev/null; then echo «Firefox запущен»; fi’

Теперь, чтобы узнать, запущен ли ваш любимый браузер, достаточно выполнить команду isff.

  • Зацикливаем циклы

Условные операторы превосходны для основных задач, но истинная мощь Bash заключается в циклах – в них оператор неоднократно повторяется, обрабатывая новые данные. Иногда это просто выполнение команды несколько раз, например:

while (true); do sleep 1; date; done

Эта команда ежесекундно выводит на экран дату и время, пока не нажмут Ctrl+C. Но вам, скорее всего, захочется пройтись циклом по строкам файла или файлам в каталоге и что-нибудь с ними сделать.

Как, например, распаковать несколько файлов tar.bz2 одной командой? Новички вообразят, что можно скомандовать

 tar xjf *.tar.bz2

Но при попытке это сделать возникает сообщение об ошибке: «tar: foo.tar.bz2: Not found in archive (не найден в архиве)». Дело в том, что Bash разворачивает регулярное выражение *.tar.bz2 в список файлов каталога, фактически превращая введённую команду в такую:

tar xjf bar.tar.bz2 baz.tar.bz2 foo.tar.bz2

Когда вы передаёте утилите tar несколько файлов, первый из них рассматривается как имя архива, и tar попытается извлечь оттуда перечисленные далее файлы. Приведённая выше команда читается так: «извлечь baz.tar.bz2 и foo.tar.bz2 из bar.tar.bz2».

Значительно лучшее решение – использовать циклы: воспользуйтесь командой ls, чтобы получить список bz2-файлов в каталоге, и пройдитесь по ним в цикле, распаковывая каждый по отдельности. Итак:

for i in `ls *.tar.bz2`; do tar xjf «$i»; done

Здесь используется оператор «`» (обратный апостроф, который обычно расположен на клавиатуре слева от цифры 1), он выполняет ls *.tar.bz2 и вставляет её результат в команду на соответствующее место. Вы можете заставить Bash читать данные из файла, используя cat, например, так:

ls *.tar.bz2 > bzip_files
for i in `cat bzip_files`; do tar xjf «$i»; done

Шаг 2 — Могучие команды Unix

Вторая часть нашего урока посвящена тому, как выжать всё из команд, которыми вы пользуетесь ежедневно – или, по крайней мере, должны бы пользоваться. Все команды Unix очень хорошо выполняют какую-то одну простую задачу, но чтобы предоставить опытным пользователям (вроде вас – по крайней мере, такими вы должны стать после наших уроков) максимальную гибкость, эти команды имеют множество параметров, чтобы изменять их поведение.

  • «Меньше» значит «больше»

Рассмотрим команду less. Вероятно, вы используете её так:

cat /etc/somefile | less

Она выводит на экран файл и позволяет вам перемещаться по нему с помощью стрелок курсора. Пользователи поумнее (это мы) вместо этого употребляют команду

less /etc/somefile

Эффект будет тот же. А если я скажу вам, что у less множество параметров, изменяющих ее работу? На них прямо-таки нехватает букв алфавита, а некоторые даже чувствительны к регистру символов! И это только параметры, которые вы передаёте в программу – а ведь после запуска less ею можно управлять с помощью различных комбинаций клавиш.

Сильно ли вас бесит сообщение об ошибке, говорящее, что в файле somefile.txt есть проблема в строке 780? Не все так плохо: вспомните, что команда less с параметром -N (заметьте: не -n) распечатает номера строк, и вы узнаете, в чем дело. А чтобы получить больше информации, можете попробовать ключ -M – в строке статуса будут выведены имя файла, диапазон строк и текущая позиция в процентах.

Можно передать less несколько имён файлов, и они будут открыты все за одну сессию. Например:

less /etc/passwd /mnt/backup/etc/passwd

Когда less запустится, в её буфер будет загружен /etc/passwd, и в строке статуса появится сообщение «Файл 1 из 2». Для перемещения к следующему файлу (/mnt/backup/etc/passwd) используйте :n, а чтобы вернуться назад к первому – :p. Открыть следующий файл, сохраняя уже открытые два, можно взять :e и ввести имя файла, используя Tab для автодополнения, если потребуется. Чтобы закрыть текущий файл и убрать его из буфера less, пригодится :d.

Наконец, мощная клавиша «!». Если вы наберёте ! с последующей командой, которую нужно выполнить, less запустит эту команду, покажет вам её вывод и вернётся к просмотру файлов. Бесполезное вроде занятие; но вспомните, что текущий файл обозначается «%». Допустим, вы просматриваете в less файл /home/paul/somefile.txt и сообразили, что хотели включить в него список файлов из каталоге /etc. Сделать это можно прямо из less:

!ls /etc >> %

Перенаправление >> припишет вывод команды ls к концу файла. Когда вы вернётесь в less, её буфер будет обновлён, чтобы показать результат программы, и вы можете продолжить чтение.

  • top-парад

Команда top – одна из тех, которые новички осваивают в первую очередь, поскольку это простейший способ узнать, какая программа сжирает все процессорное время в вашей системе. Но поначалу top может напугать: уйма данных вверху, далее 12 или больше столбцов информации, напичканной акронимами...

Столбцы, которые нам интересны – PID (идентификатор запущенного процесса), User (пользователь, запустивший процесс), NI (значение niceness, показывающее, с какой лёгкостью процесс отдаёт свои ресурсы) и сама команда. Остальные значения можно либо игнорировать, либо просто удалить из списка отображаемых полей. Для этого нажмите клавишу F, и вы увидите список всех отображаемых полей, вместе с клавишей, которую следует нажать для отключения поля. Например, «* N: %MEM =Memory usage (RES)» означает, что %MEM сейчас отображается (помечено звёздочкой), а нажатие n исключит это поле из списка. Выбрав нужные поля, нажмите Enter – и вернетесь к основному экрану.

Если вы нажмёте F (заметьте, что буква на сей раз заглавная), вы увидите примерно такой же список, но теперь сможете выбрать, какое поле будет использоваться для сортировки. Для пробы нажмите F (чтобы попасть на экран сортировки), a (выбор сортировки по PID), Enter (возврат в основной экран) и затем R (сортировка в обратном порядке – первыми отображаются PID с наименьшим значением).

top умеет не только показывать цифры: это мощнейший инструмент администрирования. Например, нажмите k и введите PID процесса, который нужно завершить (по умолчанию используется сигнал 15, который вежливо просит программу прекратить работу; в случае неудачи сигнал 9, так сказать, «вырубить питание»). Можно также нажать <r>, указать PID процесса и изменить его значение nice, и вашей системе гарантирован более высокий приоритет. Здесь есть одна хитрость – чем ниже значение nice, тем выше приоритет, самое низшее значение – 20, наивысшее – минус 19. Будьте внимательны при установке значений nice: повышать приоритеты разрешено только от имени суперпользователя, и любое значение ниже нуля требует особой осторожности.

  • Грызем grep

Держу пари, что я смогу по пальцам сосчитать людей, которые регулярно используют grep в ситуациях, отличных от этих двух:

somecommand | grep «foo»

или

grep «foo» *

Увы, при своей-то чудовищной мощности, grep обычно прикован к дебильным задачам, едва отвлекающим процессор от спячки. Grep тоже имеет столько параметров, что и не упомнишь, но некоторые всё же следует выучить:
• -c Подсчитывает число вхождений искомой строки.
• -i Поиск, не зависящий от регистра символов.
• -l Выводит на экран имена совпавших файлов (это строчная L).
• -n Отображает номер соответствующей запросу строки.
• -r Выполняет рекурсивный поиск по каталогам.
• -v Инвертирует условие поиска (строки, не содержащие цель поиска).
Их можно объединять, перенаправив grep на самого себя. Например, если нужно подсчитать число файлов, которые содержат слово «paul» (или «PAUL», «PaUl» и т.д.), кроме тех, которые имеют расширение .txt, вам следует сделать что-то подобное:

grep -ilr paul * | grep -cv «\.txt$»

Здесь мы используем пять из шести важнейших параметров, превращая сложную задачу в простой конечный результат: число соответствующих условию файлов. В этом примере -ilr означает, что выполняется поиск по файлам слов Paul, PAUL, PaUl и т.д., поиск проходит рекурсивно по вашей файловой системе (начните с корневого каталога, чтобы выполнить поиск по всему диску) и возвращает имена подходящих файлов. Всё это поступает на вход другого экземпляра grep, который использует флаги -cv, включающие режим подсчёта и поиск файлов, которые не соответствуют регулярному выражению «\.txt$». Обратный слеш здесь экранирует точку: без него мы получили бы специальный символ. Знак доллара в конце означает, что .txt должно находиться в конце имени файла, то есть foo.txt.bar не будет соответствовать выражению.

Если вам предстоит прошлепать по огромному тексту, настоятельно рекомендую использовать дополнительный ключ --color, чтобы grep подсвечивал в выводе соответствующие выражения.

  • Ищите и обрящете

Команда find печально знаменита своим коварством: никто не может правильно её использовать, не прочитав предварительно руководство. Впервые принимаясь за find, многие думают, что нужно попробовать нечто вроде find <иголка> <стог_сена>. Например, find myfile.txt /etc должна бы просматривать каталог /etc и его подкаталоги в поисках файла myfile.txt. Ха-ха! Когда я вижу новичков, набирающих подобное, я обычно хлопаю их по спине, говорю, что всё у них получится, и расхаживаю, невинно посвистывая.

Вместо того чтобы работать в соответствии со здравым смыслом, find работает как фильтр. Наиболее общая команда выглядит так:

find .

Первый параметр (путь, по которому выполняется поиск) – это «.», так что будет возвращён список всех файлов в текущем каталоге. Теперь сузим вывод при помощи параметров. Например, -name указывает, что find должна возвратить только файлы с указанным именем, скажем, myfile.txt или «*bar*», соответствующий файлам с «bar» где-нибудь в имени. Например:

find . -name «*bar*»

Мы могли бы добавить параметр -size, который ограничивает результаты поиска файлами, размер которых больше, меньше или равен заданному. Например:

find . -name «*bar*» -size +1M
find . -name «*bar*» -size -10k

Первая команда найдёт все файлы с нужными именами, которые больше 1 МБ, а вторая – те, которые меньше 10 КБ. Файлы, размер которых точно равен заданному (например, 1 МБ), не будут возвращены, если поиск выполняется со строгим условием «больше» или «меньше».

Параметр -user возвращает только файлы, принадлежащие указанному пользователю. Например, -user paul вернёт файлы, принадлежащие пользователю paul. В частности, это полезно с параметром -not, который может предшествовать любому параметру и выполняет инвертирование значения. Вот несколько примеров:

# все файлы, не принадлежащие пользователю paul
find . -name «*bar*» -not -user paul
# все файлы, кроме myfile.txt и тех, которыми владеет paul
find . -not -name «myfile.txt» -not -user paul
# аналогично первому примеру, но с двойным отрицанием для прикола!
find . -not -not -name «*bar*» -not -user paul

Ещё один небезынтересный фильтр – -newer, он возвращает все файлы, которые новее, чем указанный файл. Это очень удобно для скриптов резервного копирования: когда делаете копию, просто укажите произвольный файл, и он будет служить временной меткой, которую можно использовать в команде find -newer. Вы получите список всех файлов, которые изменились с момента создания этого файла. Вот нужная вам команда:

find . -newer /path/to/myfile
  • Последние штрихи

Есть целая группа параметров find, которые мы не затронули: действия. Каждый раз, когда find наталкивается на файл, соответствующий вашим критериям, она может что-то с этим файлом проделать. Например, -ls выведет на экран информацию об этом файле в стиле ls -l, а параметром -exec заставит find запустить для этого файла определённую команду. Скажем, вы хотите найти все текстовые файлы в своём домашнем каталоге и вывести их на экран. Это можно сделать так:

find /home/someuser -name «*.txt» -exec cat {} \;

Фигурные скобки {} заменятся именем соответствующего файла, и при каждом совпадении будет выполняться cat. Конструкция \; в конце необходима, потому что find считает всё, что после -exec, выполняемой программой, пока не наткнется на точку с запятой. Но если вы просто наберете -exec cat {};, то Bash в процессе обработки строки эту точку с запятой удалит, и find пожалуется на ошибку.

Альтернативой -exec является -ok, который работает точно таким же образом, но запрашивает ввод пользователя перед выполнением каждой команды. Нажмите <y> для выполнения команды (опять-таки, для каждого соответствующего файла), или <n>, чтобы пропустить её.

К сожалению, на этот месяц больше места нам не досталось, и я сумел лишь обсудить Bash и четыре самых популярных команды Unix. Мы надеемся, что наступит день, когда вы полюбите командную строку с той же страстью, что и мы – или, по крайней мере, не так будете пугаться пролетающего во время загрузки текста.

...Включаем главный экран

Работа в терминале воспринимается некоторыми программистами как возврат в восьмидесятые –точка взаимодействия с компьютером всего одна, и воспользоваться многозадачностью не так-то легко. Большинство систем Unix несколько сглаживают проблему, предоставляя возможность работать в нескольких виртуальных терминалах – нажатие <Ctrl+Alt+ c F1по F6> позволит войти в систему несколько раз и запустить разные задачи. Случай удалённого подключения – посложнее: если вы используете SSH на сервере и запустили долго выполняющуюся команду в интерактивном режиме, то как запускать следующую?

Если вы не придумали ничего лучше, чем «открыть ещё одно SSH-соединение», вас следует долго бить по голове толстенным руководством по Unix. Команда screen – это умножитель терминалов, то есть она преобразует один терминал в несколько и таким образом решает нашу проблему.

Сначала введите screen и нажмите <Enter>. Экран очистится, и вы увидите приглашение командной строки, ожидающее ввод; запустите команду top. Пока всё выглядит как обычно – вы можете подумать, что запуск screen совершенно ни к чему не привёл. Но нажмите <Ctrl+a>+<c> (нажмите и удерживайте <Ctrl>, нажмите <a>, отпустите <Ctrl> и нажмите <c>), и перед вами предстанет новый терминал. Команды управления в screen чувствительны к регистру: <Ctrl+A> не то же самое, что <Ctrl+a>. Старый терминал (и его команда top) всё ещё запущен, не приостановлен и не изменён, он работает в фоновом режиме, но мы сейчас находимся в виртуальном терминале 1. Чтобы вернуться назад, нажмите <Ctrl+a>+<0>, и вы обнаружите, что top всё ещё следит за работой вашего ПК. Для перехода обратно в новый терминал, нажмите <Ctrl+a>+<1>.

Есть множество других команд, которые вы можете освоить: <Ctrl+a>+<n> и <Ctrl+a>+

позволяют переходить на следующий и предыдущий терминал (переключаясь с последнего на первый и наоборот), <Ctrl+a>+<A> позволит задать имя терминалу (вместо общего для всех имени «Bash»), а <Ctrl+a>+ выведет меню терминалов, по которому можно перемещаться с помощью стрелок курсора, не озадачиваясь точными номерами. Но важнее всех – <Ctrl+a>+<d>, которая отключает вас от сессии screen, но сохраняет её (включая терминалы и связанные с ними программы). Вы можете выйти из системы, прийти домой, набрать screen -r, чтобы подключиться к покинутой сессии, и вернетесь к тому же состоянию.

...Графические терминалы

«Графические терминалы» – не оксюморон. Оказывается, использование приложений вроде Konsole может сэкономить ваше время, сделав работу за вас. Моя любимая функция – «monitor», это когда Konsole следит за активностью терминала и высвечивает сообщение о перемене состояния. Так что если вы ожидаете завершения длительного процесса компиляции, просто поручите Konsole проследить и доложить.

...Полезные советы


• Меняйте права доступа мгновенно: используйте chmod --reference /path/to/somefile.txt *, и у всех файлов в текущем каталоге будут такие же права, как у somefile.txt.
• Команда tail -f /var/log/somefile.log загрузит последние десять строк лог-файла и будет обновлять вывод по мере появления новых.
• Вместо того, чтобы повторно набирать команду в ожидании события, используйте команду watch. Например, watch ls -l будет запускать ls -l каждые две секунды и выводить полученный результат на экран.
• Если вам нравится мониторинг активности в Konsole и хочется получить то же самое в screen, просто используйте

<Ctrl+a>+<M>.


• Хороший снимок рабочего стола X получится с помощью следующей жуткой команды:

chvt 7; sleep 3; import -display :0.0 -window root screenshot.png

Личные инструменты
  • Купить электронную версию
  • Подписаться на бумажную версию