Не удается успешно получить исходный код.bashrc из сценария оболочки
Обычно мы можем источник ~/.bashrc
файл с помощью этой команды
source ~/.bashrc
но если я напишу это в сценарии оболочки и выполню, ничего не произойдет. Зачем?
Есть какой-либо способ сделать это?
Мой сценарий:
#!/bin/bash
chmod a+x ~/.bashrc
source ~/.bashrc
Также попробовал .
(точка) вместо source
, Тот же результат.
6 ответов
Сценарий оболочки запускается в своем собственном экземпляре оболочки. Все настройки переменных, определения функций и тому подобное влияют только на этот экземпляр (и, возможно, на его дочерние элементы), но не на вызывающую оболочку, поэтому они исчезают после завершения сценария.
В отличие от source
Команда не запускает новый экземпляр оболочки, но использует текущую оболочку, поэтому изменения остаются.
Если вы хотите использовать ярлык для чтения вашего.bashrc, используйте функцию оболочки или псевдоним вместо сценария оболочки, например
alias brc='source ~/.bashrc'
Я хочу дополнить ответ Рави:
Это поведение специфично для Ubuntu (и, вероятно, большинства производных дистрибутивов), так как по умолчанию ~/.bashrc
файл начинается с короткого замыкания, Ubuntu 18.04, например:
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
Это остановит оценку файла, если он работает в неинтерактивной оболочке, как в случае с вашим сценарием, так как все сценарии запускаются в неинтерактивной оболочке, а затем каждый файл, который вы source
унаследует это свойство.
eval
мотыга
Я обнаружил уродливый хак для обхода Ubuntu специально, используя eval
вместо source
:
eval "$(cat ~/.bashrc | tail -n +10)"
Он просто пропускает несколько первых строк и оценивает остальные ~/.bashrc
поэтому остальное оценивается и изменяет текущее исполнение.
Имейте в виду, что это магическое число, которое может не работать во всех версиях Ubuntu; но может быть хорошим решением, если вы создаете сценарии для более или менее известных систем.
Более подходящее решение может включать использование регулярных выражений для определения конкретных битов, которые останавливают оценку.
Альтернатива Шебангу
Другая альтернатива, которая может работать лучше в некоторых сценариях, - заставить скрипт запускаться в интерактивной оболочке, добавив флаг в shebang:
#!/bin/bash -i
Помните о нескольких вещах:
- Лучше использовать
#!/usr/bin/env bash
форма, но таким образом вы не можете запустить оболочку с аргументами. - С использованием
-i
имеет свой собственный набор последствий, среди которых программы будут запрашивать взаимодействие с пользователем, и это обычно не предназначено для сценариев, например, установкаdeb
пакеты могут остановить скрипт вdpkg configure
подсказки - Я изначально пытался использовать
set -i
а такжеset +i
включить и выключить функцию там, где она мне нужна, но это не работает.
Ваш .bashrc
обычно начинается:
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
Поскольку ваш сценарий не имеет установленного PS1 (потому что он не интерактивный), он не сбрасывает путь, потому что он выходит рано. Чтобы продемонстрировать, измените ваш скрипт:
#!/bin/bash
chmod a+x ~/.bashrc
PS1='$ '
source ~/.bashrc
теперь это позволит вашим скриптам работать с новым .bashrc
, Примечание: как только ваш скрипт завершится, env будет установлен на то, что было до запуска скрипта. Изменения будут отражены при следующем запуске терминала.
Пытаться:
exec bash
Это должно перезагрузить ~/.bashrc, ~/.bash_aliases и т. Д.
Ни один из других методов не работал для меня [source /path/to/file
против . ./path/to/file
, псевдоним и т. д.], пока, благодаря этому руководству, я обнаружил, что с помощью:
#!/usr/bin/env bash
притон
вместо простого #!/usr/bin/env
один позволяет аргументам передаваться интерпретатору, который, я думаю, является ключевым здесь - см. этот документ для получения дополнительной информации.
В любом случае, если исходные команды в любой форме не работают для вас, попробуйте проверить свой шебанг, это может быть проблемой:)
Я просто скопировал содержимое оригинального файла, удалил его, создал новый
~/.bashrc
и вставил содержимое. И это сработало.