Основы использования командной строки

[suspended]

Здесь мы прекращаем разговор про shell как про интегратор, оставив незатронутыми две очень важные темы, которые напрямую связанны с shell как языком программирования:

  • операторы, которые обеспечивают shell алгоритмическую полноту( циклы, условные операторы)
  • написание собственных командных сценариев.

Пока что не говорилось про shell в своей первой ипостаси- как удобный инструмент для работы с командной строкой. А между тем грамотно настроенный shell хорошо помогает облегчить работу с командной строкой.

Среди различных удобств, которые предлагает shell, есть, например, подсказка командной строки. Её можно задавать самому, она хранится в переменной окружения PS1. Начнем с простого:

  PS1='$ '

Такую подсказку обычно используют в качестве примера во многих книжках по Unix-системам. Теперь давайте сделаем её более разумной. При задании подсказки можно использовать спецпоследовательности, которые при выводе shell будут заменятся значимой информацией. Таких спецпоследовательностей на самом деле довольно много:

\u

имя пользователя

\n

имя хоста до первой точки

\W

последняя часть текущего каталога

\n

новая строка

Рассмотрим , например, один из способов отделить начало результата работы команды и подсказку:

PS1="[\[`tput smso`\]\u@\h \W\[`tput rmso`\]]\$ "

Команда tput --- выводит на терминал некую управляющую последовательность которая изменяет режим вывода. Например изменение цвета букв,перестановка курсора в произвольное место и т.д. Это свойства самого терминала. Программа tput всего лишь программный интерфейс к этому свойству. На самом деле практически все программы, которые работают с терминалом, и работают не только с командной строкой, но и со всем экраном пользуются этими свойствами. Что собой являет результат работы программы tput?. Результатом являются символы. Эти символы называются escape-последовательностями или управляющими последовательностям, т.е. для того, чтобы заставить терминал показывать как-то по-другому на него опять таки нужно вывести символы, но это будут уже специальные символы, например, Esc[38m, Esc[0m, которые, вместо того, чтобы отображаться на экране , как-то управляют терминалом, например изменяют цвет вывода. Это пошло с тех времён, когда графических дисплеев не было, а основным устройством управления системой был алфавитно-цифровой терминал, который через последовательное подключение соединялся с компьютером и гонял байты туда-сюда. Когда выяснилось, что было бы неплохо чтобы на этих терминалах можно было хотя бы печатать текст в определенном месте, уж не говоря о различных цветах, стали думать, как можно сделать так, чтобы это устройство, которое по сути аналогично печатной машинке, могло,например, показать буквы другим цветом. Было принято следующее решение - некоторые символы непечатные - при выдаче на экран ничего не происходит, более того, при выдаче этого символа на экран он переходит в режим, когда им управляют, и следующие несколько символов указывают команды. Такая последовательность управляющих символов получила название "управляющая последовательность". В период когда это все разрабатывалось было придумано несколько сотен разных типов терминалов с различными возможностями и управляющими последовательностями. После того как алфавитно-цифровые терминалы вышли из употребления эта ситуация вовсе не стала проще, так как до сих пор существует с дюжину разных программ, которые эмулируют терминал, и у них у всех по-прежнему разные управляющие последовательности. Именно поэтому не стоит запоминать наизусть конкретные управляющие последовательности, а лучше изучить документацию по подсистеме terminfo - база данных информации про терминал- и пользоваться командой tput. Примеры

tput bold

полужирный

tput smso

set mode standout --- наиболее выраженный режим, у разных терминалов он разный.

Обратите внимание, что командой echo $PS1 нельзя узнать какие именно управляющие последовательности были задействованы, т.к. экран честно выполнит поступившие к нему команды. Самая удобная программа для просмотра --- hexdump с ключом -C

$echo $PS1 | hexdump -C
00000000  5b 5c 5b 1b 5b 37 6d 5c  5d 5c 75 40 5c 68 20 5c  |[\[.[7m\]\u@\h \|
00000010  57 5c 5b 1b 5b 32 37 6d  5c 5d 5d 24 0a           |W\[.[27m\]]$.|
0000001d

Последний вопрос, который мы рассмотрим - зачем команда tput была обрамлена \[ и \] --- bash рассматривает подсказку весьма примитивно - он считает ширину подсказки суммируя ширину всех её составляющих, после чего считает что подсказка занимает подсчитанное место, а все остальное место --- строка ввода. Но если встречаются управляющие последовательности, то их длина точно также прибавляется к ширине подсказки, однако управляющие последовательности не сдвигают курсор, поэтому у bash формируется неправильное представление о том, где встречается курсор. Специально для этого в PS1 и существуют \[ и \]

Понятие терминала (suspended)

До этого мы воспринимали терминал как нечто само-собой разумеющееся, но на самом деле там есть много возможностей о которых обычно не знают. Мы уже обнаружили такие вещи, как управляющие последовательности терминала. Это с точки зрения терминала как аппаратного устройства. А нет ли особых свойств у терминала как у программной абстракции, почему он имеет название terminal- "конечное устройство"? С точки зрения ОС Linux, терминал это не просто аппаратное устройство, занимающееся передачей байт, он обладает свойством эти байты при передаче преобразовывать. В частности,Когда мы запускали программу cat и потом надо было окончить ввод, мы нажимали Ctrl-D. Если бы это устройство не было бы зарегистрировано в системе как терминал, то ввод Ctrl-D привел бы к тому что программе cat передался бы символ с ASCII кодом 4, и она бы продолжала бы работать. Аналогично с символами Ctrl-C. Здесь мы как раз имеем дело с тем фактом, что при передаче данных посредством терминала эти данные обрабатываются, при чём в обе стороны. В приведенных примерах использованы два вида обработки данных:

  • Ctrl-D --- система закрывает для текущей запущенной программы стандартный ввод. Это очень удобно когда программа считывает данные из файла, а скажем с клавиатуры и надо сообщить ей что данные кончились. Первый вид обработка данных -некие манипуляции с системой. Нажатие Ctrl-C приводит к тому что программе посылается сигнал ( короткое сообщение, состоящее только из номера сигнала) который программа должна обработать сама, либо вызовется стандартный обработчик, который в большинстве случаев приводит к завершению программы. Есть отдельная утилита которая и управляет соответствием между нажатиями клавиш и системными манипуляциями- stty.
    $ stty -a
    speed 38400 baud; rows 45; columns 143; line = 0;
    intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z;
    rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
    -parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts
    -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl -ixon -ixoff -iuclc -ixany -imaxbel iutf8
    opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
    isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke
    Если вы вдруг перевели терминал в режим , в котором он не обрабатывает такого рода последовательности. то например можно применить такую последовательность команд
    $ stty sane ^J
    Почему именно Ctrl-J? - это еще одно свойство т.н. обрабатываемого режима передачи данных в терминале- в свое время бич всех компьютеров и принтеров - сколько символов в конце строки и какие они. В некоторых системах два - "перевод строки" и "возврат каретки". Некоторые используют эти же два символа, но в обратном порядке. Аналогично и с принтерами. В Unix и вслед за ним в Linux поступили просто - сказали что в конце строки стоит символ конца строки. Как вы его определите- такой и будет. Допустим он совпадает с переводом строки. А когда вы выводите это на экран пусть терминал и разбирается. В режиме необрабатываемого ввода никакого преобразования не происходит, поэтому и надо нажимать ^J поскольку он и есть символ "конец строки"
  • Среди прочих вариантов преобразования ввода\вывода проходящих через терминал есть целых три символа редактирования ввода --- erase(удаление символа), kill(удаление строки), werase(удаление слова) (bs, u, w). Т.е. если вы запустили скажем программу cat то вы можете редактировать её ввод этими тремя символами.

Возвратимся к shell, как к удобному интерфейсу командной строки: разумеется, этих трёх команд недостаточно, поэтому любой уважающий себя shell имеет огромное кол-во команд редактирования ввода. Например, стрелочки вверх\вниз производит просмотр история, а стрелочки влево\вправо отвечают перемещениям курсора по строке. Ctrl-R --- поиск по истории. На самом деле, таких функций --- десятки. Одна из важных возможностей - способ привязать конкретную клавиши\ последовательность к конкретной функции. Это суть команды bind. Именно эта команда определяет для многих программ, привязку клавиш к тем функциям. Эти привязки относятся не к bash как таковому, а к специальной библиотеке readline. Формат таков --- Справа стоит название функции, которую надо вызвать, слева - последовательность клавиш. \C- означает Ctrl, \M- --- meta(эта клавиша присутствует не на всех кдавиатурах)

Идея команды bind --- назначить какие функции редактирования командной строки по нажатию каких клавиш выполнять. Например так делается хождение по словам с помощью PgUp/PgDn:

  • bind '"^[[5~": backward-word'
  • bind '"^[[6~": forward-word'


Сведения о ресурсах

Продолжительность (ак. ч.)

Подготовка (календ. ч.)

Полный текст (раб. д.)

Предварительные знания

Level

1

1

1

1


CategoryLectures CategoryPspo CategoryMpgu CategoryUneex