Вопрос или проблема
В данный момент, когда я открываю терминал на своем Mac, он автоматически вызывает:
source ~/.bash_profile
.
Меня, однако, озадачивает тот факт, что моя оболочка, похоже, не унаследовала никакого содержимого из ~/.bashrc
или ~/.profile
. Но это может быть типично.
У меня есть несколько скриптов, которые нужно загружать с помощью source
или .
; если я помещаю эти вызовы в ~/.bash_profile
, загрузка нового окна оболочки может занять некоторое время, иногда 3 или 4 секунды, и это становится утомительным. Я предполагаю, что существует способ загрузить эти скрипты лишь один раз и сделать так, чтобы мой файл ~/.bash_profile
каким-то образом наследовал это.
Обратите внимание, что вызов source ~/.bashrc
или source ~/.profile
из моего ~/.bash_profile
– это не то, что я хочу сделать, и, вероятно, это плохая идея. Это не то, что я хочу сделать, потому что это не решает проблему медленной загрузки для каждой новой оболочки.
Я добавил несколько операторов вывода; каждый раз, когда я открываю новое окно терминала bash, это фиксируется:
начинаю загрузку /etc/profile
завершил загрузку /etc/profile
начинаю загрузку bash_profile
завершил загрузку bash_profile
это имеет смысл, но что расстраивает – мне действительно нужно загружать их каждый раз, когда открывается новая оболочка? Почему не может быть какой-то хитрой наследственности, чтобы нам не приходилось перезагружать все каждый раз?
Я создал видео, демонстрирующее проблему. У меня есть 4 приложения терминала, которые я регулярно использую:
terminal.app # ведет себя неправильно
iterm2 # ведет себя неправильно
webstorm терминальный эмулятор # ведет себя неправильно
vscode терминальный эмулятор # ведет себя правильно!
VSCode на самом деле ведет себя так, как я бы хотел. Я предполагаю, что он делает это, загружая ~/.bash_profile
в родительской оболочке и делая это только один раз, когда vscode запускается. Все окна терминала в приложении затем являются подпроектами этой одной родительской оболочки.
Надеюсь, это видео прояснит проблему:
https://www.useloom.com/share/4e62f0cb24434c4a83b8bd32844b596a
Это настоящая проблема – большинство приложений для терминала делают это неправильно, однако, довольно чудесным образом, похоже, что VSCode от Microsoft на самом деле делает это правильно, см. эту проблему:
Мне интересно, было бы лучше писать клише на стороне загружаемого, а не на стороне загрузки. (например, заголовочные файлы C)
[[ "${_NAME_OF_THIS_LIBSCRIPT:-""}" == "yes" ]] && return 0
_NAME_OF_THIS_LIBSCRIPT=yes
С этим вам не нужно повторять один и тот же стандартный текст каждый раз, когда вы загружаете файл скрипта, который должен содержать что-то, предназначенное для совместного использования в нескольких местах.
Или я что-то упускаю?
Если быть честным, я не мастер программирования на bash, поэтому я действительно хотел бы получить идеи от других.
Сегодня утром я перенес кучу личной информации из своего bash_profile
и bashrc
и добавил их в новый файл, который я называю privaterc
.
В своем файле privaterc
я установил эту переменную:
PRIVATERC_RUN=yes
Теперь в своем bash_profile
я добавил эту строку:
[[ $PRIVATERC_RUN != yes && -f ~/.privaterc ]] && source ~/.privaterc
Это заставит privaterc
загружаться только в том случае, если он ранее не был загружен в этой оболочке.
Что касается странностей профиля, которые вы наблюдаете, статья, на которую я ссылался в комментарии, утверждает следующее о mac:
Mac OS X — исключение
Исключением из руководящих принципов окон терминала является Terminal.app в Mac OS X, который по умолчанию запускает входную оболочку для каждого нового окна терминала, вызывая .bash_profile вместо .bashrc. Другие GUI-эмуляторы терминала могут делать то же самое, но большинство из них этого не делают.
Поместите уникальную переменную в rc файл – с длиной 1 или более символов – затем проверьте, имеет ли она длину больше 0 перед загрузкой bash_profile.
if [ ! X”” = X”$uniq_var” ] ; then . ~/.bash_profile ; fi
Я просто установил bash в качестве входной оболочки на MacOS и не столкнулся с этой проблемой. Возможно, они снова что-то изменили.
Это моя версия теста, основанная на ответе Hiroshi_U.
Я хочу протестировать функцию в mylib.sh
с помощью $ source mylib.sh;sysLog Hey
, функция не будет актуальна, если я изменил что-то после этого и пытаюсь получить более новый результат. Мне нужно удалить _NAME_OF_THIS_LIBSCRIPT
, чтобы сделать ее новой. Поскольку $ echo $0
выдает что-то вроде -sh
и -bash
, я проверяю на -
, чтобы определить, была ли она запущена в файле скрипта или в оболочке.
mylib.sh
#!/bin/sh
MY_BASE=$0
[[ "${_NAME_OF_THIS_LIBSCRIPT:-""}" == "yes" ]] && return 0
[[ "${MY_BASE:0:1}" != "-" ]] && _NAME_OF_THIS_LIBSCRIPT=yes
function sysLOG() {
echo $1 $_NAME_OF_THIS_LIBSCRIPT
}
test.sh
#!/bin/sh
source /tmp/mylib.sh
sysLOG 1
source /tmp/mylib.sh
sysLOG 2
source /tmp/mylib.sh
sysLOG 3
$ test.sh;echo $_NAME_OF_THIS_LIBSCRIPT
1 yes
2 yes
3 yes
$ source mylib.sh;sysLog Hey;echo $_NAME_OF_THIS_LIBSCRIPT
Hey! yes
Без [[ "${MY_BASE:0:1}" != "-" ]] &&
$ source mylib.sh;sysLog Hey;echo $_NAME_OF_THIS_LIBSCRIPT
Hey! yes
yes
Вы можете создать своего рода флаг, чтобы отследить, загружен ли он уже:
Этот пример от мастера Adrelanos:
get_colors(){
get_colors_sourced=1
## Отключить цвета, если присутствуют некоторые переменные окружения.
if test -n "${NO_COLOR:-}" || test -n "${ANSI_COLORS_DISABLED:-}"; then
nocolor=""
bold=""
nobold=""
underline=""
nounderline=""
red=""
green=""
yellow=""
blue=""
magenta=""
cyan=""
return 0
fi
nocolor="\033[0m"
bold="\033[1m"
nobold="\033[22m"
underline="\033[4m"
nounderline="\033[24m"
red="\033[31m"
green="\033[32m"
yellow="\033[33m"
blue="\033[34m"
magenta="\033[35m"
cyan="\033[36m"
}
if test "${get_colors_sourced:-}" != "1"; then
get_colors
fi
Простое решение для запуска скриптов и других ситуаций:
test -z "$(declare -f some_function_inside_file)" >/dev/null || source "yourfile.sh" || printf '%s' 'Уже загружен'
Ответ или решение
Избегание многократной источниковой загрузки скриптов в Bash
При работе с командной оболочкой Bash на macOS, многие пользователи сталкиваются с проблемой долгой загрузки терминала из-за многократной инициализации скриптов, указанных в ~/.bash_profile
. Давайте рассмотрим, как можно оптимизировать этот процесс и избежать многократной загрузки одном и том же скрипта.
Понимание процесса загрузки
При каждом открытии нового сеанса терминала, macOS выполняет команду source ~/.bash_profile
, если используется стандартное приложение Terminal.app. В результате этого, каждый раз, когда вы открываете новый терминал, выполняются все команды, находящиеся в bash_profile
, что может занимать время, особенно если в нем есть множество вызовов source
для других скриптов и конфигурационных файлов.
Решение проблемы с медленной инициализацией
Для избежания многократной инициализации, существует несколько методов, которые могут помочь оптимизировать загрузку:
-
Использование флагов для загрузки скриптов:
Вы можете использовать переменные-флаги для отслеживания того, загружались ли скрипты ранее. Это может выглядеть следующим образом:# ~/.bash_profile if [ -z "$SCRIPTS_LOADED" ]; then export SCRIPTS_LOADED=1 source ~/.script_one source ~/.script_two # Добавьте другие сценарии по мере необходимости fi
Так, если
~/.bash_profile
загружается повторно, скрипты не будут загружены повторно, что значительно ускорит процесс. -
Создание общего файла конфигурации:
Можно создать отдельный файл конфигурации, который будет загружаться только один раз:# ~/.bash_profile if [ -f ~/.config_loaded ]; then source ~/.config_loaded else # Выполняем ваши скрипты source ~/.script_one echo "Конфигурация загружена" > ~/.config_loaded fi
Как избежать повторного источника скриптов
Для того чтобы не загружать один и тот же скрипт несколько раз в текущем сеансе, можно реализовать проверку:
# Внутри вашего скрипта
if [[ "${_MY_SCRIPT_LOADED:-}" == "yes" ]]; then
return 0
fi
export _MY_SCRIPT_LOADED=yes
# Ваш код здесь
Такой подход позволит вашему скрипту быть загруженным только один раз за сессию, что особенно полезно для библиотек и функций, которые вы хотите использовать в нескольких местах.
Итоги и рекомендации
Эти стратегии помогут вам значительно сократить время загрузки нового терминала на вашем Mac. Следует помнить, что конфигурация вашего терминала – это далеко не пустяк, и правильный подход к организации загрузки скриптов может значительно улучшить ваш опыт работы с Bash. Настоятельно рекомендуется применять переменные-флаги или условия загрузки, чтобы избежать ненужных повторных загрузок.