如何才能學好Shell編程
- 為什么要學習shell編程
- Shell是Linux底層核心
- Linux運維工作常用工具
- 自動化運維必備基礎課程
- 學好shell編程所需Linux基礎
- 熟練使用vim編輯器
- 熟練使用Linux的常用命令
- 熟練使用三劍客和正則表達式
- 如何才能學好shell編程
- 掌握shell腳本的常見語法
- 從簡單判斷、循環做起
- 多模仿、多練習、多思考
- 鍛煉編程思維:先將需求理解,然后將大需求分解,逐步分成小的程序或者模塊,然后再開發,或者先分析最終需求的基礎實現,最后逐步擴展批量實現
- 不要拿來主義:從簡單做起
- 多解決企業實際問題
- 找一本合適的教科書
- 反復實現本課程,反復練習
- 學完課程后的可達到的shell編程高度
Shell腳本初步入門
什么是是shell?
shell原意,是貝殼,
它在Linux內核和應用程序之間。就像一個翻譯官,中間人,讓程序員員寫的應用程序能和系統之間相互交流
什么是shell腳本?
簡單點說,就是許多shell命令,寫在一個文件中,實現一個需求
先看一個清除日志的腳本
# clean logs ,v0.1 cd /var/log cat /dev/null>message echo "Logs clean up"
這個腳本的問題在於,三條命令之間沒有表現明確的關系
我們不知道腳本執行后,會是什么樣的結果!
下面看一個完善的版本
#! /bin/bash LOG_DIR=/var/log ROOT_UID=0 # 第一關,必須是root用戶才能執行腳本,否則提示,並終止 if ['$UID' -ne '$ROOT_UID'] then echo 'Must be root to run this script!' exit 1 fi # 第二關,成功切換到目錄,否則提示,並終止 cd $LOG_DIR || { echo 'Can not change to necessary directory!' exit 1 } # 第三關,清理日志,如果清理成功,給出正確的提示 cat /dev/null>message && { echo 'Logs cleaned up!' exit 0 } # 第四關,通關失敗,給出提示 echo 'cleaned logs fail!' exit 1
shell腳本在Linux中的地位
Shell腳本語言很擅長處理純文本類型的數據,而Linux系統中幾乎所有的配置文件、日志文件(如NFS、 Rsync、 Httpd、 Nginx、 LVS、 MySQL等),以及絕大多數的啟動文件都是純文本類型的文件。
自然學好Shell腳本語言,就可以利用它在Linux系統中發揮巨大的作用。
形象的將shell和各種運維工具比喻為一串項鏈以及三種SHELL語言分類


Shell腳本的建立
1、腳本的第一行
一個規范的Shell腳本在第一行會指出由哪個程序(解釋器)來執行腳本中的內容,這一行內容在Linux bash編程中一般為:
#!/bin/bash或#!/bin/sh #<==255個字符以內
2、bash和sh的區別
早期的bash與sh稍有不同,它還包含了csh和ksh的特色,但大多數腳本都可以不加修改地在sh上運行。
3、需要注意的地方
CentOS和Red Hat Linux下默認的Shell均為bash。因此,在寫Shell腳本的時候,腳本的開頭即使不加#!/bin/bash,它也會交給bash解釋。
如果寫腳本不希望使用系統默認的Shell解釋,那么就必須要指定解釋器了。否則腳本文件執行的結果可能就不是你想要的。
建議讀者養成好的編程習慣,不管什么腳本最好都加上相應的開頭解釋器語言標識,養成Shell編程規范。
Shell腳本的執行
1. bash script-name或sh script-name
這是當腳本文件本身沒有可執行權限(即文件權限屬性x位為-號)時常使用的方法,或者腳本文件開頭沒有指定解釋器時需要使用的方法,這也是老男孩老師推薦的使用方法
2. path/script-name或./script-name
指在當前路徑下執行腳本(腳本要有執行權限),需要先將腳本文件的權限改為可執行(即文件權限屬性加x位),
具體方法為chmod +x script-name。然后通過腳本絕對路徑或相對路徑就可以直接執行腳本了。
3. source script-name或. script-name
關於點和souece的妙用,就是父子shell之間可以相互調用變量
[root@dao scripts]# sh sh_user.sh # 文件中是user=‘whoami’ 相當於定義了局部變量 [root@dao scripts]# echo $user [root@dao scripts]# . ./sh_user.sh # 使用點,調用了子變量(局部變量) [root@dao scripts]# echo $user whoami
4. sh<script-name或cat scripts-name|sh
[root@dao scripts]# chkconfig --list |grep 3:on |awk '{print "chkconfig",$1,"off"}'|bash
shell腳本執行一個重要的例子

當我們登陸命令行,就相當於開啟一個shell,也就是局部變量和全局變量的意思,只能在創建他們的shell函數或者shell腳本中使用。
https://www.cnblogs.com/yxiaodao/p/10401327.html#_label2
取消定義變量unset user
shell中批量注釋
1、vim批量操作
2、:EOF
EOF (這個EOF前面不能有空格)原理就是,EOF把中間的內容交給冒號,但是冒號表示什么都不做,所以,也就是注釋了
3、cat > /dev/null <<EOF
EOF
shell腳本的執行過程

shell腳本的編程規范和習慣
1.開頭加腳本解釋器 2.附帶作者及版權信息 3.腳本擴展名為*.sh 4.腳本存放在固定的目錄下 5.腳本中不用中文 6.成對的符號一次書寫完成 7.循環格式一次性輸入完成
Shell變量核心基礎知識與實踐
什么是變量?
x=1,x就是變量名,=號表示賦值。用一個字符或者字符串表示一堆內容。這個字符或者字符串叫做變量
變量的特性?
在bash shell中不會區分變量的類型
變量的分類?
兩類,環境變量(全局變量)和普通變量(局部變量)。https://www.cnblogs.com/yxiaodao/p/10401327.html#_label2
Shell環境變量
環境變量(全局變量),系統中默認就存在的,作用就是解決系統的一些問題。
顯示環境變量的方法:
1、echo $變量名
2、env
3、set set -o 查看bash編程的配置
定義環境變量:
PS1、PATH、HOME、UID 系統固有的,默認就表示一定意義。
3種定義環境變量的方法(環境變量盡量大寫)
1、直接export
export PIZZA=1
2、先賦值,在export
PIZZA=2
export PIZZA
3、declare
-x A=1
-i 表示定義整型
環境變量永久生效的配置/etc/profile
環境變量取消 unset PIZZA
環境變量的文件執行順序
全局文件
/etc/profile
/etc/bashrc/
用戶環境變量文件
~/.bashrc
~/.bash_profile

上圖是文件加載的順序
注意:新添加的環境變量要加在文件的前面,不要加在最后面,其中的代碼會影響執行順序。
注意:在ssh 遠程登錄或者其他特殊情況下,也許不會加載/etc/profile和~/.bash_profile
所以在添加變量的時候,添加在/etc/bashrc下
Shell普通變量
局部變量
當前用戶或者腳本中生效
a.變量名: 規則:字母、數字、下划線,3者組合,以字母開頭。 要求:見名知意。 1)OldboyAge=1 2)oldboy_age=1 3) oldboyAge=1 ###駝峰語法 b.變量內容 字符串: 變量名=value #<==不加引號。 ##解析變量或者命令,然后輸出,純數字選擇不加引號。 變量名=’value’ #<==加單引號。 ###所見即所得 變量名=”value” #<==加雙引號。 ##解析變量或者命令,然后輸出,字符串默認選擇雙引號,可以把要定義的內容作為一個整體。 命令變量,把一個命令的結果賦值給變量 變量名=`ls` 變量名=$(ls)
小結:
針對變量名:
1、變量名一定要有一定的命令規范,並且要見名知意,推薦使用駝峰法
2、變量名僅能使用字母、數字、下划線的任意多個字符,並且要字母開頭
針對變量內容:
3、在腳本中定義普通字符變量,盡量使用雙引號括起來。
4、單純數字的變量內容可以不加引號
5、希望變量的內容鴛鴦輸出需加單引號
6、希望變量值引用命令並獲取命令的結果就用反引號或者$()
針對賦值符號:
7、變量定義使用賦值等號(=),賦值符號兩端不要有空格
針對變量輸出:
8、使用或者輸出變量的內容,可用 $ 變量名,$PS1
9、若變量名(db)后面有其他字符鏈接的時候,就必需給變量名加上大括號
Shell特殊位置參數變量
在Shell中存在一些特殊且重要的變量,例如: $0、 $1、 $#,我們稱之為特殊位置參數變量,
要從命令行、函數、或腳本執行等處傳遞參數時,就需要在Shell腳本中使用位置參數變量。

特殊位置變量: $0 獲取腳本的名字,如果腳本前面跟着路徑的話,那就獲取路徑加上腳本名字。 [root@web01 scripts]# cat test.sh #!/bin/bash echo $0 [root@web01 scripts]# bash test.sh test.sh [root@web01 scripts]# bash /server/scripts/test.sh /server/scripts/test.sh 企業應用; 一般在啟動腳本的結尾會使用$0獲取腳本的路徑和名字給用戶提示用。 /etc/init.d/crond $1,$2----$n $1表示腳本后的第一個參數 $2表示腳本后的第二個參數 .... 超過$9,${10} 要加{}大括號 企業應用: case "$1" in start) rh_status_q && exit 0 $1 ;; stop) $# 腳本后面所有參數的個數 企業應用: [root@web01 scripts]# cat test.sh #!/bin/bash if [ $# -ne 2 ] then echo "Usage:$0 arg1 arg2" exit 1 fi echo ok $* 獲取腳本的所有參數,“$1 $2 $3” $@ 獲取腳本的所有參數,"$1" "$2" "$3" 當需要接收腳本后面所有參數時,但是又不知道參數個數就用這兩個變量。 區別: [root@web01 scripts]# cat test.sh #!/bin/bash for arg in "$*" do echo $arg done echo -------------------------- for arg1 in "$@" do echo $arg1 done [root@web01 scripts]# bash test.sh "I am" oldboy teacher. I am oldboy teacher. -------------------------- I am oldboy teacher. make echo $?
Shell進程特殊狀態變量

$? 獲取上一個命令的返回值,如果返回值為0就證明上一個命令執行正確, 非0,就證明上一個命令執行失敗的。 ***** $$ 獲取當前執行腳本的進程號 $! 獲取上一個后台工作進程的進程號 $_ 獲取上一個執行腳本的最后一個參數
Shell變量子串

Shell變量子串(變量內容相關知識) [root@web01 scripts]# oldboy="I am oldboy" [root@web01 scripts]# echo ${oldboy} I am oldboy [root@web01 scripts]# echo ${#oldboy} 11 [root@web01 scripts]# echo $oldboy|wc -L 11 [root@web01 scripts]# expr length "$oldboy" 11 [root@web01 scripts]# echo $oldboy|awk '{print length}' 11 [root@web01 scripts]# echo $oldboy|awk '{print length ($1)}' 1 [root@web01 scripts]# echo $oldboy|awk '{print length ($0)}' 11 練習題: I am oldboy I teach linux 打印這些字符串中字符數小於3的單詞。 涉及知識點:取字符串長度,for,if。 [root@web01 scripts]# echo ${oldboy:2} am oldboy [root@web01 scripts]# echo ${oldboy:2:2} am [root@web01 scripts]# echo ${oldboy:2:4} am o OLDBOY=abcABC123ABCabc [root@web01 scripts]# echo ${OLDBOY} abcABC123ABCabc [root@web01 scripts]# echo ${OLDBOY%a*C} abcABC123ABCabc [root@web01 scripts]# echo ${OLDBOY%a*c} abcABC123ABC [root@web01 scripts]# echo ${OLDBOY%%a*c} [root@web01 scripts]#
Shell特殊變量擴展知識
只挑了4個,最重要的是第1個

[root@web-01 ~]# [root@web-01 ~]# result=${test:-UNSET} [root@web-01 ~]# echo $test [root@web-01 ~]# echo $result UNSET [root@web-01 ~]# echo $test [root@web-01 ~]# #當變量test為空的時候,就把UNSET內容賦值給result
result 媳婦
test 銷售 空
UNSET 備胎 賦值給result
企業用途
find $path -name "*.name" -mtime +7|xrangs rm -f
當 $path 為空的時候,命令會從根目錄開始刪,所以我們准備一個備胎
find ${path:-/tmp} -name "*.name" -mtime +7|xrangs rm -f
系統中的應用---httpd的啟動腳本中
- = ? +
Shell變量的數值計算
算數運算符
如果要執行算術運算,就離不開各種運算符號,和其他編程語言類似, Shell也有很多算術運算符,下面就給大家介紹下常見的Shell算術運算符

Bash編程常見運算命令匯總

只適合整數運算 1、(()) 推薦 2、let 次推薦 3、expr 4、$[] 既適合整數,又適合小數運算。 1、bc 2、awk 推薦
(())
[root@web-01 ~]# a=1
[root@web-01 ~]# b=2
[root@web-01 ~]# echo $a+1 不加
1+1
[root@web-01 ~]# $(a+1) 更不加了
-bash: a+1: command not found
[root@web-01 ~]# echo $(a+1)
-bash: a+1: command not found
[root@web-01 ~]# echo $((a+1)) 雙括號才加
2
[root@web01 scripts]# echo $((2**3))
8
[root@web01 scripts]# echo $((1+2**3-5/3))
8
[root@web01 scripts]# echo $((1+2**3-5%3))
7
問? ++a 和 a++有什么區別
let
[root@web-01 ~]# a=1
[root@web-01 ~]# b=2
[root@web-01 ~]# i=$a+$b
[root@web-01 ~]# echo $i
1+2
[root@web-01 ~]# let i=$a+$b
[root@web-01 ~]# echo $i
3
expr用於運算,必須要有空格
[root@web-01 ~]# expr 1 + 1
2
[root@web-01 ~]# expr 1+1
1+1
$[]
[root@web-01 ~]# echo $[2+2]
4
[root@web-01 ~]# echo $[2 + 2]
4
===========
bc 就像啟動計算器,高端點用法自己在了解一下
[root@web-01 ~]# bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
1+1
2
3+4
7
1
1
1*1.2
1.2
[root@web-01 /server/scripts]# echo "scale=2;355/113"|bc
3.14 使用scale來保留2位小數
[root@web-01 /server/scripts]# echo "scale=3;355/113"|bc
3.141
awk的運算效果很好!運算精確,好用
[root@web-01 ~]# echo 1.1 0.5 |awk '{print $1-$2}'
0.6
expr命令的多種企業應用實踐
1、判斷變量的類型是否為整數
在shell編程里,由於函數庫很少,因此在判斷字符串是否為整數時,就不是很容易的事情
可以利用expr做計算時必須是整數的規則,把一個變量或者字符串和一個一直西橫豎(非0)相加,
看命了返回值是否為0。就認為做加法的變量為整數,否則就不是整數。
[root@web-01 ~]# i=pizza 將字符串賦值給i [root@web-01 ~]# expr $i + 6 &>/dev/null 把i和6相加,&>/dev/null表示不保留任何輸出 [root@web-01 ~]# echo $? 輸出返回值 2 非0 就證明輸出了錯誤,證明1不是整數
[root@web-01 ~]# i=4 [root@web-01 ~]# expr $i + 6 &>/dev/null [root@web-01 ~]# echo $? 0 返回為0,則證明i的值是整數
編寫一個腳本來判斷變量是不是整數
[root@web-01 /server/scripts]# vim judge1.sh #!/bin/bash echo 6 + $1 &>/dev/null if [ $? -eq 0 ] then echo "$1 是整數" else echo "$1 不是整數" fi "judge1.sh" [New] 9L, 112C written [root@web-01 /server/scripts]# bash judge1.sh 123 123 是整數 [root@web-01 /server/scripts]# bash judge1.sh ll ll 是整數
2、判斷文件擴展名是否符合要求
[root@web-01 /server/scripts]# vim judge2.sh 1 #!/bin/bash 2 # :冒號兩邊要有空格 3 expr "$1" : ".*\.txt" &>/dev/null 4 if [ $? -eq 0 ] 5 6 then 7 echo "$1 是文本" 8 else 9 echo "$1 不是文本" 10 fi ~ ~ ~ "judge2.sh" 10L, 152C written [root@web-01 /server/scripts]# bash judge2.sh old old 不是文本 [root@web-01 /server/scripts]# bash judge2.sh old.txt old.txt 是文本
expr 好有很多功能,請自行了解(man expr)
bash內置核心命令
Shell變量除了可以 直接賦值 或者 腳本傳參 外!還可以使用read命令從標准輸入中獲得,
read為bash內置命令,可以通過help read查看幫助。
語法格式:read [參數] [參數]
常用參數如下。
-p prompt:設置提示信息
-t timeout:設置輸入等待時間,單位默認為秒。
[root@web-01 /server/scripts]# read -p "請輸入一個數字:" a 請輸入一個數字:11 [root@web-01 /server/scripts]# echo $a 11
read一般的作用就是和用戶交互
[root@web-01 /server/scripts]# read -p "請輸入兩個數字:" a b 請輸入兩個數字:12 56 [root@web-01 /server/scripts]# echo $((a+b)) 68
bash內置核心命令read的企業級應用實踐
打印一個菜單,讓用戶選擇要做的事情
#!/bin/bash cat <<EOF 1、install lamp 2、install lnmp 3、exit EOF read -p "請選擇一個序號(必須是一個數字):" num
# 先判斷一下是不是數字 expr 2 + $num &>/dev/null if [ $? -ne 0 ] then echo "usage:$0 {1|2|3}" exit 1 fi if [ $num -eq 1 ] then echo "install lamp..." elif [ $num -eq 2 ] then echo "install lamp..." elif [ $num -eq 3 ] then echo "bye" else echo "usage:$0 {1|2|3}" exit 1 fi
數值運算命令: 只適合整數運算 1、(()) 推薦 2、let 次推薦 3、expr 4、$[] 既適合整數,又適合小數運算。 1、bc 2、awk 推薦 1、(()) 推薦 [root@web01 scripts]# i=$((a+1)) [root@web01 scripts]# echo $i 2 [root@web01 scripts]# [root@web01 scripts]# echo $((a+3)) 4 [root@web01 scripts]# echo $((1+3)) 4 [root@web01 scripts]# echo $((2**3)) 8 [root@web01 scripts]# echo $((1+2**3-5/3)) 8 [root@web01 scripts]# echo $((1+2**3-5%3)) 7 2、let 次推薦 [root@web01 scripts]# let i=$a+1 [root@web01 scripts]# echo $i 2 3、expr用於運算 4、$[] ============= bc awk [root@web01 scripts]# echo 1+2|bc 3 [root@web01 scripts]# [root@web01 scripts]# echo 1.1+2|bc 3.1 [root@web01 scripts]# echo 1.1+2.3|bc 3.4 [root@web01 scripts]# echo 2.1 1.4|awk '{print $1-$2}' 0.7 [root@web01 scripts]# echo 2.1 1.4|awk '{print $1*$2}' 2.94 [root@web01 scripts]# expr 2 + 2 4 [root@web01 scripts]# expr 2 + a expr: non-numeric argument [root@web01 scripts]# echo $? 2 [root@web01 scripts]# [root@web01 scripts]# [root@web01 scripts]# [root@web01 scripts]# a=2 [root@web01 scripts]# expr 2 + $a &>/dev/null [root@web01 scripts]# echo $? 0 [root@web01 scripts]# a=oldboy [root@web01 scripts]# expr 2 + $a &>/dev/null [root@web01 scripts]# echo $? 2 [root@web01 scripts]# cat judge1.sh #!/bin/bash expr 2 + $1 &>/dev/null if [ $? -eq 0 ] then echo "$1 is 整數" else echo "$1 不是整數" fi [root@web01 scripts]# bash judge1.sh 123 123 is 整數 [root@web01 scripts]# bash judge1.sh oldboy oldboy 不是整數 root@web01 scripts]# cat judge_kuozhan.sh #!/bin/bash expr "$1" : ".*\.txt" &>/dev/null if [ $? -eq 0 ] then echo "$1 是文本" else echo "$1 不是文本" fi [root@web01 scripts]# sh judge_kuozhan.sh oldboy.txt oldboy.txt 是文本 [root@web01 scripts]# sh judge_kuozhan.sh alex.log alex.log 不是文本 [root@web01 scripts]# sh judge_kuozhan.sh peiqi.log peiqi.log 不是文本 [root@web01 scripts]# sh judge_kuozhan.sh 老男孩老師.txt 老男孩老師.txt 是文本 [root@oldboy scripts]# cat test.sh #!/bin/bash a=6 b=2 echo "a-b=$(($a-$b))" echo "a+b=$(($a+$b))" echo "a*b=$(($a*$b))" echo "a/b=$(($a/$b))" echo "a**b=$(($a**$b))" echo "a%b=$(($a%$b))" 變量的賦值: 1、定義法 a=1 2、傳參法 [root@web01 scripts]# cat test7.sh #!/bin/bash a=$1 b=$2 echo "a-b=$(($a-$b))" echo "a+b=$(($a+$b))" echo "a*b=$(($a*$b))" echo "a/b=$(($a/$b))" echo "a**b=$(($a**$b))" echo "a%b=$(($a%$b))" 3、read讀入,讀取用戶輸入。 -p 提示 -t 等待用戶輸入的時間 read -t 30 -p "請輸入一個數字:" [root@web01 scripts]# read -t 30 -p "請輸入一個數字:" a 請輸入一個數字:11 [root@web01 scripts]# echo $a 11 [root@web01 scripts]# a=11 [root@web01 scripts]# echo $a 11 read讀入有什么作用 和用戶交互。 [root@web01 scripts]# cat test6.sh #!/bin/bash read -p "請輸入兩個數字:" a b echo "a-b=$(($a-$b))" echo "a+b=$(($a+$b))" echo "a*b=$(($a*$b))" echo "a/b=$(($a/$b))" echo "a**b=$(($a**$b))" echo "a%b=$(($a%$b))" read企業應用 [root@web01 scripts]# cat select1.sh #!/bin/bash cat <<EOF 1.install lamp 2.install lnmp 3.exit EOF read -p "請選擇一個序號(必須是數字):" num #1.判斷是否為整數 expr 2 + $num &>/dev/null if [ $? -ne 0 ] then echo "Usage:$0 {1|2|3}" exit 1 fi #2.判斷執行處理 if [ $num -eq 1 ] then echo "install lamp..." elif [ $num -eq 2 ] then echo "install lnmp..." elif [ $num -eq 3 ] then echo "bye." exit else echo "Usage:$0 {1|2|3}" exit 1 fi
Shell的常見條件表達式語法介紹和實踐
通常,在bash的各種條件結構和流程控制結構中都要進行各種測試,然后根據測試結果執行不同的操作,有時也會與if等條件語句相結合,來完成測試判斷,減少程序運行的錯誤。執行測試條件表達式后通常會返回“真”或“假”,就像執行命令后的返回值為0表示真,非0表示假一樣。
條件表達式常見語法

條件表達式的編程語法
[ 測試表達式 ] && 命令1 | | 命令2
如果前面的表達式成功,name就執行命令1,否則執行命令2
========相當於========
if [ 測試表達式 ]
then
命令1
else
命令2
fi
當命令很多的時候
[ 測試表達式 ] && {
命令1
命令2
}| |{
命令3
命令4
}
如果前面的表達式成功,那么久執行后面命令
[ 測試表達式 ] && 命令1
如果前面表達式失敗,那么就執行后面的命令
[ 測試表達式 ] | | 命令2
條件表達式 [root@web-01 /server/scripts]# [ -e /etc/hosts ] && echo 1 || echo 0 1 [root@web-01 /server/scripts]# [ -e /etc/host ] && echo 1 || echo 0 0 命令表達式 [root@web-01 /server/scripts]# (expr 1 + 1 &>/dev/null) && echo 1 || echo 0 1 [root@web-01 /server/scripts]# (expr 1 + a &>/dev/null) && echo 1 || echo 0 0
文件測試表達式的常見功能
在man test 中可以找到這些內容

字符串測試表達式常見功能說明

注意:
1、字符串就用雙引號
2、等號可以用一個或者兩個
3、等號兩端必須要有空格
整數測試表達式

記住在單括號和雙括號的寫法的區別,測試一下
邏輯測試表達式

不同符號測試表達式 [ ] [[ ]] (( )) test 的區別

條件表達式6種寫法:if,while 語法1: test <測試表達式> 語法2: [ <測試表達式> ] #兩端有空格 語法3:[[ <測試表達式> ]] #兩端有空格 語法4:((<測試表達式>)) #不需要空格 語法5:(命令表達式) 語法6:`命令表達式` 編程語法: [ <測試表達式> ] && 命令1 如果前面表達式成功,那么就執行后面命令。 [ <測試表達式> ] || 命令1 如果前面表達式失敗,那么就執行后面命令。 [ <測試表達式> ] && { 命令1 命令2 命令3 } 如果前面表達式成功,那么就執行后面命令。 [ <測試表達式> ] && 命令1 || 命令2 如果前面表達式成功,那么就執行命令1,否則執行命令2。 [ <測試表達式> ] && { 命令1 命令2 }||{ 命令3 命令4 } 如果前面表達式成功,那么就執行命令1,2,否則執行命令3,4。 <測試表達式>有哪些: 文件測試表達式: 為什么需要文件測試表達式? 操作一個對象,就要看對象條件是否滿足,否則不要操作。 1、常見功能 2、實踐 3、企業應用:啟動腳本中的應用。 字符串測試表達式 [ -n "字符串" ] 字符串長度[不]為0,表達式為真。 not zero。 [ -z "字符串" ] 字符串長度為0,表達式為真。 zero。 [ "字符串1" == "字符串2" ] 兩個字符串相同則為真。 [ "字符串1" !== "字符串2" ] 兩個字符串不相同則為真。 注意: 1、字符串就用雙引號 2、等號可以用一個或者兩個。 3、=號兩端必須要有空格。 實踐: [root@web01 ~]# [ -n "oldboy" ] && echo 1 || echo 0 1 [root@web01 ~]# [ -z "oldboy" ] && echo 1 || echo 0 0 [root@web01 ~]# char="oldboy" [root@web01 ~]# [ -z "$char" ] && echo 1 || echo 0 0 [root@web01 ~]# unset char [root@web01 ~]# [ -z "$char" ] && echo 1 || echo 0 1 [root@web01 ~]# [ "dd" == "dd" ] && echo 1 || echo 0 1 [root@web01 ~]# [ "dd" == "ff" ] && echo 1 || echo 0 0 [root@web01 ~]# [ "dd" = "ff" ] && echo 1 || echo 0 0 [root@web01 ~]# [ "dd" != "ff" ] && echo 1 || echo 0 1 [root@web01 ~]# [ "dd" != "dd" ] && echo 1 || echo 0 0 改造上面的四則運算的腳本 企業應用: [root@db03 scripts]# cat yunsuan1.sh #!/bin/bash ############################################################## # File Name: yunsuan.sh # Version: V1.0 # Author: oldboy # Organization: www.oldboyedu.com # Created Time : 2018-05-30 09:03:10 # Description: ############################################################## #!/bin/bash read -p "pls input two num:" a b
# b沒有值,肯定是沒有輸入或者沒有輸入2個 if [ -z "$b" ] then echo "請輸入兩個數" exit 1 fi
# 判斷是不是數字
expr $a + $b + 1 &>/dev/null if [ $? -ne 0 ] then echo "Usage:$0 num1 num2" exit 1 fi echo "a-b=$(($a-$b))" echo "a+b=$(($a+$b))" echo "a*b=$(($a*$b))" echo "a/b=$(($a/$b))" echo "a**b=$(($a**$b))" echo "a%b=$(($a%$b))" 整數測試表達式: 小題:使用read的交互方式,來比較兩個整數的大小。 分析: 1、要求整數 2、2個數 3、比較大小 大於 等於 小於 [root@web01 scripts]# cat com1.sh #!/bin/bash read -p "請輸入兩個整數:" a b #1.判斷是不是輸入兩個數 [ -z "$b" ] &&{ echo "請輸入兩個整數" exit 1 } #2.判斷整數 expr $a + $b + 1 &>/dev/null [ $? -ne 0 ] &&{ echo "請輸入兩個整數" exit 2 } #3.判斷是否大於 [ $a -gt $b ] &&{ echo "$a>$b" exit 0 } #4.判斷是否等於 [ $a -eq $b ] &&{ echo "$a=$b" exit 0 } #5.判斷是否小於 echo "$a<$b" [root@db03 scripts]# cat comp.sh #!/bin/bash ############################################################## # File Name: comp.sh # Version: V1.0 # Author: oldboy # Organization: www.oldboyedu.com # Created Time : 2018-05-30 11:36:19 # Description: ############################################################## read -p "Pls input two num:" a b #1.第一關判斷傳入的內容都是整數 expr $a + $b + 100 &>/dev/null [ $? -ne 0 ] &&{ echo "Usage:$0 num1 num2" exit 1 } #2.第二關輸入兩個數 [ -z "$b" ] &&{ echo "Usage:$0 num1 num2" exit 2 } #3.比較大小 [ $a -gt $b ] && { echo "$a>$b" exit 0 } [ $a -eq $b ] && { echo "$a=$b" exit 0 } echo "$a<$b" exit 0 ==============升級使用if [root@db03 scripts]# cat comp.sh #!/bin/bash ############################################################## # File Name: comp.sh # Version: V1.0 # Author: oldboy # Organization: www.oldboyedu.com # Created Time : 2018-05-30 11:36:19 # Description: ############################################################## read -p "Pls input two num:" a b #1.第一關判斷傳入的內容都是整數 expr $a + $b + 100 &>/dev/null [ $? -ne 0 ] &&{ echo "Usage:$0 num1 num2" exit 1 } #2.第二關輸入兩個數 [ -z "$b" ] &&{ echo "Usage:$0 num1 num2" exit 2 } #3.比較大小 if [ $a -gt $b ] then echo "$a>$b" elif [ $a -eq $b ] then echo "$a=$b" else echo "$a<$b" fi 邏輯測試表達式 ! 非 && -a 並且 || -o 或者 []中 使用 -a -o [[]]或(())里面 使用&& || [] [[]] (()) 這些符號之間連接 使用&& || make && make install ==================== [root@db03 scripts]# [ 1 -eq 1 -a -f /etc/hosts ] && echo 1 || echo 0 1 [root@db03 scripts]# [ 1 -eq 2 -a -f /etc/hosts ] && echo 1 || echo 0 0 [root@db03 scripts]# [ 1 -eq 2 && -f /etc/hosts ] && echo 1 || echo 0 -bash: [: missing `]' 0 [root@db03 scripts]# [[ 1 -eq 2 && -f /etc/hosts ]] && echo 1 || echo 0 0 [root@db03 scripts]# [ 1 -eq 2 ] && [ -f /etc/hosts ] && echo 1 || echo 0 [root@db03 scripts]# [ -f /etc/hosts ] && echo 1 || echo 0 1 [root@db03 scripts]# [ ! -f /etc/hosts ] && echo 1 || echo 0 0 小題:如果/tmp/oldboy.sh是普通文件,並且可執行,就執行改腳本。 file="/tmp/oldboy.sh" if [ -f $file ] && [ -x $file ] then bash $file fi 1. 單分支結構 第一種語法: if <條件表達式> then 指令 fi 第二種語法: if <條件表達式>; then 指令 fi 如果 <你有房> 那么 我就嫁給你 果如 if條件句的雙分支結構語法為: if <條件表達式> then 指令集1 else 指令集2 fi 如果 <你有房> 那么 我就嫁給你 否則 我再考慮下 果如 多分支: if <條件表達式1> then 指令1... elif <條件表達式2> then 指令2... elif <條件表達式3> then 指令3... else 指令4... fi 范例7_2:開發Shell腳本判斷系統剩余內存的大小,如果低於100MB就郵件報警給系統管理員, 並且將腳本加入系統定時任務,即每3分鍾執行一次檢查。 分析思路: 1、取內存 free -m|awk 'NR==3{print $NF}' 2、發郵件 mail -s "主題" 郵件地址 </etc/hosts echo ""|mail -s "主題" 郵件地址 3、開發腳本判斷發郵件 full="內存充足。" leak="內存不足。" free=`free -m|awk 'NR==3{print $NF}'` if [ $free -lt 1000 ] then echo "$leak"|tee /tmp/mail.log mail -s "$leak`date`" 31333741-@qq.com </tmp/mail.log else echo "$full" fi 4、加入定時任務 [root@db03 scripts]# crontab -l|tail -2 ########### */3 * * * * /bin/sh /server/scripts/judge.sh >/dev/null 2>&1 課后練習:開發Shell腳本判斷系統根分區剩余空間的大小,如果低於1000MB報警空間不足, 如果低於500M,就報警空間嚴重不足,最后把結果郵件發給系統管理員, 並且將腳本加入系統定時任務,即每3分鍾執行一次檢查。 預習: 函數 case for while
Shell編程第一章節前六小節復習
Shell編程實戰:第一模塊前六節復習:Shell編程基礎 01-第一章:如何學好shell編程。 必備基礎: 1)熟練vim編輯器,.vimrc配置。 2)120個左右Linux命令。(跟老男孩學習Linux運維:核心命令實戰) 3)網絡服務,rsync,nfs,lamp,lnmp,ltmp,keepalived,lvs 如何學好: 1、鍛煉編程思維
比如要先有大綱 第一章 1.1 1.1.1 1.1.2 第二章 2.1 2.1.1 2.1.2 2、多練,多思考,不要拿來主義。 3、有一本教科書。跟老男孩學習Linux運維:Shell編程實戰 02-第二章:Shell基礎入門 什么是shell 什么是shell腳本 shell腳本的建立 #!/bin/bash #### shell腳本的執行 4種方式: 1)bash/sh oldboy.sh #推薦使用 2)source/. oldboy.sh ***** 3)sh/bash<oldboy.sh 4)./oldboy.sh或/server/scripts/oldboy.sh #必須要有執行權限。 Shell的執行過程 oldboy.sh: pwd ls oldgirl.sh #子shell ls oldgirl.sh & 放到后台執行。 並行,執行的同時,也執行下面的額ls 重點也是難點 source/. oldgirl.sh 相當於子Shell和父Shell相當於在一個shell里運行。 03-第三章 變量基礎 1、什么是變量? oldboy="I am oldboy" oldboy是變量名,= 是賦值符號,"I am oldboy"是變量的內容。 OldboyAge oldboyAge #推薦。 oldboy_age 2、變量類型,shell里面是弱類型 decalre -i A #定義一個整形,一般沒有這種需求 3、變量分類 環境變量(全局變量) 特點:大寫 全局生效 1)系統的環境變量 PS1,PATH,LANG 直接用。 2)自定義環境變量 export OLDBOY=1 OLDBOY=1 export OLDBOY decalre OLDBOY=1 查看: env/set echo $變量名 取消: unset 變量名 普通變量(局部變量) 局部生效: oldboy="I am oldboy" oldboy是變量名,=是賦值符號,"I am oldboy"是變量的內容。 變量名: OldboyAge oldboyAge #推薦。 oldboy_age = 兩邊不能有空格 變量內容: 4種方式 a=test #不加引號,也會解析變量,推薦連續數字用此方法。 a='test' #所見即所得。 a="test" #默認雙引號,解析變量。 a=`date` #解析一個命令結果。就用``或$()。 輸出變量: $oldboy_age ${oldboy_age}dddd 04-第四章 變量的擴展 1)特殊位置變量 $0 ***** 企業應用-腳本的結尾 $1,$2,$n ***** $# ***** 獲取參數的個數 $* 兩個的相同點和不同點 $@ 2)特殊狀態變量 $? ***** $$ 進程號 $!上一個腳本的進程 $_ 上一個腳本的最后一個參數 相當於 esc+點 3)變量的子串 ${oldboy} ${#oldboy} wc -L ,expr length "$oldboy",awk '{print length }' ${oldboy:2} ${oldboy:2:2} ${oldboy#word} ${oldboy##word} ${oldboy%word} ${oldboy%%word} ${oldboy/dd/ff} ${oldboy//dd/ff} 4)變量特殊擴展 result=${oldboy:-word} # 推薦 **** result=${oldboy:=word} result=${oldboy:?word} result=${oldboy:+word} 霸道 第五章 變量的數值計算 整數: (()) 推薦 let 推薦 $[] expr declare declare -i a=4+3 echo $a 小數: bc 推薦加減 awk 乘除推薦 expr: 1)判斷是否為整數。 2)擴展名 。忘記判斷,記憶竅門 vim ·which ssh-copy-id· 3)取字符串長度 變量的定義: 1)a=1 2)傳參 3)read讀入 read -t 10 -p "輸入提示:" a 用途:菜單選擇,和用戶交互
第六章 條件測試與比較 6種: [] #推薦 [[]] test (()) (命令) `命令` 等價if單分支 []&&{ dddd } 等價if雙分支 []&&{ dddd }||{ ddd } =================================== [ -f /etc/hosts ] || exit 5 常用的推薦用法,簡簡潔,命令多的時候,用if比較好 make && make install ================================= if,whlie 當做一個條件判斷。 文件、字符、整數 測試 邏輯符
都可以用man test 找到
if、case、while、for、函數、數組和企業實踐
Shell案例實戰和企業面試題
第五階段-模塊作業
章節一
試題1:用source執行腳本和用bash執行Shell腳本的區別是什么? 考試題2:如何自定義環境變量? 考試題3:定義變量內容,不加引號、單引號、雙引號、反引號結果有什么不同?應該怎么用? 考試題4:請分別說出2個以上用於整數運算特殊符號或命令,以及適合小數運算的命令。 考試題5:寫出特殊變量對應的意義及應用 $0、$n、$#、$*、$@、$?、$$、$!、$_ 考試題6:寫出下面特殊變量擴展的意義 ${oldboy}、${#oldboy}、${oldboy:offset:length}、${oldboy#word}、${oldboy##word}、${oldboy%word}、${oldboy%%word}、${oldboy/pattern/string}、${oldboy//pattern/string}、${oldboy:-word} 考試題7:在條件測試與表達式中,[]和[[]]有何區別? 考試題8:說出適合在[]以及test中整數比較的特殊運算符號? 考試題9、輸出下面菜單 1.install MySQL 2.install Tomcat 3.exit 當用戶選擇對應的數字就開始安裝對應的服務(可echo輸出替代),需要對用戶輸入的數字進行判斷是否為整數(用條件測試表達式實現)。 考試題10、使用read讀入方式比較兩個整數大小(用條件表達式實現)。
章節二
考試題1:開發Shell腳本判斷系統根分區剩余空間的大小,如果低於1000MB就提示不足,否則提示充足。 考試題2:分別使用變量定義、read讀入及腳本傳參方式實現比較2個整數的大小。 考試題3:打印一個菜單如下,當用戶選擇對應的數字時,就執行對應項的應用,最好對用戶的輸入進行是否為整數判斷。 1.install lamp 2.install lnmp 3.exit 考試題4:通過腳本傳參的方式,檢查Web網站URL是否正常(要求主體使用函數)。 考試題5:利用case語句開發Rsync服務啟動停止腳本,並能通過chkconfig實現開機自啟動。 考試題6:猜數字游戲。首先讓系統隨機生成一個數字,給這個數字定一個范圍(1-60),讓用戶輸入猜的數字,對輸入進行判斷,如果不符合要求,就給予高或低的提示,猜對后則給出猜對用的次數,請用while語句實現。 考試題7:分析nginx訪問日志(自備),把日志中每行的訪問字節數對應字段數字相加,計算出總的訪問量。給出實現程序,請用while循環實現。 考試題8:計算從1加到100之和(要求用for和while,至少給出兩種方法)。 考試題9:利用bash for循環打印下面這句話中字母數不大於6的單詞(某企業面試真題)。I am oldboy teacher welcome to oldboy training class 考試題10:使用read讀入方式比較兩個整數大小,要求對用戶輸入的內容嚴格判斷是否為整數,是否輸入了兩個數字。
