Skip to content

Latest commit

 

History

History
 
 

intro

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

Вводная лекция

Мотивация курса

Как инженеры мы знаем, что компьютеры отлично справляются с вычислительными задачами. У нас есть широкий спектр инструментов, которые позволяют нам быть более продуктивными и решать более сложные задачи при работе над любыми проблемами, которые так или иначе что-то выполняют. Однако многие из нас используют лишь малую часть этих инструментов: мы знаем достаточно магических заклинаний только наизусть, и слепо копируем команды из stackoverflow, когда мы не знаем, как что-то сделать с системой. Примерами таких систем является apt, vim, git, docker и такой список можно достаточно длинно продолжать.

Этот курс мы решили провести, чтобы закрыть проблему непонимания таких популярных технологий и рассказать, что стоит за многими инструментами/фреймворками, а также повысить Вашу продуктивность, чтобы Вы лучше понимали, как работают Ваши повседневные вещи. Я, лектор, решил взять на себя смелость рассказать достаточно большой и сложный багаж знаний, который я накапливал долгое время (в том числе и со stackoverflow, друзей, индустрии) и который, кажется, не был рассказан ни на одном курсе Факультета Компьютерных Наук. Я не утверждаю, что я знаю всё, я до сих пор учусь и повышаю свою инженерную продуктивность — этот процесс достаточно долгий и постоянно развивающийся, к тому же у каждого свой идеальный набор инструментов.

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

У меня нет задачи заставить Вас использовать что-то, что я использую. Я хочу показать различные варианты, рассказать интересные идеи, стоящие за ними, и показать, как оно работает изнутри, чтобы оно перестало казаться "магией".

Структура

Будет 13 лекций, каждая из которых затронет какую-то тему. Темы по большей части не связаны между собой, но каждая так или иначе всплывает в работе инженера на системах Linux и MacOS (извините, Windows почти не затронем), чтении и написании статьей или документации, при запуске сервисов, виртуализации, open-source культуры, тестирования, сборки и воспроизведении результатов других. Последняя лекция будет посвящена темам, которые интересны Вам, если Вы хотите, чтобы я покрыл какие-то темы на последней лекции, заполните форму, она будет полностью в записи и без конспектов.

Оценка

Будет 4 домашних задания. Например, идеи, которые на начало курса есть у лектора и которые скорее всего воплотятся:

  • Shell scripting
  • git practice
  • gdb coredumps debug
  • Опубликовать своё резюме в LaTeX через github actions

Финальная оценка будет ставиться как среднее всех домашних заданий и только из них, экзамена не будет, семинаров тоже, обязательного посещения тоже нет. Домашние задания не округляются и берутся дробные оценки в зависимости от критериев. Лекции будут записываться и выкладываться. Единственные преимущества быть на лекции — возможность задавать вопросы лично и получать быстрые ответы. Текстовые лекции не будут такими захватывающими, потому что в этом курсе много надо показывать, что тоже может являться мотивацией быть на онлайн-лекциях. Также если несколько людей найдут достаточное количество опечаток в конспектах или хорошие замечания, могут рассчитывать на бонусы, размер бонуса будет абсолютно субъективным на усмотрение лектора.

Также подписывайтесь на телеграм канал, я там буду делать объявления. Он является основной и полной точкой получения информации. Чата не будет, если есть вопросы, пишите напрямую мне в Telegram.

Shell

У компьютеров сейчас уже очень много интерфейсов работы, будь то полностью графический, как в Windows, будь то уже голосовой, как у ассистентов. Но они достаточно ограничены в своих действиях — мы пока не умеем голосом объяснять любые команды или UX может быть ограниченным. Исторически так сложилось (и по существу), что текстовые интерфейсы самые гибкие и намного проще для реализации. Откуда появился старый добрый Shell.

Все платформы, которые Вы используете, имеют тот или иной shell. Сегодня мы поговорим о самом популярном shell — Bourne Again SHell, или "bash" как его ещё называют. Чтобы открыть терминал, который запустит Вам bash на Ubuntu, надо ввести shortcut Ctrl + Alt + T, на MacOS нет дефолтного шортката, поэтому надо через поиск или графический интерфейс. Если у Вас что-то другое, Вы уже сами знаете, как открывать терминал.

Когда Вы открываете терминал с bash, у Вас перед глазами будет что-то похожее на следующее:

danlark@danlark:~$

Это основной текстовый интерфейс. Он показывает Вам, кто Вы, на какой машине, и где Вы находитесь. Первый danlark — это кто я, второй danlark — машина на которой я нахожусь. ~ — стандартное обозначение home директории в Вашей системе, $ обозначает, что Вы не root пользователь.

Дальше shell предоставляет Вам исполнять команды

danlark@danlark:~$ whoami
danlark
danlark@danlark:~$ hostname
danlark

Как они исполняются? Как и в языках программирования, в Shell есть глобальные переменные, которые Вас окружают. В bash одна из основных глобальных переменных — это $PATH. Ещё такие переменные называются переменными окружения. Чтобы их вывести, надо обязательно перед ними поставить знак $, а команда echo умеет выводить аргументы командной строки, причём echo ничего не знает про $PATH — сам bash раскрывает эту переменную при исполнении.

danlark@danlark:~$ echo PATH
PATH
danlark@danlark:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Теперь, когда Вы пишите любую команду, shell поочередно смотрит на все пути, указанные в $PATH, и исполняет эту команду. Конфликты решаются по первому попавшемуся пути в переменной. Например, у меня бинарный файл whoami на самом деле лежит по /usr/bin/whoami. Вы можете это узнать, написав команду which.

danlark@danlark:~$ which whoami
/usr/bin/whoami
danlark@danlark:~$ which which
/usr/bin/which

Вы также можете переопределять эти переменные перед командами, например:

danlark@danlark:~$ PATH=/usr/local/bin whoami
bash: whoami: command not found
danlark@danlark:~$ PATH=/usr/bin whoami
danlark

С аргументами в shell есть сложности: основной разделитель является пробелом, а иногда аргументы хочется иметь с пробелами. Для этого используют так называемую технику escaping через обратный слеш \, а также кавычки. Например, при навигации по директориям, если какая-то названа hse course, то её создавать или в неё входить можно так:

danlark@danlark:~$ mkdir hse\ course
danlark@danlark:~$ cd "hse course"
danlark@danlark:~/hse course$ pwd
/home/danlark/hse course
danlark@danlark:~/hse course$

Кавычки можно брать как и одинарные, так и двойные. И если Вам хочется какую-то кавычку использовать в названии, то её можно окружить кавычками другого типа и всё будет работать:

danlark@danlark:~$ mkdir 'hse\ "course'
danlark@danlark:~$ cd 'hse\ "course'
danlark@danlark:~/hse\ "course$

Кстати, про навигацию внутри файловой системы. В Linux системах всё находится под одной точкой, называемой "root" или /. Все остальные файлы, девайсы находятся под /. Основные команды для навигации:

danlark@danlark:~$ pwd
/home/danlark
danlark@danlark:~$ cd /home
danlark@danlark:/home$ pwd
/home
danlark@danlark:/home$ cd ..
danlark@danlark:/$ pwd
/
danlark@danlark:/$ cd ./home
danlark@danlark:/home$ pwd
/home
danlark@danlark:/home$ cd danlark
danlark@danlark:~$ pwd
/home/danlark
danlark@danlark:~$ ../../bin/echo hello
hello

Путь, начинающийся с / — абсолютный путь, иначе он относительный. . — это текущая директория, .. — родительская директория (предыдущая до последнего /), pwd — это команда print working directory.

Стоит отметить, что команда cd - вернёт Вас на предыдущую директорию, в которой Вы были. Бывает полезно, когда Вы прыгаете между двумя директориями. А cd ~ вернёт Вас в Вашу home директорию.

Почти все команды работают с текущей директорией. Например, чтобы посмотреть, что за файлы и папки находятся в текущей директории, достаточно запустить команду ls — list.

danlark@danlark:~$ ls
 -                                       Documents
 1_5zVzH8TuK1M-oxVnVEY1GA.png            Downloads
 2020-07-29-155724_1113x656_scrot.png    First
 2020-07-29-163555_1585x422_scrot.png    format-benchmark
...

Аргументы

У команд как правило есть аргументы (или опции), это то, что вы пишете после команды. Аргументы неформально делятся на два типа

  • Позиционные. Например, $ cd /etc, вы передаёте команде cd аргумент, что надо пойти в директорию /etc.
  • Опциональные. Это аргументы обычно начинаются с - или -- (как их разделить не знаю, почти везде работает просто -). Пример: $ ls -l (см. ниже)

Аргументы позиционные и опциональные могут совмещаться

  • $ ls -d /etc
  • $ ls -dl /etc, пример, что однобуквенные аргументы в некоторых командах можно склеивать
  • $ ls --author -l ., пример, когда можно совмещать много различных других аргументов

Сложно, конечно, запомнить аргументы, и они очень несистематичны. Я лично пользуюсь tldr, который показывает наиболее популярные использования той или иной команды, если я что-то не помню. Особенно полезно для каких-нибудь find и tar. Например, на картинке ниже показана динамика количества аргументов у популярных bash команд за время их развития:

Num args

Продолжение Shell

Чтобы посмотреть больше информации, у ls есть опция -l, вывод будет более полным:

danlark@danlark:~$ ls -l
total 250928
drwxr-xr-x  1 danlark primarygroup    224044 May  4 13:11  dir_name
-rw-r-----  1 danlark primarygroup    110021 Jul 29 15:45  1_5zVzH8TuK1M-oxVnVEY1GA.png
-rw-r-----  1 danlark primarygroup    144485 Jul 29 15:57  2020-07-29-155724_1113x656_scrot.png
-rw-r-----  1 danlark primarygroup     92167 Jul 29 16:35  2020-07-29-163555_1585x422_scrot.png
-rw-r-----  1 danlark primarygroup     92031 Jul 29 16:36  2020-07-29-163646_1585x418_scrot.png

На некоторых современных bash ls -l можно просто заменить на ll.

drwxr-xr-x  1 danlark primarygroup    224044 May  4 13:11  dir_name

Разберём, что оно выводит. d бит показывает, что это директория, первый rwx показывает, что директория может читаться, перезаписываться и входиться от пользователя danlark. Вторые r-x показывают, что группа primarygroup может читать и заходить, третьи показывают r-x, что все остальные помимо owner и owner group могут читать и заходить. Стоит отметить, что бит x это execute, для файлов это означает, что файл может исполняться (например, скомпилированный бинарный файл или скрипт), а для директорий это возможность в неё входить. Единица после доступов показывает количество hard link на директорию, но это выходит за рамки нашей лекции. Так как битов по 3, то их представляют в 8-ричной системе счисления и эти доступы можно менять, например:

danlark@danlark:~$ chmod 775 dir_name
danlark@danlark:~$ ls -ld dir_name
drwxrwxr-x 2 danlark primarygroup 4096 Aug 16 15:55 dir_name

Остальные интересные команды для работы с директориями — это mv $src $dst (move), cp $src $dst (copy), mkdir $dir (make directory), rm $file (remove), rmdir $dir (remove empty directory), rm -r $dir (remove recursive), touch $file (touch a file, то есть создание файла).

Если Вы хоть когда-то хотите что-то большее узнать про какую-либо команду, её опции и прочее, всегда можно ввести man $cmd или cmd --help, которые должны помочь или tldr (см. выше).

В man навигация идёт обычными стрелками, но если Вы хотите что-то поискать, то shortcuts следующие:

  • / search string — ищёт “search string” в текущем man
  • n — к следующему совпадению строки
  • shift + n — предыдущее совпадение строки

Super User

Вы скорее всего уже часто сталкивались с тем, что Вам приходится писать sudo в командах, в частности при установке пакетов. sudo обозначает "super user do" и нужно, когда Вам нужны доступы к папкам/файлам, которые защищены от всех остальных пользователей. В общем случае sudo позволяет привилегированным пользователям исполнять команды из-под любого другого пользователя. Например, при установке пакетов в /usr/bin вы должны быть привилегированным. Это создано для безопасности, поэтому будьте осторожны всегда, когда Вас просят что-то сделать с sudo привилегиями, например, не запускайте сторонние бинарные файлы с этим доступом. Пароль от sudo по умолчанию хранится 15 минут, то есть Вам не надо будет вводить новый пароль при повторном использовании sudo. Если же Вы хотите всегда быть в root в каких-то операциях, Вы можете войти в su (super user) мод.

danlark@danlark:~$ sudo su
[sudo] password for danlark:
root@danlark:/home/danlark#

Межпроцессное взаимодействие

Запускать программы по одной очень хорошо, но иногда хотелось бы вывести вывод программы в файл или на вход другой программы. Для этого в shell есть множество способов, основанные на так называемых потоках или файловых дескрипторах.

Самые простые формы перенаправления — <file и >file. Первое обозначает, что вход программы должен браться из file, а последнее означает, что file должен перезаписаться выводом программы. >>file означает, что в file будет добавлен вывод программы. Рассмотрим простейшие примеры (cat, кстати, команда для прочтения файла или stdin, если запущена без аргументов):

danlark@danlark:~$ echo hello >hello.txt
danlark@danlark:~$ cat hello.txt
hello
danlark@danlark:~$ cat <hello.txt # нет аргументов, просто запуск из stdin hello.txt
hello
danlark@danlark:~$ cat <hello.txt >hello2.txt
danlark@danlark:~$ cat hello2.txt
hello
danlark@danlark:~$ echo " world" >>hello2.txt
danlark@danlark:~$ cat hello2.txt
hello world

Также выход одной программы можно перенаправлять на вход другой через оператор pipe |, например:

danlark@danlark:~$ ls -l | head -n 3
total 250712
-rw-r-----  1 danlark primarygroup    110021 Jul 29 15:45 1_5zVzH8TuK1M-oxVnVEY1GA.png
-rw-r-----  1 danlark primarygroup    144485 Jul 29 15:57 2020-07-29-155724_1113x656_scrot.png

Или что-то более сложное:

danlark@danlark~$ curl --head -s google.com | grep -i content-length | cut --delimiter=' ' -f2
219

Последняя команда взяла header сайта google.com, поискала с помощью grep слово content-length в любом регистре и вывела 2-й токен с разделителем пробел.

Помните, что иногда в файлы нельзя ничего записать:

danlark@danlark:~$ touch hello.txt
danlark@danlark:~$ chmod 000 hello.txt
danlark@danlark:~$ echo hello >hello.txt
bash: hello.txt: Permission denied

Но для некоторых может стать удивлением, что в hello.txt нельзя записать с sudo:

danlark@danlark:~$ sudo echo hello >hello.txt
bash: hello.txt: Permission denied

Так происходит, потому что echo запускается с sudo, а >hello.txt это всего лишь перенаправление, которое контролируется самим bash. Чтобы избежать такого в будущем, стоит использовать sudo su, как писалось выше, или окружать полностью команду в sudo:

danlark@danlark:~$ sudo echo hello >hello.txt
bash: hello.txt: Permission denied
danlark@danlark:~$ sudo bash -c 'echo hello >hello.txt'
danlark@danlark:~$ sudo cat hello.txt
hello
danlark@danlark:~$ sudo cat <hello.txt
bash: hello.txt: Permission denied

Если Вы хотите исключить весь вывод, стандартным способом является перенаправление stdout >/dev/null.

Стоит отметить, что существует 2>file — это перенаправление stderr в file. Если Вы хотите полностью исключить любой вывод в консоль, лучший способ >/dev/null 2>/dev/null. А если Вам надо что-то поискать по stderr, можно его перенаправить в stdout с помощью 2>&1 | grep $your_token:

danlark@danlark:~$ man | grep you
What manual page do you want?
For example, try 'man man'.
danlark@danlark:~$ man 2>&1 | grep you
What manual page do you want?
danlark@danlark:~$ man 2>&1 >/dev/null | grep you
What manual page do you want?
danlark@danlark:~$ man 2>&1 2>/dev/null | grep you
What manual page do you want?
danlark@danlark:~$ man 2>/dev/null | grep you

Множество команд

Вы можете писать множество команд через &&, где часть справа выполнится только если часть слева корректно (с кодом возврата 0) завершилась:

danlark@danlark:~$ ls | head -n 5 && echo OK!
1_5zVzH8TuK1M-oxVnVEY1GA.png
2020-07-29-155724_1113x656_scrot.png
2020-07-29-163555_1585x422_scrot.png
2020-07-29-163646_1585x418_scrot.png
2020-07-29-163706_1582x421_scrot.png
OK!

Иногда Вы можете встретить команду &, она делает detach процесса — это значит, что процесс принадлежит терминалу (при его закрытии, он умрет), но shell этот процесс не блокирует, то есть другие команды выполнять можно. Чтобы быть уверенным, что Ваша команда выполнится в фоне, даже если закрыть терминал, можно использовать tmux (будет в конце лекции), либо использовать команду nohup:

danlark@danlark:~$ nohup ./server --port=1488 &

Всё, сервер работает и будет работать даже если закроете терминал.

Aliases

Если Вам не нравится печатать долго какую-то команду, то в bash можно выстраивать алиасы. А именно в Вашей home dir должен быть файл .bashrc, в котором можно в конце писать алиасы, которыми можно дальше пользоваться в bash:

alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'
alias lah='ls -lah'
alias lmao='touch all'

TAB completion

Когда Вы ходите по директориям или работаете в git, могут предоставляться так называемые tab-completions. Например, если я хочу пойти в какую-то директорию с префиксом Do, я пишу cd Do и жму TAB 1 или 2 раза и появляются варианты:

danlark@danlark:~$ cd Do
Documents/ Downloads/

И Вы можете видеть весь список предложенных. В итоге достаточно хорошим правилом является жать TAB примерно всегда, чтобы быстрее перемещаться по директориям или чтобы автодополнялись команды. К сожалению, в bash не самая лучшая поддержка tab-completion.

zsh, fish

Bash, к сожалению, достаточно ограничен в своём функционале. Существуют множество расширений shell, одни из самых примечательных — это oh my zsh и fish. Последний не совсем совместим с bash, поэтому для начала я рекомендую использовать просто oh my zsh.

Он лучше умеет дополнять по tab, умеет предлагать выборы при повторном нажатии tab. Одна из отличительных способностей этих shell — возможность искать по истории Ваших команд, когда в bash Вы только можете взять предыдущие команды, нажимая на стрелку вверх, например:

~ mv Down
# Нажимаю стрелку вверх~ mv Downloads/big_max_cost_flow.in .

И команда, которую я делал недавно, вывелась.

fish делает это умнее: выдаёт предложения исходя из частоты использования и т.д.

Мой совет — откажитесь от обычного bash и используйте zsh или fish. Чтобы их запускать при открытии терминала, существует один всегда работающий способ: в конце .bashrc добавить команду exec zsh или exec fish. В интернете полно туториалов по кастомизации этих терминалов, возьмите тот, который Вам нравится больше всего. У меня нет задачи заставить Вас пользоваться тем, чем я пользуюсь.

Пример установки и кастомизации zsh от TmLev.

tmux

tmux — отдельная утилита для шелла, которая рассчитана на мультиработу и хранение состояний терминалов. Например, каждый раз Вам надо открывать новый терминал, чтобы сделать что-то интересное, как ни странно, если Вы делаете какую-то долгую работу и отправляете машину в спящий режим, случайно закрываете терминал или сеть обрывается с сервером, то процесс остановится. tmux создан для решений этих проблем, он работает в фоне всегда путём сохранения state Ваших терминальных окон.

В tmux можно создавать сессии, в которых Вы работаете, сессии состоят из окон — это наборы терминалов, а окна из панелей — это отдельные обычные терминалы. Вот некоторые шорткаты, как работать с панелями:

  • Ctrl+b " — создать новую панель горизонтально от выбранной
  • Ctrl+b % — создать новую панель вертикально от выбранной
  • Ctrl+b arrow key — смена панели
  • Ctrl+b c — создание нового окна
  • Ctrl+b n — переключение на следующее окно
  • Ctrl+b p — переключение на предыдудщее окно
  • Ctrl+b w — показ всех сессий и окон и интерфейс для переключения
  • Ctrl+b ? — показ всех команд
  • Ctrl+d, exit — выход из панели, возвращение на предыдущую панель

Более подробный список команд можно найти здесь и здесь.

Полезные команды

  • cd, mkdir, touch, rm, pwd, ls — см. выше
  • sort, uniq — сортировка и вывод уникальных (вход должен быть отсортированным)
  • grep, cut — поиск по регулярному выражению (см. след лекцию) и сплит строк
  • head, tail — вывод первых и последних строк
  • wc — подсчёт количества байт, строк в файле и т.д.
  • df — статистика использованного места на машине
  • cat, tac — вывод файла с начала или с конца соответственно
  • echo — повторение аргументов
  • find — мощная команда для поиска в директории
  • chmod, chown, sudo — изменение permissions и овнеров, работа в режиме super user
  • Используйте перенаправления >, <, 2>, >>, 2>>, 2>&1, |. Вспомните, что каждое означает