- Вопрос или проблема
- Предыстория:
- Проблема:
- Вопросы:
- Ответ или решение
- Проблема исполнения скриптов в /etc/profile.d дважды в CentOS 7
- Введение
- Причина проблемы
- Ответы на вопросы
- 1. Является ли это багом в CentOS 7?
- 2. Есть ли хороший обходной путь для установки глобальных настроек окружения без их двойного исполнения?
- Заключение
Вопрос или проблема
Предыстория:
Я пытаюсь настроить сервер Linux с CentOS 7 для нескольких пользователей. После установки Java я хочу глобально установить переменную среды $JAVA_HOME
для всех пользователей и добавить ее в $PATH
.
Для этого я открыл скрипт /etc/profile
, который вызывается при старте системы. Я следовал совету в начале скрипта:
# НЕ рекомендуется изменять этот файл, если вы не знаете, что делаете.
# Намного лучше создать собственный shell-скрипт custom.sh в
# /etc/profile.d/, чтобы внести изменения в окружение, так вы
# предотвратите необходимость объединения в будущих обновлениях.
Я создал собственный скрипт /etc/profile.d/custom.sh
для настройки окружения для Java
custom.sh
# Конфигурация Java
export JAVA_HOME=/usr/lib/jvm/java
export PATH=${JAVA_HOME}/bin:${PATH}
Проблема:
Каждый раз при входе в систему, скрипт /etc/profiles.d/custom.sh
(вместе с любыми другими скриптами, которые я помещаю в /etc/profiles.d
) вызывается дважды и добавляет $JAVA_HOME
в $PATH
дважды.
Я понял, что это происходит потому, что все скрипты в /etc/profiles.d
вызываются как из /etc/profile
, так и из /etc/bashrc
.
# Это есть как в /etc/profile, так и в /etc/bashrc
for i in /etc/profile.d/*.sh ; do
if [ -r "$i" ]; then
if [ "${-#*i}" != "$-" ]; then
. "$i"
else
. "$i" >/dev/null
fi
fi
done
Это действительно кажется неправильным, но я провел исследование и оказалось, что это просто так работает…
Вопросы:
-
Является ли это ошибкой в операционной системе CentOS 7?
-
Есть ли хороший обходной путь, который я могу использовать для создания глобальных настроек окружения без их двойной установки? (Я не хочу устанавливать их в
/etc/environment
, потому что не могу использовать bash-переменные в этом файле.)
Последние 6 месяцев я запускал сотни серверов с CentOS 7, настраивая их разными способами, и я никогда не сталкивался с тем, о чем вы говорите.
Как сказал Томас, по умолчанию, /root/.bashrc не вызывает скрипты из /etc/profile.d.
ИСПРАВЛЕНИЕ:
На самом деле, /root/.bashrc ДЕЙСТВИТЕЛЬНО вызывает /etc/prodile.d/* через /etc/bashrc и предотвращает вывод echos:
# Показывать echos из скриптов profile.d только если мы не входим в локальную оболочку
# и интерактивны - иначе просто выполняем их для установки переменных окружения
for i in /etc/profile.d/*.sh; do
if [ -r "$i" ]; then
if [ "$PS1" ]; then
. "$i"
else
. "$i" >/dev/null
fi
fi
done
Полагаю, мои недавние проблемы были другими, которые нужно было решить быстро и я не углубился в них достаточно. Прошу прощения.
СТАРЫЙ ОТВЕТ
1/ Я думаю, это действительно не ошибка (какой ISO вы получили для своего CentOS 7? Вы вычисляли md5sum? Задавая этот вопрос, я сам чувствую себя странно)
2/ и в таком случае нет обходного пути, кроме как удалить код, который вызывает скрипты дважды?
/etc/profiles.d кажется правильным местом для размещения скриптов, если они “молчат”, то есть определяют некоторые переменные окружения, но не выводят echo или вызывают какой-нибудь динамический motd, или это будет взаимодействовать с другими скриптами, которые вы запустите (у меня был опыт с установкой netdata недавно).
Некоторые интересные моменты для чтения на unix.stackexchange.
Ответ или решение
Проблема исполнения скриптов в /etc/profile.d дважды в CentOS 7
Введение
В процессе настройки сервера на базе CentOS 7 для нескольких пользователей возникла необходимость глобально задать переменную окружения $JAVA_HOME
для всех пользователей и добавить ее в $PATH
. Это было выполнено путем создания скрипта /etc/profile.d/custom.sh
, который выполняется при входе в систему, подобно другим скриптам в этой директории.
Но возникла проблема: скрипты из /etc/profile.d
выполняются дважды при каждом входе в систему, что приводит к двойному добавлению пути $JAVA_HOME
в $PATH
.
Причина проблемы
Эта ситуация вызвана тем, что скрипты из /etc/profile.d
вызываются как из /etc/profile
, так и из /etc/bashrc
. Оба эти файла содержат цикл, исполняющий все доступные скрипты в /etc/profile.d
:
for i in /etc/profile.d/*.sh ; do
if [ -r "$i" ]; then
if [ "${-#*i}" != "$-" ]; then
. "$i"
else
. "$i" >/dev/null
fi
fi
done
За счет этого при каждом входе в систему интерактивной оболочкой их исполнение дублируется.
Ответы на вопросы
1. Является ли это багом в CentOS 7?
Это не считается багом в ОС CentOS 7. Это скорее архитектурная особенность работы профилей и bashrc в системе. Несмотря на потенциальную неудобность, такое решение оставляет на усмотрение пользователей выполнение необходимых изменений в конфигурации.
2. Есть ли хороший обходной путь для установки глобальных настроек окружения без их двойного исполнения?
Существует несколько методов для устранения проблемы двойного исполнения скриптов:
Предотвращение двойного импорта:
Вы можете модифицировать свои скрипты в /etc/profile.d/
, добавив проверки на дублирующее определение переменных. Например:
# Java configuration
if [[ -z "$JAVA_HOME" ]]; then
export JAVA_HOME=/usr/lib/jvm/java
export PATH=${JAVA_HOME}/bin:${PATH}
fi
Оптимизация через корректировку файла /etc/bashrc:
Если проблема не разрешается, и вам не требуется запуск скриптов в /etc/profile.d
для всех пользователей, можно изменить одно из мест вызова этих скриптов. Но это требует внимательности — изменения могут повлиять на всех пользователей и новые сессии.
Заключение
Скрипты в директории /etc/profile.d
предназначены для глобальных настроек и исполняются всеми пользователями. Они позволяют организовывать настройки, не меняя основной файл /etc/profile
. Решение проблемы двойного исполнения чаще заключается в правильной организации самих скриптов, для корректной работы с логикой допускается использование bash-кода, что предотвращает неожиданные результаты.
Надеюсь, это руководство поможет вам лучше справиться с настройками вашей системы и достичь нужных результатов.