Обзор курса + shell
Мотивация
Как инженеры и программисты мы знаем, что компьютеры отлично справляются с повторяющимися задачами. Однако слишком часто забываем, что это применимо как к нашей работе с компьютером, так и к вычислениям, которые выполняют программы. У нас под рукой есть широкий спектр утилит, которые позволяют нам работать более продуктивно и решать более сложные задачи при работе над любой связанной с компьютерами проблемой. Тем не менее многие из нас используют лишь небольшую часть этих инструментов. С одной стороны, мы знаем достаточно «магических заклинаний» наизусть, но, столкнувшись с трудными случаями, бездумно копипастим команды из интернета.
Цель лекций – решить эту проблему.
Мы хотим научить вас, как выжимать максимум из утилит, показать вам новые средства, которые обязательно пригодятся, а также вызвать интерес к дальнейшему изучению (и, возможно, даже созданию) дополнительных программ. Мы считаем, что это семестр, которого не хватает в большинстве учебных курсов по компьютерным наукам.
Структура курса
Курс состоит из 11 лекций по часу, каждая из которых посвящена определенной теме. Лекции не зависят друг от друга, хотя по ходу курса мы будем предполагать, что вы знакомы с прошлыми темами и содержанием предыдущих лекций. В текстовых конспектах лекций нет некоторых материалов (например, демо), поэтому все видео к урокам также выложены в открытый доступ. В 11 лекционных часов вошло много тем, поэтому каждый урок достаточно «плотный» и насыщенный информацией. У вас будет время ознакомиться с содержанием уроков в удобном темпе, каждая лекция включает в себя набор упражнений, которые помогут вам разобраться в ключевых моментах.
По сравнению с традиционными офлайн-курсами у нас мало времени для детального изучения утилит. Поэтому там, где это возможно, мы предоставляем ссылки на материалы для самостоятельного изучения.
Лекция 1: Shell
Что за shell?
У современных компьютеров много разных интерфейсов для команд: причудливые графические пользовательские интерфейсы, голосовые и даже AR/ VR интерфейсы. Они отлично подходят для 80% случаев, но ограничены определенным набором команд. Так, вы не можете нажать кнопку, которой нет, или дать голосовую команду, которая не была запрограммирована. Чтобы в полной мере воспользоваться возможностями компьютера, обычно прибегают к проверенному олдскульному способу и переходят на текстовый интерфейс – shell (шелл, оболочка, консоль, CLI, командная строка).
Работа с оболочкой
Почти у всех платформ есть оболочка или даже несколько на выбор. Хотя они могут различаться в деталях, по сути все примерно одинаковые: позволяют запускать программы и выводить результат их выполнения в структурированном виде.
В этой лекции рассмотрим самый распространенный – Bourne Again Shell или bash. Для запуска bash на Ubuntu для начала нужно открыть терминал. На Windows он запускается с помощью шортката Ctrl + Alt + T, на macOS – через поиск или графический интерфейс. После запуска терминала вы увидите что-то вроде этого:
missing:~$
Это основной текстовый интерфейс. Он показывает, что вы на машине missing
, ваша текущая директория ~
(это стандартное обозначение
home директории в системе). Значок $
сообщает, что вы не root пользователь (подробнее об этом позже).
В командной строке вы можете ввести команду, которую интерпретирует оболочка. Самое простое – узнать дату:
missing:~$ date
Fri 10 Jan 2020 11:49:31 AM EST
missing:~$
Выше программа date
печатает текущую дату и время. Затем шелл просит выполнить другую команду. Можем выполнить команду с
аргументами:
missing:~$ echo hello
hello
В примере выше шелл выполняет программу echo
с аргументом hello
. echo
просто выводит hello
. Оболочка анализирует команду,
разделяя ее пробелами, и запускает программу слева направо, начиная с первого слова и передавая каждое последующее слово в качестве
аргумента. Если вы хотите задать аргумент, содержащий пробелы или другие специальные символы (например, папку с именем My Photos), вы
можете либо заключить аргумент в кавычки '
или "
("My Photos"
), либо использовать так называемую технику escaping с помощью
символа \
(My\ Photos
).
Но как вообще оболочка исполняет программы, например, date
или echo
? Как и в языках программирования, в шелл есть переменные,
условные операторы, циклы, функции (об этом в следующих лекциях!). Когда вы запускаете команды, вы пишете небольшие фрагменты кода,
которые интерпретирует шелл. Shell по очереди смотрит все пути, указанные в переменной окружения (она же глобальная переменная) $PATH
и исполняет команду.
missing:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
missing:~$ which echo
/bin/echo
missing:~$ /bin/echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Когда мы запускаем команду echo
, оболочка понимает, что должна выполнить ее. Поэтому ищет ее в списке каталогов $PATH
файл с таким
именем. Каталоги разделены символом :
. Оболочка находит команду и запускает ее (при условии, что файл исполняемый; подробнее об этом
позже). Мы можем узнать, какой файл выполняется для конкретной программы, используя which
. Можем обойтиcь и без $PATH
, сразу указав
весь путь к файлу.
Навигация по оболочке
Путь – список каталогов с разделителем /
на Linux и macOS и \
на Windows. На Linux и macOS путь /
– это корень файловой системы
(root), ниже которого находятся все остальные файлы и каталоги. На Windows свой root есть для каждого раздела диска (например, C:\
).
На курсе мы по умолчанию предполагаем, что вы используете Linux. Путь, начинающийся с /
— абсолютный путь, любой другой –
относительный. Относительный путь связан с каталогом, в котором мы находимся сейчас. Увидеть его можно с помощью команды pwd
, а
изменить – с помощью cd
. .
это текущая директория, ..
— родительская директория (предыдущая до последнего /
).
missing:~$ pwd
/home/missing
missing:~$ cd /home
missing:/home$ pwd
/home
missing:/home$ cd ..
missing:/$ pwd
/
missing:/$ cd ./home
missing:/home$ pwd
/home
missing:/home$ cd missing
missing:~$ pwd
/home/missing
missing:~$ ../../bin/echo hello
hello
Обратите внимание, что в командной строке отображается текущий рабочий каталог.
В общем, когда мы запускаем программу, она будет работать в текущем каталоге, если мы не укажем иное. Например, в текущем каталоге в
первую очередь начинается поиск файлов и при необходимости создаются новые файлы. Чтобы увидеть содержимое текущего каталога,
используем команду ls
:
missing:~$ ls
missing:~$ cd ..
missing:/home$ ls
missing
missing:/home$ cd ..
missing:/$ ls
bin
boot
dev
etc
home
...
Если каталог не указан в качестве первого аргумента, ls
выведет содержимое текущего каталога. Большинство команд принимают флаги и
параметры (флаги со значениями), которые начинаются со знака -
для изменения их поведения. Обычно при запуске программы с флагом -h
или --help
выводится справка, в которой перечислены все доступные флаги и параметры. Например, ls --help
сообщает нам:
-l use a long listing format
missing:~$ ls -l /home
drwxr-xr-x 1 missing users 4096 Jun 15 2019 missing
Какую информацию мы получили?
Во-первых, d
в начале строки говорит нам, что missing
– это наша директория.
Затем следуют три символа (rwx
). Они показывают, что у владельца есть полные права к директории (чтение, запись и выполнение).
Следующие символы r-x
показывают, что группа users есть права на чтение и на выполнение поиска в этом каталоге.
Символ –
указывает на то, какого разрешения у пользователя нет.
Из командной строки выше видно, что только у владельца есть права на изменение (w
) директории missing
(т.е. добавление или удаление
файлов).
Чтобы войти в каталог, пользователь должен иметь разрешения на поиск (представленное «execute»: x
) в этом каталоге (и родительском).
Чтобы вывести его содержимое, пользователь должен иметь права на чтение (r
) в этом каталоге.
Для файлов разрешения такие же. Обратите внимание, что почти все файлы в /bin
имеют разрешение x
, установленное для последней
группы, «все остальные», так что каждый может выполнять эти программы.
Некоторые другие удобные обозначения, о которых следует знать на этом этапе:
mv
– для переименования или перемещения файла,
cp
– для копирования файла,
mkdir
– для создания нового каталога.
Если вам когда-нибудь понадобится дополнительная информация, попробуйте команду man
. Она принимает в качестве аргумента имя программы
и показывает ее справочную страницу. Для выхода используйте q
.
missing:~$ man ls
Подключение программ
В консоли с программами связаны два основных «потока»: ввод и вывод. Когда программа пытается прочитать введенные команды, она читает их из входного потока, а когда что-то отображает на экране – она работает с выходным потоком. Обычно ввод и вывод видны в терминале. Клавиатура отвечает за ввод, монитор – за вывод. Но можно перепрограммировать эти потоки!
Самый простой способ перенаправления – это команды < file
и > file
. Они позволяют перенаправить потоки ввода и вывода программы в
файл:
missing:~$ echo hello > hello.txt
missing:~$ cat hello.txt
hello
missing:~$ cat < hello.txt
hello
missing:~$ cat < hello.txt > hello2.txt
missing:~$ cat hello2.txt
hello
Можно использовать >>
для добавления в файл. Этот тип перенаправления ввода /
вывода наиболее полезен при использовании
конвейеров. |
оператор позволяет «связывать» программы так, чтобы выходные данные одной были вводными данными другой:
missing:~$ ls -l / | tail -n1
drwxr-xr-x 1 root root 4096 Jun 20 2019 var
missing:~$ curl --head --silent google.com | grep --ignore-case content-length | cut --delimiter=' ' -f2
219
В лекции по обработке данных мы более подробно рассмотрим, как использовать конвейеры.
Универсальный и мощный инструмент
В большинстве Unix-подобных систем один пользователь особенный – root пользователь. Вы видели его в списках файлов выше. Пользователь с
такими правами находится выше (почти) всех ограничений доступа и может создавать, читать, обновлять и удалять любой файл в системе. В
большинстве случаев вы не будете входить в систему как root пользователь, поскольку слишком легко случайно что-то сломать. Вместо этого
вы будете использовать команду sudo
. Как следует из названия, она позволяет «делать» («do») что-то «как su» («as su» – сокращение от
«суперпользователь» («super user») или «root»). Когда вы столкнетесь с ошибкой отказа в доступе, обычно это будет значить, что вам
нужно сделать что-то от имени root пользователя. Хотя сначала убедитесь, что вы действительно хотите это сделать!
Root права нужны для внесения изменений в файловую систему sysfs
, заданную как /sys
. sysfs
предоставляет пользователю
детализированную информацию о параметрах ядра, так что вы можете легко перенастроить ядро без специальных инструментов.
Обратите внимание, что sysfs
не существует в Windows или macOS.
Например, яркость экрана ноутбука отображается в файле под названием brightness
/sys/class/backlight
Записав значение в этот файл, мы изменим яркость экрана. Вашим первым инстинктом может быть что-то вроде:
$ sudo find -L /sys/class/backlight -maxdepth 2 -name '*brightness*'
/sys/class/backlight/thinkpad_screen/brightness
$ cd /sys/class/backlight/thinkpad_screen
$ sudo echo 3 > brightness
An error occurred while redirecting file 'brightness'
open: Permission denied
Неожиданная ошибка, ведь мы выполнили команду с помощью sudo
! Что важно знать об оболочке: такие операции, как |
, >
и <
обрабатываются оболочкой, а не отдельными программами. echo
и его «друзья» не «знают» о |
. Они просто читают из ввода и записывают
в вывод, каким бы он ни был. В приведенном выше случае оболочка (которая распознается как пользователь) пытается открыть файл яркости
для записи до того, как он будет установлен как вывод sudo echo
, но останавливает выполнение, потому что оболочка не запускается с
правами root. Используя эти знания, мы можем попробовать другой способ:
$ echo 3 | sudo tee brightness
Поскольку программа tee
открывает файл /sys
для записи и запускается от имени root
пользователя, все разрешения работают.
С помощью /sys
можно управлять разными полезными вещами, например, состоянием светодиодов (ваш путь может быть другим):
$ echo 1 | sudo tee /sys/class/leds/input6::scrolllock/brightness
Следующие шаги
На данный момент вы знаете, как работать с оболочкой, чтобы выполнять базовые задачи. Вы должны уметь перемещаться по файлам и использовать основные функции большинства программ. В следующем уроке поговорим о том, как выполнять и автоматизировать более сложные задачи с помощью шелла и множества удобных программ командной строки.
Упражнения
- Создайте новую директорию с именем
missing
в/tmp
. - Ознакомтесь с программой
touch
. Программаman
- ваш друг в изучении новых команд. - Используйте
touch
для создания нового файла с именемsemester
в директорииmissing
. - Запишите в созданный ранее файл, построчно, следующее:
#!/bin/sh curl --head --silent https://missing.csail.mit.edu
Первая строка имеет особенности при выполнении скрипта. Будет полезным знать, что символ
#
означает начало комментария в Bash, а символ!
имеет особое значение даже внутри строки в двойных кавычках ("
). Bash обрабатывает строки в одинарных кавычках ('
) иначе. Обратитесь к quoting справочной информацию для ознакомления с особенностями. - Попробуйте запустить скрипт, введя путь к файлу (
./semester
) в вашей оболочке и нажмите Enter. Разберитесь, почему скрипт не запускается с помощью информации из вывода командыls
(подсказка: обратите внимание на биты доступа к файлу). - Запустите скрипт, явно указав интерпретатор
sh
в начале, и укажите путь кsemester
первым аргументом, образец:sh semester
. Почему скрипт в этом случае сработал, когда при запуске./semester
- нет? - Ознакомьтесь с программой
chmod
(подсказка: введитеman chmod
). - Используя
chmod
, сделайте возможным запуск скрипта при вводе./semester
, без необходимости вводаsh semester
. Как ваша оболочка узнала, что файл может быть интерпретированsh
? Обратитесь к shebang за дополнительной информацией. - Используя
|
и>
, запишите дату “last modified” из вывода скриптаsemester
в файл с именемlast-modified.txt
в вашей домашней директории. - Напишите скрипт, который считывает уровень заряда батареи вашего ноутбука или
температуру процессора ПК из
/sys
. Пометка: если вы пользователь macOS, вы можете пропустить данное упражнение, т.к. ваша операционная система не имеет sysfs.
Лицензия CC BY-NC-SA.