找出启动时bash正在运行哪些脚本


15

启动bash终端后,我注意到PATH变量包含重复项。我的终端启动了一个登录shell,因此~/.bash_profile是Source,然后是~/.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首先检查决定。


巴什只读取~/.profile 如果~/.bash_profile不存在 ...
jasonwryan

@jasonwryan,我源~/.profile~/.bashrc~/.bash_profile
smac89

Answers:


30

如果您的系统有,strace则可以列出外壳程序打开的文件,例如使用

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

-li表示登录shell是交互式的;仅-i用于交互式非登录shell。)

这将显示外壳程序打开或尝试打开的文件列表。在我的系统上,它们如下:

  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以获取更多信息。


感谢您的投入,但我认为bash出现了严重问题。echo $0在终端中运行给出的-bash而不是预期的bash。您对此还有其他建议吗?
smac89

3
@ smac89:这对于登录shell是正常的。当Bash的第一个字符$0是破折号-或使用option调用时,Bash充当登录shell -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上使用。(只需替换stracedtruss
Max Coplan,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.