Рейтинг@Mail.ru

Наши друзья и партнеры

UnixForum
купить дешевый 
компьютер родом из Dhgate.com


Книги по Linux (с отзывами читателей)

Библиотека сайта rus-linux.net

Исследуем процесс загрузки Linux

(C) В.А.Костромин, 2007
(версия файла от 21.08.2007 г.)


Назад Оглавление Вперед

Этап 9: Старт оболочки Bash

Итак, демон getty запустил программу login, которая выводит предложение ввести имя пользователя (рис.3). Получив это имя, login обращается к файлу /etc/passwd за получением необходимых данных об этом пользователе, в частности, о его идентификаторе, идентификаторе группы, домашнем каталоге и о том, какую оболочку для него запускать. Одновременно выводится запрос на ввод пароля пользователя.
Когда пользователь введет пароль, программа login считывает его, криптует и сравнивает результат с тем, что лежит в соответствующей строке файла etc/shadow.

Если пользователь ввел правильный пароль, программа login, наконец, запускает командный процессор (оболочку). Как уже было сказано, какую именно оболочку запускать (ибо тут возможен довольно широкий выбор), определяется соответствующим полем в файле /etc/passwd.

Поскольку наиболее часто применяемым вариантом командной оболочки является bash, в дальнейшем будем рассматривать именно процесс загрузки этой программы (могу честно признаться, что главным основанием выбора этого варианта является то, что у меня используется именно эта оболочка и с другими я не работал).

9.1. Регистрационный shell

Теперь необходимо пояснить, что оболочка bash может запускаться в нескольких различных режимах. Рассказывать здесь полностью о том, чем режимы различаются, нет возможности, для этого загляните в man bash. Здесь же скажем только, что тот режим, который используется при запуске через программу login, называется режимом "интерактивного регистрационного shell или login shell" . Интерактивность в данном случае означает, что оболочка взаимодействует со стандартными потоками ввода-вывода, то есть стандартный входной и выходной потоки оболочки подключены к терминалу (просто существует и неинтерактивный режим запуска оболочки, например, для выполнения какого-то скрипта в фоновом режиме).

В случае запуска в режиме "login shell" процесс, в котором запускается оболочка, имеет тот же идентификатор, что и начальный getty-процесс, и является процессом, возглавляющим группу процессов. Чтобы убедиться в этом (вы же не обязаны верить мне на слово), выполните команду ps –axf, затем перейдите в свободную виртуальную консоль, запустите там программу Midnight Commander, вернитесь в ту консоль, где вы работали и снова запустите ps –axf. Сравнив вывод этой команды в первом и втором случае, вы увидите, что еще один процесс getty заменился на shell, причем из этой оболочки запущена команда mc.

В зависимости от режима запуска bash использует немного различные настроечные файлы. Какие именно из этих файлов используются в том или ином режиме запуска, рассказано в man bash (русский перевод этого руководства есть здесь). Я не буду приводить здесь описание всех вариантов, ограничусь только тем, который нас в данном случае интересует.

9.2. Запуск регистрационного экземпляра оболочки bash

При вызове bash в режиме интерактивного регистрационного интерпретатора команд, bash сначала читает и выполняет команды из файла /etc/profile, если этот файл существует. После прочтения этого файла, он последовательно ищет файлы ~/.bash_profile, ~/.bash_login и ~/.profile, читает и выполняет команды из первого же из них, который существует и доступен на чтение.

Давайте рассмотрим эти файлы из системы Mandriva Free 2007.1 и на этом примере разберем процесс загрузки оболочки bash в варианте регистрационного интерпретатора команд ("login shell").

Листинг 16. Файл /etc/profile системы Mandriva Free 2007.1.

# /etc/profile -*- Mode: shell-script -*- 
# (c) MandrakeSoft, Chmouel Boudjnah <chmouel@mandrakesoft.com>

loginsh=1

if [ "$UID" -ge 500 ] && ! echo ${PATH} |grep -q /usr/games ; then
    PATH=$PATH:/usr/games
fi

umask 022

USER=`id -un`
LOGNAME=$USER
MAIL="/var/spool/mail/$USER"
HISTCONTROL=ignoredups
HOSTNAME=`/bin/hostname`
HISTSIZE=1000

if [ -z "$INPUTRC" -a ! -f "$HOME/.inputrc" ]; then
    INPUTRC=/etc/inputrc
fi

# some old programs still use it (eg: "man"), and it is also
# required for level1 compliance for LI18NUX2000
NLSPATH=/usr/share/locale/%l/%N

export PATH PS1 USER LOGNAME MAIL HOSTNAME INPUTRC NLSPATH
export HISTCONTROL HISTSIZE 

for i in /etc/profile.d/*.sh ; do
	if [ -r $i ]; then
		. $i
	fi
done

unset i
Как видите,
  • вначале задается переменная loginsh, которая должна свидетельствовать о том что это именно "login sheell".
  • Далее проверяется, что пользователь не является привилегированным и если это так, то в число путей поиска добаляется каталог /usr/games (простому пользователю разрешается поиграть!).
  • Переменной umask присваивается значение 022, что означает что создаваемые данным пользователем файлы по умолчанию будут заданы права доступа ???
  • Задаются значения переменных:
    USER=`id -un`  
    LOGNAME=$USER        		# переменным  USER и LOGNAME присваивается имя пользователя;
    MAIL="/var/spool/mail/$USER"    # переменной MAIL присваивается имя каталога, 
    				# где будет храниться почта данного пользователя;
    HISTCONTROL=ignoredups		# если я правильно понимаю английский, будем 
    				# игнорировать повторы в истории команд; 
    HOSTNAME=`/bin/hostname`        # мне почему-то кажется, что где-то раньше мы эту 
    				# переменную уже задавали
    HISTSIZE=1000  			# задаем число команд, которые будут храниться в истории команд.
    
  • Если переменная INPUTRC имеет нулевую длину и (-a) файл $HOME/.inputrc не является простым файлом (то ли его не существует, то ли это сылка), то переменной INPUTRC присваивается значение /etc/inputrc.
  • Для некоторых старых программ (например, man) требуется задать переменную NLSPATH=/usr/share/locale/%l/%N
  • Экспортируются значения всех заданных переменных, чтобы они были доступны для всех процессов, запускаемых из данного экземпляра оболочки.
  • Ну, и наконец, запускаются на выполнение все скрипты (файлы с расширением .sh) из каталога /etc/profile.d/, если только такие файлы существуют и для них установлено право на чтение.
В моей системе в каталоге /etc/profile.d/ файлов с расширением .sh нашлось 19 штук (и еще примерно столько же - срасширением .csh). Немного поразмыслив я решил не включать их все в основной текст заметки, а привести в виде отдельного приложения. Если мы просмотрим это приложение, то увидим, что скрипты из /etc/profile.d/ выполняют следующие задачи:
  • - устанавливаются параметры локализации (скрипт 10lang.sh);
  • - задаются общесистемные алиасы (скрипт alias.sh); причем вначале проверяется, не отказался ли пользователь от использования общесистемных алиасов; между прочим, среди этих общесистемных алиасов есть очень интересные, загляните в этот список в вашей системе и, возможно, вы будете использовать сокращенные написания некоторых часто употребляемых команд;
  • - настройки клавиатуры немного изменяются в зависимости от аппаратной архитектуры (скрипт configure_keyboard.sh);
  • - задаются установки, связанные с безопасностью (скрипт msec.sh);
  • - создается директория для временных файлов (если ее не было) и указание на нее запоминается в переменной TMPDIR (скрипт tmpdir.sh);
  • - корректируется поведение клавиши NumLock (скрипт numLock.sh);
  • - значения многих переменных сразу после их задания экспортируются.
и так далее.

Как было сказано в начале этого раздела, после общесистемного файла /etc/profile оболочка bash последовательно ищет файлы ~/.bash_profile, ~/.bash_login и ~/.profile и выполняет команды из этих файлов. Файлов ~/.bash_login и ~/.profile в моей системе не нашлось, а файл ~/.bash_profile приведен в листинге 36:

Листинг 36. Файл ~/.bash_profile системы Mandriva Free 2007.1.

# .bash_profile

# Initialize keychain if needed
if [ -r $HOME/.ssh/identity -o -r $HOME/.ssh/id_dsa -o -r $HOME/.ssh/id_rsa ]; then
 	if [ ! -d $HOME/.keychain ]; then
	        keychain
        fi
fi

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
	. ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/bin

export PATH
unset USERNAME
Как видите в этом скрипте корректируется переменная PATH (в список путей для поиска добавляется каталог ~/bin) и вызывается на выполнение еще один скрипт - ~/.bashrc, причем комментарий к этому вызову сообщает, что тем самым снова задаются алиасы и функции. Впрочем, как видно из листинга 37, в самом вызываемом скрипте мало что задается - он всего лишь содержит вызов общесистемного скрипта /etc/bashrc (см. листинг 38).

Листинг 37. Файл ~/.bashrc системы Mandriva Free 2007.1.

# .bashrc

# User specific aliases and functions

# Source global definitions
if [ -f /etc/bashrc ]; then
	. /etc/bashrc
fi

Листинг 38. Файл /etc/bashrc системы Mandriva Free 2007.1.

# /etc/bashrc

# System wide functions and aliases
# Environment stuff goes in /etc/profile

# by default, we want this to get set.
# Even for non-interactive, non-login shells.
if [ "`id -gn`" = "`id -un`" -a `id -u` -gt 99 ]; then
	umask 002
else
	umask 022
fi

# are we an interactive shell?
if [ "$PS1" ]; then
    case $TERM in
	xterm*)
	    PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"'
	    ;;
	*)
	    ;;
    esac
    [ "$PS1" = "\\s-\\v\\\$ " ] && PS1="[\u@\h \W]\\$ "
    
    if [ -z "$loginsh" ]; then # We're not a login shell
	# Not all scripts in profile.d are compatible with other shells
	# TODO: make the scripts compatible or check the running shell by
	# themselves.
	if [ -n "${BASH_VERSION}${KSH_VERSION}${ZSH_VERSION}" ]; then
            for i in /etc/profile.d/*.sh; do
	        if [ -x $i ]; then
	            . $i
	        fi
	    done
	fi
    fi
fi

unset loginsh

На этом загрузка интерактивного регистрационной оболочки завершена и пользователь может работать в системе. При этом он получает окружение, сформированное перечисленными файлами скриптов.

Отмечу, что если в Mandriva файла ~/.profile не оказалось, то в системе OpenSUSE 10.2 от существует. В комментариях внутри этого файла говорится, что этот файл прочитывается, то есть вызывается на выполнение каждый раз, когда стартует регистрационный шелл. Все другие интерактивные оболочки вызывают только файл ~/.bashrc.

Еще раз приведем список файлов, оказывающих влияние на то, какую именно конфигурацию оболочки мы получим после запуска. Этот список выглядит примерно следующим образом:

/etc/passwd
Глобальный файл, содержащий регистрационную информацию о пользователе

/etc/shadow
Глобальный файл паролей;

/etc/profile
Общесистемный файл инициализации (файл профилей), выполняется начальными командными интерпретаторами. Устанавливает общесистемную переменную $PATH и другие важнейшие переменные; заглянув в него, вы увидите, что в нем вызываются все файлы из подкаталога /etc/profile.d, в частности, файл, задающий параметры локализации системы;

/etc/bashrc
Глобальный файл конфигурации bash, устанавливает синонимы (алиасы) и функции, и т.п.;
/etc/issue
Содержит сообщение, выдаваемое на терминал перед входом в систему (перед запросом имени и пароля); однако редактировать этот файл с целью изменения текста сообщения не стоит, потому что сам он формируется инициализационным скриптом /etc/rc.d/rc.local;
/etc/motd
Устанавливает сообщение, выдаваемое пользователю после входа в систему (после правильного ввода пароля).
~/.bash_profile
Личный файл инициализации (файл личного профиля), выполняется начальными командными интерпретаторами
~/.bashrc
Отдельный файл начального запуска для интерактивных командных интерпретаторов
~/.inputrc
Отдельный файл инициализации библиотеки readline
~/.profile
Личный файл инициализации (файл личного профиля), выполняется начальными командными интерпретаторами

Если вы что-то хотите поменять в той конфигурации, которую получаете при входе в систему, то, очевидно, имеет смысл подкорректировать ваш личный файл профиля ~/.bash_profile или файл ~/.bashrc.


Примечание: При завершении работы в качестве начального командного интерпретатора bash читает и выполняет команды в файле ~/.bash_logout, если он существует. В моем случае файл этот оказался на удивление простым (листинг 39):

Листинг 39. Файл ~/.bash_logout системы Mandriva Free 2007.1.

# ~/.bash_logout

clear

Назад Оглавление Вперед

Если вам понравилась статья, поделитесь ею с друзьями: