Не удается успешно получить исходный код.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и вставил содержимое. И это сработало.

Другие вопросы по тегам