Linux bash shell環境變量以及語法規範

bash環境加載

Login Shell讀取配置文件流程


而非登錄shell僅僅會讀取 ~/.bashrc


bash的登錄與歡迎信息

/etc/issue 文件: 記錄了bash登錄前的歡迎信息,相關信息可以用 man issue 查看

/etc/motd 文件: 記錄了bash登錄成功後的歡迎信息


bash的環境配置文件

 login shell: 在輸入帳號密碼登錄的時候取得的bash,例如從tty1-tty6登錄

non-login shell: 取得bash不需要完整的登錄流程,例如在圖形界面開啓Terminal



語法結構規範

賦值語句 : var=value

變量解析 : ${var}

命令解析 : ${command}

雙引號 " " : 變量內容,並做轉義

單引號 ' ' : 變量內容,但不做轉義 

反單引號 ` ` : 同 $()

End Of File  : "EOF"

複製代碼
alexis@Smilodon:~$ version=v1.0
alexis@Smilodon:~$ echo $version
v1.0
alexis@Smilodon:~$ v2="$(uname) abc ${version}"
alexis@Smilodon:~$ echo $v2
Linux abc v1.0
alexis@Smilodon:~$ echo "$LANG"
en_US.UTF-8
alexis@Smilodon:~$ echo '$LANG'
$LANG
alexis@Smilodon:~$ echo `uname -r`
3.2.0-33-generic-pae
複製代碼


Shell命令結構和規範

Shell作爲外圍軟件生態羣其中一個非常重要的組件。它是操作系統最外層的接口,負責直接面向用戶交互並提供內核服務,包括命令行接口(CLI)或圖形界面接口(GUI)兩種形式。以CLI爲例,它提供一套命令規範,是一種解釋性語言,將用戶輸入經過解釋器(interpreter)輸出使其轉化成真正的系統調用,實現人機交互的功能。

命令結構和規範
Thompson Shell命令語言結構和規範的基礎,其解釋器具有跨平臺的可移植性,並影響到了後來包括Bourne Shell在內的各種腳本語言設計實現。Bourne Shell的5個特性和命令規範,可以通過sh(1)手冊查看原始資料。

過濾器/管道線(filter/pipeline)。這絕對是要載入Unix史冊的發明,創立者是Douglas McIlroy,Thompson Shell引入並實現了這個偉大的概念——一個或多個命令組成一根過濾器的鏈條,由’|'或’^'符號分隔。除最後一個命令之外,每個命令的標準輸出都被作爲下一個命令的標準輸入。這樣每個命令都作爲一個獨立的進程來運行,並通過管道與鄰近的進程相連接。圓括弧內的命令序列整體上可以替代單個命令作爲過濾器實現,比如用戶可以輸入”(A;B)|C”。

命令序列和後臺進程。分號’;'指示多個命令序列化執行。’&’符號指示該命令在後臺異步執行,使得前面的管道線不必等待其終止,僅僅報告一個進程id,這樣用戶以後可以通過kill命令與它通信。有益於進程管理。


I/O重定向。它利用了Unix設計上的一個重要特性——一切皆文件,用三個符號表示:”重定向輸出,如果文件不存在則創建它,如果文件存在則截斷它;’>>’追加模式重定向輸出,如果文件不存在則創建它,如果文件存在則追加輸出至末尾處。


通配符擴展(globbing)。通配符的概念源自於正則表達式,使得解釋器智能地處理用戶不完全輸入,比如記不清文件名、一次性輸入多個文件等。’?'匹配任意單一字符;’*'匹配任意字符串(包括空串);成對’['和']‘定義了字符集合一個類,可匹配方括號內任意成員,用’-'兩端可指定一系列連續字符匹配範圍。


參數傳遞。這裏主要引入了位置參數和選項參數的概念:’$n’指示shell調用的第n個參數替代;還定義了兩個選項參數’-t’和’-c’,前者用於交互,導致shell從標準輸入中讀入一行作爲用戶執行的系統命令,後者指示shell將附帶的下一個參數作爲命令執行(可正確處理換行符),是對’-t’的補充,特別是調用者已經讀取了命令其中某些字符的情況下。如果不帶選項參數則直接讀取文件名。


注:

通配符(wildcard)

*:  代表任意個任意字符

?: 代表1個任意字符

[abc]: 代表a或b或c中的一個

[a-z]: 代表 a~z這個範圍

[^abc] : 代表除了a或b或c以外的字符


數據流重定向:

0: STDIN 標準輸入

1: STDOUT 標準輸出

2: STDERR 標準錯誤輸出

>, >>: 輸出流重定向, > 爲 覆蓋,>> 爲追加 

cat infile 1> outfile 2>&1

將 2 重定向到 1, 再將 1 重定向到 outfile 文件,意思是將標準錯誤輸出和標準輸出都存入outfile

find /home 2> /dev/null

將錯誤輸出 /dev/null, /dev/null是垃圾黑洞,可以將信息忽略

< : 輸入重定向

cat > catfile < ~/test

用 test 文件的內容代替STDIN輸入到 catfile裏

<<: eof符號

cat > catfile << 'eof'

你可以使用STDIN(鍵盤輸入)來輸入到catfile,當輸入eof時,輸入結束,相當於點了 ctrl + d


命令執行依據 ; && ||

; : 順序執行

&& : 且 邏輯, cmdA && cmdB, 只有cmdA成功了纔會繼續執行cmdB,成功的依據就是 $? 這個狀態回傳碼

|| : 或邏輯, cmdA || cmdB 只有cmdA執行失敗纔會繼續執行cmdB

 

管道(pipe | )

管道可以將前一個命令的stdout當作後一個命令的stdin,只有特定的管道命令才能使用

管道命令有 cut,grep,sort,wc,uniq,tee,tr,col,join,paste,expand等

而ls cd這些命令則不是管道命令,如果需要使用管道則需要用xargs作參數代換


- 號的用途

- 號可以代替 STDOUT STDIN

tar -czv -f - /home | tar -xzv -f -

第一個 - 代替stdout,第二個 - 代替stdin,想當於用tar來實現cp


算數運算

$((a*b)) : 計算a與b的乘積,只支持整數 


變量操作

export與子進程:

如果需要在子進程(在一個shell中打開另一個shell)中使用父進程的變量,則需要使用export將自定義變量轉爲環境變量

複製代碼
alexis@Smilodon:~$ name=alexis
alexis@Smilodon:~$ echo $name
alexis
alexis@Smilodon:~$ bash
alexis@Smilodon:~$ echo $name

alexis@Smilodon:~$ exit
alexis@Smilodon:~$ export name
alexis@Smilodon:~$ bash
ealexis@Smilodon:~$ echo $name
alexis
alexis@Smilodon:~$ exit
複製代碼

unset: 取消變量

alexis@Smilodon:~$ name=liu
alexis@Smilodon:~$ echo $name
liu
alexis@Smilodon:~$ unset name
alexis@Smilodon:~$ echo $name


read, array, declare

read: 讀取用戶輸入到某個變量

alexis@Smilodon:~$ read -p "Please enter your name: " name
Please enter your name: Alexis
alexis@Smilodon:~$ echo $name
Alexis

屏幕會輸出 Please enter your name: 並等待用戶輸入,最後將輸入賦值到name


array: bash數組的賦值與輸出

複製代碼
alexis@Smilodon:~$ arr[0]=1
alexis@Smilodon:~$ arr[1]=2
alexis@Smilodon:~$ arr[2]=3
alexis@Smilodon:~$ echo ${arr}
1
alexis@Smilodon:~$ echo ${arr[1]}
2
alexis@Smilodon:~$ echo ${arr[2]}
3
複製代碼


declare: 聲明變量類型

declare -x name: 將 name 變成環境變量

declare +x name: 將 name 恢復成自定義變量

declare -i product=10*10: 將product定義成整形,這樣後面的表達式就會得到計算

alexis@Smilodon:~$ declare -i product=10*10
alexis@Smilodon:~$ echo $product
100

declare -r name: 將 name 定義成只讀變量

declare -a product: 將 product 定義成數組類型

declare -p product: 查看 product 的類型信息


變量微調

變量內容的刪除

複製代碼
alexis@Smilodon:~$ path=${PATH}
alexis@Smilodon:~$ echo ${path}
/usr/local/glassfish3/jdk7/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
alexis@Smilodon:~$ echo ${path#/*bin:}
/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
alexis@Smilodon:~$ echo ${path}
/usr/local/glassfish3/jdk7/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
alexis@Smilodon:~$ echo ${path##/*bin:}
/usr/games
複製代碼


${path#/*bin:}

path: 需要微調的變量名

#: 從左邊開始刪除所匹配的最短的字符串,類似與正則裏的非貪婪匹配

##: 表示從左邊開始刪除匹配的最長的字符串,類似與正則的貪婪匹配

/*bin: : 表示以 / 開頭, *是通配符表示任意個任意字符, 以 bin: 結尾的字符串

注意執行這個表達式以後原來的path並不會被修改,我們只是將修改後的值輸出了而已

如果要從右邊開始匹配則用 % , %% 替換 #, ##


 變量內容的替換

var=${str-val}: 當變量str未設置,則 var=val, 若變量str已經設置,則var=str

var=${str:-val}: 當變量str未設置或者爲空串, 則var=val

var=${str+val}: 當變量str已經設置, 則var=val,否則var=空串

var=${str:+val}: 當變量str已經設置且非空串,則var=val,否則var=空串

var=${str=val}: 若str已經設置,則var=val,str不變,若str未設置,則var=str=val

var=${str:=val}: 若str已經設置且非空,則var=val,str不變,若str未設置或爲空串,則var=str=val

var=${str?val}: 若str未設置,則輸出str到stderr,若str已經設置,則var=str

var=${str:?val}: 若str爲設置或者爲空串,則輸出str到stderr,若str已經設置切非空,則var=str



source命令*--shell腳本編寫

source命令用於運行shell腳本,它與bash/sh或者直接以路徑運行腳本的區別在於,source是在父進程中運行,而bash是在子進程中運行,在子進程中產生的變量在父進程中將不可見,所以在運行系統配置腳本的時候應該使用source

文件比較運算符
  運算符                            描述                                            示例
  -e filename        如果 filename 存在,則爲真             [ -e /var/log/syslog ]
  -d filename        如果 filename 爲目錄,則爲真         [ -d /tmp/mydir ]
  -f filename         如果 filename 爲常規文件,則爲真 [ -f /usr/bin/grep ]
  -L filename        如果 filename 爲符號鏈接,則爲真  [ -L /usr/bin/grep ]
  -r filename         如果 filename 可讀,則爲真              [ -r /var/log/syslog ]
  -w filename       如果 filename 可寫,則爲真              [ -w /var/mytmp.txt ]

  $? 上一個指令的返回值


比較運算符

  -x filename         如果 filename 可執行,則爲真           [ -L /usr/bin/grep ]



$# 與 $@

$0 : 腳本名稱

$1 , $2 , $3 ... : 參數 1 2 3 ...

$# : 腳本參數個數

$@ : 腳本所有參數名

if ... elif ... then ... fi 條件判斷語句

複製代碼
#!/bin/bash
# 使用 if then else fi 獲取端口狀態

testing=$(netstat -tualn | grep ":80")
if [ "$testing" != "" ]; then
    echo "WWW port 80 is running in your system"
fi

testing=$(netstat -tualn | grep ":21")
if [ "$testing" != "" ]; then
    echo "FTP port 21 is running in your system"
fi

testing=$(netstat -tualn | grep ":22")
if [ "$testing" != "" ]; then
    echo "SSH port 22 is running in your system"
fi

testing=$(netstat -tualn | grep ":25")
if [ "$testing" != "" ]; then
    echo "MAIL port 25 is running in your system"
fi 
複製代碼

case ... esac 選擇語句

複製代碼
#!/bin/bash
#test case ... esac

echo "Exit system?"
echo "1.yes 2.no"
read -p "Enter your choice: " choice
case $choice in
    "1")
        echo "Exit now"
        ;;
    "2")
        echo "Not exit"
        ;;
    *)
        echo "Plase enter 1 or 2"
        ;;
esac
複製代碼

function函數

複製代碼
#!/bin/bash
#use function()

function printit() {
    echo "$0 Printing $1"
}

printit "myparam"
複製代碼

while 循環

複製代碼
#!/bin/bash
# test while loop

while [ "$yn" != "yes" -a "$yn" != "no" ]
do
    read -p "Please input yes/no: " yn
done
echo "Good!"

i=0
s=0
while [ "$i" -lt 100 ]
do
    i=$(($i+1))
    s=$(($s+$i))
done
echo "The sum is $s"
複製代碼

for的用法

1.使用 for ... in ... do ... done 

複製代碼
#!/bin/bash
# test for ... in ... do ... done

# 查看子網是否聯通
ip="192.168.1"

for sitenu in $(seq 1 100)
do
    ping -c 1 -w 1 "${ip}.${sitenu}" &> /dev/null && result=1 || result=0
    if [ "$result" == 1 ]; then
        echo "${ip}.${sitenu} is ON"
    else
        echo "${ip}.${sitenu} is DOWN"
    fi
done
複製代碼
複製代碼
#!/bin/bash

#查看目錄下所有文件權限

read -p "Enter a directory: " dir

if [ "$dir" == "" -o ! -d "$dir" ]; then
    echo "The $dir is NOT exist in your system."
    exit 1
fi

filelist=$(ls $dir)
for filename in $filelist
do
    perm=""
    test -r "$dir/$filename" & perm="$perm readable"
    test -w "$dir/$filename" & perm="$perm writable"
    test -x "$dir/$filename" & perm="$perm executable"
    echo "The file $filename's permission is $perm"
done
複製代碼

2. 使用 for (()) 語法

複製代碼
#!/bin/bash
# test for

if [ $# != 1 ]; then
    echo "Usage $0 {maxnum}"
    exit 1;
fi

s=0
for (( i=1; i<=$1; i++ ))
do
    s=$(($s+$i))
done

echo "The sum of 1+2+3..+$1 is $s"
複製代碼
複製代碼
 1 #!/bin/bash  #表明該腳本使用sh或bash
 2 #This is a sample
 3 
 4 #usage of variable
 5 year=1999;  #變量賦值語句
 6 
 7 #usage of expression
 8 year=`expr $year + 1`;  #變量運算,使用expr或let
 9 echo $year
10 year="olympic'"$year  #字符串直接連接,不需要連接符
11 echo $year
12 
13 #usage of if statement  
14 if [ $year = 1999 ]
15 then
16 echo "greate"
17 else
18 echo "not greate"
19 fi  #語句使用相反的單詞結束
20 
21 #usage of function and local variable
22 function echoyear {
23     local year=1998;  #局部變量使用local修飾
24     echo $year
25 }
26 echo $year;
27 echoyear;  #函數調用
28 
29 #usage of for loop
30 for day in Sun Mon Tue Ooo  #for語句,day爲循環變量,in後面的是循環內容
31 do
32 echo $day
33 done
34 
35 # usage of while loop and array
36 users=(Jim Liu Dick Jack Rose)  #數組賦值
37 i=0
38 while [ ! -z ${users[$i]} ]  #數組取值使用${users[$i]}
39 do
40 echo ${users[$i]}
41 i=`expr $i + 1`
42 done
43 
44 # usage of util
45 var="I'm not empty"
46 until [ -z "$var" ];do #字符串變量需要用雙引號括起,否則會拋出"too many argumet"異常,因爲腳本會認爲每個空格隔開的字符串都是一個參數47
48 echo $var
49 var=
50 done
51 
52 # usage of case and input from keyboard
53 echo "Hit a key, then press return" 
54 read Keypress  #從鍵盤讀入輸入
55 
56 case "$Keypress" in  #使用case語句
57 [a-z]) echo "Lowercase letter";;  #選擇符可以使用正則匹配
58 [A-Z]) echo "Uppercase letter";;
59 [0-9]) echo "Digit";;
60 *) echo "Other";;
61 esac
62 
63 # usage of function
64 function pow() {  #函數參數使用$1, $2表示第一個參數和第二個參數,以此類推
65     local res=`expr $1 \* $1` # use \* instead of * here
66     return $res
67 }
68 param=5
69 pow $param  #函數傳參
70 result=$?  #$?代表函數返回值,$#代表參數個數,$@代表所有參數集合
71 echo $result
72 
73 # usage of random digit
74 a=$RANDOM  #隨機數的使用
75 echo $a
76 
77 # usage of select
78 OPTIONS="Hello Quit"
79 select opt in $OPTIONS  $使用select自動產生選項供用戶選擇
80 do
81     case $opt in
82         "Hello") 
83             echo "Hello There"
84             ;;
85         "Quit") 
86             echo "Done"
87             ;; 
88         *) 
89             echo "Bad Option"
               ;;
90     esac
91 done
92 
93 # usage of read
94 echo "Insert your name";
95 read name  #鍵盤輸入數據
96 echo "Hi "$name
複製代碼


環境變量

環境變量就是系統或軟件設置的一些參數,用戶環境變量就是用戶登錄系統後,都有自已專用的運行環境。在Windows系統中用戶環境變量保存在用戶家目錄,Linux也是同樣的。Linux常用的環境變量和環境變量的設置。

PATH環境變量作用是決定了shell將到哪些目錄中尋找命令或程序。arm-linu-gcc屬於命令。

export PATH=$PATH:/usr/local/arm/3.4.1/bin意思是讓PATH以前的值($PATH)和新設的環境變量值(/usr/local/arm/3.4.1/bin)並列,通過符號進行分離。因爲arm-Linux-gcc只有在/usr/local/arm/3.4.1/bin下才存在,所以在執行時就能通過符號分離出arm-linux-gcc的路徑爲/usr/local/arm/3.4.1/bin

在用戶目錄下用ls -a,能看見很多“.”開頭的隱藏文件。如果不是用戶建立的,那麼這些文件都是環境設置文件。有其它Shell的設置文件,也有軟件設置的文件。比如:.lftp,它就是lftp軟件的設置文件。如果安裝了x-window的話,菜單和桌面設置都在.local裏面。


開啓啓動Xwindow,有些Linux發行版不會加載SHELL環境變量,因爲Xwindow有自已的會話設置。例如gnome,有~/.gnomerc 或 /etc/X11/Xsession.d/55gnome-session_gnomerc。


以下內容說明特殊符號的用法

export A=/q/jing:aaa/cc/ld

export B=.:/liheng/wang

export A=/cd/cdr:$A

大家注意紅色的符號:

: 表示並列含義,例如A變量值有多個,用:符號進行分離。

.表示你操作的當前目錄。例如pap命令會查找B環境變量。

在/home鍵入pap命令,系統首先在/home目錄下(即當前路徑)查找關於 B 的內容,如果沒有在/liheng/wang目錄下查找關於B的內容。

$ 表示該變量本次定義之前的值,例如$A代表/q/jing:aaa/cc/ld。也就是說A=/cd/cdr:/q/jing:aaa/cc/ld



環境變量相關操作--只應用於當前,要永久保存需要寫入到相關文件

#echo $PATH

顯示PATH設置。

#env

顯示當前用戶變量。

#set

顯示當前Shell變量。

#export

顯示當前導出成用戶變量的shell變量。

#a=abc

定義一個Shell變量。

#export a=abc

定義一個Shell變量,並導出成用戶變量。

#unset a

清除環境變量

#readonly a

設置只讀環境變量


常見的環境變量

PATH      決定了shell將到哪些目錄中尋找命令或程序

HOME       當前用戶主目錄

HISTSIZE     歷史記錄數

LOGNAME     當前用戶的登錄名 

HOSTNAME   指主機的名稱

SHELL      前用戶Shell類型 

LANGUGE     語言相關的環境變量,多語言可以修改此環境變量

MAIL      當前用戶的郵件存放目錄 

PS1       基本提示符,對於root用戶是#,對於普通用戶是$

PS2       附屬提示符,默認是“>”


幾個重要的環境變量

$OSTYPE: 操作系統類型

$HOSTTYPE:  主機默認安裝的軟件主要類型,32位的有 i386, i586, i686, 64位爲 x86_64

$MACHTYPE:  安裝的機器類型

$$: 當前shell的PID

$?: 上一個命令的返回值,如果上一個命令執行成功則返回0

$0 這個程序的執行名字

$n  這個程序的第n個參數值,n=1...9

$*  這個程序的所有參數
$# 這個程序的參數個數
$! 執行上一個背景指令的PID

Linux環境變量設置文件

/etc/profile

全局用戶,應用於所有的Shell。

/$HOME/.profile

當前用戶,應用於所有的Shell。

/etc/bash_bashrc

全局用戶,應用於Bash Shell。

~/.bashrc

局部當前,應用於Bash Sell。


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