Узнайте, какие скрипты запускаются bash при запуске

15

После запуска терминала bash я заметил, что переменная PATH содержит повторяющиеся записи. Мой терминал запускает оболочку входа в систему , поэтому ~/.bash_profileполучает источник, а затем ~/.profileи ~/.bashrc. Только в этом случае ~/.profileя создаю записи путей, которые дублируются.

Чтобы быть педантичным, это порядок, в котором файлы должны быть получены:

Sourced /etc/profile
Sourced /etc/bash.bashrc
Sourced .bash_profile
Sourced .profile
Sourced .bashrc

Прежде чем кто-либо пометит это как дубликат «переменная PATH содержит дубликаты», продолжайте чтение.

Сначала я подумал, что это связано с тем, ~/.profileчто он был получен дважды, поэтому я записывал файл в файл журнала всякий раз, когда он был получен, и, что удивительно, он регистрировал только одну запись, что говорит мне, что он был получен только один раз. Еще более удивительным является тот факт, что когда я закомментирую записи, которые были в ~/.profile, записи все еще появляются в PATHпеременной. Это привело меня к трем выводам, один из которых был быстро исключен:

  1. Bash игнорирует действительные комментарии bash и по-прежнему выполняет закомментированный код
  2. Существует скрипт, который читает ~/.profileи игнорирует любой код, который печатает вывод (например, файл журнала)
  3. Есть еще одна копия моего, ~/.profileкоторая в других источниках

Первый, я быстро пришел к выводу, что это не так из-за быстрого тестирования. Во втором и третьем вариантах мне нужна помощь.

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

Если вышеупомянутое невозможно, то кто-нибудь может подсказать, где еще я могу посмотреть, какие скрипты запускаются .


Будущая ссылка

Это скрипт, который я сейчас использую для добавления к моему пути:

function add_to_path() {
    for path in ${2//:/ }; do
        if ! [[ "${!1}" =~ "${path%/}" ]]; then # ignore last /
            new_path="$path:${!1#:}"
            export "$1"="${new_path%:}" # remove trailing :
        fi
    done
}

Я использую это так:

add_to_path 'PATH' "/some/path/bin"

Сценарий проверяет, существует ли путь в переменной, прежде чем добавить его.

Для пользователей zsh вы можете использовать этот эквивалент:

function add_to_path() {
    for p in ${(s.:.)2}; do
        if [[ ! "${(P)1}" =~ "${p%/}" ]]; then
            new_path="$p:${(P)1#:}"
            export "$1"="${new_path%:}"
        fi
    done
}

Изменить 28/8/2018

Еще одна вещь, которую я нашел в этом сценарии, - это также исправить путь. Итак, в начале моего .bashrcфайла я делаю что-то вроде этого:

_temp_path="$PATH"
PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin'
add_to_path 'PATH' "$_temp_path"
unset _temp_path

Вам решать, с чего PATHначинать. Изучите PATHсначала, чтобы решить.

smac89
источник
Bash только читает, ~/.profile если ~/.bash_profileне существует ...
jasonwryan
@jasonwryan, источник I ~/.profileи ~/.bashrcот~/.bash_profile
smac89

Ответы:

30

Если ваша система имеет, straceвы можете перечислить файлы, открытые оболочкой, например, с помощью

echo exit | strace bash -li |& grep '^open'

( -liозначает интерактивную оболочку входа; используйте только -iдля интерактивной оболочки без входа в систему.)

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

  1. /etc/profile
  2. /etc/profile.d/*(различные сценарии в /etc/profile.d/)
  3. /home/<username>/.bash_profile (это не удается, у меня нет такого файла)
  4. /home/<username>/.bash_login (это не удается, у меня нет такого файла)
  5. /home/<username>/.profile
  6. /home/<username>/.bashrc
  7. /home/<username>/.bash_history (история командных строк; это не скрипт)
  8. /usr/share/bash-completion/bash_completion
  9. /etc/bash_completion.d/* (различные скрипты, обеспечивающие функциональность автозаполнения)
  10. /etc/inputrc (определяет привязки клавиш; это не скрипт)

Используйте man straceдля получения дополнительной информации.

AlexP
источник
Спасибо за ваш вклад, но я думаю, что с моим bash что-то серьезно не так. Запуск echo $0в терминале дает -bashскорее, чем ожидалось bash. У вас есть другие предложения по этому поводу?
smac89
3
@ smac89: Это нормально для оболочки входа в систему. Bash ведет себя как оболочка входа в систему, когда 1-й символ $0является тире -или когда вызывается с опцией -l.
AlexP
Хорошо, это немного облегчение. Я выполнил команду, которую вы дали, и результат выглядит действительно сложным, но, тем не менее, все показанные файлы не содержат дублированных записей. Это наводит меня на мысль, что дублированные записи происходят, когда я впервые захожу в свою учетную запись, то есть что-то изначально получает записи в этом файле, и это делается снова, когда я открываю терминал? На самом деле я думаю, что это может быть так. Когда я вхожу в свою учетную запись, записи поступают, и снова, когда я открываю терминал, процесс повторяется. Это звучит возможно?
smac89
Почему бы вам не отладить старомодный способ, поставив echo PATH=\""$PATH"\"в начале и в конце .profileи .bashrc? И почему вы не делаете то, что делают все, и не устанавливаете PATH полностью, или, если добавляете каталог, защищены echo ":$PATH:" | grep -q ":/path/to/dir:" || export PATH="$PATH:/path/to/dir":?
AlexP
4
Используйте sudo bash -c "echo exit|dtruss bash -li|& less|grep '^open'"на macOS. (просто заменить straceна dtruss)
Макс Коплан