Bash. Part 2

Wednesday, October 20 2021

Bash. Part 2

Процес запуска bash

Было бы странно предполагать, что bash запускается одинаково, статично и без кучи настроек как, например, при входе в систему, так и при простом открытии терминала. Или просто запускается без всего выше перечисленного. Почитав статьи с примерами, или пообщавшись с unixоидами, почти наверняка можно заметить, что у каждого терминал выглядит по-своему (даже если не брать возможное отличие shell). Каждый настраивает sh как ему удобно, отображая нужную информацию в удобном виде, и все это делается в нескольких startup файлах. Подробнее о конфигурациях я напишу в другой статье, а лишь укажу какие из них считываются при каком запуске. Итак:

Запуск интерактивного логин shell или с параметром ‘–login’

Интерактивного - значит что вы можете вводить команды.

Q: Как узнать, является ли мой *shell* интерактивным?
A: echo $-  
Если в выводе есть "i" - значит интерактивный

Логин - значит, вы получите доступ к shell только после авторизации, например логином и паролем.

‘~’ в начале пути означает, домашний каталог;
'/' в начале пути означает, root каталог на диске системы;
‘.’ - текущий каталог;
‘.’ часто файлы, которые начинаются с точки являются “скрытыми”;

Startup файлы, которые считываются:

  • /etc/profile (глобальные настройки, общие для всех пользователей);

  • ~/.bash_profile, ~/.bash_login or ~/.profile: считывается первый существующий файл. Настройки индивидуальные для каждого пользователя. Стоит обратить внимание, что они лежат в домашней директории пользователя;

  • ~/.bash_logout перед logout. Тоже является индивидуальным для каждого пользователя.

Bash покажет, если в процессе считывания произошла ошибка, однако если этих фала не существует (они не обязательны), то bash продолжит искать следующий по цепочке.

Запуск интерактивного shell без логина

Как следует из описания, авторизироваться не нужно. Для примера: когда вы открываете, терминал с помощью иконки просто набрав bash в текущем shell, то открывается именно non-login shell.

В этом случае настройки читаются из файла ~/.bashrc, который очень часто ссылается на знакомый нам ~/.bash_profile. if [ -f ~/.bashrc ]; then . ~/.bashrc; fi

Запуск не интерактивной оболочки

Все скрипты являются не интерактивными shells. Они делают только то, для чего написаны и не могут выполнить работу, для которой не запрограммированы.

Настройки читаются из файла, который объявлен в глобальной переменной BASH_ENV (про переменные чуть позже).

Кстати, на заметку:

PATH is not used to search for this file, so if you want to use it, best refer to it by giving the full path and file name.

Запуск с помощью *sh*

Отдавая дань уважения sh, на которой он построен, и ,собственно, потому что он на sh построен, bash старается (очень) работать как sh, но и отвечая при этом стандартам POSIX.

Читаются файлы:

  • /etc/profile
  • ~/.profile

При запуске в интерактивном режиме, переменная ENV может указывать на дополнительную startup информацию.

Запуск в POSIX mode

Сейчас может быть не понятно! Начинающему пользователю не нужно знать это на данном этапе. Просто запомните, что такое есть.

Эту опцию можно включить, используя стандартный set: set -o posix

или вызвав bash с параметром —posix. Bash будет вести себя (честно!) как можно ближе к стандартам POSIX. Этого же можно добиться, присвоив переменной POSIXLY_CORRECT значение АГА

При запуске читается файл, который находится по пути описанному в переменной ENV

Запуск удаленно

При запуске с помощью rshd читается файл настроек ~/.bashrc

Лучше не использовать rlogin, telnet, rsh, rcp, потому что данные, передаваемые с их помощью являются не зашифрованными

Выполнение команд

Bash определяет тип программы, которая должна быть выполнена. Обычно программы - это системные команды, которые существуют в скомпилированой форме в системе. Когда такая программа запускается, создается новый процесс, т.к. bash делает копию самого себя. Этот процесс-наследник имеет ту же среду выполнения, что и наследник, но с другим processID. Этот процесс называется forking.

После того, как форк был создан, адрессное пространство нового процесса переписывается новой инфрормацией из нужной команды. Это и происходит во время вызова команды exec.

Процесс fork-and-exec заменяет старую команду на новую, сохраняя при этом идентичую среду выполениня, включая конфигурации устройств ввода и вывода, переменные и приоритеты. Этот механизм используется для создания всех процессов в UNIX. Даже первый процесс, init, который имеет process ID 1 форкается в во время загрузки в так называемой bootstrapping процедуре.

Built-in комманды

Shell содержит в себе так называемые built-in или “встроенные” команды. Когда такая команда используется первым словом в веденной пользователем простой команде, shell выполняет команду “в себе”, без forkа, т.е без создания нового процесса.

Bash поддерживает три типа built-in команд:

  • Sh built-in команды: :, ., break, cd, continue, eval, exec, exit, export, getopts, hash, pwd, readonly, return, set, shift, test, [, times, trap, umask and unset.;

  • Bash built-in команды:alias, bind, builtin, command, declare, echo, enable, help, let, local, logout, printf, read, shopt, type, typeset, ulimit and unalias.

  • Специальные built-in команды. Отличаются от других при запуске bash в POSIX-mode тем, что:

    • Эти команды ищутся интерпретатором перед остальными built-in командами;
    • Если специальная built-in команда возвращает ошибку, то не интерактивная оболочка закрывается;
    • Операторы присваивания перед командой остаются в силе в среде оболочки после завершения работы этой команды.

    The POSIX special built-ins:, ., break, continue, eval, exec, exit, export, readonly, return, set, shift, trap and unset;

Запуск скриптов

Если запущенная программа является shell скриптом, bash создаст новый bash процесс использя fork метод. Это subshell будет читать построчно файл скрипта. Команды в каждой строке после прочтения интерпретируются и выполняются так, как и в случае простого ввода с клавиатуры.

Запустить скрипт, не создавая процесс можно с помощью команды source. Она является чем-то вроде . для shell. Тогда скрипт выполнится в текущем shell

Пока subshell читает скрипт построчно, родительский shell ждет окончания этого процесса. Если subshell достигнул конца файла и не осталось непрочтенных строк, то он закрывается, возвращая родителю контроль, а родитель выводит новый prompt.


Ну а что такое prompt и как его настраивать, я расскажу в следующей статье.


Ссылки

Про bash (Arch Documentation. Куда же без нее)