Дізнайтеся, які сценарії виконуються 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.08.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спочатку, щоб вирішити.


Баш читає лише, ~/.profile якщо ~/.bash_profileйого немає ...
jasonwryan

@jasonwryan, я джерело ~/.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для отримання додаткової інформації.


Дякую за ваш внесок, але я думаю, що в моєму ударі щось серйозно не так. Біг 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)
Макс Coplan
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.