Skip to content

Latest commit

 

History

History
539 lines (436 loc) · 33.2 KB

README.md

File metadata and controls

539 lines (436 loc) · 33.2 KB

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

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

Как инженеры мы знаем, что компьютеры отлично справляются с вычислительными задачами. У нас есть широкий спектр инструментов, которые позволяют нам быть более продуктивными и решать более сложные задачи при работе над любыми проблемами, которые так или иначе что-то выполняют. Однако многие из нас используют лишь малую часть этих инструментов: мы знаем достаточно магических заклинаний только наизусть, и слепо копируем команды из 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, |. Вспомните, что каждое означает