Типы командных оболочек. Инициализация bash - bashrc и bash_profile
Командные оболочки по типам могут рассмартиваться относительно их интерактивности:
- interactive shell - интерактивный шелл (интерактивная командная оболочка)
- non-interactive shell - не интерактивный шелл (не интерактивная командная оболочка)
И по наличию полноценного входа в систему:
- login shell - шелл (командная оболочка) с полноценным авторизованным входом в систему
- non-login shell - шелл (командная оболочка) без полноценного входа в систему
- interactive shell или интерактивная оболочка - это оболочка, в которой пользователь может вводить команды с клавиатуры и получать вывод этих команд на экран.
- non-interactive shell или не интерактивная оболочка - это оболочка, которая не позволяет вам вводить команды с клавиатуры в интерактивном режиме. Это могут быть собственные скрипты, или скрипты, запущенные через cron, или это может быть вызов команд через ssh без получения интерактивного шелла.
Отличие интерактивного от не интерактивного
- Интерактивный шелл имеет возможностью постоянного общения через выбранную оболочку с операционной системой и возможностью выполннения необходимых команд в интерактивном режиме (т.е. с возможностью ожидания ввода с клавиатуры).
- Не интерактивный вариант шелла используется для выполнения скриптов "в фоне" без участия человеческой руки.
- login shell или оболочка со входом в систему - это оболочка, при которой пользователь проходит этап аутентификации и авторизации. То есть, по сути, это первый вход в систему по ssh или через консоль с помощью подключенной клавиатуры. Его можно также назвать сессионным или главным шеллом.
Когда пользователь пытается подключиться к операционной системе, вызывается работа специальной утилиты под названием /bin/login, после успешной проверки аутентификационных данных (например username, password) проводится поиск утилиты, которая должна предоставлять интерфейс взаимодействия с операционной системой. Для этого считываются данные из файла /etc/passwd. Как вы должны помнить из практикума по Linux, в файле /etc/passwd напротив имени пользователя в конце строки будет указан путь к приложению, которое должно запускаться при входе пользователя в операционную систему. Обычно, это наш шелл, например: /bin/bash. Поэтому его и называют login shell. Естественно, это может быть любая утилита, не обязательно шелл (но это уже совсем другая история).
Как вызвать login shell?
- Оболочка login shell создаётся при каждом новом входе в систему:
- terminal (терминальный вход)
- X-11 (графический вход)
- Оболочка login shell также создаётся при подключении через ssh:
- ssh root@serverIP
- оболочка login shell может быть создана явным указанием на вход в систему
- sudo -i
- su -
- su -l
- su –login
- su - username
- su -l username
- su –login username
Чтобы понять, в какой оболочке вы находитесь, нужно выполнить команду:
echo $0
Если в выводе будет присутствовать имя оболочки, перед которой стоит дефис (dash), то значит это login shell. Примеры вывода: -bash, -zsh, -csh, -su Если же дефиса (dash) нет, то эта оболочка –> non-login shell
- non-login shell или оболочка без входа в систему - это оболочка, которая запускается внутри другой оболочки, пользователь которой уже прошел аутентификацию. К примеру, вы можете запустить второй bash внутри существующей сессии, и он будет non-login interactive shell.К примеру, вы можете запустить второй bash внутри существующей сессии, и он будет non-login interactive shell. Такой non-login shell может быть вызван следующими способами:
- Вызывая non-login shell из login shell
- Выполняя скрипты из терминала
- Используя вызов графических терминалов
В зависимости от того, какой тип шелла используется, система будет вызывать различные скрипты для инициализации пространства (окружения) пользователя.
BASH
etc/profile - основной файл для настройки окружения пользователя. Этот файл вызывается только в interactive login shell. Внутри него вызывается проверка используемого шелла и подключается /etc/bash.bashrc в случае использования bash. Помимо этого данный скрипт считывает все файлы из /etc/profile.d/ и поочередно вызывает каждый из них.
/etc/bash.bashrc - как указывалось выше, данный файл будет выполнен скриптом /etc/profile. Но также этот файл будет вызван напрямую при использовании любого типа шелла - interactive / non-interactive / login / non-login.
Единственное, на что стоит обратить внимание, в самом начале этого скрипта встречается конструкция:
# If not running interactively, don't do anything [ -z "$PS1" ] && return
Данная конструкция проверяет, вызывается ли шелл интерактивно или нет (это первый из способов определения интерактивности - вывод переменной $PS1 не должен быть пустым). Во втором случае обработка будет прервана. Это следует учитывать при добавлении различных переменных для крон скриптов - в не интерактивном шелле они просто не будут применены.
~/.bash_profile - пользовательский файл, который запускается в первую очередь (если существует) при использовании login interactive shell.
~/.profile - локальный пользовательский файл, который не запустится, если существует .bash_profile. Он вызывается только для login shell. Его основная задача - подключить ~/.bashrc, который настроит bash для пользователя.
~/.bash_logout - пользовательский файл, который будет вызван при закрытии login shell пользователем.
~/.bashrc - локальный пользовательский файл, который настраивает рабочее окружение, специфичное для данного пользователя. Если все предыдущие файлы были системными - то есть исполнялись для всех пользователей, то данный файл будет для каждого пользователя различным. В нем также используется конструкция, которая прерывает выполнение в случае использования не интерактивного логин шелла:
# If not running interactively, don't do anything case $- in *i*) ;; *) return;; esac
На заметку! Код выше - это еще один из вариантов проверки наличия интерактивности вашего шелла.
Если посмотреть на это со стороны команд, то выглядеть это будет вот так:
bash echo $0 bash echo $- himBHs
$- настройки выставленных опций (параметров) вашего bash-шелла. В выводе информации из $-может присутствовать опция -i - interactive, которая покажет, что данный шелл является интерактивным.
*interactive login shell**
- LOGIN вызывает /etc/profile
- → /etc/profile вызывает /etc/bash.bashrc
- → /etc/profile последовательно вызывает cкрипты в /etc/profile.d/
- → LOGIN вызывает ~/.bash_profile . Если его нет, то вызывает ~/.profile
- → ~/.bash_profile или ~/.profile вызывает ~/.bashrc
- → ~/.bashrc вызывает ~/.bash_aliases
ZSH
В zsh опций гораздо больше, но -i тоже присутствует:
echo $0 -zsh echo $- 569JNRXZghikms
~/.bash_profile - пользовательский файл, который запускается в первую очередь (если существует) при использовании login interactive shell. ~/.profile - локальный пользовательский файл, который не запустится, если существует .bash_profile. Он вызывается только для login shell. Его основная задача - подключить ~/.bashrc, который настроит bash для пользователя. ~/.bash_logout - пользовательский файл, который будет вызван при закрытии login shell пользователем.
Теперь конкретно по последовательности вызова скриптов процессом, предоставляющим доступ к системе (назовем его LOGIN). Для interactive login shell:
interactive login shell
- → LOGIN вызывает /etc/profile
- → /etc/profile вызывает /etc/bash.bashrc
- → /etc/profile последовательно вызывает cкрипты в /etc/profile.d/
- → LOGIN вызывает ~/.bash_profile . Если его нет, то вызывает ~/.profile
- → ~/.bash_profile или ~/.profile вызывает ~/.bashrc
- → ~/.bashrc вызывает ~/.bash_aliases
interactive non-login shell
Для interactive non-login shell схема по проще, ввиду того, что осуществлять вход в систему ненужно, поэтому запускающий процесс будем называть shell:
- → shell вызывает /etc/bash.bashrc
- → shell вызывает ~/.bashrc
- → ~/.bashrc вызывает ~/.bash_aliases
Для non-interactive non-login shell схема такая же, как и для interactive non-login shell, но есть один нюанс, в файлах /etc/bash.bashrc и ~/.bashrc нужно убрать ограничение [ -z "$PS1" ] && return. Это можно осуществить через комментарий или просто удалив строку:
# If not running interactively, don't do anything # [ -z "$PS1" ] && return
Ну или указывать то, что вы хотели бы выполнить, до объявления вышеуказанного блока.