Thinking_Out_Loud

说说login shell和non-login shell

2018-09-06

背景

最近又要在公司的CentOS上配一遍开发环境,这就避不了要编辑一番PATH,那么问题来了,这是要写在/etc/profile~/.profile~/.bash_profile还是~/.bashrc~/.bash_login呢?首先,可以排除影响全局的/etc/profile,这改了听起来就是给后来的自己挖坑(还有一个/etc/bash.bashrc)。接着我们就要厘清后四个的区别了,这就要从login shellnon-login shell的区别说起。

定义

不用Google,有事先找man

1
> man bash

我们在bash的手册中INVOCATION一节就可以找到login shell的定义:

A login shell is one whose first character of argument zero is a -, or one started with the --login option.

顺便还有interactive shell的定义:

An interactive shell is one started without non-option arguments 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.

可知有:

  • 交互式的 login shell:本地登录、ssh登录、bash --loginsu - <user>;
  • 交互式的 non-login shellsu <user>;
  • 非交互的 non-login shellssh example.com my-script-which-is-on-the-remote-machine;
  • 非交互的 login shell:脚本中使用--login(如#!/bin/bash --login);

上述的情况并没有列全,可以通过如下方法区分login和non-login shell:

1
2
3
4
5
> echo $0
-bash #第一个字符是 "-", 所以是 login shell。

> echo $0
bash #不是一个login shell。

发生了什么

当一个bash是以交互式的login shell被调用时,它首先会读取/etc/profile文件,然后按照~/.bash_profile~/.bash_login~/.profile的顺序依次查找并读取,但这是短路式的,按顺序成功读取了三者之一就不继续往后查找了。最后在退出时会执行~/.bash_logout中的命令。

交互式的non-login shell则先后读取/etc/bash.bashrc~/.bashrc

非交互的non-login shell只展开环境变量BASH_ENV并执行其指向的文件。

总结一下

如果需要统一交互式的login shellnon-login shell环境,我们可以在~/.bashrc中编写配置,然后在~/.bash_profile读取~/.bashrc。非交互式的情况一般与脚本有关,一般是主动载入环境变量(因为环境变量问题,dockerfile中也建议使用绝对路径),所以暂且不管。

参考资料

  1. login shell与non-login shell的区别
  2. difference-between-login-shell-and-non-login-shell