前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Shell 编程(3)-bash 配置文件

Shell 编程(3)-bash 配置文件

原创
作者头像
懒人的小脑
修改于 2019-01-28 01:43:03
修改于 2019-01-28 01:43:03
1.5K00
代码可运行
举报
运行总次数:0
代码可运行

用户登录系统时,bash 会进行一系列操作,如加载各种 bash 配置文件,设置或清空一些列的变量,有时还会执行一些自定义的命令。

有些时候登录系统时可以交互的,如正常登录系统,有些时候时无交互的,如执行一个脚本。bash 启动类型分为交互式 shell 和非交互式 shell。交互式 shell 还分为交互式的登录 shell 和交互式的非登录 shell。

非交互式 shell 在某些时候可以在 bash 的 命令后面带上“--login|-l”,这样是非交互式的登录式 shell。

判断交互式和登录式shell

交互式 shell

交互式模式就是在终端上执行,shell等待你的输入,并且立即执行你提交的命令。这种模式被称作交互式是因为shell与用户进行交互。这种模式也是大多数用户非常熟悉的:登录、执行一些命令、退出。当你退出后,shell也终止了。

非交互式模式,以shell script(非交互)方式执行。在这种模式 下,shell不与你进行交互,而是读取存放在文件中的命令,并且执行它们。当它读到文件的结尾EOF,shell也就终止了。

判断交互式shell

方法一:判断变量"-",如果值中包含字母“i”,表示交互式

代码语言:txt
AI代码解释
复制
echo $-
himBH

vim a.sh
#! /bin/bash
echo $-

bash a.sh
hB

方法二:判断变量 PS1,如果值非空,则为交互式,否则非非交互式,因为非交互式会清空该变量。

代码语言:txt
AI代码解释
复制
[root@localhost ~]# echo $PS1
[\u@\h \W]\$

登录式 shell

登录式shell需要用户名、密码登录后才能进入的shell(或者通过"--login"选项生成的shell)。

非登录shell不需要输入用户名和密码即可打开的Shell,例如:直接命令“bash”就是打开一个新的非登录shell,在Gnome或KDE中打开一个“终端”(terminal)窗口程序也是一个非登录shell。

执行exit命令,退出一个shell(登录或非登录shell);

执行logout命令,退出登录shell(不能退出非登录shell)。

bash是 login shell时,其进程名为"-bash"而不是bash。

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

代码语言:txt
AI代码解释
复制
# 在 login shell 中
[root@localhost ~]# echo $0
-bash
[root@localhost ~]# ps -ef | grep '\-bash' | grep -v grep
root     11338 11337  0 08:17 pts/0    00:00:00 -bash

#在非登录式 shell 中
[simon@localhost ~]$ echo $0
bash
[simon@localhost ~]$ ps -ef | grep '\-bash' | grep -v grep

判断登录式

shopt login\_shell,值为 on 为登录式,否则为非登录式。

代码语言:txt
AI代码解释
复制
[root@localhost ~]# shopt login_shell
login_shell    	on
[root@localhost ~]# bash
login_shell    	off

判断交互式和登录式的情况,一句话命令:

代码语言:txt
AI代码解释
复制
[root@localhost ~]# echo $PS1;shopt login_shell

[root@localhost ~]# echo $-;shopt login_shell

分析几种 bash 的启动方式

正常登录

伪终端登录,如 ssh 登录,或虚拟终端登录时,为交互式登录 shell

代码语言:txt
AI代码解释
复制
[root@localhost ~]# echo $PS1;shopt login_shell 
[\u@\h \W]\$
login_shell     on

su 命令

执行 su 命令不带"--login"时为交互式非登录shell,带“--login”时,为交互式登录 shell。

执行不带"--login"选项的bash命令时为交互式、非登录式shell。但指定"--login"时,为交互式、登录式shell。

代码语言:txt
AI代码解释
复制
[root@localhost ~]# su root

[root@localhost ~]# echo $PS1;shopt login_shell 
[\u@\h \W]\$
login_shell     off

[root@localhost ~]# su -
Last login: Sat Aug 19 13:24:11 CST 2017 on pts/0

[root@loalhost ~]# echo $PS1;shopt login_shell
[\u@\h \W]\$
login_shell     on

[root@localhsot ~]# bash

[root@loalhost ~]# echo $PS1;shopt login_shell
[\u@\h \W]\$
login_shell     off

[root@localhost ~]# bash -l

[root@localhost ~]# echo $PS1;shopt login_shell
[\u@\h \W]\$
login_shell     on

命令组合

使用命令组合(使用括号包围命令列表)以及命令替换进入子 shell 时,继承父 shell 的交互和登录属性

代码语言:txt
AI代码解释
复制
[root@localhost ~]# (echo $BASH_SUBSHELL;echo $PS1;shopt login_shell)
1
[\u@\h \W]\$
login_shell     on

[root@localhost ~]# su

[root@localhost ~]# (echo $BASH_SUBSHELL;echo $PS1;shopt login_shell)
1
[\u@\h \W]\$
login_shell     off

ssh 执行的远程命令

ssh 执行远程命令,但不登录时,为非交互、非登录式。

代码语言:txt
AI代码解释
复制
[root@localhost ~]# ssh localhost 'echo $PS1;shopt login_shell'
 
login_shell     off

Shell 脚本

执行 shell 脚本时,为非交互、非登录式 shell。执行--login 时,为非交互、登录式 shell。

代码语言:txt
AI代码解释
复制
[root@localhost ~]# vim b.sh
#!/bin/bash
echo $PS1
shopt login_shell

[root@localhost ~]# bash b.sh
 
login_shell     off

[root@localhost ~]# bash -l b.sh
 
login_shell     on

图像界面终端

在图形界面下打开终端时,为交互式、非登录式 shell。不过可以在设置中设置为 login shell。

bash 环境配置文件的加载顺序

bash环境配置主要是通过加载bash环境配置文件来完成。根据shell是否交互、是否登陆,将会影响加载的配置文件,除了交互登录属性,有些特殊的属性也会影响读取配置文件。

bash 的环境配置文件主要有

  • /etc/profile
  • ~/.bash_profile
  • ~/.bashrc
  • /etc/bashrc
  • /etc/profile.d/*.sh

为了测试各种情况读取哪些配置文件,先分别向几个配置文件中写入echo语句,用以判断该配置文件是否在启动bash时被读取加载。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
echo "echo '/etc/profile goes'" >>/etc/profile
echo "echo '~/.bash_profile goes'" >> ~/.bash_profile
echo "echo '~/.bashrc goes'" >> ~/.bashrc
echo "echo '/etc/bashrc goes'" >> /etc/bashrc
echo "echo '/etc/profile.d/test.sh goes'" >> /etc/profile.d/test.sh
chmod +x /etc/profile.d/test.sh

①交互式登录 shell 或非登录式但带有“--login|-l”选项

bash 启动时,将先读取/etc/profile,在依次搜索~/.bash_profile、~/.bash_login和~/.profile,并仅加载第一个搜索到且可读的文件。当退出时,将执行~/.bash_logout中的命令。

在/etc/profile中有一条加载 `/etc/profile.d/*.sh` 的语句,它会使用source加载/etc/profile.d/下所有可执行的sh后缀的脚本。

代码语言:shell
AI代码解释
复制
grep -A 8 \*\.sh /etc/profile
 
for i in /etc/profile.d/*.sh ; do
    if [ -r "$i" ]; then
        if [ "${-#*i}" != "$-" ]; then # 将"$-"从左向右模式匹配"*i"并将匹配到的内容删除(即进行变量切分),如果"$-"切分后的值不等于"$-",则意味着是交互式shell
            . "$i"
        else
            . "$i" >/dev/null 2>&1
        fi
    fi
done

在~/.bash_profile中也一样有加载~/.bashrc的命令。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
grep -A 1 \~/\.bashrc ~/.bash_profile

if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi

~/.bashrc中又有加载/etc/bashrc的命令。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
grep -A 1 /etc/bashrc ~/.bashrc

if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

其实/etc/bashrc中还有加载 /etc/profile.d/*.sh 的语句,但前提是非登录式shell时才会执行。

代码语言:shell
AI代码解释
复制
if ! shopt -q login_shell ; then   # We're not a login shell
...
    for i in /etc/profile.d/*.sh; do
        if [ -r "$i" ]; then
            if [ "$PS1" ]; then
                . "$i"
            else
                . "$i" >/dev/null 2>&1
            fi
        fi
    done
...
fii

交互式的登录 shell 加载 bash 环境配置文件的实际过程如下:

交互式登录 shell 的配置文件加载过程
交互式登录 shell 的配置文件加载过程

验证:

新开终端登录时:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Last login: Sat Jan 26 08:32:46 2019
/etc/profile.d/test.sh goes
/etc/profile goes
/etc/bashrc goes
~/.bashrc goes
~/.bash_profile goes

ssh 远程登录时:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ssh localhost
Last login: Sat Jan 26 09:58:20 2019 from 192.168.1.110
/etc/profile.d/test.sh goes
/etc/profile goes
/etc/bashrc goes
~/.bashrc goes
~/.bash_profile goes

执行带有“--login”选项的 login:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
bash -l
/etc/profile.d/test.sh goes
/etc/profile goes
/etc/bashrc goes
~/.bashrc goes
~/.bash_profile goes

su 带上“--login”时:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@localhost ~]# su -
上一次登录:六 126 10:00:10 CST 2019从 localhostpts/2/etc/profile.d/test.sh goes
/etc/profile goes
/etc/bashrc goes
~/.bashrc goes
~/.bash_profile goes

执行 shell 脚本时,带有"--login"时:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
vim a.sh
#!/bin/bash --login
echo $-
echo Yeah
 
[root@localhost ~]# ./a.sh
/etc/profile goes
/etc/bashrc goes
~/.bashrc goes
~/.bash_profile goes
hB
Yeah

之所以执行shell脚本时没有显示执行 /etc/profile.d/*.sh ,是因为它是非交互式的,根据/etc/profile中的 if["${-#*i}"!="$-"] 判断,它将会把 /etc/profile.d/*.sh 的执行结果重定向到/dev/null中。也就是说,即使是shell脚本(带"--login "选项),它也加载了所有bash环境配置文件。

总结一下:

交互式非登录 shell

读取~/.bashrc,不会读取/etc/profile 和~/.bash_profile、~/.bash_login和~/.profile

交互式非登录 shell 的配置文件加载过程
交互式非登录 shell 的配置文件加载过程

验证:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@localhost ~]# bash
/etc/profile.d/test.sh goes
/etc/bashrc goes
~/.bashrc goes
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@localhost ~]# su
/etc/profile.d/test.sh goes
/etc/bashrc goes
~/.bashrc goes

非交互非登录式 shell

启动 bash 时,不会加载任何 bash 环境配置文件,但会搜索变量BASH_ENV。如果搜索到,则加载其所指定的文件。但并非所有非交互式,非登录式 shell 启动时都会如此。

几乎执行所有的shell脚本都不会特意带上"--login"选项,因此shell脚本不会加载任何bash环境配置文件,除非手动配置了变量BASH_ENV。

远程 shell 启动 bash

虽然属于非交互非登录式,但会加载~/.bashrc,所以还会加载/etc/bashrc,由于是非登录式,所以最终还会加载/etc/profile.d/*.sh,只不过因为是非交互式而使得执行的结果全部重定向到了/dev/null中。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[root@localhost ~]# ssh localhost echo hahaha
root@localhost's password:
/etc/bashrc goes
~/.bashrc goes
hahaha

它同样加载了 /etc/profile.d/*.sh ,只不过/etc/bashrc中的if判断语句 if["$PS1"];then 使得非交互式的shell要将执行结果重定向到/dev/null中。

总结一下

我们可以把bash配置文件分为两种,一种是全局配置文件,一种是在用户家目录的个人配置文件。

profile 类文件的作用:定义环境变量、运行命令或脚本

bashrc 类文件的作用:定义本地变量和函数、命令别名

先加载的配置文件的配置,可能会被后加载的配置所覆盖。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
Angularjs基础(十二)
ng-model-options       描述:规定如何更新模型             实例: 在失去焦点时绑定输入框的值scope 变量中。                 <div ng-app="myApp" ng-controller="myCtrl">                   <input ng-model ="name">                 </div>                 <script>          
用户1197315
2018/01/22
3.2K0
【一起来烧脑】一步学会AngularJS系统
AngularJS是一个JavaScript框架 一个用JavaScript编写的库
达达前端
2019/07/18
5.8K0
【一起来烧脑】一步学会AngularJS系统
Angularjs基础(三)
    AngularJS ng-model 指令     ng-model 指令用于绑定应用程序数据到HTML 控制器(input,select,textarea)的值 ng-model指令     ng-model指令可以将输入域的值与AngularJS 创建的变量绑定。       实例:         <div ng-app="myApp" ng-controller="myCtrl">             名字:<input ng-model="name">  
用户1197315
2018/01/19
3.3K0
Angularjs基础(六)
AngularJS HTML DOM     AngularJS为HTML DOM 元素的属性提供了绑定应用数据的指令。 ng-disabled指令     ng-disabled指令直接绑定应用数据到HTML的disabled属性。       实例:       <div ng-app="" ng-init="mySwitch=true">         <p>           <button ng-disableled="mySwitch">点我!</button
用户1197315
2018/01/19
3.2K0
7-进军 angular1.x 表单和事件、模块
通常 AngularJS 应用程序将模块和控制器包含在 JavaScript 文件中。
西南_张家辉
2021/02/02
2.5K0
Angularjs基础(七)
AngularJS表单     AngularJS表单时输入控件的集合 HTML控件     一下HTML input 元素被称为HTML 控件:         input 元素         select元素         button元素         textarea元素 HTML 表单     AngularjS表单上实例       <div ng-app="myApp" ng-controller="formCtrl">          <from nova
用户1197315
2018/01/19
2.2K0
AngularJS ng-model 指令
ng-model 指令用于绑定应用程序数据到 HTML 控制器(input, select, textarea)的值。
陈不成i
2021/07/23
1.1K0
AngularJS系列(五)——下拉框
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
逝兮诚
2019/10/30
1.6K0
Angularjs基础(十)
ng-blur  描述:规定blur 事件的行为       实例:当输入框失去焦点的(onblur)时执行表达式:         <input ng-blur="count = count + 1" ng-init="count=0"/>         <h1>{{count}}</h1>       定义和用法           ng-blur 指令用于告诉AngularJS HTML 元素在失去焦点时须执行的表达式。           语法:<element ng-blur
用户1197315
2018/01/22
3.5K0
AngularJS 事件
ng-hide 指令设置 <p>元素及两个输入域是否可见, 根据 myVar 的值 (true 或 false) 来设置是否可见。
陈不成i
2021/07/23
1.7K0
AngularJS系列(八)——事件
ng-click :点击 ng-click 指令定义了 AngularJS 点击事件。 <div ng-app="myApp"ng-controller="myCtrl"> <buttonng-click="count=count+1">点我!</button> <p>{{count}}</p> </div> <script> var app = angular.module('myApp', []); app.controller('myCtrl', function
逝兮诚
2019/10/30
5300
Angularjs基础(九)
AngularJS 应用 应用程序讲解     实例:         <html ng-app="myNoteApp">           <head>             <meat charset="utf-8">             <script src="http://apps.bdimg.com/libs/angular.js/1.4.6angular.min.js"></script>           </head>           <body>
用户1197315
2018/01/22
1.3K0
Angularjs基础(四)
AngularJS过滤器     过滤器可以使用一个管道符(|)添加到表达式和指令中。       AngularJS过滤器可用于转换数据:           currency     格式化数字为货币格式           filter       从数组中选着应子集。           lowercase      格式化字符串为小写。           orderBy      根据某个表达式排列数组           uppercase     格式化
用户1197315
2018/01/19
3.1K0
3-进军 angular1.x 模型和作用域 scope
View(视图), 即 HTML。 Model(模型), 当前视图中可用的数据。 Controller(控制器), 即 JavaScript 函数,可以添加或修改属性。 scope 是模型。
西南_张家辉
2021/02/02
1.4K0
AngularJS Scope(作用域)
Scope(作用域) 是应用在 HTML (视图) 和 JavaScript (控制器)之间的纽带。
陈不成i
2021/07/23
1.6K0
第215天:Angular---指令
在 AngularJS 中将前缀为 ng- 这种属性称之为指令,其作用就是为 DOM 元素调用方法、定义行为绑定数据等
半指温柔乐
2018/09/11
3.4K0
AngularJS系列之select下拉选择第一个选项为空白的解决办法
今天给大家介绍一下AngularJS系列之select下拉选择第一个选项为空白的解决办法。 相信大家也经常遇到这种情况吧:在使用AngularJS中的select组件开发的时候,莫名其妙的第一个选项就
林老师带你学编程
2018/01/03
3.3K0
AngularJS Select(选择框)
在 AngularJS 中我们可以使用 ng-option 指令来创建一个下拉列表,列表项通过对象和数组循环输出,如下实例:
陈不成i
2021/07/23
2.6K0
【AngularJS】—— 2 初识AngularJs(续)
前一篇了解了AngularJS的一些简单的使用,这里继续跟着w3c学习一下剩下的内容。   本篇根据w3cschool.cc继续学习AngularJS剩余的内容,包括:   1 事件   2 模块   3 表单   4 数据验证   5 bootstrap CSS风格   6 include包含其他页面   7 应用程序   8 参考手册   首先看一下html的事件   关于html的事件,文中给出了三个例子,点击、隐藏、显示。使用方法基本相同:   先看一下点击的例子,点击按钮后,会触发ng-clic
用户1154259
2018/01/17
2.4K0
AngularJS 控制器
控制器是 JavaScript 对象,由标准的 JavaScript 对象的构造函数 创建。
陈不成i
2021/07/23
1.2K0
相关推荐
Angularjs基础(十二)
更多 >
目录
  • 判断交互式和登录式shell
    • 交互式 shell
    • 判断交互式shell
    • 登录式 shell
    • 判断登录式
  • 分析几种 bash 的启动方式
    • 正常登录
    • su 命令
    • 命令组合
    • ssh 执行的远程命令
    • Shell 脚本
    • 图像界面终端
  • bash 环境配置文件的加载顺序
    • ①交互式登录 shell 或非登录式但带有“--login|-l”选项
    • 交互式非登录 shell
    • 非交互非登录式 shell
    • 远程 shell 启动 bash
  • 总结一下
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档