shell腳本編程之一

shell腳本編程之一

shell腳本基礎

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

格式要求:首行shebang機制

#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl

shell腳本的用途有:

  • 自動化常用命令

  • 執行系統管理和故障排除

  • 常見簡單的應用程序

  • 處理文本或文件

創建shell腳本

第一步:使用文本編輯器來創建文本文件

  • 第一行必須包括shell聲明序列:#!

#!/bin/bash

添加注釋

注釋以#開頭

  • 第二步:運行腳本

給予執行權限,在命令行指定腳本的絕對或相對路徑

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

shell腳本范例

#!/bin/bash
#author:root
#Version:1.0
#description:the script displays some information about your environment

echo "greentings.the date and tiem are $(date)"
echo "your working directory is :$(pwd)"

腳本調試

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

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

變量

  • 變量:命名的內存空間

數據存儲方式

字符:

數值:整形,浮點型

  • 變量:變量類型

作用:

1、數據存儲格式

2、參與的運算

3、表示的數據范圍

類型

字符

數值:整形、浮點型

編程語言的分類

強類型:Java、Python

弱類型:bash

變量命名法則:

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

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

3、見名知義

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

bash中變量的種類

根據變量的生效范圍等標準

本地變量:生效范圍為當前shell;對當前shell之外的其他shell進程,包括但當前shell的字shell進程均無效

環境變量:生效范圍為當前shell進程及其子進程

局部變量:生效范圍為當前shell進程中某代碼片段(通常指函數)

位置變量:$1,$2…${10}..來表示,用于讓腳步在腳本代碼中調用通過命令行傳遞給它的參數

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

本地變量

變量賦值:name=‘value’,
可以使用引用value:
(1) 可以是直接字串; name=“root"
(2) 變量引用:name="$USER"
(3) 命令引用:name=`COMMAND`, name=$(COMMAND)
變量引用:${name}, $name
    "":弱引用,其中的變量引用會被替換為變量值
    '':強引用,其中的變量引用不會被替換為變量值,而保持原字符串
顯示已定義的所有變量:set
刪除變量:unset name


環境變量

變量聲明、賦值:
    export name=VALUE
    declare -x name=VALUE
變量引用:$name, ${name}
顯示所有環境變量:
    export
    env
    printenv
刪除:unset name
bash有許多內建的環境變量:PATH, SHELL, USRE,UID, HISTSIZE, HOME, PWD, OLDPWD, HISTFILE, PS1


只讀和位置變量

只讀變量:只能聲時,但不能修改和刪除
    readonlyname
    declare -r name

位置變量:在腳本代碼中調用通過命令行傳遞給腳本的參數
    $1, $2, ...:對應第1、第2等參數,shift [n]換位置
    $0: 命令本身
    $*: 傳遞給腳本的所有參數,全部參數合為一個字符串
    $@: 傳遞給腳本的所有參數,每個參數為獨立字符串
    $#: 傳遞給腳本的參數的個數
    $@ $* 只在被雙引號包起來的時候才會有差異

示例:判斷給出的文件的行數
 linecount="$(wc-l $1| cut -d' ' -f1)"
 echo "$1 has $linecountlines."


算術運算

bash中的算術運算:help let
    +, -, *, /, %取模(取余), **(乘方)
    實現算術運算:
        (1) let var=算術表達式
        (2) var=$[算術表達式]
        (3) var=$((算術表達式))
        (4) var=$(expr arg1 arg2 arg3 ...)
        (5) declare –ivar= 數值
        (6) echo ‘算術表達式’ | bc
乘法符號有些場景中需要轉要轉義,如*
bash有內建的隨機數生成器:$RANDOM(1-32767)
    echo $[$RANDOM%50] :0-49之間隨機數

邏輯運算

true 0

false 1

短路運算:

短路與:

第一個為0,結果必定為0

第一個為1,第二個必須要參與運算;

短路或:

第一個為1,結果必定為1;

第一個為0,第二個必須要參與運算;

聚集命令

兩種聚集命令的方法:

復合式:date ; who | wc -l

命令會一個接一個地運行

子shell:(date ; who | wc -l) >> /tmp?trace

所有輸出都被發送給單個stdout和stderr

退出狀態

0 表示成功,1-255代表失敗

$? 變量保存最近的命令退出狀態

example

$ ping -c1 -w1 hostdown $> /dev/null

$ echo $?

退出狀態嗎

bash自定義退出狀態碼

extinct [n]:自定義退出狀態碼

注意:腳本中一旦遇到exit命令,腳本會立即終止;終止退出狀態取決于exit命令后面的數字

注意:若果為給腳本指定退出狀態碼,整個腳本的退出狀態碼取決于腳本中執行的最后一條命令的狀態碼

條件測試

判斷某需求是否滿足,需要由測試機制來實現;
專用的測試表達式需要由測試命令輔助完成測試過程;

評估布爾聲明,以便用在條件性執行中
    ?若真,則返回0
    ?若假,則返回1

測試命令:
    ?test EXPRESSION
    ?[ EXPRESSION ]
    ?[[ EXPRESSION ]]
    注意:EXPRESSION前后必須有空白字符



根據退出狀態而定,命令可以有條件地運行
    ?&& 代表條件性的AND THEN
    ?|| 代表條件性的OR ELSE

test命令

長格式的例子:
    $test "$A" == "$B" && echo"Stringsareequal"
    $test “$A” -eq “$B” && echo "Integersareequal"

簡寫格式的例子:
    $[ "$A" == "$B" ] && echo"Stringsareequal"
    $[ "$A" -eq "$B" ] && echo "Integersareequal"

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權限;
文件大小測試:
    -s FILE: 是否存在且非空;
文件是否打開:
    -t fd: fd表示文件描述符是否已經打開且與某終端相關
    -N FILE:文件自上一次被讀取之后是否被修改過
    -O FILE:當前有效用戶是否為文件屬主
    -G FILE:當前有效用戶是否為文件屬組
雙目測試:
    FILE1 -efFILE2: FILE1與FILE2是否指向同一個設備上的相同inode
    FILE1 -ntFILE2: FILE1是否新于FILE2;
    FILE1 -otFILE2: FILE1是否舊于FILE2;
組合條件測試
第一種方式:
    COMMAND1 && COMMAND2 并且
    COMMAND1 || COMMAND2 或者
    ! COMMAND 非
    如:[ -e FILE ] && [ -r FILE ]
第二種方式:
    EXPRESSION1 -a EXPRESSION2 并且
    EXPRESSION1 -o EXPRESSION2 或者
    ! EXPRESSION
必須使用測試命令進行;
    # [ -z “$HOSTNAME” -o $HOSTNAME "==\
    "localhost.localdomain" ] && hostname www.magedu.com
    # [ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab


附加:bash特殊變量$* $@詳解

[root@centos7 sh]# cat arg1.sh 
./arg2.sh "$*"
echo ===================
./arg2.sh "$@"

[root@centos7 sh]# cat arg2.sh
echo 1st is "$1" 
echo 2st is "$2"
echo all args are is "$*"
echo number is "$#"


[root@centos7 sh]# arg1.sh openstack mysql marindb 
1st is openstack mysql marindb
2st is 
all args are is openstack mysql marindb
number is 1
===================
1st is openstack
2st is mysql
all args are is openstack mysql marindb
number is 3


重以上的實例中我們可以看到

$* 把所有的參數當做一個參數來輸入
$@ 原來有幾個參數,輸出還是幾個 


注:對于位置參數為$1 $2 $3... 當多個10的時候 我們采用 ${11} ${12} ... 這種方法表示即可

下面用幾道練習題來加深印象

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

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

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

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

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

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

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

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

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

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

附錄參考:

第一題

#!/bin/bash

host_name=`hostname`
Ipv4_addr=`ifconfig | grep -A 1 '^e' | tail -1 | sed -r 's@inet (addr:)?(.*) (netmask|Bc).*@\2@' | tr -d ' '`
os_version=`cat /etc/redhat-release`
kernel_version=`uname -r`
CPU_type=`cat /proc/cpuinfo | grep "model name" | cut -d: -f2 | tr -d ' '`
mem_size=`cat /proc/meminfo | grep "MemT"| cut -d: -f2 | tr -d ' '`
disk_size=`fdisk -l /dev/sda | sed -rn "s@Disk /dev/sd[a-z]: (.*), .*, .*@\1@p"`

red="\033[31m"
end_color="\033[0m"

echo -e "${red}Current OS information$end_color"
echo "hostname is $host_name"
echo "ipaddr is $Ipv4_addr"
echo "OS version is $os_version"
echo "kernel version is $kernel_version"
echo "cpu type is $CPU_type"
echo "mem size is $mem_size"
echo "disk size is $disk_size"

第二題

#!/bin/bash

backup_file="/etc/"
cp -ar $backup_file /root/etc`date +%F`

第三題

#!/bin/bash

total=`df | sed -rn 's@/(dev/sd[a-z][0-9]+).* ([0-9]+)%.*@\1:\2@p' | sort -nr -t: -k2 | head -1`

max_diskuse_name=`echo $total | cut -d: -f1`
max_diskuse_number=`echo $total | cut -d: -f2`

echo "Max disk use name is $max_diskuse_name"
echo "IT use ${max_diskuse_number}%"
~

第四題

#!/bin/bash


links=`netstat -tn | grep "^tcp" | tr -s ' ' | cut -d' ' -f4 | cut -d: -f1 | sort | uniq -c | sort -r`

links_number=`echo $links | wc -l`
echo "links number is $links_number"
echo -e "they are\n$links"

第五題

#!/bin/bash

uid_10=`cat /etc/passwd | sed -n '10p' | cut -d: -f3`
uid_20=`cat /etc/passwd | sed -n '20p' | cut -d: -f3`

total=$[$uid_10+$uid_20]

echo "The 10st UID is $uid_10"
echo "The 20st UID is $uid_20"
echo "The sum of is $total"

第六題

#!/bin/bash

first_spacelines=`cat $1 | grep "^$" | wc -l`
second_spacelines=`cat $2 | grep "^$" | wc -l`

total=$[$first_spacelines+$second_spacelines]

echo "the 1st spacelines is $first_spacelines"
echo "the 2st spacelines is $second_spacelines"
echo "the sum of id $total"
~

第七題

#!/bin/bash

total=`ls -A /etc/ /var/ /usr | wc -l`
echo "the sum of is $total"
~

第八題

#!/bin/bash

[ $# -lt 1 ] && echo "at least one arg" && exit || cat $1 | grep "^$" | wc -l

第九題

#!/bin/bash

ping -c1 -W1 $1 &> /dev/null && echo "$1 is up" || echo "$1 is down"

第十題

#!/bin/bash

[ ! -r /tmp/file1 -a ! -w /tmp/file1 ] && echo "not write and not read" || echo "match fail"

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

(0)
sixijiesixijie
上一篇 2016-08-18
下一篇 2016-08-18

相關推薦

  • Linux系統的終端類型

    Linux系統的終端類型    Linux系統的終端主要包括控制臺終端、控制終端、串口終端、偽終端、虛擬終端。 1.  控制臺終端(/dev/console)。    在Unix系統中,計算機顯示器通常被稱為控制臺終端。Console與虛擬終端相關聯,內核將信息送到控制臺終端上(/dev/conso…

    Linux干貨 2015-09-14
  • 2016-10-17作業

    1 生產環境發現一臺服務器系統時間產生偏差,造成服務異常,請幫忙校正。 答:hwclock -s 2 生產有一個數據同步腳本需要執行很長時間,怎樣做到無人值守,在管理工具退出的情況下,腳本依然能正常運行。 答:screen -S work  進去后開始做工作,暫時離開時可使用 ctrl+a,d 剝離當前會話。 3 Linux系統中命令共分為內建命令…

    Linux干貨 2016-10-18
  • N22第三周作業

    1、列出當前系統上所有已經登錄的用戶的用戶名,注意:同一個用戶登錄多次,則只顯示一次即可 [root@localhost ~]# who |cut -d' ' -f1 |sort -u   root   xuc 2、取出…

    Linux干貨 2016-08-29
  • Linux系統grep正則表達式

    一、grep命令的使用 首先,我們來了解grep命令,grep (global search regular expression and printing),全面搜索正則表達式并把行打印出來)是一種強大的文本搜索工具,它能使用正則表達式搜索文本,并把匹配的行打印出來。Linux中的grep命令包括、grep, egrep和fgrep 。egrep是grep…

    Linux干貨 2017-04-23
  • CentOS7.3系統上編譯安裝httpd.2.4.25

    本文所做的所有操作是在一部新安裝的CentOS7.3系統上。 1.環境與配置 環境說明:VMware上安裝的CentOS7.3系統,7.3完整版光盤做成的yum源 配置:編譯生成的所有的文件都存放在/usr/local/httpd24/這個目錄下 2.安裝GCC編譯器 #安裝Development tools這個軟件包組 [root@pxe68 ~]# yu…

    2017-04-20
  • 馬哥教育面授班22期:第一天課程練習

    Linux發展史:        1984年:Richard Stallman發起GNU項目和自由軟件基金會創建開源的UNIX實用工具版本        創建通用公共許可證(GPL)        1991年:Linux Torvalds發…

    Linux干貨 2017-05-16
欧美性久久久久