shell脚本编程笔记(一)—— shell简介与变量

一、 shell简介

1. shell的类型

系统启用什么样的shell取决于用户配置,在/etc/passwd的最后一个字段列出了用户的默认shell,一般为/bin/bash,其他还有zsh,tcsh,dash,csh等。

bash shell程序位于/bin目录下,使用长列表可以看出它是一个可执行程序:

另外一个默认的shell是/bin/sh,作为默认的系统shell,用于需要在启动时使用的系统shell脚本。centos中使用软链接将默认的系统shell设置成bash shell。这样说来,sh其实就是bash。


     

2. shell的父子关系

bash shell及之前提到的shell 都是父shell,要创建一个子shell程序很简单,输入bash就会创建一个新的shell程序,被称为子shell。要区分是父shell还是子shell,需要使用ps 查看进程。

在root用户下,先看没有子shell的父shell进程,如下图所示:

接下来输入bash,创建一个子shell,该子shell的PPID父进程是1748,对应-bash进程的(PID) 1748

当然子shell还可以继续创建子shell,但注意生成子shell的成本不低,速度还慢,创建嵌套的子shell去处理性能更为糟糕。

可以用ps -forest命令查看树状关系图

 

3. 命令列表与进程列表

通过;可以在一行中执行一系列命令,称为命令列表,例如

pwd ; ls ; cd /etc ; pwd ; ls

上面的命令可以依次执行,但这并不是进程列表。命令列表要想变为进程列表,将这些命令包含在()中即可。

(pwd ; ls ; cd /etc ; pwd ; ls)

对于进程列表,Linux会生成一个子shell执行对应命令。Linux有一个环境变量 $BASH_SUBSHELL,可以查看该值判断是否有子shell(为0则没有)。

pwd ; ls ; cd /etc ; pwd ; ls ; echo $BASH_SUBSHELL # echo $BASH_SUBSHELL返回0
(pwd ; ls ; cd /etc ; pwd ; ls ; echo $BASH_SUBSHELL) # echo $BASH_SUBSHELL返回1

 

4. 外部命令与内建命令

外部命令即存在于bash shell之外的程序,通常位于各类bin目录下,例如ps、sqlplus等。执行外部命令会自动forking出一个子进程,由子进程实际执行该外部命令。前面说过forking子进程需要额外代价,因此外部命令效率相对较低。

内建命令则是存在于bash shell中的程序,它们和shell编译成了一体,例如cd、exit等。

可以使用type查看命令是外部命令还是内建命令

type ps
type cd

 

二、 shell变量

编程语言总绕不过变量,shell也是一样。bash中每个变量都是字符串,都以字符串形式存储。

1. 变量分类及使用

  • 根据是系统自带还是用户自定义,分为:环境变量、用户定义变量
  • 根据作用范围又分为:全局变量、局部变量

① 环境变量

用于存储shell会话和工作环境信息,通常是事先定义好的。

  • 全局环境变量:对所有shell都可见
#查看所有与此终端相关的环境变量
env
#或
printenv

#查看进程环境变量
cat /proc/$PID/env

#查看单个环境变量值
printenv $ORACLE_HOME
echo $ORACLE_HOME
  • 局部环境变量:只对创建它们的shell可见。Linux中没有只显示局部环境变量的命令
#set 命令可显示为特定进程设置的所有变量,包括局部、全局环境变量、用户定义变量,还会按字母排序,输出通常很长
set

 

② 用户定义变量

  • 局部用户定义变量:在当前shell进程中创建的仅当前进程可见的变量(子进程不可见)

使用等号=定义

my_var=123  #等号两边不要有空格
echo $my_var
my_var2="Hello World"
echo $my_var2
#删除变量
unset my_var2
  • 全局用户定义变量:在当前shell进程创建的当前进程及其子进程可见的变量(注意对别的进程和其父进程还是不可见的)

使用export可将变量导出至全局环境(对其子进程可见)

 

2. 默认的shell环境变量

以下仅为部分,完整版非常长,大部分编程时也用不上,不列出了

variable_name variable_value instructions
BASH /bin/bash bash二进制执行文件
BASH_VERSINFO[0] 4 主版本号
BASH_VERSINFO[1] 2 次版本号
BASH_VERSINFO[2] 46 更新次数
BASH_VERSINFO[3] 2 构建次数
BASH_VERSINFO[4] release 分发状态
BASH_VERSINFO[5] x86_64-redhat-linux-gnu 架构
BASH_VERSION 4.2.46(2)-release bash版本号
DIRSTACK $PWD 当前目录
FUNCNAME 正在执行的函数的名字 可以放在函数里定位函数执行过程
GROUPS 0 当前登录的用户所属组的组id号,root默认为0
HOME /root 当前登录的用户家目录
HOMENAME 主机名 主机名
HOSTTYPE x86_64 设备硬件类型
IFS 内部域分隔,默认为空白,可以自定义设置 Bash 在解释字符串时如何识别域,或者单词边界
LINENO 记录其所在的行号 记录其所在shell脚本中的行号
MACHTYPE 系统硬件架构 系统设备

 

3. 定位系统环境变量

当登入Linux系统启动bash shell时,bash默认会在几个文件中查找可执行命令,这些文件称为启动文件或环境文件。

根据不同的bash启动方式,检查的启动文件有所不同:

  • 登录时作为默认登录shell
  • 非登录时的交互式shell
  • 非交互式shell

 

① 登录时作为默认登录shell

当登入Linux系统时,bash shell会作为登录shell启动,此时会从5个启动文件中查找可执行命令。

  • /etc/profile
  • $HOME/.bash_profile
  • $HOME/.bashrc
  • $HOME/.bash_login
  • $HOME/.profile

其中/etc/profile是共用的,是默认的主启动文件,每个用户登录时都会执行。

其余4个不一定存在,一般建在各用户家目录下,针对每个用户进行定制。shell会按照以下顺序运行第一个被找到的文件,其他则被忽略。

  • $HOME/.bash_profile
  • $HOME/.bash_login
  • $HOME/.profile

可以看到顺序中并没有$HOME/.bashrc文件,它的检查和调用包含在$HOME/.bash_profile中

可以看到$HOME/.bashrc做了两件事:

  • 定制命令别名
  • 查找/etc/bashrc文件(不建议修改),若存在则调用

 

② 非登录时的交互式shell

如果bash shell不是在登录时启动也不是在脚本中启动,而是类似在命令行中输入bash启动的,它就不会访问/etc/profile文件,只检查$HOME/.bashrc文件

 

③ 非交互式shell

运行脚本时的情况,bash会检查BASH_ENV环境变量,若设置则使用。若未设置,对于会启动子shell的脚本,会继承父shell的全局变量;对于不启动子shell的脚本,则执行进程为当前进程,可使用当前进程所有变量。

 

4. 数组变量

要给某个变量设置多个值,可以将值放在括号中并用空格分隔,不太常用但可以了解。

mydb=(oracle mysql mssql pg redis)
#仅显示第一个值
echo $mydb
#显示指定下标值(从0开始)
echo ${mydb[3]}
#显示所有值
echo ${mydb[*]}

 

参考:《Linux命令行与shell脚本编程大全》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章