shell腳本編程初步入門

shell腳本編程初步入門

   說到shell腳本編程,那我們就來先看下shell,shell既是一種命令語言,又是一種程序設計語言。作為命令語言,它交互式地解釋和執行用戶輸入的命令;作為程序設計語言,它定義了各種變量和參數,并提供了許多在高級語言中才具有的控制結構,包括循環和分支。它雖然不是Linux系統內核的一部分,但它調用了系統核心的大部分功能來執行程序、建立文件并以并行的方式協調各個程序的運行。因此,對于用戶來說,shell是最重要的實用程序,深入了解和熟練掌握shell的特性極其使用方法,是用好Linux系統的關鍵。

   Shell有兩種執行命令的方式:

      交互式:解釋執行用戶的命令,用戶輸入一條命令,Shell就解釋執行一條。

      批處理:用戶事先寫一個Shell腳本(Script),其中有很多條命令,讓Shell一次把這些命令執行完,而不必一條一條地敲命令。

   大體上,可以將程序設計語言可以分為兩類:編譯型語言和解釋型語言。

      編譯:高級語言–>編譯器–>目標代碼 例如:java,C# 

      解釋:高級語言–>解釋器–>機器代碼 例如:shell, perl, python

   Linux上常見的Shell有bash、sh、csh、ksh等,bash是Linux標準默認的shell,我們這里講到的就是現階段運用最多的bash。

   shell腳本是包含一些命令或聲明,并符合一定格式的文本文件。

編寫shell腳本:

1、格式要求:首行shebang機制 

    #!/bin/bash

    #!/usr/bin/python

    #!/usr/bin/perl

  打開文本編輯器,新建一個文件,擴展名為sh(sh代表shell),擴展名并不影響腳本執行。看下面的例子:

    #!/bin/bash

    echo "Hello World !"

    “#!” 是一個約定的標記,它告訴系統這個腳本需要什么解釋器來執行,即使用哪一種Shell。echo命令用于向窗口輸出文本。

2、運行腳本

   給予執行權限,在命令行上指定腳本的絕對或相對路徑,將上面的代碼保存為test.sh,并 cd 到相應目錄;

    chmod +x ./test.sh     使腳本具有執行權限

    ./test.sh              執行腳本

   直接運行解釋器,將腳本作為解釋器程序的參數運行

   bash /bin/test.sh

腳本調試:

   bash -n /path/to/some_script 檢測腳本中的語法錯誤

   bash -x /path/to/some_script 調試執行

變量

   變量:命名的內存空間。

變量類型:

   強類型:定義變量時必須指定類型、參與運算必須符合類型要求;調用未聲明變量會產生錯誤如:java,python

   弱類型:無須指定類型,默認均為字符型;參與運算會自動進行隱式類型轉換;變量無須事先定義可直接調用如:bash不支持浮點數

變量命名法則:

   1、不能使程序中的保留字:例如if, for;

   2、只能使用數字、字母及下劃線,且不能以數字開頭

   3、見名知義

   4、統一命名規則:駝峰命名法。

bash中變量的種類:

   環境變量:導出一個變量,作用域為當前shell進程及其子進程

      export NAME=VALUE;declare -x name=VALUE

      變量引用:$name, ${name}

      顯示所有環境變量: export  env  printenv

      刪除:unset name

   本地變量:NAME=VALUE:作用域為整個bash進程

      變量賦值:name=‘value’

      可以使用引用value:

       (1) 可以是直接字串;name=“root"

       (2) 變量引用:name="$USER"

       (3) 命令引用:name=`COMMAND`, name=$(COMMAND)

       變量引用:${name}, $name 

       "":弱引用,其中的變量引用會被替換為變量值

       '':強引用,其中的變量引用不會被替換為變量值,而保持原字符串。

       顯示已定義的所有變量:set

       刪除變量:unset name

   局部變量:作用域為當前代碼段

   只讀變量:只能聲時,但不能修改和刪除

       readonly name

       declare -r name

Shell特殊變量:$0, $#, $*, $@, $?

    $1, $2, …:對應第1、第2等參數,shift [n]換位置

    $0: 命令本身

    $*: 傳遞給腳本的所有參數,全部參數合為一個字符串

    $@: 傳遞給腳本的所有參數,每個參數為獨立字符串

   ($@ $* 只在被雙引號包起來的時候才會有差異)

    $#: 傳遞給腳本的參數的個數

    $?:上個命令的退出狀態,或函數的返回值。

看下面的例子:

[root@centos7 ~]# ./test.sh zhl zanghl
File Name: ./test.sh
First : zhl
Second : zanghl
Quoted Values: zhl zanghl
Quoted Values: zhl zanghl
Total Number of Parameters : 2
[root@centos7 ~]# cat test.sh 
#!/bin/bash
echo "File Name: $0"
echo "First : $1"
echo "Second : $2"
echo "Quoted Values: $@"
echo "Quoted Values: $*"
echo "Total Number of Parameters : $#"

$* 和 $@ 的區別

   $* 和 $@ 都表示傳遞給函數或腳本的所有參數,不被雙引號"" 包含時,都以"$1" "$2" … "$n" 的形式輸出所有參數。但是當它們被雙引號""包含時,"$*" 會將所有的參數作為一個整體,以"$1 $2 … $n"的形式輸出所有參數;"$@" 會將各個參數分開,以"$1" "$2" … "$n" 的形式輸出所有參數。

這里我們引用網上一個資料中的例子來看一下:

程序是這樣的:

#!/bin/bash
echo "\$*=" $*
echo "\"\$*\"=" "$*"
echo "\$@=" $@
echo "\"\$@\"=" "$@"
echo "print each param from \$*"
for var in $*
do
    echo "$var"
done
echo "print each param from \$@"
for var in $@
do
    echo "$var"
done
echo "print each param from \"\$*\""
for var in "$*"
do
    echo "$var"
done
echo "print each param from \"\$@\""
for var in "$@"
do
    echo "$var"
done
執行 ./test.sh "a" "b" "c" "d",看到下面的結果:
$*=  a b c d
"$*"= a b c d
$@=  a b c d
"$@"= a b c d
print each param from $*
a
b
c
d
print each param from $@
a
b
c
d
print each param from "$*"
a b c d
print each param from "$@"
a
b
c
d

邏輯運算:

true 1, false 0

  與: 1 與 1 = 1

     1 與 0 = 0

     0 與 1 = 0

     0 與 0 = 0 

 或:

     1 或 1 = 1

     1 或 0 = 1

     0 或 1 = 1

     0 或 0 = 0

 非:!

     ! 1 = 0

     ! 0 = 1 

短路運算:

     短路與:第一個為0,結果必定為0;第一個為1,第二個必須要參與運算;

     短路或:第一個為1,結果必定為1;第一個為0,第二個必須要參與運算;

     異或:^ 異或的兩個值,相同為假,不同為真

條件測試:

    判斷某需求是否滿足,需要由測試機制來實現;

    專用的測試表達式需要由測試命令輔助完成測試過程;若真,則返回0 若假,則返回1

測試命令:

     test EXPRESSION

     [ EXPRESSION ]

     [[ EXPRESSION ]] 

     注意:EXPRESSION前后必須有空白字符

條件性的執行操作符

     && 代表條件性的  AND THEN

     ||  代表條件性的  OR ELSE 

test命令

     長格式的例子:test "$A" == "$B" && echo "Strings are equal" $ test “$A” -eq “$B” && echo "Integers are equal" 

     簡寫格式的例子:[ "$A" == "$B" ] && echo "Strings are equal" $ [ "$A" -eq "$B" ] && echo "Integers are equal"

bash的測試類型

    數值測試:

        -gt: 是否大于;

        -ge: 是否大于等于;

        -eq: 是否等于;

        -ne: 是否不等于;

        -lt: 是否小于;

        -le: 是否小于等于;

    字符串測試:

        ==:是否等于;

        >: ascii碼是否大于ascii碼

        <: 是否小于

        !=: 是否不等于

        =~: 左側字符串是否能夠被右側的PATTERN所匹配     注意: 此表達式一般用于[[  ]]中;

        -z "STRING":字符串是否為空,空為真,不空為假

        -n "STRING":字符串是否不空,不空為真,空為假

    文件測試:

        -a FILE:同-e

        -e FILE: 文件存在性測試,存在為真,否則為假; 

    存在性及類別測試:

        -b FILE:是否存在且為塊設備文件

        -c FILE:是否存在且為字符設備文件;

        -d FILE:是否存在且為目錄文件;

        -f FILE:是否存在且為普通文件;

        -h FILE 或 -L FILE:存在且為符號鏈接文件;

        -p FILE:是否存在且為命名管道文件;

        -S FILE:是否存在且為套接字文件;

    文件權限測試:

        -r FILE:是否存在且可讀

        -w FILE: 是否存在且可寫

        -x FILE: 是否存在且可執行

    文件特殊權限測試:

        -g FILE:是否存在且擁有sgid權限;

        -u FILE:是否存在且擁有suid權限;

        -k FILE:是否存在且擁有sticky權限;

下面是一些編程的示例習題:

編寫腳本/root/bin/systeminfo.sh,顯示當前主機系統信息,包括主機名,IPv4地址,操作系統版本,內核版本,CPU型號,內存大小,硬盤大小。

[root@centos7 bin]# bash systeminfo.sh 
hostname is centos7.zang
IPV4:10.1.252.189
version informationcat: CentOS Linux release 7.2.1511 (Core) 
kernel information: 3.10.0-327.el7.x86_64
cpu information:  Intel(R) Core(TM) i7-4710MQ CPU @ 2.50GHz
memory :3.7G
Disk : 214.7 GB
[root@centos7 ~]# cat /bin/systeminfo.sh 
#!/bin/bash
echo "hostname is `hostname`"
echo "IPV4:`ifconfig | egrep -A1 'eno'| tail -1 | tr -s ' '| cut -d' ' -f3`"
echo "version informationcat: `cat /etc/redhat-release`"
echo "kernel information: `uname -r`"
echo "cpu information: `lscpu | sed -n '/Model name/p'| tr -s ' '|cut -d: -f2`"
echo "memory :`free -h | sed -n '/Mem/p' |tr -s ' ' | cut -d' ' -f2`"
echo "Disk :`fdisk -l | egrep 'Disk /dev/' | cut -d',' -f1 | cut -d: -f2`"

編寫腳本/root/bin/backup.sh,可實現每日將/etc/目錄備份到/root/etcYYYY-mm-dd中

[root@centos7 bin]# bash backup.sh
backup is the /etc is success
[root@centos7 ~]# ll
total 20
-rw-------.   1 root root 1354 Jul 20 17:49 anaconda-ks.cfg
drwxr-xr-x.   2 root root    6 Jul 20 17:53 Desktop
drwxr-xr-x.   2 root root    6 Jul 20 17:53 Documents
drwxr-xr-x.   2 root root    6 Jul 20 17:53 Downloads
drwxr-xr-x. 129 root root 8192 Aug 11 19:41 etc2016-08-11
-rw-------.   1 root root 1402 Jul 20 17:52 initial-setup-ks.cfg

編寫腳本/root/bin/disk.sh,顯示當前硬盤分區中空間利用率最大的值

[root@centos7 bin]# bash disk.sh 
當前硬盤分區中空間利用率最大的值 :71
[root@centos7 bin]# cat disk.sh 
#!/bin/bash
echo "當前硬盤分區中空間利用率最大的值 :`df | egrep '/dev/sd.*' | tr -s ' ' | cut -d' ' -f5 | tr -d '%'| sort |tail -1`"

編寫腳本/root/bin/links.sh,顯示正連接本主機的每個遠程主機的IPv4地址和連接數,并按連接數從大到小排序

[root@centos7 bin]# bash links.sh 
      3 10.1.250.72
[root@centos7 bin]# cat links.sh
#!/bin/bash
netstat -nt | tr -s ' '|cut -d' ' -f5 | egrep -v '[[:alpha:]]'|cut -d: -f1|sort|uniq -c| sort -nr

寫一個腳本/root/bin/sumid.sh,計算/etc/passwd文件中的第10個用戶和第20用戶的ID之和

[root@centos7 bin]# bash sumid.sh 
70
[root@centos7 bin]# cat sumid.sh 
#!/bin/bash
s1=`sed -n '10p' /etc/passwd | cut -d: -f3`
s2=`sed -n '20p' /etc/passwd | cut -d: -f3`
let sum=$s1+$s2
echo $sum

寫一個腳本/root/bin/sumspace.sh,傳遞兩個文件路徑作為參數給腳本,計算這兩個文件中所有空白行之和

[root@centos7 bin]# cat /etc/fstab ; cat /etc/issue
#
# /etc/fstab
# Created by anaconda on Wed Jul 20 14:39:10 2016
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
UUID=030d27aa-d817-4330-8de8-90f87c7d0e1f /                       xfs     defaults        0 0
UUID=15819ecc-8ae9-4cc3-8f3f-54b7be0ac610 /boot                   xfs     defaults        0 0
UUID=14cd35c6-b195-4ec6-a202-781d2a850aad /testdir                xfs     defaults        0 0
UUID=f13adfd3-a620-4ec6-b1c3-d9b997b72fca swap                    swap    defaults        0 0
\S
Kernel \r on an \m
[root@centos7 bin]# bash sumspace.sh /etc/fstab /etc/issue
2
[root@centos7 bin]# cat sumspace.sh 
#!/bin/bash
f1=`sed -n '/^$/p' $1 | wc -l`
f2=`sed -n '/^$/p' $2 | wc -l`
let f=$f1+$f2
echo $f

寫一個腳本/root/bin/sumfile.sh,統計/etc, /var, /usr目錄中共有多少個一級子目錄和文件

[root@centos7 bin]# bash sumfile.sh 
/etc下一級子目錄和文件個數:262
/var下一級子目錄和文件個數:22
/usr下一級子目錄和文件個數:12
[root@centos7 bin]# cat sumfile.sh 
#!/bin/bash
f1=`ls -A /etc/ | wc -l`
f2=`ls -A /var/ | wc -l`
f3=`ls -A /usr/ | wc -l`
echo "/etc下一級子目錄和文件個數:$f1"
echo "/var下一級子目錄和文件個數:$f2"
echo "/usr下一級子目錄和文件個數:$f3"

寫一個腳本/root/bin/argsnum.sh,接受一個文件路徑作為參數;如果參數個數小于1,則提示用戶“至少應該給一個參數”,并立即退出;如果參數個數不小于1,則顯示第一個參數所指向的文件中的空白行數

[root@centos7 bin]# cat argsnum.sh 
#!/bin/bash
[[ $# -lt 1 ]] && echo "至少給一個路經作為參數"|| egrep '^$' $1 | wc -l
[root@centos7 bin]# bash argsnum.sh /etc/issue
1
[root@centos7 bin]# cat argsnum.sh 
#!/bin/bash
[[ $# -lt 1 ]] && echo "至少給一個路經作為參數"|| egrep '^$' $1 | wc -l

寫一個腳本/root/bin/hostping.sh,接受一個主機的IPv4地址做為參數,測試是否可連通。如果能ping通,則提示用戶“該IP地址可訪問”;如果不可ping通,則提示用戶“該IP地址不可訪問”

[root@centos7 bin]# cat hostping.sh 
#!/bin/bash
ping -c1 -w1 $1 > /dev/null
[[ $? == 0 ]] && echo "該IP可以訪問" || echo "該IP不可訪問"
[root@centos7 bin]# bash /bin/hostping.sh 192.168.1.99
該IP不可訪問
[root@centos7 bin]# bash /bin/hostping.sh 192.168.1.1
該IP可以訪問

chmod -rw /tmp/file1,編寫腳本/root/bin/per.sh,判斷當前用戶對/tmp/fiile1文件是否不可讀且不可寫

[root@centos7 bin]# cat per.sh 
#!/bin/bash
z1=`[ -r /tmp/file1 ]; echo $?`
z2=`[ -w /tmp/file1 ]; echo $?`
[ $z1 == 1 ] && [ $z2 == 1 ] && echo "對此文件不可讀寫" || echo "`ls -l /tmp/file1`"
[root@centos7 bin]# ./per.sh 
----------. 1 zzz root 20 Aug 12 11:44 /tmp/file1
[zang@centos7 bin]$ ./per.sh 
對此文件不可讀寫
[zzz@centos7 bin]$ ./per.sh 
-rw-------. 1 zzz root 20 Aug 12 11:44 /tmp/file1

編寫腳本/root/bin/nologin.sh和login.sh,實現禁止和充許普通用戶登錄系統。

[root@centos7 bin]# cat nologin.sh 
#!/bin/bash
[ -f /etc/nologin ] && echo "用戶已經禁止登陸" || touch /etc/nologin ; echo "用戶已經禁止登陸"
[root@centos7 bin]# bash login.sh 
用戶已經可以登陸
[root@centos7 bin]# cat login.sh 
#!/bin/bash
[ -f /etc/nologin ] && (rm -f /etc/nologin ; echo "用戶已經可以登陸") || echo "用戶已經可以登陸"

原創文章,作者:zanghonglei,如若轉載,請注明出處:http://www.www58058.com/35549

(0)
zanghongleizanghonglei
上一篇 2016-08-15
下一篇 2016-08-15

相關推薦

  • OpenSSL

    加密和解密技術 本章內容: 安全機制 對稱加密 不對稱加密 散列算法 PKI和CA 相關知識: 1)傳輸層協議:        TCP(面向連接),UDP(面向無連接),SCTP(流控協議) 2)port(端口):傳輸層協議都會提供端口,        端口(port)是標記進程…

    Linux干貨 2016-09-29
  • 關于man的幾個重要命令

    接觸Linux有很多年了,以前對于linux我覺得自己懂得的還算一般吧,可是聽了馬哥的關于linux的視頻課程,發現自己就是一個還沒入門的菜鳥,所以果斷的狠心的報了馬哥的網絡班,拜在馬哥旗下,以后就打著馬哥的旗號到外面混,哈哈最初的這幾天學習,因為工作和時間的等等等的關系,所以才到現在還在趕著寫我的博客作業,現在就最有感觸的幾個命令串聯一下。學習linux肯…

    Linux干貨 2016-10-31
  • 磁盤分區及lvm管理

    1. 硬盤類型 /dev/sda VS /dev/hda /dev/sda     /dev/sda1     /dev/sda2     /dev/sda3 而又的安裝時硬盤驅動設備名為 /dev/hda    /dev/hda1 &nb…

    Linux干貨 2016-09-19
  • linux基礎學習-網絡基礎

    一、OSI七層模型 二、TCP/IP模型         三次握手原理 三、常見服務的默認端口 四、IP地址、子網劃分基礎知識     通信原理:一般數據的交互產生是在應用層(TCP/IP模型),應用層以下可以看成是搬運工,不同層的協議定義了不同的搬運工的工作內容,直到最后,把數…

    Linux干貨 2016-09-05
  • samba服務

    一、什么是SAMBA   Linux之間可以通過NFS服務方便的掛載遠程主機上的共享目錄,那么SAMBA主要是用于實現Windows主機與Linux主機之間共享文件互訪。它們之間的通信依賴于CIFS協議。 二、SAMBA使用的daemon     1、nmbd:在Linux上實現NetBIOS;     &n…

    Linux干貨 2016-02-14
  • yum命令的使用及磁盤管理中命令的使用方法(mkfs ,blkid,e2label等)

    yum      #cd /etc/yum.repos.d          #yum repolist(在 #cd下)其他命令在 #cd /etc/yum.repos.d運行          #yum-config-manag…

    2017-08-19

評論列表(1條)

  • 馬哥教育
    馬哥教育 2016-08-15 17:04

    態度端正,完成的不錯,再接再勵

欧美性久久久久