天天看點

bash腳本程式設計

程式設計語言:

編譯器,解釋器

程式設計語言:機器語言,彙編語言、進階語言

靜态語言:編譯型語言

強類型(變量)

關鍵字:

事先轉換成可執行格式

c,c++,JAVA,C#

動态語言:解釋型語言 on the fly

弱類型

邊解釋變執行

php,shell,python,perl(面向過程)

面向對象:shell,c

面向對象:JAVA,Python,perl,C++

bash:腳本解釋器

程式設計能力:

腳本程式設計

變量:記憶體空間,命名的記憶體空間(可以回收)

記憶體:編址的存儲單元

程序:臨時存儲資料要用到變量

映射表:變量名和實體位址的映射

變量類型:

事先确定資料的存儲格式和長度

字元

數值

整型

浮點型:11.23(1.12310^1)(0.112310^2)

2013/10/10

布爾型:真假型 邏輯

邏輯運算:與、或,非、異或(相同為假,不同為真)

&, !

短路邏輯運算

與:其中一個為假,結果為假

或:其中一個為真,結果為真。

shell:弱類型程式設計語言

強:變量在使用前,必須事先聲明,甚至還需要初始化:

弱類型程式設計語言:變量用時聲明,甚至不區分類型:(預設為字元)

顯式轉換,隐式轉換

1+c=(ASCII)

10:16bit

10:1010,8bit

整型:8bit,256

0-255;溢出

緩沖區溢出:攻擊(填入資料前,先判斷)

變量指派:var_name=value

bash變量類型:

環境變量

本地變量(局部變量)

位置變量

特殊變量

本地變量:(作用域目前bash)

變量聲明: varname=value

局部變量(作用域為目前代碼)

local varname=value

bash:程序的變量
 echo $VAR_name
           

引用變量:${VARNMAE} $varname(防止混淆要用{})

''強引用

“” 弱引用

環境變量(作用域為目前shell程序及其子程序)

export varname=value
  “導出”
  varname=value
  export varname
           

腳本在執行時會啟動一個子shell程序,

指令行中啟動的腳本就會繼承目前shell環境變量

系統自動執行的腳本(非指令行啟動)就需要自我定義需要各環境變量。

位置變量:

$1,$2,$3,......

特殊變量:

$?:上一個指令的執行狀态傳回值(回傳碼)

程式執行結果

程式狀态傳回代碼(0-255)

0:表示正确

1-255:表示錯誤 1,2,127系統預留

id 使用者

echo $?

輸出重定向:

<

2>

2>>

&>

/dev/null:裝置,軟體裝置(軟體模拟) ,bit bucket,資料黑洞

id student &> /dev/null
echo $?
           

撤銷變量:

set (省略)
unset  varname
           

檢視目前shell的變量:(本地變量,環境變量)

set   (所有變量)
檢視目前shell中的環境變量
printenv
env
export
           

變量添加

animal=$animal:goat
animal=$animal:shell
export PATH=$PATH:/usr/local/apache/bin
export PATH=/usr/local/apache/bin/:$PATH
           

預設為字元串

腳本:指令的堆砌,按實際需求,結合指令流程控制機制實作的源程式。

ELF:可執行的連結的二進制檔案。

shebang:魔數
#!/bin/bash(可執行程式的路徑)
#:注釋行,不執行
chmod +x *.sh
./*.sh(獨立執行)


bash *.sh   (可以沒有執行權限)
           

練習:寫一個腳本:

1.添加5個使用者,user1,user5

2.每個使用者的密碼同使用者名,而且,添加密碼完成後不顯示passwd指令的執行結果

3.每個使用者添加完成後,都要顯示使用者某某已完成。

練習:寫一個腳本:

1.使用一個變量儲存一個使用者名

2.删除此變量中的使用者,且一并删除其家目錄

3.顯示“使用者删除完成”類的資訊。

條件判斷:

如果使用者不存在

添加使用者,給密碼并顯示添加成功。

否則

顯示已經存在,不添加。

bash中如何實作條件判斷:

條件測試類型:

整數測試

字元測試

檔案測試

條件測試的表達式:

[ expression ] (注意空格)

[[ expression ]]

test expression

整數比較:

-eq:測試兩個整數是否相等:比如   [ $A -eq  $B ]  echo $?
  -ne:測試兩個整數是否不等,不等為真,相等為假 
  -gt:測試一個數是否大于一個數:大于為真,小于為假
  -lt:測試一個數是否小于 一個數。
  -ge:測試一個數是否大于等于一個數
  -le:小于等于
           

指令間邏輯關系:

邏輯與: &&

第一個條件為假時,第二個條件不用再判斷了,最終結果已經有了

第一個條件為真時,第二個條件必須判斷。

邏輯或:|| 第一個條件為假時,第二個條件判斷

第二個條件為真時,第二個條件不判斷

(短路操作)

id user01 && echo "hello,user1"

id user1 || useradd user1

變量名稱:

1.隻能包含字母、數字、下劃線、并且不能數字開頭

2.變量名不能和系統變量同名

3.最好做到見名知義。

! id user2 && useradd user2
[ $FINELINE -gt 100 ] && echo "/etc/inittab is a big file " || echo "/etc/inittab is a small file"

id user1 && echo "user is exists" || useradd user
! id user && useradd user && echo "user exits"
! id userr &&  useradd user && echo "nihao"  | passwd --stdin user  || echo "user is exits" 
如果使用者存在,就顯示使用者已存在;否則,就添加此使用者;
id user1 && echo "user1 exists." || useradd user1

如果使用者不存在,就添加;否則,顯示其已經存在;
! id user1 && useradd user1 || echo "user1 exists."

如果使用者不存在,添加并且給密碼;否則,顯示其已經存在;
! id user1 && useradd user1 && echo "user1" | passwd --stdin user1  || echo "user1 exists."

條件判斷:控制結構:
單分支if語句:
if 判斷條件 ; then (如果then 和 if 不在一行  可以省略;)
     statement1
     statement2
     ....
fi 

雙分支的if語句:
if 判斷條件 ; then
    statement1
    statement2
    ....
    else
    statememt3
    ...
fi 

        userid=`id -u $username` 
    if [ $userid -eq 0] ;then
         echo "it is admin"
         else
           echo  "it is not admin"
    fi

if id $name ;then
    判斷使用者是否存在
    
    
#!/bin/bash
username=user1
userid=`id -u $useranme`
groupid=`id -g $useranm`
if [ $userid -eq $groupid ] ;then
  echo "good guy"
  else
       echo "bad guy"
fi
           

shell中進行算術運算:

a=1
b=2 
let: 讓字元轉換成數值進行算術運算
1.let 算術運算表達式
   let c=$a+$b 
2.$[算術運算表達式]
  c=[$a+$b]
3.$((算術運算表達式))
   c=(($a+$b)
4.expr 算術運算表達式   (注意表達式中各操作數及運算符之間要有空格) 
c=`expr $a + $b`
           

提前結束腳本

exit:退出腳本。可以自定義回傳碼(指令執行狀态碼),沒有跟數字,預設最後一次執行的狀态碼。
   exit 數值#
           

測試方法:

[  expression ]指令 
[[ expression ]] 關鍵字 
test expresión
           

bash常見的測試有三種:

整數測試:

-gt
-le;
-ne
-eq
-lt
-ge:

[ $a -eq 4b ]
[[ $a -eq $b ]]
test $a -eq $b

 
檔案測試:
-e file   :測試檔案是否存在
-f  file   測試檔案是否為普通檔案
-d file    測試檔案是否為目錄
-r  file   測試目前使用者對指定檔案是否有讀取的權限
-w   file  
-x   file 
 [  -e /etc/inittab ]
 [ -w /etc/rc.d/rc/sysconfig ]   
 
if [ ! -e $FILE ];then 
 echo ""
  exit 0

圓整:丢棄小數點後的數。
           

多分支的if語句

if 判斷條件1; then
  statement1
  .......
  elif  判斷條件2;then
      statement2
      ......
      elif   判斷條件3;then
           statement3
           ...
        else
           statement4
           ....
fi
           

測試腳本是否有文法錯誤:

bash -n file.sh
bash -x 腳本  單步執行指令
           

編寫一個腳本

給定一個檔案,如果是普通檔案,就顯示
如果是目錄,就顯示目錄,否則此為不能識别。

#!/bin/bash

FILE=/etc/rc.d/rc.sysconfig
if [ ! -e $FILE ];then
    echo "NO such file"
fi
if  [ -f $FILE ];then
   echo "common file"
   elif [ -d $FILE ];then
      echo "$FILE is directory "
      else
        echo "UNknown"
fi

定義退出狀态碼
exit:退出腳本
exit #
如果腳本沒有明确定義退出狀态碼,那麼執行最後一條指令的的狀态碼即為腳本的退出狀态碼。
           

bash變量的類型:

本地變量(局部變量):作用域隻是目前shell

環境變量:作用域是目前shell,及其子shell

位置變量:$1,$2,$3....

shift:輪替 位置參數的輪替。
 #!/bin/bash
 echo $1
 shift
 echo $
 shift
 echo $1 
 shift
 
 shift #:一下輪替n個
 

 
./filetest.sh  /etc/fstab /etc/inittab
$1: /etc/fstab
$2: /etc/inittab

           

$?:
$#:參數的個數
$*:參數清單
$@:參數清單

           

練習:寫一個腳本

能接受一個參數(檔案路徑)

判定:此參數

#!/bin/bash

if [ $# -eq 0 ];then
echo""
 exit 0
if [ ! -e $1  ];then
    echo "NO such file"
fi
if  [ -f $1  ];then
   echo "common file"
   elif [ -d $1  ];then
      echo "$1  is directory "
      else
        echo "UNknown"
fi   
           

$?:
$#:參數的個數
$*:參數清單
$@:參數清單
           

字元串測試:

==或=:   [ $a == $b ]  (等号兩端要有空格)
!=:測試是否不等,不等為真,相等為假。
>
<
=>
<=

-n string :測試指定字元串是否為空,空為真,不空為假。
-s  string :測試指定字元串是否為空,空為假,不空為真。

#!/bin/bash
if ! id $1 &> /dev/null;then
      echo "no user"
        exit 1
fi
if [ `id -n -u $1` == `id -n -g $1` ];then
   echo      "yiyang"
   else
         "buyiyang"
fi

if  [ $1 == "q" ];then
    echo "quiting..."
   exit 1
   elif [ $1 == 'Q' ];then
     echo "quiting.."
     exit 2
     esle 
     exit 3
fi

echo "scale=2;111/22;" | bc
bc <<<  "scale=2;111/22;"(注意3個小于号)

           

循環:進入條件,退出條件

for
while
until

for   變量 in 清單;do
       循環體
     done

for i in 1 2 3 4 5 6 7 8 9 10;do
    加法運算
    done
    
    周遊完成後,退出。


如何生成清單:
{1..100}
seq  起始數 步進長度  結束數


#!/bin/bash

let sum=0
for i in {1..100};do
   let sum=$sum+$i
done 
echo "$sum"
           

decalre -i sum

declare  
  -i:整型 
  -x :聲明為環境變量
  
取模,取餘 %

           

測試:

整數測試:
  -le
  -lt
  -ge
  -gt
  -eq
  -ne
字元測試:
  ==
 !=
  >
  <
  -n
  -z
檔案測試:
 -f 
  -d
 -r
  -x
 -w
  -e 
if [ $# -gt 1 ];then
組合測試條件:
    -a:與關系
    -o:或關系
     !:非關系

if [ $# -gt 1 -a $# -le 3  ]
if [ $# -gt 1 ] && [ $# -le 3 ]

Q,q,quit 
if [ $1 == q -o $1 == Q  -o  $1 == quit -o $1 == Quit ];then
        echo "quiting"
       exit 1
fi

let i=$[$i+1]
let sum=$[$sum+$i]
let sum+=$i

let i+=1 
let i++

-=  i--
*=
/=
%=

++i,--i  
           

面向過程:

控制結構:

順序結構

選擇結構

循環結構

選擇結構:

if:單分支、雙分支的,多分支

if condaiction;then

statment

.....

fi

if condation;then

....

else

if condation;then

..

elif condation;then

statment;

case語句:選擇結構

case switch in

value)

;;

value2)

*)

esac

由鍵盤輸入一個字元,給出判斷?

case.sh
#!/bin/bash

case $1 in
[0-9]) 
   echo "a digtal";;
[a-z]) 
    echo "lower";;
[A-Z])
  echo "upper";;
  *)
    echo "unknown";;
esac

隻接受參數,start,stop,restart,status

#!/bin/bash
 case $1 in 
 'stat')
    echo "start server...";;
'restart')
   echo "restart server...";;
 'stauts')
   echo "stuts service...";;
   *)
     echo "`basename $0` {start |stop |restart |status}";;
     esac
     
#!/bin/bash
case $1 in
-y|--verbose)
  debug=1 
  ;;
  *)

           

腳本程式設計:

case

循環結構:

for

while

until

while循環:适用于循環次數未知的情況下,必須要有退出條件。
文法: 
     while condition ; do 
          statemant
          ....
          done 
計算100以内正整數的和:
#!/bin/bash 
declare  -i i=1 
declare -i sum=0 
 while [ $i -le 100  ];do
    let sum+=$1 
      let $i+=1
    done

    
  read -p "please input string" string 
while [  $string != 'quit' ];do
     echo $string |tr 'a-z'  'A-Z'
     read -p "please input string "string 
     done 
    
    
    
while [ 1 -eq 1 ] 
or
while true
or
while ((1))
or
while [[ 1 ]]
or 
while :  


while循環 
while ,until,for 
break:提前退出循環
continue:退出本次循環,進行下一次循環。

while的特殊用法一:
while : ;do

done 
while的特殊用法二:
while read LINE;do

done </path/to/somefile

           

函數:功能 function

代碼重用:

庫:so

函數:就是把其中某個特定的功能的代碼封裝起來,進行調用。
定義函數:
function FUCname {
    command

}
FUncname() {
command

}

function showmenu {
}
函數不能直接執行,必須調用才行。
showmenu

自定義狀态傳回值
return #

#!/bin/bash
ADD() {
a=9
b=7
let c=$a+$b`
echo $c
}
ADD
sum=`ADD`
echo $sum
let m=1
sm=$[$m+`ADD`]  #函數執行結果引用  ``

ADD 
echo $?    執行狀态結果 
bash -x *.sh 逐漸執行顯示
注意:執行結果,狀态結果
           

函數的執行狀态結果是最後一條指令的執行結果的狀态傳回值。

自定義狀态傳回值
return  #
0--255

if [ $? -eq 0 ];then
echo ""
else 
   fi
根據傳回結果判斷程式執行成功與否

接受參數的函數:
./a.sh aa bb cc
位置參數:
$1:
$2:
函數的參數:
ADD 5 6
$1 
$2 :函數參數

ADD(){
  echo $[$1+$2]
}
ADD 5 6
sum=`ADD 5 6`
echo $sum 
echo "$i+$j=`ADD $i $j`"

#!/bin/bash
PING() {
    if ping -c 1 -W 1 $1 &> /dev/null; then
     return 0 
   else
    return 1 
  fi
}
for i in {200..254};do
  PING 192.168.0.$i
  if [ $? -eq 0 ];then 
    echo "192.168.0.$i is up"
    else 
    echo "192.168.0.$i is down"
    fi 
  done
for i in {220..254};do
  PING 172.16.0.$i
done

if ping 192.168.0.$i ;then
傳回執行狀态結果。 
``:引用echo結果