Общие сведения
Бесполезно знакомиться с ОС, не имея её под рукой и регулярно не практикуясь. Поэтому первым делом необходимо POSIX-совместимой ОС обзавестись.
Это можно сделать одним из следующих образов:
- если у Вас на компьютере уже установлен какой-нибудь дистрибутив GNU/Linux — ничего делать не нужно
- если у Вас Mac OS или же FreeBSD (они не относятся к POSIX-совместимым ОС), при некотором желании можно пытаться использовать их, но некоторые вещи в них работают по-другому
- если у Вас Windows 10 или 11, то в нём достаточно включить WSL и установить на него какой-нибудь дистрибутив (рекомендуется Ubuntu LTS наиболее актуальной версии)
- если у Вас что-то другое, то нужно дополнительно установить на компьютер какой-нибудь дистрибутив Linux (например, Ubuntu LTS наиболее актуальной версии или же Arch Linux, к которому имеется очень обширная документация)
- если у Вас вообще нет ПК, а есть Android-устройство, то на них есть всякие POSIX-окружения, которые, хотя и не являются полноценными GNU-системами, всё равно вполне могут быть использованы
- если у Вас только iPhone или iPad, то, к сожалению, единственное, что остаётся — использовать какой-нибудь веб-сервис; например, replit даёт доступ к почти полноценному Linux-окружению
Интерпретатор команд
Интерпретатор команд (или, как его ещё называют, командная оболочка) — программа, соединённая стандартными потоками ввода/вывода с драйвером терминала, на вход которой пользователь подаёт команды, реализующие ту или иную функциональность ОС. Интерпретатор распознаёт эти команды и вызывает соответствующую функциональность ядра ОС.
Далее будут описаны только основы работы с интерпретатором bash (бывают и другие, но bash — де-факто стандартный интерпретатор в большинстве ОС).
Простейшие команды и запуск приложений
Наиболее простая форма команды для bash — просто последовательность слов, разделённых пробелами (количество пробелов между словами несущественно). Словом может являться произвольный текст, хотя некоторые слова нельзя ввести напрямую (например, нельзя напрямую ввести слово, содержащее пробел). Для ввода нетривиальных слов есть три механизма:
- Одинарные кавычки: то, что между ними, воспринимается как одно слово
- Двойные кавычки: некоторые символы и последовательности символов
между ними преобразуются в другие (это преобразование называется интерполяцией);
например, последовательность
\"
преобразуется в двойную кавычку (без обратной косой черты) - Конкатенация: два слова, записанных без пробелов между ними, объединяются;
например
"a\$b"waa'qq'"x"
— это словоa$bwaaqqx
Также важно помнить, что в рамках незакавыченных слов некоторые символы и их последовательности (как и внутри двойных кавычек) имеют специальный смысл, причём зачастую отличный от такового для двойных кавычек.
Последовательность слов bash интерпретирует следующим образом:
- если первое слово является одним из определённого набора зарезервированных слов или же названием одной из встроенных в bash функций, он выполняет действия, определённые семантикой соответствующего слова/функции
- если первое слово не содержит косых черт
/
, он ищет файл с таким названием в рамках одной из определённого набора папок (чем этот набор определяется, будет сказано немного ниже) и (в случае положительного результата поиска) запускает его - если же первое слово содержит
/
, bash считает это слово относительным или абсолютным путём к файлу; в случае наличия такого файла bash запускает его
Под запуском понимается следующее:
- если содержимое файла представляет собой один из форматов, которые ОС считает исполняемыми, bash создаёт потомка, процедура работы которого определяется тем, как ОС интерпретирует этот формат; при этом все слова команды передаются этому потомку при помощи механизма, позволяющего потомку их в случае надобности получить (слова команды называются аргументами командной строки; они нумеруются, начиная с нуля)
- если файл является текстовым и начинается со строчки вида
#!путь_к_файлу
, bash запускает указанный этим путём файл, передавая ему слова команды как аргументы командной строки
Поясним обе эти ситуации на примере. Предположим, что в системе установлен
интерпретатор языка Python, причём его исполняемая часть находится в файле
/usr/bin/python3
. Предположим также, что в текущей директории
находится файл foobar.py
с программой вида
import sys
print(sum(map(int,sys.argv[1:])))
Тогда команда
python3 foobar.py 1 2 3
приведёт к следующему:
- bash найдёт файл
python3
и запустит его, передав ему в качестве аргументов словаpython3
,foobar.py
,1
,2
,3
- файл
python3
представляет собой правильным образом обёрнутый машинный код с программой, интерпретирующей язык программирования Python; эта программа первый аргумент командной строки интерпретирует как название файла с программой на Python - в переменной
sys.argv
(языка Python) хранятся аргументы командной строки, начиная с первого; соответственно, программа вычислит значение выражения1+2+3
и напечатает его
Теперь командой chmod +x foobar.py
добавим хозяину файла (а также заодно —
всем остальным пользователям ОС) foobar.py
право его запускать. Также
допишем в начало этого файла комментарий:
#!/usr/bin/python3
После этого команда
./foobar.py 1 2 3
приведёт к следующему:
- поскольку ОС (скорее всего) откажется воспринимать текстовый файл как
исполняемый, bash посмотрит на его первую строчку, где написано
#!/usr/bin/python3
- bash выполнит команду
/usr/bin/python3 ./foobar.py 1 2 3
- далее всё произойдёт ровно так же, как и в предыдущем случае
Несколько простейших команд
Здесь мы приведём наиболее часто используемые команды (некоторые из них являются встроенными в bash, некоторые — отдельными исполняемыми файлами).
echo
— печатает свои аргументы, разделяя их пробелами, и заканчивая печать переходом на следующую строчкуecho -e
— интерпретирует некоторые экранирующие последовательности в своих аргментах (например,\n
как символ перехода на следующую строчку)echo -n
— не переходит на следующую строчкуecho -ne
илиecho -n -e
— совмещает два вышеописанных пунктаcat
— печатает друг за другом содержимое файлов, названия которых указаны в аргументахpwd
— текущий рабочий каталог для bashls
— его содержимоеls -a
— его содержимое, включая файлы, названия которых начинаются с точкиls -l
— содержимое с кучей подробностей~
— вообще говоря, не команда, а слово, которое, будучи незакавыченным, интерполируется в абсолютный путь к домашней папке пользователя*
— как и тильда, не команда, а слово, которое, будучи незакавыченным, интерполируется в содержимое текущей папкиcd
— смена текущей папки (если запустить без аргументов, то переходит в домашнюю папку)bash
— обычно используется с названием файла в качестве аргумента командной строки; выполняет все команды, записанные в файле, друг за другом в неинтерактивном режимеwhich
— для команд, соответствующих исполняемому файлу, показывает, какому именно файлу команда, поданная аргументом, соответствуетman
— стандартное средство просмотра документации; в качестве аргумента принимает название команды, документация к которой требуетсяinfo
— ещё одно средство просмотра документации; часть документации уinfo
свояless
— интерактивное средство просмотра текстовых файлов; выйти из него можно клавишейq
(ни Ctrl-C, ни Ctrl-D на него не работают)nano
— очень простой (и неудобный) текстовый редакторvi
илиvim
— один из лучших текстовых редакторов, существующих в природе (внимание: он обладает очень крутой кривой обучения)
Переменные окружения
В bash есть механизм переменных. У каждой переменной есть название — последовательность латинских букв и цифр, начинающаяся с буквы (при этом нижнее подчёркивание также считается буквой). Чтобы определить переменную, нужно написать
название_переменной=слово
Ключевой момент: между названием переменной, знаком =
и словом не должно
быть пробелов!
Далее значение этой переменной можно получить интерполяцией выражения
$название_переменной
. Здесь есть ещё один очень важный момент:
если интерполяция была произведена вне двойных кавычек, значение переменной
разбивается на отдельные слова. То есть, например, последовательность команд
foo="abc def"
cat $foo
печатает содержимое файлов abc
и def
, а не одного файла с названием abc def
.
Для достижения же последнего эффекта нужно дать команду cat "$foo"
.
Важно знать про следующие стандартные переменные:
PATH
— тут хранятся разделённые двоеточиями пути, в которых bash ищет исполняемые файлы0
,1
,2
,3
, и т.д. — аргументы командной строки (существенно, если bash запущен в неинтерактивном режиме)?
— код ошибки последней выполненной команды (равен 0, если команда завершилась без ошибок)
Перенаправление потоков
Когда команда запускается, её стандартные потоки ввода/вывода те же, что и у запустившей её оболочки. Но их можно изменить. Наиболее часто встречаются следующие варианты:
команда < foobar # на вход подаётся содержимое файла foobar
команда > foobar # выход записывается в новый файл foobar
команда >> foobar # выход дописывается в конец файла foobar
Также есть возможность объединить несколько команд в цепочку:
команда_1 | команда_2 | команда_3 | ... | команда_n
В такой цепочке стандартный выход каждой команды (кроме последней) связывается со стандартным входом следующей.
Ещё одно полезное средство — интерполяция стандартного выхода: если
команду взять в обратые кавычки (те, что ставятся клавишей с тильдой),
это выражение преобразуется в тот текст, который взятая в обратные кавычки команда
напечатает. Опять же, как и с интерполяцией переменных, если не взять
такое выражение в двойные кавычки, его значение будет разбито на отдельные слова.
Если хочется интерполировать результат работы нескольких команд, их
можно разделить точкой-с-запятой ;
. Например, так:
echo "`echo a; echo b`"
Полезные возможности
Стрелками вверх/вниз можно перематывать историю команд.
По кнопке Tab происходит автодополнение текущей команды. В современных версиях bash механизм автодополнения довольно продвинутый: он учитывает особенности большинства распространённых приложений.