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腳本編程大全》

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