得之我幸 失之我命

when someone abandons you,it is him that gets loss because he lost someone who truly loves him but you just lost one who doesn’t love you.

bash 启动加载了谁

书接上文,“bashrc 里修改环境变量要加 export 吗” 结尾提到 “至此,定义环境变量的时候为什么需要加 export 结”,但是原问题涉及的 bashrc 并没有解决掉

以前粗浅的知道 bash 启动是会加载 ~/.bashrc 文件的,那么如果是在 bashrc 中设置了一个变量,照往常的粗浅理解应该是会加载一遍 ~/.bashrc 文件从而使得其中的变量都生效的,按这个逻辑来看,bashrc 中的变量无论环境变量还是普通变量都应该可以生效,那么为什么实际实验后发现,没有生效呢?为什么还要加 export 呢

那么 bash 启动的时候是什么样的规则,又去加载了谁呢

先公布加载规则(之所以用英文是为了防止翻译带来的不准确)

如果启动的是 bash

interactive login shell or non-interactive shell with --login option

  1. 首先加载 /etc/profile

  2. 按顺序遍历并且仅执行最先找到的那个 ~/.bash_profile, ~/.bash_login, and ~/.profile

    –noprofile 选项可以禁止上述行为

interactive non-login shell

  1. 加载 ~/.bashrc

    –norc 选项可以禁止上述行为

    –rcfile file 可以强制 bash 从指定文件加载而不加载 ~/.bashrc

non-interactive shell without --login option(原文是 non-interactively,但从第一种情形可以判断,此处应该是不带 --login 的)

  1. 检索变量 BASH_ENV,如果存在就加载它

    常见的例子:执行一个 shell 脚本的时候多数就是这种启动方式

如果使用 sh 调用,那么情况又不太一样了

interactive login shell or non-interactive shell with --login option

  1. 按顺序加载 /etc/profile 和 ~/.profile

    –noprofile 选项可以禁止上述行为

interactive non-login shell

  1. 检索变量 ENV,如果存在就加载它

    不难发现,–rcfile 对这种调用方式而言是没有用的,但是可以通过设置变量 ENV 的值来指定加载的文件

non-interactive shell without --login option

  1. 不加载任何文件

在加载完启动时需要加载的文件后,bash 会进入 POSIX 模式

至于什么是 POSIX 模式,以及 bash 的其他几种调用模式,会在后续记录中分析,本次讨论先记录常见的两类调用方式

interactive shell

什么是交互式(interactive)shell

An interactive shell is one started without non-option arguments (unless -s is specified) and without the -c option whose standard input and error are both connected to terminals (as determined by isatty(3)), or one started with the -i option.

  1. 那 non-option arguments 怎么理解?

    1
    2
    $ ls -a -l /path
    # 首先 -a -l 是 ls 的选项,那么剩下的 /path 就是 ls 的非选项参数
  2. 白话文就是:一个不带非选项参数(-s 是一个例外,它可以携带非选项参数),也不带 -c(这是一个选项,而不是非选项参数),并且标准输入流和错误流都连接到终端(这里可以粗略的理解为,从终端获取输入,错误输出到终端)的 shell;或者是带 -i 选项启动的 shell

判断是否交互式

  1. 判断变量 “-”,如果值中含有字母 “i”,表示交互式

    1
    2
    3
    4
    5
    6
    7
    8
    $ echo $-
    himBH

    $ vim test.sh
    #!/bin/bash
    echo $-
    $ bash test.sh
    hB
  2. 判断变量 PS1,如果值非空,则为交互式,否则为非交互式,因为非交互式会清空该变量

    1
    2
    3
    4
    5
    6
    7
    8
    $ echo $PS1
    \s-\v\$

    $ vim test.sh
    #!/bin/bash
    echo $PS1
    $ bash test.sh

login shell or with --login

什么是登录(login)shell

A login shell is one whose first character of argument zero is ‘-’, or one invoked with the --login option.

这个就比较好懂,满足 $0 的首字母是 - 或者使用 --login 调用就是 login shell

判断是否登录

  1. 判断变量 “0”,如果值中首字母为 “-”,表示登录

    1
    2
    $ ps aux | grep bash
    test 28748 0.0 0.1 116500 3232 pts/0 Ss 22:51 0:00 -bash
  2. 如果启动的时候带 --login 选项,表示登录,这时候可以用 logout 验证

    1
    2
    3
    4
    5
    6
    $ bash
    $ logout
    bash: logout: not login shell: use 'exit'

    $ bash --login
    $ logout # 正常退出

be slow to promise and quick to perform.