shell腳本編程

shell腳本編程

程序的組成

程序:算法+數據結構
數據:是程序的核心
數據結構:數據在計算機中的類型和組織方式
算法:處理數據的方式

程序編程風格

#面向過程語言
作一件事情,排出個步驟,第一步幹什麼,第二步幹什麼,若是出現狀況A,作什麼處理,如
果出現了狀況B,作什麼處理
問題規模小,能夠步驟化,循序漸進處理
以指令爲中心,數據服務於指令
C,shell
#面嚮對象語言
一種認識世界、分析世界的方法論。將萬事萬物抽象爲各類對象
類是抽象的概念,是萬事萬物的抽象,是一類事物的共同特徵的集合
對象是類的具象,是一個實體
問題規模大,複雜系統
以數據爲中心,指令服務於數據
java,C#,python,golang等

編程語音

計算機:運行二進制指令
編程語言:人與計算機之間交互的語言。分爲兩種:低級語言和高級語言
低級編程語言:
機器:二進制的0和1的序列,稱爲機器指令。與天然語言差別太大,難懂、難寫
彙編:用一些助記符號替代機器指令,稱爲彙編語言
 如:ADD A,B 將寄存器A的數與寄存器B的數相加獲得的數放到寄存器A中
 彙編語言寫好的程序須要彙編程序轉換成機器指令
 彙編語言稍微好理解,即機器指令對應的助記符,助記符更接近天然語言
高級編程語言:
編譯:高級語言-->編譯器-->機器代碼文件-->執行,如:C,C++
解釋:高級語言-->執行-->解釋器-->機器代碼,如:shell,python,php,JavaScript,perl
編譯和解釋型語言

腳本語言的基本用法

自動化經常使用命令
執行系統管理和故障排除
建立簡單的應用程序
處理文本或文件

shell腳本的執行方法

#執行方法1
[root@centos8 ~]#bash /data/hello.sh
#執行方法2
[root@centos8 ~]#cat /data/hello.sh | bash
#執行方法3
[root@centos8 ~]#chmod +x /data/hello.sh
但你寫了一個腳本卻沒法被執行是由於你的hash裏面沒有這個路徑,路徑沒法被查到,就是在環境變量裏面沒法被查到,要寫到環境變量裏面 並且還要用  .激活一下
#絕對路徑
[root@centos8 ~]#/data/hello.sh
#相法路徑
[root@centos8 ~]#cd /data/
[root@centos8 ~]#./hello.sh
#執行方法4,本方法能夠實現執行遠程主機的shell腳本
[root@centos8 ~]#yum -y install httpd
[root@centos8 ~]#systemctl start httpd
[root@centos8 ~]#mv /data/hello.sh /var/www/html/
[root@centos8 ~]#curl -s http://www.wanghua.com/hello.sh|bash   #執行互聯網上的腳本  -s 能夠隱藏下載的信息
[root@centos8 ~]#wget -qO - http://www.wangxiaochun.com/testdir/hello.sh |bash
hello, world
Hello, world!
調用別人寫的腳本,將將腳本放在服務器上,調用服務器上的腳本

範例:備份腳本

[root01:52 PMcentos7 ]#cat a.sh 
#!/bin/bash
echo -e "\033[1;32m 開始備份 \033[0m"
sleep 3
cp -a /etc  /back/`date +%F_%T`
echo -e "\033[1;32m 備份完成 \033[0m"

shell 腳本調試

只檢測腳本中的語法錯誤,但沒法檢查出命令錯誤,但不真正執行腳本javascript

bash -n /path/to/some_script

調試並執行php

bash -x /path/to/some_script          -x:真正執行了的,每次執行一行,執行的結果就顯示一下

總結:腳本錯誤常見的有三種html

​ 語法錯誤,會致使後續的命令不繼續執行,能夠用bash -n 檢查錯誤,提示的出錯行數不必定是準java

​ 確的node

​ 命令錯誤,默認後續的命令還會繼續執行,用bash -n 沒法檢查出來 ,可使用 bash -x 進行觀察python

​ 邏輯錯誤:只能使用 bash -x 進行觀察linux

變量

變量表示命名的內存空間,將數據放在內存空間中,經過變量名引用,獲取數據c++

變量類型

變量類型:
內置變量,如:PS1,PATH,UID,HOSTNAME,$$(當前進程),BASHPID,PPID(父進程),$?,HISTSIZE
用戶自定義變量
不一樣的變量存放的數據不一樣,決定了如下
1. 數據存儲方式
2. 參與的運算
3. 表示的數據範圍
變量數據類型:
字符
數值:整型、浮點型,bash 不支持浮點數

編程語言分類

#靜態和動態語言
靜態編譯語言:使用變量前,先聲明變量類型,以後類型不能改變,在編譯時檢查,如:java,c
動態編譯語言:不用事先聲明,可隨時改變類型,如:bash,Python

#強類型和弱類型語言
強類型語言:不一樣類型數據操做,必須通過強制轉換才同一類型才能運算,如java , c# ,
python
如:參考如下 python 代碼
 print('magedu'+ 10) 提示出錯,不會自動轉換類型
 print('magedu'+str(10)) 結果爲magedu10,須要顯示轉換類型
弱類型語言:語言的運行時會隱式作數據類型轉換。無須指定類型,默認均爲字符型;參與運算會
自動進行隱式類型轉換;變量無須事先定義可直接調用
如:bash ,php,javascript

Shell**中變量命名法則**

不能使程序中的保留字:如:if, for
只能使用數字、字母及下劃線,且不能以數字開頭,注意:不支持短橫線 「 - 」,和主機名相反
見名知義,用英文單詞命名,並體現出實際做用,不要用簡寫,如:ATM
統一命名規則:駝峯命名法, studentname,大駝峯StudentName 小駝峯studentName 
變量名大寫:STUDENT_NAME
局部變量小寫
函數名小寫

變量定義和引用

變量的生效範圍等標準劃分變量類型golang

普通變量:生效範圍爲當前shell進程;對當前shell以外的其它shell進程,包括當前shell的子shell
進程均無效
環境變量:生效範圍爲當前shell進程及其子進程
本地變量:生效範圍爲當前shell進程中某代碼片段,一般指函數

變量賦值:

直接字串:name='root'
變量引用:name="$USER"
命令引用:name=`COMMAND` 或者 name=$(COMMAND)

注意:變量賦值是臨時生效,當退出終端後,變量會自動刪除,沒法持久保存,腳本中的變量會隨着腳面試

本結束,也會自動刪除

變量引用:

弱引用和強引用
"$name " 弱引用,其中的變量引用會被替換爲變量值
'$name ' 強引用,其中的變量引用不會被替換爲變量值,而保持原字符串

範例:變量的各類賦值方式和引用

[root@centos8 ~]#TITLE='cto'  
[root@centos8 ~]#echo $TITLE
cto
[root@centos8 ~]#echo I am $TITLE
I am cto
[root@centos8 ~]#echo "I am $TITLE"
I am cto
[root@centos8 ~]#echo 'I am $TITLE'
I am $TITLE
[root@centos8 ~]#NAME=$USER
[root@centos8 ~]#echo $NAME
root
[root@centos8 ~]#USER=`whoami`
[root@centos8 ~]#echo $USER
root
[root@centos8 ~]#FILE=`ls /run`
[root@centos8 ~]#echo $FILE
agetty.reload atd.pid auditd.pid autofs.fifo-misc autofs.fifo-net console 
cron.reboot cryptsetup dbus faillock fsck initctl initramfs lock log mount 
NetworkManager plymouth rsyslogd.pid screen sepermit setrans sshd.pid sssd.pid 
sudo systemd tmpfiles.d tuned udev user utmp vmware
[root@centos8 ~]#FILE=/etc/*   命令的執行結果
[root@centos8 ~]#echo $FILE
/etc/adjtime /etc/aliases /etc/alternatives /etc/anacrontab /etc/at.deny 
/etc/audit /etc/authselect /etc/autofs.conf /etc/autofs_ldap_auth.conf

垃圾回收

[root03:27 PMcentos7 ]#title=cto
[root03:33 PMcentos7 ]#name=wang
[root03:33 PMcentos7 ]#title=$name
[root03:34 PMcentos7 ]#echo $name 
wang
[root03:34 PMcentos7 ]#echo $title
wang
[root03:35 PMcentos7 ]#name=wo
[root03:35 PMcentos7 ]#echo $name
wo
[root03:35 PMcentos7 ]#echo $title 
wang
[root03:35 PMcentos7 ]#name=ow
[root03:37 PMcentos7 ]#echo $name
ow
[root03:37 PMcentos7 ]#

wo這個字符串沒有人使用了,就是一塊垃圾了,會被回收
[root@centos8 ~]#seq 10
1
2
3
4
5
6
7
8
9
10
[root@centos8 ~]#NUM=`seq 10`
[root@centos8 ~]#echo $NUM
1 2 3 4 5 6 7 8 9 10
[root@centos8 ~]#echo "$NUM"     #加雙引號才能保留多行格式
1
2
3
4
5
6
7
8
9
10

[root03:43 PMcentos7 ]#name="
> wang
> zhang
> li
> "
[root03:44 PMcentos7 ]#echo $name
wang zhang li
[root03:44 PMcentos7 ]#echo "$name"

wang
zhang
li

[root03:44 PMcentos7 ]#name="wang
> zhang
> zhao
> li"
[root03:48 PMcentos7 ]#echo $name
wang zhang zhao li
[root03:48 PMcentos7 ]#echo "$name"
wang
zhang
zhao
li
[root03:48 PMcentos7 ]#

顯示已定義的全部變量

set

刪除變量:

unset <name>        #  跟的是變量名,無須要加$
[root@centos8 ~]#NAME=mage
[root@centos8 ~]#TITLE=ceo
[root@centos8 ~]#echo $NAME $TITLE
mage ceo
[root@centos8 ~]#unset NAME TITLE
[root@centos8 ~]#echo $NAME $TITLE

不設置環境變量子進程沒法調用父進程變量

[root04:29 PMcentos7 ]#cat parent.sh 
#!/bin/bash
NAME=name
echo $NAME
/data/son.sh
[root04:29 PMcentos7 ]#cat son.sh 
#!/bin/bash
echo " 調用父進程的變量 $NAME"
NAME="myvalue"
echo "調用本身的變量 $NAME"
[root04:29 PMcentos7 ]#/data/parent.sh 
name
 調用父進程的變量        ( #子進程沒法調用父進程的變量)
調用本身的變量 myvalue
[root04:29 PMcentos7 ]#/data/son.sh 
 調用父進程的變量 
調用本身的變量 myvalue
[root04:29 PMcentos7 ]#
[root04:29 PMcentos7 ]#vim parent.sh  (添加export之後,子進程就調用父進程的環境變量)
  1 #!/bin/bash
  2 export  NAME=name                                                                                       
  3 echo $NAME
  4 /data/son.sh

[root04:48 PMcentos7 ]#/data/parent.sh  
name
 調用父進程的變量 name
調用本身的變量 myvalue

父進定義的環境變量,子進程能使用,當子進程本身定義的變量和父進程定義的環境變量一致的時候,子進程優先使用本身的變量

環境變量

環境變量:
可使子進程(包括孫子進程)繼承父進程的變量,可是沒法讓父進程使用子進程的變量
一旦子進程修改從父進程繼承的變量,將會新的值傳遞給孫子進程
通常只在系統配置文件中使用,在腳本中較少使用
#聲明並賦值
export name=VALUE
declare -x name=VALUE
#或者分兩步實現
name=VALUE
export name

範例:變量引用

[root@centos8 data]#NAME=mage
[root@centos8 data]#AGE=20
[root@centos8 data]#echo $NAME
mage
[root@centos8 data]#echo $AGE
20
[root@centos8 data]#echo $NAME $AGE
mage 20
[root@centos8 data]#echo $NAME$AGE
mage20
[root@centos8 data]#echo $NAME_$AGE  #由於下劃線是能夠當作變量名的,將$NAME_ 認爲是一個變量
20
[root@centos8 data]#echo ${NAME}_$AGE    
mage_20

env

系統全部的環境變量,只是列環境變量
[root05:03 PMcentos7 ]#echo $$
3365
[root05:12 PMcentos7 ]#bash
[root05:12 PMcentos7 ]#echo $$
5155
[root05:12 PMcentos7 ]#echo $PPID        $SHLVL:嵌套深度      $$:當前的進程的PID     $PPID:父進程的PID
3365
[root05:12 PMcentos7 ]#echo $SHLVL
2
[root05:13 PMcentos7 ]#bash
[root05:14 PMcentos7 ]#echo $SHLVL
3
[root05:14 PMcentos7 ]#

範例:利用變量實現動態命令

[root05:48 PMcentos7 ]#CD=hostname
[root05:48 PMcentos7 ]#$CD
centos7

範例:顯示主機的信息

[root03:11 PMcentos7 ]#cat b.sh 
#!/bin/bash
echo -e "\033[1;31m ---------------------主機信息----------------------- \033[0m"
echo -e  "\033[1;32m主機名:`hostname` \033[0m"
echo -e  "\033[1;32mIP地址:`ifconfig ens33 |grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' |head -1 `\033[0m"
echo -e  "\033[1;32m發行版本號:`cat /etc/redhat-release`\033[0m"
echo -e  "\033[1;32m內核版本:`uname -r` \033[0m "  
echo -e  "\033[1;32mCPU信息:`lscpu |grep -i "model name"|tr -s ' ' |cut -d: -f2`\033[0m"
echo -e "\033[1;32m內存的使用狀況:`free -h |grep -iE  "mem"|tr -s ' ' : |cut -d: -f2`\033[0m"
echo -e "\033[1;32m磁盤的使用狀況:`lsblk |grep "^sd" |awk '{print $4}' ` \033[0m"
echo -e "\033[1;31m-------------------------------------------------------\033[0m"

只讀變量

只讀變量:只能聲明定義,但後續不能修改和刪除,即常量

聲明只讀變量:

[root06:05 PMcentos7 ]#type declare
declare is a shell builtin
#申明只讀變量
readonly name
declare  -r name

#查看只讀變量:
readonly [-p]
declare -r

[root@centos8 ~]#readonly PI=3.14159
[root@centos8 ~]#echo $PI
3.14159
[root@centos8 ~]#PI=3.14
-bash: PI: readonly variable
[root@centos8 ~]#unset PI
-bash: unset: PI: cannot unset: readonly variable
[root@centos8 ~]#echo $PI
3.14159
[root@centos8 ~]#exit   #退出之後變量就消失了
logout
Connection closed by foreign host.

位置變量

位置變量:在bash shell中內置的變量, 在腳本代碼中調用經過命令行傳遞給腳本的參數

$1, $2, ... 對應第1個、第2個等參數,shift [n]換位置
$0 命令自己,包括路徑
$* 傳遞給腳本的全部參數,所有參數合爲一個字符串
$@ 傳遞給腳本的全部參數,每一個參數爲獨立字符串
$# 傳遞給腳本的參數的個數
注意:$@ $* 只在被雙引號包起來的時候纔會有差別

#清空全部位置變量
set --
[root@centos8 ~]#cat /data/scripts/arg.sh 
#!/bin/bash
echo "1st arg is $1"
echo "2st arg is $2"
echo "3st arg is $3"
echo "10st arg is ${10}"
echo "11st arg is ${11}"
echo "The number of arg is $#"
echo "All args are $*"
echo "All args are $@"
echo "The scriptname is `basename $0`"        `basename $0`不顯示路徑名
[root@centos8 ~]#bash /data/scripts/arg.sh {a..z}
1st arg is a
2st arg is b
3st arg is c
10st arg is j
11st arg is k
The number of arg is 26
All args are a b c d e f g h i j k l m n o p q r s t u v w x y z
All args are a b c d e f g h i j k l m n o p q r s t u v w x y z
The scriptname is arg.sh

範例:刪庫跑路之命令rm的安全實現

[root06:24 PMcentos7 ]#cat rm.sh 
#!/bin/bash
STA="echo -e \033[1;31m"
END="\033[0m"
DIR=/tmp/`date +%F_%T`
mkdir $DIR
mv $* $DIR
$STA MOVE $* TO $DIR  $END

範例:$*和$@的區別

[root@centos8 scripts]#cat file.sh
#!/bin/bash
echo "file.sh:1st arg is $1"

[root@centos8 scripts]#cat f2.sh
#!/bin/bash
echo "f2.sh:all args are $@"
echo "f2.sh:all args are $*"
./file.sh "$@"
[root@centos8 scripts]#cat f1.sh
#!/bin/bash
echo "f1.sh:all args are $@"
echo "f1.sh:all args are $*"
./file.sh "$*"

[root@centos8 scripts]#./f1.sh a b c
f1.sh:all args are a b c
f1.sh:all args are a b c
file.sh:1st arg is a b c           # 嵌套之後$* 是全部的參數  $@是一個參數
[root@centos8 scripts]#./f2.sh a b c
f2.sh:all args are a b c
f2.sh:all args are a b c
file.sh:1st arg is a

退出狀態碼變量

進程執行後,將使用變量 $? 保存狀態碼的相關數字,不一樣的值反應成功或失敗,$?取值範例 0-255

$?的值爲0 #表明成功
$?的值是1到255   #表明失敗

[root@centos8 scripts]#curl http://www.wangxiaochun.com &> /dev/null
[root@centos8 scripts]#echo $?
0
ping -c1 -W1 hostdown &> /dev/null 
echo $?
#最近一條命令的執行結果

注意:

腳本中一旦遇到exit命令,腳本會當即終止;終止退出狀態取決於exit命令後面的數字

若是未給腳本指定退出狀態碼,整個腳本的退出狀態碼取決於腳本中執行的最後一條命令的狀態碼

展開命令行

展開命令執行順序
把命令行分紅單個命令詞
展開別名
展開大括號的聲明{}
展開波浪符聲明 ~
命令替換$() 和 ``
再次把命令行分紅命令詞
展開文件通配*、?、[abc]等等
準備I/0重導向 <、>
運行命令
反斜線(\)會使隨後的字符按原意解釋
        echo Your cost: \$5.00 
        Your cost: $5.00

腳本安全和 set

set 命令:能夠用來定製 shell 環境
$- 變量
h:hashall,打開選項後,Shell 會將命令所在的路徑hash下來,避免每次都要查詢。經過set +h將h選
項關閉
i:interactive-comments,包含這個選項說明當前的 shell 是一個交互式的 shell。所謂的交互式shell,
在腳本中,i選項是關閉的
m:monitor,打開監控模式,就能夠經過Job control來控制進程的中止、繼續,後臺或者前臺執行等
B:braceexpand,大括號擴展
H:history,H選項打開,能夠展開歷史列表中的命令,能夠經過!感嘆號來完成,例如「!!」返回上最近的
一個歷史命令,「!n」返回第 n 個歷史命令

[root08:02 PMcentos7/boot ]#ls /etc/redhat-release 
/etc/redhat-release
[root08:03 PMcentos7/boot ]#cat $_      echo $_是前一條命令的最後一個參數
CentOS Linux release 7.9.2009 (Core)

[root@centos8 ~]#echo $-   
himBHs
[root08:05 PMcentos7/boot ]#set +h
[root08:05 PMcentos7/boot ]#echo $-
imBH
[root08:05 PMcentos7/boot ]#hash     #這樣之後hash就被禁用了
-bash: hash: hashing disabled  
[root08:05 PMcentos7/boot ]#
[root08:05 PMcentos7/boot ]#set -h   #恢復hash功能
[root08:07 PMcentos7/boot ]#hash 
hits    command
   2    /usr/bin/cat
   4    /usr/bin/ls
[root08:07 PMcentos7/boot ]#echo $-  #恢復原狀
himBH
[root@centos8 ~]#set +B   關閉{}的功能
[root@centos8 ~]#echo $-
imHs
[root@centos8 ~]#echo {1..10}
{1..10}

set 命令實現腳本安全

-u 在擴展一個沒有設置的變量時,顯示錯誤信息, 等同set -o nounset
 -e 若是一個命令返回一個非0退出狀態值(失敗)就退出, 等同set -o errexit
 -o option 顯示,打開或者關閉選項
 顯示選項:set -o 
 打開選項:set -o 選項
 關閉選項:set +o 選項
 -x 當執行命令時,打印命令及其參數,相似 bash -x
[root08:08 PMcentos7/boot ]#set  -o
allexport       off
braceexpand     on
emacs           on
errexit         off  #出現錯誤不退出
errtrace        off
functrace       off
hashall         on
histexpand      on
history         on
ignoreeof       off
interactive-comments    on
keyword         off
monitor         on
noclobber       off
noexec          off
noglob          off
nolog           off
notify          off
nounset         off
onecmd          off
physical        off
pipefail        off
posix           off
privileged      off
verbose         off
vi              off
xtrace          off

[root08:18 PMcentos7~ ]#set  -o errexit on   #開啓功能,出現錯誤之後退出
[root08:18 PMcentos7~ ]#set  -o |grep errexit
errexit         on

[root08:21 PMcentos7~ ]#bash  f.sh
line1
f.sh: line 4: xxx: command not found
[root08:21 PMcentos7~ ]#cat f.sh
#!/bin/bash
set  -e      
echo line1                   set  -e  安全,可是一條命令不成功,後面的都不執行
xxx
echo line2
[root08:32 PMcentos7~ ]#cat b.sh 
#!/bin/bash
DIR=/data1
rm -rf  /data/tmp/$DIR1/*         由於沒有$DIR1這個變量,沒有定義的變量
[root08:33 PMcentos7~ ]#mkdir /data/tmp/
[root08:33 PMcentos7~ ]#touch  /data/tmp/a
[root08:33 PMcentos7~ ]#touch  /data/tmp/b
[root08:33 PMcentos7~ ]#bash b.sh 
[root08:34 PMcentos7~ ]#ls  /data/tmp/

[root08:39 PMcentos7~ ]#cat b.sh 
#!/bin/bash
set -u 
DIR=/data1
rm -rf  /data/tmp/$DIR1/*
[root08:38 PMcentos7~ ]#bash b.sh 
b.sh: line 4: DIR1: unbound variable   加了-u 之後就不準哪些未知的變量

因此工做中基於安全考慮,腳本中加
set -ue

格式化輸出 printf

printf "指定的格式" "文本1" 」文本2「……
%s 字符串
%f 浮點格式
%b 相對應的參數中包含轉義字符時,可使用此替換符進行替換,對應的轉義字符會被轉
義
%c ASCII字符,即顯示對應參數的第一個字符
%d,%i 十進制整數
%o 八進制值
%u 不帶正負號的十進制值
%x 十六進制值(a-f)
%X 十六進制值(A-F)
%% 表示%自己
[root@centos8 ~]#printf "%s\n" 1 2 3 4
1
2
3
4
[root@centos8 ~]#printf "%f\n" 1 2 3 4
1.000000
2.000000
3.000000
4.000000
#.2f 表示保留兩位小數
[root@centos8 ~]#printf "%.2f\n" 1 2 3 4
1.00
2.00
3.00
4.00
[root@centos8 ~]#printf "(%s)" 1 2 3 4;echo 
(1)(2)(3)(4)
[root@centos8 ~]#printf " (%s) " 1 2 3 4;echo ""
 (1) (2) (3) (4) 
[root@centos8 ~]#printf "(%s)\n" 1 2 3 4
(1)
(2)
(3)
(4)
[root@centos8 ~]#printf "%s %s\n" 1 2 3 4
1 2
3 4
[root@centos8 ~]#printf "%s %s %s\n" 1 2 3 4
1 2 3
4  
#%-10s 表示寬度10個字符,左對齊
[root@centos8 ~]#printf "%-10s %-10s %-4s %s \n" 姓名 性別 年齡 體重 小明 男 20 70 
小紅 女 18 50
姓名     性別     年齡   體重
小明     男        20   70
小紅     女        18   50
#將十進制的17轉換成16進制數
[root@centos8 ~]#printf "%X" 17
11[root@centos8 ~]# #將十六進制C轉換成十進制
[root@centos8 ~]#printf "%d\n" 0xC
12
[root@centos8 ~]#VAR="welcome to Magedu";printf "\033[31m%s\033[0m\n" $VAR
welcome
to
Magedu
[root@centos8 ~]#VAR="welcome to Magedu";printf "\033[31m%s\033[0m\n" "$VAR"
welcome to Magedu

算術運算

shell 支持算術運算,但只支持整數,不支持小數

bash中的算術運算

+
-
*
/
% 取模,即取餘數,示例:9%4=1,5%3=2
** 乘方

乘法符號有些場景中須要轉義

加強型賦值:

+= i+=10 至關於 i=i+10
-= i-=j   至關於 i=i-j
*=
/=
%=
++ i++,++i   至關於 i=i+1
-- i--,--i   至關於 i=i-1

實現算術運算:

(1) let var=算術表達式
(2) ((var=算術表達式)) 和上面等價
            [root@centos8 ~]#let i=10*2
            [root@centos8 ~]#echo $i
            20
            [root@centos8 ~]#((j=i+10))
            [root@centos8 ~]#echo $j
            30

[root09:29 AMcentos8 ~]#let i=10*2
[root09:29 AMcentos8 ~]#((j=i+10))
[root09:30 AMcentos8 ~]#echo $j
30

(3) var=$[算術表達式]
(4) var=$((算術表達式))
(5) var=$(expr arg1 arg2 arg3 ...)
(6) declare –i var = 數值
(7) echo '算術表達式' | bc

內建的隨機數生成器變量:

$RANDOM   取值範圍:0-32767
[root08:53 PMcentos7~ ]#echo $RANDOM
16020
[root08:57 PMcentos7~ ]#echo $RANDOM
26272
#生成 0 - 49 之間隨機數
echo $[$RANDOM%50]
#隨機字體顏色
[root@centos8 ~]#echo -e "\033[1;$[RANDOM%7+31]mhello\033[0m"
magedu
[root09:25 PMcentos7~ ]#echo -e "\e[1;$[RANDOM%7+31]mhello\033[0m"
hello

let 支持算數運算

[root08:59 PMcentos7~ ]#n=10
[root09:00 PMcentos7~ ]#m=20
[root09:00 PMcentos7~ ]#sum=$m+$n
[root09:00 PMcentos7~ ]#echo $sum
20+10
[root09:00 PMcentos7~ ]#let sum=$m+$n
[root09:02 PMcentos7~ ]#echo $sum
30
[root09:02 PMcentos7~ ]#n=30
[root09:02 PMcentos7~ ]#let sum=$m+$n
[root09:02 PMcentos7~ ]#echo $sum
50

取餘數爲0到50

[root09:05 PMcentos7~ ]#let result=RANDOM%50
[root09:05 PMcentos7~ ]#echo $result 
24
[root09:05 PMcentos7~ ]#let result=RANDOM%50+1
[root09:06 PMcentos7~ ]#echo $result 
48

i++ 和++1的區別

[root09:06 PMcentos7~ ]#i=10
[root09:08 PMcentos7~ ]#let i++
[root09:08 PMcentos7~ ]#echo $i
11
[root09:08 PMcentos7~ ]#let i++
[root09:08 PMcentos7~ ]#echo $i
12
[root09:08 PMcentos7~ ]#let i--
[root09:08 PMcentos7~ ]#echo $i
11
[root09:08 PMcentos7~ ]#let ++i
[root09:09 PMcentos7~ ]#echo $i
12
[root09:09 PMcentos7~ ]#let ++i
[root09:09 PMcentos7~ ]#echo $i
13
[root09:09 PMcentos7~ ]#i=10;let j=i++;echo j=$j i=$i    #賦值給j之後再加
j=10 i=11
[root09:13 PMcentos7~ ]#i=10;let j=++i;echo j=$j i=$i    #加完了賦給j
j=11 i=11

expr

[root09:33 PMcentos7~ ]#expr 2 + 3
5
[root09:33 PMcentos7~ ]#expr 2 * 3
expr: syntax error
[root09:34 PMcentos7~ ]#expr 2 / 3
0
[root09:34 PMcentos7~ ]#expr 23 / 3
7
[root09:34 PMcentos7~ ]#expr 27 / 3
9
[root09:34 PMcentos7~ ]#expr 2 \* 3  乘法被誤認爲通配符,轉義
6

bc

[root09:36 PMcentos7~ ]#echo 2*3 |bc
6
[root09:39 PMcentos7~ ]#echo "scale=3;20/3" |bc
6.666

result

[root09:40 PMcentos7~ ]#i=10
[root09:43 PMcentos7~ ]#j=20
[root09:43 PMcentos7~ ]#declare -i result=i*j
[root09:44 PMcentos7~ ]#echo $result 
200

邏輯運算

true, false

1, 0

#與:&:和0相與,結果爲0,和1相與,結果保留原值
     1 與 1 = 1
     1 與 0 = 0
     0 與 1 = 0
     0 與 0 = 0
#或:|:和1相或結果爲1,和0相或,結果保留原值
     1 或 1 = 1
       1 或 0 = 1
     0 或 1 = 1
     0 或 0 = 0
 #非:!
     ! 1 = 0 ! true
     ! 0 = 1 ! false
#異或:^
    異或的兩個值,相同爲假,不一樣爲真。兩個數字X,Y異或獲得結果Z,Z再和任意二者之一X異或,將得出
    另外一個值Y
    1 ^ 1 = 0
    1 ^ 0 = 1
    0 ^ 1 = 1
    0 ^ 0 = 0
[root@centos8 ~]#true 
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#false
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#! true
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#! false
[root@centos8 ~]#echo $?
0

#交換兩個值
[root@centos8 ~]#x=10;y=20;temp=$x;x=$y;y=$temp;echo x=$x,y=$y
x=20,y=10
[root@centos8 ~]#x=10;y=20;x=$[x^y];y=$[x^y];x=$[x^y];echo x=$x,y=$y
x=20,y=10

短路運算

短路與
 CMD1 短路與 CMD2
第一個CMD1結果爲真 (1),第二個CMD2必需要參與運算,才能獲得最終的結果
第一個CMD1結果爲假 (0),總的結果一定爲0,所以不須要執行CMD2
短路或
 CMD1 短路或 CMD2
第一個CMD1結果爲真 (1),總的結果一定爲1,所以不須要執行CMD2
第一個CMD1結果爲假 (0),第二個CMD2 必需要參與運算,,才能獲得最終的結果

條件測試命令

條件測試:判斷某需求是否知足,須要由測試機制來實現,專用的測試表達式須要由測試命令輔助完成

測試過程

,實現評估布爾聲明,以便用在條件性環境下進行執行

若真,則狀態碼變量 $? 返回0

若假,則狀態碼變量 $? 返回1

條件測試命令

test EXPRESSION

[ EXPRESSION ] #和test 等價,建議使用 [ ]

[[ EXPRESSION ]]
==========================================================================
[root11:40 PMcentos7~ ]#type [      中括號自己就是一個內部命令
[ is a shell builtin

[root11:45 PMcentos7~ ]#help [
[: [ arg... ]
    Evaluate conditional expression.

    This is a synonym for the "test" builtin, but the last argument must
    be a literal `]', to match the opening `['.
[[ ... ]]: [[ expression ]]
    Execute conditional command.

    Returns a status of 0 or 1 depending on the evaluation of the conditional
    expression EXPRESSION.  Expressions are composed of the same primaries used
    by the `test' builtin, and may be combined using the following operators:

      ( EXPRESSION )    Returns the value of EXPRESSION
      ! EXPRESSION      True if EXPRESSION is false; else false
      EXPR1 && EXPR2    True if both EXPR1 and EXPR2 are true; else false
      EXPR1 || EXPR2    True if either EXPR1 or EXPR2 is true; else false

    When the `==' and `!=' operators are used, the string to the right of
    the operator is used as a pattern and pattern matching is performed.
    When the `=~' operator is used, the string to the right of the operator
    is matched as a regular expression.

    The && and || operators do not evaluate EXPR2 if EXPR1 is sufficient to
    determine the expression's value.

    Exit Status:
    0 or 1 depending on value of EXPRESSION.

注意:EXPRESSION先後必須有空白字符

幫助:

面試題:求年紀之和

[root10:56 PMcentos7~ ]#cat a
xiaoing=20
xiaohong=18
xiaoqiang=22
方法一:
[root11:08 PMcentos7~ ]#cut -d"=" -f2 a  |tr -s "\n"  + |cut -d'+' -f1-3 
20+18+22
[root11:01 PMcentos7~ ]#cut -d"=" -f2 a  |tr -s "\n"  + |cut -d'+' -f1-3 |bc
60
方法二:
[root11:14 PMcentos7~ ]#cut -d"=" -f2 a  |tr -s "\n"  + |grep  -Eo "([0-9]+\+){2}[0-9]+"|bc
60
方法三
[root11:14 PMcentos7~ ]#cut -d"=" -f2 a  |tr -s "\n"  + 
20+18+22+[root11:16 PMcentos7~ ]#cut -d"=" -f2 a  |tr -s "\n"  + |grep -Eo ".*[0-9]+" |bc
60
方法四:
[root10:11 AMcentos8 ~]#awk -F"=" '{print $2}' |paste -sd+ |bc
60

test -v 測試變量是否存在 ,無論裏面有沒有值

[root11:47 PMcentos7~ ]#test -v n
[root11:52 PMcentos7~ ]#echo $?
0
[root11:52 PMcentos7~ ]#echo $n
30
[root11:54 PMcentos7~ ]#name=
[root11:54 PMcentos7~ ]#test -v name
[root11:54 PMcentos7~ ]#echo $?
0
[root11:55 PMcentos7~ ]#echo $name

[root11:55 PMcentos7~ ]#
[root11:55 PMcentos7~ ]#unset name
[root11:57 PMcentos7~ ]#test -v name
[root11:57 PMcentos7~ ]#echo $?
1
[root11:58 PMcentos7~ ]#hi="hi"
[root11:59 PMcentos7~ ]#[ -v hi ]      test和中括號等價
[root11:59 PMcentos7~ ]#echo $?
0

數值測試

-eq 是否等於
-ne 是否不等於
-gt 是否大於
-ge 是否大於等於
-lt 是否小於
-le 是否小於等於
[root@centos8 ~]#i=10
[root@centos8 ~]#j=8
[root@centos8 ~]#[ $i -lt $j ]   即便是數字也要加$
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#[ $i -gt $j ] 
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#[ i -gt j ] 
-bash: [: i: integer expression expected

字符串測試

test和 [ ]用法
-z STRING 字符串是否爲空,沒定義或空爲真,不空爲假,
-n STRING 字符串是否不空,不空爲真,空爲假 
   STRING   同上
STRING1 = STRING2 是否等於,注意 = 先後有空格,沒有空格是賦值,有空格是比較
STRING1 != STRING2 是否不等於
> ascii碼是否大於ascii碼
< 是否小於
[[]] 用法,建議,當使用正則表達式或通配符使用,通常狀況使用 [ ]
== 左側字符串是否和右側的PATTERN相同
 注意:此表達式用於[[ ]]中,PATTERN爲通配符
=~ 左側字符串是否可以被右側的正則表達式的PATTERN所匹配
 注意: 此表達式用於[[ ]]中;擴展的正則表達式
[root@centos8 ~]#unset str
[root@centos8 ~]#[ -z "$str" ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#str=""
[root@centos8 ~]#[ -z "$str" ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#str=" "
[root@centos8 ~]#[ -z "$str" ]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#[ -n "$str" ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#unset str
[root@centos8 ~]#[ -n "$str" ]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#[ "$str" ]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#str=magedu
[root@centos8 ~]#[ "$str" ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#str=magedu
[root@centos8 ~]#[ "$str" ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#str1=magedu
[root@centos8 ~]#str2=mage
[root@centos8 ~]#[ $str1 = $str2 ]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#str2=magedu
[root@centos8 ~]#[ $str1 = $str2 ]      有空格是比較,沒有空格是賦值
[root@centos8 ~]#echo $?
0

變量放中括號要加雙引號

[root@centos8 ~]#[ "$NAME" ]
[root@centos8 ~]#NAME="I love linux"
[root@centos8 ~]#[ $NAME ]
-bash: [: love: binary operator expected
[root@centos8 ~]#[ "$NAME" ]    #省略了一個  -n 
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#[ I love linux ]
-bash: [: love: binary operator expected

[[ ]] 雙中括號的使用

#通配符
[root@centos8 ~]#FILE=test.log
[root@centos8 ~]#[[ "$FILE" == *.log ]]  
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#FILE=test.txt
[root@centos8 ~]#[[ "$FILE" == *.log ]]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#[[ "$FILE" != *.log ]]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#NAME="linux1"             左側的變量加雙引號,右側的不加
[root@centos8 ~]#[[ "$NAME" == linux* ]]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#[[ "$NAME" == "linux*" ]]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#NAME="linux*"
[root@centos8 ~]#[[ "$NAME" == "linux*" ]]
[root@centos8 ~]#echo $?
0
#結論:[[ == ]] == 右側的 * 作爲通配符,不要加「」,只想作爲*, 須要加「」 或轉義
遇到正則表達式這樣複雜的就用雙中括號
#正則表達式
[root@centos8 ~]#[[ "$FILE" =~ \.log$ ]]    #判斷後綴
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#FILE=test.log
[root@centos8 ~]#[[ "$FILE" =~ \.log$ ]]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#N=100
[root@centos8 ~]#[[ "$N" =~ ^[0-9]+$ ]]     #雙中括號用的擴展的正則表達式
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#N=Magedu10
[root@centos8 ~]#[[ "$N" =~ ^[0-9]+$ ]]     #純數字的判斷
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#IP=1.2.3.4
[root@centos8 ~]#[[ "$IP" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]    #ip地址的判斷
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#IP=1.2.3.4567
[root@centos8 ~]#[[ "$IP" =~ ^([0-9]{1,3}.){3}[0-9]{1,3}$ ]]   
[root@centos8 ~]#echo $?
1

#是不是合法的IP 
[root10:27 AMcentos8 ~]#[[ "$IP" =~(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$ ]]
[root10:27 AMcentos8 ~]#echo $?
1

shell腳本編程

shell腳本編程
19.jpg20.png

#!/bin/bash   
read -p "請輸入IP:" IP
    if [[ $IP =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
        FIELD1=$(echo $IP|cut -d. -f1)
        FIELD2=$(echo $IP|cut -d. -f2)
        FIELD3=$(echo $IP|cut -d. -f3)
        FIELD4=$(echo $IP|cut -d. -f4)
        if [ $FIELD1 -le 255 -a $FIELD2 -le 255 -a $FIELD3 -le 255 -a $FIELD4 -le 255 ]; then
            echo "IP $IP available."
        else
            echo "IP $IP not available!"   
        fi
    else
        echo "IP format error!"   
    fi   

 #!/bin/bash
read -p "請輸入一個IP:"  IP
function check_ip() {
    if [[ $IP =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
        FIELD1=$(echo $IP|cut -d. -f1)
        FIELD2=$(echo $IP|cut -d. -f2)
        FIELD3=$(echo $IP|cut -d. -f3)
        FIELD4=$(echo $IP|cut -d. -f4)
        if [ $FIELD1 -le 255 -a $FIELD2 -le 255 -a $FIELD3 -le 255 -a $FIELD4 -le 255 ]; then
            echo "IP $IP available."
        else
            echo "IP $IP not available!"   
        fi
    else
        echo "IP format error!"   
    fi   
} 
check_ip

文件測試

存在性測試
-a FILE:同 -e
-e FILE: 文件存在性測試,存在爲真,不然爲假
-b FILE:是否存在且爲塊設備文件
-c FILE:是否存在且爲字符設備文件 
-d FILE:是否存在且爲目錄文件
-f FILE:是否存在且爲普通文件
-h FILE 或 -L FILE:存在且爲符號連接文件
-p FILE:是否存在且爲命名管道文件
-S FILE:是否存在且爲套接字文件
[root@centos8 ~]#[ -a /etc/nologin ] 
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#! [ -a /etc/nologin ] 
[root@centos8 ~]#echo $?
0
[root01:18 AMcentos7~ ]# [ ! -a /etc/nologin ]   !放中括號裏面
[root01:20 AMcentos7~ ]#echo $?
0

[root@centos8 ~]#[ -d /etc ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#[ -d /etc/issue ]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#[ -L /bin ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#[ -L /bin/ ]  軟連接
[root@centos8 ~]#echo $?
1

[root01:10 AMcentos7~ ]#ll /etc/redhat-release 
lrwxrwxrwx 1 root root 14 Apr 30 10:16 /etc/redhat-release -> centos-release
[root12:07 AMcentos7~ ]#[ -f /etc/redhat-release  ] 該文件雖然是軟連接文件可是卻也是普通文件,他判斷的是軟連接指向的
[root01:09 AMcentos7~ ]#echo $?
0
[root01:13 AMcentos7~ ]#ll /lib  該文件也是軟連接,可是卻不是普通文件,由於他指向的是一個文件夾
lrwxrwxrwx 1 root root 7 Apr 30 10:16 /lib -> usr/lib
[root01:13 AMcentos7~ ]#[ -f /lib ]
[root01:13 AMcentos7~ ]#echo $?
1
[root01:15 AMcentos7~ ]#[ -h /lib ]  軟連接
[root01:16 AMcentos7~ ]#echo $?
0

文件權限測試:

-r FILE:是否存在且可讀
-w FILE: 是否存在且可寫
-x FILE: 是否存在且可執行
-u FILE:是否存在且擁有suid權限
-g FILE:是否存在且擁有sgid權限
-k FILE:是否存在且擁有sticky權限

注意:最終結果由用戶對文件的實際權限決定,而非文件屬性決定

[root@centos8 ~]#[ -w /etc/shadow ] 
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#[ -x /etc/shadow ] 
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#[ -w test.txt ]
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#chattr +i test.txt 
[root@centos8 ~]#lsattr test.txt
----i-------------- nianling.txt
[root@centos8 ~]#[ -w test.txt ]
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#chattr -i test.txt 
[root@centos8 ~]#[ -w test.txt ]
[root@centos8 ~]#echo $?
0

文件屬性測試

-s FILE #是否存在且非空
-t fd #fd 文件描述符是否在某終端已經打開
-N FILE #文件自從上一次被讀取以後是否被修改過
-O FILE #當前有效用戶是否爲文件屬主
-G FILE #當前有效用戶是否爲文件屬組
FILE1 -ef FILE2 #FILE1是不是FILE2的硬連接
FILE1 -nt FILE2 #FILE1是否新於FILE2(mtime)
FILE1 -ot FILE2 #FILE1是否舊於FILE2

關於 () {}

(CMD1;CMD2;...)和 { CMD1;CMD2;...; } 均可以將多個命令組合在一塊兒,批量執行

[root@centos8 ~]#man bash

(list ) 會開啓子shell,而且list中變量賦值及內部命令執行後,將再也不影響後續的環境, 幫助參看:man bash

搜索(list)

{ list; } 不會啓子shell, 在當前shell中運行,會影響當前shell環境, 幫助參看:man bash 搜索{ list; }

面試題

[root@centos8 ~]#name=mage;(echo $name;name=wang;echo $name );echo $name
mage           特例:雖然不是環境變量,可是使用小括號是能夠繼承父進程的環境變量的
wang
mage
[root@centos8 ~]#name=mage;{ echo $name;name=wang;echo $name; } ;echo $name
mage           花括號不開啓子進程,會影響當前的環境
wang
wang
[root@centos8 ~]#umask
0022
[root@centos8 ~]#(umask 066;touch f1.txt)
[root@centos8 ~]#ll f1.txt 
-rw------- 1 root root 0 Dec 23 16:58 f1.txt
[root@centos8 ~]#umask
0022
[root@centos8 ~]#( cd /data;ls )
test.log
[root@centos8 ~]#pwd
/root
[root@centos8 ~]#{ cd /data;ls; }
test.log
[root@centos8 data]#pwd
/data
[root@centos8 data]#
#()會開啓子shell
[root@centos8 ~]#echo $BASHPID
1920
[root@centos8 ~]#( echo $BASHPID;sleep 100)
1979
[root@centos8 ~]#pstree -p
├─sshd(719)───sshd(1906)───sshd(1919)─┬─bash(1920)───bash(1979)───sleep(1980)
#{ } 不會開啓子shell
[root@centos8 ~]#echo $BASHPID
1920
[root@centos8 ~]#{ echo $BASHPID; }
1920

組合測試條件

第一種方式 [ ]

[ EXPRESSION1 -a EXPRESSION2 ] 而且,EXPRESSION1和EXPRESSION2都是真,結果才爲真
[ EXPRESSION1 -o EXPRESSION2 ] 或者,EXPRESSION1和EXPRESSION2只要有一個真,結果就爲
真
[ ! EXPRESSION ] 取反
說明: -a 和 -o 須要使用測試命令進行,[[ ]] 不支持
[root@centos8 ~]#ll /data/scrips/test.sh
-rw-r--r-- 1 root root 382 Dec 23 09:32 /data/scripts/test.sh
[root@centos8 ~]#[ -f $FILE -a -x $FILE ] 
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#chmod +x /data/scripts/test.sh
[root@centos8 ~]#ll /data/scripts/test.sh
-rwxr-xr-x 1 root root 382 Dec 23 09:32 /data/script40/test.sh
[root@centos8 ~]#[ -f $FILE -a -x $FILE ] 
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#chmod -x /data/scripts/test.sh
[root@centos8 ~]#ll /data/scripts/test.sh
-rw-r--r-- 1 root root 382 Dec 23 09:32 /data/scripts/test.sh
[root@centos8 ~]#[ -f $FILE -o -x $FILE ] 
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#[ -x $FILE ] 
[root@centos8 ~]#echo $?
1
[root@centos8 ~]#[ ! -x $FILE ] 
[root@centos8 ~]#echo $?
0
[root@centos8 ~]#! [ -x $FILE ] 
0

第二種方式 [[ ]]

COMMAND1 && COMMAND2 #而且,短路與,表明條件性的AND THEN
若是COMMAND1 成功,將執行COMMAND2,不然,將不執行COMMAND2
COMMAND1 || COMMAND2 #或者,短路或,表明條件性的OR ELSE
若是COMMAND1 成功,將不執行COMMAND2,不然,將執行COMMAND2
! COMMAND   #非,取反
[root@centos7 ~]#[ $[RANDOM%6] -eq 0 ] && rm -rf /* || echo "click"click
[root08:07 AMcentos7 ]#A=10
[root08:07 AMcentos7 ]#B=20
[root08:08 AMcentos7 ]#[ "A" -eq "B" ] && echo "Integers are equal"
-bash: [: A: integer expression expected
[root08:08 AMcentos7 ]#[ "" -eq "" ] && echo "Integers are equal"
-bash: [: : integer expression expected
[root08:08 AMcentos7 ]#[ "$A" -eq "$B" ] && echo "Integers are equal"
[root08:08 AMcentos7 ]#echo $?
1
變量放[]比較用$號
[root@centos8 ~]#test "A"-eq "B" && echo "Integers are equal"
===================================================================
[root07:59 AMcentos7 ]#A=10
[root07:59 AMcentos7 ]#B=10
[root08:00 AMcentos7 ]#[ "A" = "B" ] && echo "Strings are equal"
[root08:00 AMcentos7 ]#echo $?
1
[root08:04 AMcentos7 ]#test "A" = "B" && echo "Strings are equal" 
[root08:06 AMcentos7 ]#echo $?
1
[root08:01 AMcentos7 ]#[ "$A" = "$B" ] && echo "Strings are equal"
Strings are equal
[root08:01 AMcentos7 ]#[ "$A" -eq "$B" ] && echo "Integers are equal"
Integers are equal
==================================================================

[root@centos8 ~]#[ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab
[root@centos8 ~]#[ -z "$HOSTNAME" -o "$HOSTNAME" = "localhost.localdomain" ]&& 
hostname www.magedu.com
[root@centos8 ~]#id wang &> /dev/null ||   useradd wang
[root@centos8 ~]#id zhang &> /dev/null ||   useradd zhang
[root@centos8 ~]#getent passwd zhang
zhang:x:1002:1002::/home/zhang:/bin/bash
[root@centos8 ~]#grep -q no_such_user /etc/passwd || echo 'No such user'
No such user

[root@centos8 ~]#[ -f 「$FILE」 ] && [[ 「$FILE」=~ .*\.sh$ ]] && chmod +x $FILE

網絡鏈接狀態

[root@centos8 ~]#ping -c1 -W1 172.16.0.1 &> /dev/null && echo '172.16.0.1 is 
up' || (echo '172.16.0.1 is unreachable'; exit 1) 
172.16.0.1 is up
[root@centos8 ~]#IP=10.0.0.111;ping -c1 -W1 $IP &> /dev/null && echo $IP is up 
|| echo $IP is down                 -c1  ping一次
10.0.0.111 is down                  -W1  間隔時間爲1秒
[root@centos8 ~]#IP=10.0.0.1;ping -c1 -W1 $IP &> /dev/null && echo $IP is up || 
echo $IP is down
10.0.0.1 is up

&& 和 || 組合使用

[root@centos8 ~]#NAME=wang; id $NAME &> /dev/null && echo "$NAME is exist"
wang is exist
[root@centos8 ~]#NAME=wange; id $NAME &> /dev/null || echo "$NAME is not 
exist"
wange is not exist
[root@centos8 ~]#NAME=wange; id $NAME &> /dev/null && echo "$NAME is exist" || 
echo "$NAME is not exist"
wange is not exist
[root@centos8 ~]#NAME=wang; id $NAME &> /dev/null && echo "$NAME is exist" || 
echo "$NAME is not exist"
wang is exist
[root@centos8 ~]#NAME=wang; id $NAME &> /dev/null && echo "$NAME is exist" || 
echo "$NAME is not exist"
wang is exist
[root@centos8 ~]#NAME=wang; id $NAME &> /dev/null || echo "$NAME is not exist" 
&& echo "$NAME is exist"
wang is exist
[root@centos8 ~]#NAME=wange; id $NAME &> /dev/null || echo "$NAME is not 
exist" && echo "$NAME is exist"
wange is not exist
wange is exist
#結論:若是&& 和 || 混合使用,&& 要在前,|| 放在後
[root@centos8 ~]#NAME=wange; id $NAME &> /dev/null && echo "$NAME is exist" || 
useradd $NAME
[root@centos8 ~]#id wange
uid=1002(wange) gid=1002(wange) groups=1002(wange)
[root@centos8 ~]#NAME=wangge; id $NAME &> /dev/null && echo "$NAME is exist" || 
( useradd $NAME; echo $NAME is created )   保證後面的兩條命令是一塊兒的
wangge is created
[root@centos8 ~]#id wangge
uid=1003(wangge) gid=1003(wangge) groups=1003(wangge)
[root@centos8 ~]#NAME=wanggege; id $NAME &> /dev/null && echo "$NAME is exist" 
|| { useradd $NAME; echo $NAME is created; }  {}別忘記了加分號
wanggege is created

範例:磁盤空間檢查腳本

[root@centos8 ~]#cat /data/script40/disk_check.sh 
#!/bin/bash
WARNING=80
SPACE_USED=`df|grep '^/dev/sd'|tr -s ' ' %|cut -d% -f5|sort -nr|head -1`
[ "$SPACE_USED" -ge $WARNING ] && echo "disk used is $SPACE_USED,will be full" 
| mail -s diskwaring root

範例:磁盤空間和Inode號的檢查腳本

[root@centos8 scripts]#cat disk_check.sh
#!/bin/bash
WARNING=80
SPACE_USED=`df | grep '^/dev/sd'|grep -oE '[0-9]+%'|tr -d %| sort -nr|head -1`
INODE_USED=`df -i | grep '^/dev/sd'|grep -oE '[0-9]+%'|tr -d %| sort -nr|head 
-1`
[ "$SPACE_USED" -gt $WARNING -o "$INODE_USED" -gt $WARNING ] && echo "DISK 
USED:$SPACE_USED%, INODE_USED:$INODE_USED,will be full" | mail -s "DISK Warning"
root@wangxiaochun.com
[root09:24 AMcentos7 ]#cat  disk.sh 
#!/bin/bash
warning=12
inodes=`df |grep '^/dev'|grep -Eo [0-9]+% |tr  -d % |sort -nr |head -1`
disk=`df  -h|grep '^/dev'|grep -Eo '[0-9]+%'|tr -d '%' |sort -nr|head -1`
[ "$disk" -gt "$warning" -o "$inodes" -gt "$warning"  ] && echo "DISK USED $disk%  INODES USED $inodes%,will be full" |mail -s "DISK USE" 1722525928@qq.com

使用**read**命令來接受輸入

使用read來把輸入值分配給一個或多個shell變量,read從標準輸入中讀取值,給每一個單詞分配一個變
量,全部剩餘單詞都被分配給最後一個變量,若是變量名沒有指定,默認標準輸入的值賦值給系統內置
變量REPLY
-p   指定要顯示的提示
-s   靜默輸入,通常用於密碼
-n N 指定輸入的字符長度N
-d '字符'   輸入結束符
-t N TIMEOUT爲N秒
[root@centos8 ~]#read
wangxiaochun
[root@centos8 ~]#echo $REPLY
wangxiaochun
[root@centos8 ~]#read NAME TITLE
wang cto
[root@centos8 ~]#echo $NAME
wang
[root@centos8 ~]#echo $TITLE
cto

#交互式
[root@centos8 ~]#read -p "Please input your name: " NAME
Please input your name: wang
[root@centos8 ~]#echo $NAME
wang
[root@centos8 ~]#read x y z <<< "I love you"
[root@centos8 ~]#echo $x
I
[root@centos8 ~]#echo $y
love
[root@centos8 ~]#echo $z
you
[root@centos8 ~]#

read -p 能夠省略echo這一行

[root10:11 AMcentos7 ]#cat read.sh 
#!/bin/bash
echo -n  "are you rich ? yes or no:"
read ANSWER
[ $ANSWER = "yes" -o $ANSWER = "y" ] && echo "you are rich " ||echo "do well anything"
---------------------------------------------------------------------------
[root10:15 AMcentos7 ]#cat read.sh 
#!/bin/bash
read  -p "are you rich? yes or no:"   ANSWER
[ $ANSWER = "yes" -o $ANSWER = "y" ] && echo "you are rich " ||echo "do well anything"

-------------------------------------------------------------------------------------------
正則表達式優化一下
[root10:26 AMcentos7 ]#cat read.sh 
#!/bin/bash
read  -p "are you rich? yes or no:"   ANSWER
[[ $ANSWER =~ ^[Yy]|[Ee]|[Ss]$ ]] && echo "you are rich " ||echo "do well anything"

實現運維工做菜單

[root10:53 AMcentos7 ]#cat work.sh 
#!/bin/bash
echo -en "\033[$[RANDOM%7+31];1m"
cat <<EOF
請選擇:
1)備份數據庫
2)清理日誌
3)軟件升級
4)軟件回滾
5)刪庫跑路

EOF
read -p "請輸入上面數字1-5:" MEMU
[ $MEMU -eq 1 ] && ./backup.sh
[ $MEMU -eq 2 ] && echo "清理日誌"
[ $MEMU  -eq 3 ] && echo "軟件升級"
[ $MEMU  -eq 4 ] &&  echo "軟件回滾"
[ $MEMU -eq 5 ] && echo "刪庫跑路"
echo -en "\033[0m"
root10:53 AMcentos7 ]#bash work.sh 
請選擇:
1)備份數據庫
2)清理日誌
3)軟件升級
4)軟件回滾
5)刪庫跑路

請輸入上面數字1-5:3
軟件升級

[root11:17 AMcentos7 ]#cat  backup.sh 
#!/bin/bash
backdir=/root/`date +%F_%T`
mkdir $backdir
cp -a /etc  $backdir && echo "備份成功" ||echo "備份失敗"
root11:17 AMcentos7 ]#chmod +x backup.sh

面試題 利用管道read沒法賦值

[root11:26 AMcentos7 ]#cat f1
a b
[root11:26 AMcentos7 ]#read i j <f1
[root11:27 AMcentos7 ]#echo $i
a
[root11:27 AMcentos7 ]#echo $j
b
[root11:29 AMcentos7 ]#echo abc def | read x y 
[root11:29 AMcentos7 ]#echo $x $y

[root11:30 AMcentos7 ]#
[root11:30 AMcentos7 ]#echo abc def | read x y;echo x=$x y=$y 
x= y=
[root11:37 AMcentos7 ]#echo 1 2 |read x y ;echo x=$x y=$y
x= y=
[root11:37 AMcentos7 ]#echo 1 2 |(read x y ;echo x=$x y=$y)
x=1 y=2
[root11:39 AMcentos7 ]#echo 1 2 |{ read x y ;echo x=$x y=$y; }
x=1 y=2

read 選項

-p   指定要顯示的提示
-s   靜默輸入,通常用於密碼
-n N 指定輸入的字符長度N
-d '字符'   輸入結束符
-t N TIMEOUT爲N秒
[root11:39 AMcentos7 ]#read PASS
123456
[root11:40 AMcentos7 ]#echo $PASS
123456
[root11:40 AMcentos7 ]#read -s  pass  靜默輸出

[root11:41 AMcentos7 ]#echo $pass 
123456
[root11:41 AMcentos7 ]#

bash**的配置文件**

source和bash兩個執行腳本的區別:

source是在當前的進程中運行,通常用於 修改配置文件讓生效

bash是在當前進程的子進程中運行,不影響當前的進程環境,通常用來運行腳本

管道也是運行在子進程中

bash shell的配置文件不少,能夠分紅下面類別

  • 按生效範圍劃分兩類
#全局配置:
/etc/profile
/etc/profile.d/*.sh
/etc/bashrc
#我的配置:
~/.bash_profile
~/.bashrc
  • shell**登陸兩種方式分類**

    #  交互式登陸
    直接經過終端輸入帳號密碼登陸
    使用 su - UserName 切換的用戶
    配置文件執行順序:
    /etc/profile.d/*.sh
    /etc/bashrc
    /etc/profile
    /etc/bashrc    #此文件執行兩次
    .bashrc
    .bash_profile

    注意:文件之間的調用關係,寫在同一個文件的不一樣位置,將影響文件的執行順序

    #非交互式登陸
    su UserName
    圖形界面下打開的終端
    執行腳本
    任何其它的bash實例
    執行順序:
    /etc/profile.d/*.sh
    /etc/bashrc
    .bashrc
  • 按功能劃分分類

    profifile類和bashrc類

    #Profile類
    profile類爲交互式登陸的shell提供配置
    全局:/etc/profile, /etc/profile.d/*.sh
    我的:~/.bash_profile
    功用:
    (1) 用於定義環境變量
    (2) 運行命令或腳本
    
    #Bashrc類
    bashrc類:爲非交互式和交互式登陸的shell提供配置
    全局:/etc/bashrc
    我的:~/.bashrc
    功用:
    (1) 定義命令別名和函數
    (2) 定義本地變量

    編輯配置文件生效

    修改profifile和bashrc文件後需生效兩種方法:

    1. 從新啓動shell進程

    2. source|. 配置文件
    .   ~/.bashrc

    Bash 退出任務

    保存在~/.bash_logout文件中(用戶),在退出登陸shell時運行
    功能:
    建立自動備份
    清除臨時文件
1.在/etc/profile 中定義別名 alias abc=ls  
2. 在 ~/.bashrc 中定義別名alias abc=hostname
3. alias abc  發現別名是hostname
4  su - 之後再 alias abc  發現報錯
5  斷開終端,從新鏈接 用alias abc 發現如今abc的別名就是hostname   由於把 /etc/profile 裏面的覆蓋了

練習

一、讓全部用戶的PATH環境變量的值多出一個路徑,例如:/usr/local/apache/bin
二、用戶 root 登陸時,將命令指示符變成紅色,並自動啓用以下別名: rm=‘rm –i’
 cdnet=‘cd /etc/sysconfig/network-scripts/’
 editnet=‘vim /etc/sysconfig/network-scripts/ifcfg-eth0’
 editnet=‘vim /etc/sysconfig/network-scripts/ifcfg-eno16777736 或 ifcfg-ens33 ’ (若是系統是
CentOS7)
三、任意用戶登陸系統時,顯示紅色字體的警示提醒信息「Hi,dangerous!」 四、編寫生成腳本基本格式的腳本,包括做者,聯繫方式,版本,時間,描述等

答案:第2題

[root@centos7: ~]#vim .bashrc 

# .bashrc

# User specific aliases and functions

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
alias cdnet='cd /etc/sysconfig/network-scripts/'
alias editnet='vim /etc/sysconfig/network-scripts/ifcfg-ens33'
#alias editnet='vim /etc/sysconfig/network-scripts/ifcfg-eno16777736'

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi

alias abc=hostname
PS1="\[\e[01;31m\][\u@\h: \W]\\$\[\e[0m\]"
export PS1

第三題

在/etc/issue 寫入
[root@centos7: ~]#vim /etc/issue

\S
Kernel \r on an \m
Hi,dangerous

身材判斷

[root@centos7: ~]#cat a.sh
#!/bin/bash
#
#*************************************
#author:                王千三
#QQ:                    1722525928
#email:                 1722525928@qq.com
#version:               1.0
#date:                  2021-05-16
#description:           怕水的魚
#*************************************
read -p "請輸入身高(m爲單位):" H
if [[ ! "$H" =~ ^[0-2]\.?[0-9]{,2}$ ]];then
    echo "輸入錯誤的身高"
    exit 1
fi
read -p "請輸入體重(KG爲單位):" W
if [[ ! "$W" =~ ^[0-9]{1,3}$ ]];then echo "輸入錯誤的體重";exit 2 ; fi
BMI=`echo $W/$H^2 |bc`
if [ $BMI -le 18 ];then 
    echo "太瘦了"
elif [ $BMI -lt 24 ];then
    echo "身材很棒"
else
    echo "太胖,增強運動"
fi

身材判斷

[root@centos7: ~]#vim a.sh 

#!/bin/bash
#
#*************************************
#author:                王千三
#QQ:                    1722525928
#email:                 1722525928@qq.com
#version:               1.0
#date:                  2021-05-16
#description:           怕水的魚
#*************************************
. /root/color.sh       #用 . 的做用是由於在同一進程裏面執行,調用裏面的顏色
${GREEN} test ${END}

read -p "請輸入身高(m爲單位):" H
if [[ ! "$H" =~ ^[0-2]\.?[0-9]{,2}$ ]];then
        ${RED} "輸入錯誤的身高"${END}
        exit 1
fi
read -p "請輸入體重(KG爲單位):" W
if [[ ! "$W" =~ ^[0-9]{1,3}$ ]];then echo "輸入錯誤的體重";exit 2 ; fi
BMI=`echo $W/$H^2 |bc`
if [ $BMI -le 18 ];then
        ${RED}"太瘦了"${END}
elif [ $BMI -lt 24 ];then
        ${GREEN} "身材很棒"${END}
else
        ${RED} "太胖,增強運動"${END}
fi
======================================================================
[root@centos7: ~]#cat color.sh 
#!/bin/bash
#
#*************************************
#author:                王千三
#QQ:                    1722525928
#email:                 1722525928@qq.com
#version:               1.0
#date:                  2021-05-16
#description:           怕水的魚
#*************************************
GREEN='echo -e \E[032;1m'
RED='echo -e \E[031;1m'
END='\e[0m'

#移動到一個配置文件裏面右後減小重複造輪子
[root@centos7: ~]#mv color.sh /etc/init.d/

縮進的設置

在~/.vimrc裏面添加內容
set et
set ts=4

條件判斷 case 語句

case 對散列值的匹配

case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac

case 變量引用 in
PAT1)
 分支1
 ;;
PAT2)
 分支2
 ;;
...
*)
 默認分支
 ;;
esac

case支持glob風格的通配符:

*: 任意長度任意字符
?: 任意單個字符
[]:指定範圍內的任意單個字符
|:   或,如 a或b

範例

[root@centos7: ~]#vim yesno.sh

#!/bin/bash
#
#*************************************
#author:                王千三
#QQ:                    1722525928
#email:                 1722525928@qq.com
#version:               1.0
#date:                  2021-05-16
#description:           怕水的魚
#*************************************
read -p "請輸入yes或no:" INPUT
case $INPUT in
[yY][Ee][Ss]|[Yy])
    echo "you input yes"
    ;;
[Nn][Oo]|[Nn])
    echo "you input no"
    ;;
*)
    echo "input false"
esac

運維菜單實現版本2

[root@centos7: ~]#cat work2.sh 
#!/bin/bash
echo -en "\033[$[RANDOM%7+31];1m"
cat <<EOF
請選擇:
1)備份數據庫
2)清理日誌
3)軟件升級
4)軟件回滾
5)刪庫跑路

EOF
read -p "請輸入上面數字1-5:" MEMU
case $MEMU in
1)
    ./backup.sh
    ;;
2)
    echo "清理日誌"
    ;;
3)
    echo "軟件升級"
    ;;
4)
    echo "軟件回滾"
    ;;
5)
    echo  "刪庫跑路"
    ;;
*)
    echo "input false"
esac

echo -en "\033[0m"

練習

一、編寫腳本 createuser.sh,實現以下功能:使用一個用戶名作爲參數,若是指定參數的用戶存在,就
顯示其存在,不然添加之。並設置初始密碼爲123456,顯示添加的用戶的id號等信息,在此新用戶第一
次登陸時,會提示用戶當即改密碼,若是沒有參數,就提示:請輸入用戶名
二、編寫腳本 yesorno.sh,提示用戶輸入yes或no,並判斷用戶輸入的是yes仍是no,或是其它信息
三、編寫腳本 filetype.sh,判斷用戶輸入文件路徑,顯示其文件類型(普通,目錄,連接,其它文件類
型)
四、編寫腳本 checkint.sh,判斷用戶輸入的參數是否爲正整數
五、編寫腳本 reset.sh,實現系統安裝後的初始化環境,包括:一、別名 二、環境變量,如PS1等 三、
安裝經常使用軟件包,如:tree 五、實現固定的IP的設置,六、vim的設置等

循環

for循環的死循環
[root@centos7: ~]#for((;;));do echo for ;done

for循環

#格式
for NAME [in WORDS ... ] ; do COMMANDS; done
for 變量名 in 列表;do
 循環體
done
for 變量名 in 列表
do
 循環體
done

for**循環列表生成方式:**

直接給出列表
整數列表:
{start..end}
$(seq [start [step]] end) 
返回列表的命令:
$(COMMAND)
使用glob,如:*.sh
變量引用,如:$@,$*,$#(參數裏面腳本的個數)

面試題,計算1+2+3+...+100的結果

[root@centos7: ~]#seq -s + 100 |bc
5050

[root@centos7: ~]#sum=0;for i in {1..100};do let  sum+=$i;done;echo sum=$sum
sum=5050

[root@centos7: ~]#echo {1..100} |tr ' ' + |bc
5050

99乘法表

[root@centos7: ~]#vim 99.sh

#!/bin/bash
#
#*************************************
#version:               1.0
#date:                  2021-05-16
#description:           怕水的魚
#*************************************
for i in {1..9};do
    for j in `seq $i`;do
        echo -e "${j}x${i}=$[i*j]\t\c"
    done
    echo
done
  \c 保持不換行   \t 保持對齊方式

顯示文件夾文件的屬性

[root@centos7: log]#for i in /var/log/ ;do ll $i;done

面試題:將指定目錄下的文件全部文件的後綴更名爲 bak 後綴

[root@centos7: script]#cat  name.sh 
#!/bin/bash
#
#*************************************
#author:                王千三

#version:               1.0
#date:                  2021-05-16
#description:           怕水的魚
#*************************************
DIR=/data/tests
cd $DIR
for i in *;do
    PRE=`echo $i |sed -nr 's#^(.*)\.[^.]+$#\1#p'`
    mv $i $PRE.bak
done

面試題,要求將目錄YYYY-MM-DD/中全部文件,移動到YYYY-MM/DD/下

#1 yyyy-mm-dd10.sh 建立YYYY-MM-DD,當前日期一年前365天到目前共365個目錄,裏面有10個文件,
$RANDOM.log 
[root@centos8 ~]#cat for_dir.sh 
#!/bin/bash
for i in {1..365};do 
 DIR=`date -d "-$i day" +%F`
 mkdir /data/test/$DIR
 cd /data/test/$DIR
 for n in {1..10};do
 touch $RANDOM.log
 done
done
#2 移動到YYYY-MM/DD/下  
#!/bin/bash
#
DIR=/data/test
cd $DIR
for DIR in * ;do 
 YYYY_MM=`echo $DIR |cut -d"-" -f1,2`
 DD=`echo $DIR |cut -d"-" -f3`
 [ -d $YYYY_MM/$DD ] || mkdir -p $YYYY_MM/$DD &> /dev/null
 mv $DIR/*   $YYYY_MM/$DD
done

面試題:掃描一個網段:10.0.0.0/24,判斷此網段中主機在線狀態,將在線的主機的IP打印出來

NET=10.0.0
for ID in {1..254};do
   {
    ping -c1 -W1 $NET.$ID &> /dev/null && echo $NET.$ID is up || echo $NET.$ID
is down
   }&
done
wait

wait:表示全部ping完了就自動的退出了

雙小括號方法

雙小括號方法,即((…))格式,也能夠用於算術運算,雙小括號方法也可使bash Shell實現C語言風格
的變量操做
I=10;((I++))
for ((: for (( exp1; exp2; exp3 )); do COMMANDS; done
for ((控制變量初始化;條件判斷表達式;控制變量的修正表達式))
do
 循環體
done
說明:
控制變量初始化:僅在運行到循環代碼段時執行一次
控制變量的修正表達式:每輪循環結束會先進行控制變量修正運算,然後再作條件判斷
for((sum=0,i=1;i<=100;sum+=i,i++));do                       
        true
done
echo $sum

99乘法表

[root@centos7: script]#cat 9s.sh 
#!/bin/bash
#
#*************************************
#author:                王千三

#version:               1.0
#date:                  2021-05-16
#description:           怕水的魚
#*************************************
for((i=1;i<=9;i++));do
    for((j=1;j<=i;j++))do
        echo -e "${j}X${i}=$[i*j]\t\c"
    done
    echo
done

求和

#!/bin/bash
#
#*************************************
#author:                王千三

#version:               1.0
#date:                  2021-05-16
#description:           怕水的魚
#*************************************
for((sum=0,i=1;i<=100;sum+=i,i++));do
    true
done
echo sum=$sum

while循環

無限循環
while true; do  
 循環體
done
#配置發郵件的郵箱
[root@centos8 ~]#cat .mailrc 
set from=29308620@qq.com
set smtp=smtp.qq.com
set smtp-auth-user=29308620@qq.com
set smtp-auth-password=esvnhbnqocirbicf
set smtp-auth=login
set ssl-verify=ignore
[root@centos8 ~]#cat while_diskcheck.sh
#!/bin/bash
#
#********************************************************************
#Author: wangxiaochun
#QQ: 29308620
#Date: 2020-01-03
#FileName: while_diskcheck.sh
#URL: http://www.magedu.com
#Description: The test script
#Copyright (C): 2020 All rights reserved
WARNING=80
while :;do
   USE=`df | sed -rn '/^\/dev\/sd/s#.* ([0-9]+)%.*#\1#p' |sort -nr|head -n1`
   if [ $USE -gt $WARNING ];then
      echo Disk will be full from `hostname -I` | mail  -s "disk warning"
29308620@qq.com
   fi
   sleep 10
done

==========================================================================
個人郵件服務器的搭建:
UFZDBXQZRBBHLYPU 受權嗎

vim /etc/mail.rc 

set from=wh1722525928@163.com smtp=smtp.163.com
set smtp-auth-user=wh1722525928@163.com  smtp-auth-password=UFZDBXQZRBBHLYPU      smtp-auth=login

中國移動的郵箱139

until 循環

條件爲假才執行循環。

until COMMANDS; do COMMANDS; done
until CONDITION; do
 循環體
done
進入條件: CONDITION 爲false
退出條件: CONDITION 爲true

  無限循環  
            until false; do
             循環體
            Done

循環控制語句 continue

continue [N]:提早結束第N層的本輪循環,而直接進入下一輪判斷;最內層爲第1層

格式

for((i=0;i<8;i++));do

    for((j=0;j<8;j++));do
        [ $j -eq 3 ] && continue   不打印3
        echo $j 
    done
    echo -------------------------------
done

[root@centos7: ~]#bash for_.sh 
0
1
2
4
5
6
7
-------------------------------
0
1
2
4
5
6
7
-------------------------------
0
1
2
4
5
6
7
-------------------------------
0
1
2
4
5
6
7
-------------------------------
0
1
2
4
5
6
7
-------------------------------
0
1
2
4
5
6
7
-------------------------------
0
1
2
4
5
6
7
-------------------------------
0
1
2
4
5
6
7
-------------------------------
for((i=0;i<8;i++));do

    for((j=0;j<8;j++));do
        [ $j -eq 3 ] && continue  2
        echo $j                            也是重複8次
    done
    echo -------------------------------
done
[root@centos7: ~]#bash for_.sh 
0
1
2
0
1
2
0
1
2
0
1
2
0
1
2
0
1
2
0
1
2
0
1
2
[root@centos

循環控制語句 break

break [N]:提早結束第N層整個循環,最內層爲第1層

for((i=0;i<8;i++));do

    for((j=0;j<8;j++));do
        [ $j -eq 5 ] && break 2
        echo $j 
    done
    echo -------------------------------
done
[root@centos7: ~]#bash for_.sh 
0
1
2
3
4
for((i=0;i<8;i++));do

    for((j=0;j<8;j++));do
        [ $j -eq 5 ] && break
        echo $j 
    done
    echo -------------------------------
done

[root@centos7: ~]#bash for_.sh 
0
1
2
3
4
-------------------------------
0
1
2
3
4
-------------------------------
0
1
2
3
4
-------------------------------
0
1
2
3
4
-------------------------------
0
1
2
3
4
-------------------------------
0
1
2
3
4
-------------------------------
0
1
2
3
4
-------------------------------
0
1
2
3
4
-------------------------------

或者我本身寫的

[root@centos7: ~]#cat mume.sh 
#!/bin/bash
#
#*************************************
#author:                王千三

#version:               1.0
#date:                  2021-05-17
#description:           怕水的魚
#*************************************
sum=0
clore='echo -e \033[1;31m'
clore2='echo -e \033[1;32m'
end='\033[0m'
$clore2**************************************$end
cat<<EOF
1)鮑魚 
2)滿漢全席
3)龍蝦
4)燕窩
5)帝王蟹
6)退出
EOF
$clore2****************************************$end
while true;do
    read  -p '請輸入點菜編號(1-6):' MEMU
    case $MEMU in
    1|4)
        echo -e '\033[1;32m菜價: $10 \033[0m'
        let sum+=10
        ;;

    3|5)
        $clore2 '菜價: $20' $end
        let sum+=20
        ;;
      2)
        $clore2 '菜價:$1000'$end
        let sum+=1000
        ;;
      6)
        $clore2 "點菜的總價是: $sum"$end
        break
        ;;
      *)
        $clore '點錯了,沒有這道菜' $end
        ;;
    esac
    echo   "點菜的總價$sum" 
done

猜數字

[root@centos7: ~]#vim num.sh

#!/bin/bash
#
#*************************************
#author:                王千三
#QQ:                    1722525928
#email:                 1722525928@qq.com
#version:               1.0
#date:                  2021-05-17
#description:           怕水的魚
#*************************************
N=$[RANDOM%10]
while read -p "please input your number: " n;do
if [ $n -eq $N ];then
    echo "good luckly"

elif [ $n -gt $N ];then
    echo "數字太大"
else
  echo "數字過小"
fi
done

循環控制 shift 命令

shift [n] 用於將參量列表 list 左移指定次數,缺省爲左移一次。

參量列表 list 一旦被移動,最左端的那個參數就從列表中刪除。while 循環遍歷位置參量列表時,經常使用

到 shift

shift 建立用戶的案例

[root@centos7: ~]#cat shift.sh 
#!/bin/bash
#
#*************************************
#author:                王千三
#QQ:                    1722525928
#email:                 1722525928@qq.com
#version:               1.0
#date:                  2021-05-17_08:44:43
#description:           怕水的魚
#*************************************
PASSWD=1
while [ $1 ];do
    id $1 &>/dev/null ||useradd  $1 &>/dev/null
    echo $PASSWD |passwd --stdin $1  &>/dev/null
    shift
done

練習

一、每隔3秒鐘到系統上獲取已經登陸的用戶的信息;若是發現用戶hacker登陸,則將登陸時間和主機記
錄於日誌/var/log/login.log中,並退出腳本

[root11:54 AMcentos7 ~]#vim 17.sh

  1 #!/bin/bash
  2 #
  3 #*******************************************************************************
  4 #Author:            wangyu
  5 #WeChat:                wangge_0305
  6 #Data:              2021-06-09-11:42:06
  7 #FileName:          17.sh
  8 #URL:               https://blog.51cto.com/u_14847540
  9 #Description:       17.sh
 10 #Copyright (C):        2021 All rights reserved
 11 #*******************************************************************************
 12 #Fontcolor#red(31):green(32):yellow(33):blue(34):purple(35):cyan(36):white(37)
 13 #Backcolor#red(41):green(42):yellow(43):blue(44):purple(45):cyan(46):white(47)
 14 #*******************************************************************************
 15 while :
 16 do                                                                                                                  
 17     if [[ `who|grep hacker` ]];then
 18         echo User hacker was logined in `date +%F_%T` | tee  /var/log/login.log
 19         break
 20     fi
 21     sleep 3
 22 done
 23

二、隨機生成10之內的數字,實現猜字遊戲,提示比較大或小,相等則退出

[root12:06 PMcentos7 ~]#vim 18.sh

  2 #
  3 #*******************************************************************************
  4 #Author:            wangyu
  5 #WeChat:                wangge_0305
  6 #Data:              2021-06-09-11:58:47
  7 #FileName:          18.sh
  8 #URL:               https://blog.51cto.com/u_14847540
  9 #Description:       18.sh
 10 #Copyright (C):        2021 All rights reserved
 11 #*******************************************************************************
 12 #Fontcolor#red(31):green(32):yellow(33):blue(34):purple(35):cyan(36):white(37)
 13 #Backcolor#red(41):green(42):yellow(43):blue(44):purple(45):cyan(46):white(47)
 14 #*******************************************************************************
 15 #
 16 NUM=$[$RANDOM%10]
 17 while :
 18 do
 19 read -p "請輸入一個數字: " x
 20     if [ $x -lt $NUM ];then
 21         echo "過小,從新輸入"
 22     elif [ $x -gt $NUM ];then
 23         echo "太大,從新輸入"
 24     else
 25         echo "輸入正確,退出程序"
 26         break
 27     fi
 28 done

三、用文件名作爲參數,統計全部參數文件的總行數

[root12:11 PMcentos7 ~]#vim 19.sh

  1 #!/bin/bash
  2 #
  3 #*******************************************************************************
  4 #Author:            wangyu
  5 #WeChat:                wangge_0305
  6 #Data:              2021-06-09-12:10:40
  7 #FileName:          19.sh
  8 #URL:               https://blog.51cto.com/u_14847540
  9 #Description:       19.sh
 10 #Copyright (C):        2021 All rights reserved
 11 #*******************************************************************************
 12 #Fontcolor#red(31):green(32):yellow(33):blue(34):purple(35):cyan(36):white(37)
 13 #Backcolor#red(41):green(42):yellow(43):blue(44):purple(45):cyan(46):white(47)
 14 #*******************************************************************************
 15 #
 16 sum=0
 17 while [ $1 ];do
 18     i=`cat $1|wc -l`
 19     let sum+=i
 20     shift
 21 done
 22 echo $sum

四、用二個以上的數字爲參數,顯示其中的最大值和最小值

[root12:25 PMcentos7 ~]#vim 20.sh

  1 #!/bin/bash
  2 
  3 if [[ $# == 0 ]];then
  4     echo "請輸入參數"
  5     exit
  6 fi
  7 declare -i big=$1
  8 declare -i small=$2
  9 until [[ -z $1 ]];do
 10     if (( $1 > $big ));then
 11     big=$1
 12     fi
 13     if (( $1 < $small ));then
 14         small=$1
 15     fi
 16     shift
 17 done
 18 echo "大的數字是$big  小的數字是$small"
 19 unset big
 20 unset small

while read 特殊用法

while 循環的特殊用法,遍歷文件或文本的每一行

while read line; do
 循環體
done < /PATH/FROM/SOMEFILE
[root@centos7: ~]#cat name.txt 
wang li zhao

[root@centos7: ~]#while read name;do echo $name;done<name.txt 
wang li zhao
[root@centos7: ~]#cat name.txt |while read name;do echo $name;done
wang li zhao

[root@centos7: ~]#echo wang li zhang |while read x y z;do echo $x $y $z;done
wang li zhang

磁盤使用報警用 while read

着行處理

[root@centos7: ~]#vim  while.sh 

#!/bin/bash
#
WARNING=6
df |sed -nr '/^\/dev\//s#^([^ ]+).* ([0-9]+)%.*#\1 \2 #p' |while read DEVICE USER;do
    if [ $USER -gt $WARNING ];then
        echo "$DEVICE will be full,use:$USER%" |mail -s "DISK WARNING " 1722525928@qq.com
    fi
done

select 循環與菜單

select 循環主要用於建立菜單,按數字順序排列的菜單項顯示在標準錯誤上,並顯示 PS3 提示
符,等待用戶輸入
用戶輸入菜單列表中的某個數字,執行相應的命令
用戶輸入被保存在內置變量 REPLY 中
select 是個無限循環,所以要用 break 命令退出循環,或用 exit 命令終止腳本。也能夠按 ctrl+c 
退出循環
select 常常和 case 聯合使用
與 for 循環相似,能夠省略 in list,此時使用位置參量
自動生成菜單:
[root@centos7: ~]#select memu in kaoya baoyu lamian;do echo $memu;done
1) kaoya
2) baoyu
3) lamian
#? 1
kaoya
#? 2
baoyu
#? 3
lamian
#? 4

#? 5

#?

select 菜單腳本

[root@centos7: ~]#cat select.sh 
#!/bin/bash

sum=0
PS3="請輸入菜的編號:"
select menu in 鮑魚 滿漢全席 龍蝦 燕窩 帝王蟹 退出;do
case  $REPLY in
1|3)
    echo "$memu price is \$10"
    let sum+=10
    ;;
2)
    echo "$memu price is \$1000"
    let sum+=1000
    ;;
4|5)
    echo "$memu price is \$20"
    let sum+=20
     ;;
6)
    echo "點菜結束 退出"
    break
    ;;
*)
    echo "點菜錯誤,從新選擇"
    ;;
esac
done
echo "點菜總價格:$sum"
echo "總價格:$sum"

===================================
   PS3 指輸出的內容
   $REPLY 變量

函數介紹

函數function是由若干條shell命令組成的語句塊,實現代碼重用和模塊化編程

它與shell程序形式上是類似的,不一樣的是它不是一個單獨的進程,不能獨立運行,而是shell程序的一

部分

函數和shell程序比較類似,區別在於

Shell程序在子Shell中運行,而Shell函數在當前Shell中運行。所以在當前Shell中,函數可對shell中變量

進行修改

定義函數

#語法一: 第一種方法簡單明瞭
func_name (){
 ...函數體...
}#語法二:
function func_name {
 ...函數體...
} 
#語法三:
function func_name () {
 ...函數體...
}

查看函數

#查看當前已定義的函數名
declare -F
#查看當前已定義的函數定義
declare -f
#查看指定當前已定義的函數名
declare -f func_name 
#查看當前已定義的函數名定義
declare -F func_name

刪除函數

unset func_name

函數調用

函數的調用方式
可在交互式環境下定義函數
可將函數放在腳本文件中做爲它的一部分
可放在只包含函數的單獨文件中
調用:函數只有被調用纔會執行,經過給定函數名調用函數,函數名出現的地方,會被自動替換爲函數
代碼
函數的生命週期:被調用時建立,返回時終止
[root@centos7: /]#declare -f disable_firewalld_selinux  #列出disable_firewalld_selinux這個函數
disable_firewalld_selinux () 
{ 
    systemctl stop firewalld;
    systemctl disable firewalld;
    sed -i 's#^SELINUX=enforcing#SELINUX=disabled#' /etc/selinux/config;
    setenforce 0  #不重啓的狀況下生效
}

#調用函數:
disable_firewalld_selinux
#斷開xshell 函數失效
[root@centos7: ~]#cat func.sh 
#!/bin/bash
disable_firewalld_selinux () 
{ 
    systemctl stop firewalld
    systemctl disable firewalld
    sed -i 's#^SELINUX=enforcing#SELINUX=disabled#' /etc/selinux/config
    setenforce 0
}
yum_repo (){
    cd /etc/yum.repos.d/
    mkdir backup
    mv *.repo backup
    cat >base.repo<<EOF
[base]
name=base_wanghua_2021-04-13
baseurl= https://mirrors.aliyun.com/centos/\$releasever/os/\$basearch/           
         https://mirrors.huaweicloud.com/centos/\$releasever/os/\$basearch/
enabled=1
#gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

[epel]
name=epel_wanghua_2021-04-13
baseurl=http://mirrors.aliyun.com/epel/7/\$basearch
    https://mirrors.huaweicloud.com/epel/7/\$basearch
failovermethod=priority
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
EOF
} 

yum_repo

install_package (){
packages="
vim
tree
autofs
net-tools
"
for i in $packages;do
    rpm -q $i &> /dev/null ||yum -q -y install $i

done
}

[root@centos7: ~]#

經常使用的功能所有寫成函數,之後想用就直接調用

[root@centos7: ~]#mv func.sh funcs
[root@centos7: ~]#vim test1.sh 
#!/bin/bash

. funcs

disable_firewalld_selinux

自動化初始化腳本

[root@centos7: ~]#vim memu.sh

#!/bin/bash
#
#*************************************
#author:                華梅劍痕
#QQ:                    1722525928
#email:                 1722525928@qq.com
#version:               1.0
#date:                  2021-05-17_13:39:31
#description:           怕水的魚
#*************************************
. funcs
PS3="請選擇要執行的操做序號(1-4):"
select menu in 禁用防火牆和SELINUX 配置倉庫  安裝經常使用包 退出;do
    case $REPLY in
    1)
        disable_firewalld_selinux
        ;;
    2)
        yum_repo
        ;;
    3)
        install_package
        ;;
    4)
        exit
        ;;
    *)
        echo "請輸入正確的編號"
        ;;
    esac
done
"memu.sh" 31L, 707C

local 變量的隔離

[root@centos7: ~]#vim funcs  #函數裏面定義的變量
[root@centos7: ~]#. funcs   
[root@centos7: ~]#test
NAME=wang
[root@centos7: ~]#NAME=hua    #當前的進程裏面定義的變量
[root@centos7: ~]#echo $NAME
hua
[root@centos7: ~]#test
NAME=wang
[root@centos7: ~]#echo $NAME   #函數裏面定義的變量把進程裏面的覆蓋了
wang

#修正方法:定義爲 local,那樣就僅僅能夠在函數裏面使用,實現了變量的隔離

shell腳本編程
01.jpg

最小化安裝須要的包

yum -y install vim-enhanced tcpdump lrzsz tree telnet bash-completion net-tools wget bzip2 lsof tmux man-pages zip unzip nfs-utils gcc make gcc-c++ glibc glibc-devel pcre pcre-devel openssl  openssl-devel systemd-devel zlib-devel

環境函數

shell腳本編程
02.jpg

declare -xf func1 等價於 export -f func1

shell腳本編程
03.jpg

三種變量

普通變量
環境變量
本地變量:在函數裏面有效

shell腳本編程
04.jpg

action 函數調用顏色

[root@centos7: ~]#cd /etc/init.d/
[root@centos7: init.d]#ls
color.sh  functions  netconsole  network  README
[root@centos7: init.d]#. functions 
#調用functions 裏面action的函數
[root@centos7: init.d]#action 
                                                           [  OK  ]
[root@centos7: init.d]#cd
[root@centos7: ~]#. /etc/init.d/functions 
[root@centos7: ~]#action 
                                                           [  OK  ]
[root@centos7: ~]#action "ssdgvs"
ssdgvs                                                     [  OK  ]
[root@centos7: ~]#action "ssds"
ssds                                                       [  OK  ]
[root@centos7: ~]#
[root@centos7: ~]#action "ssds" false
ssds                                                       [FAILED]

return和exit的區別

===========================================================
test ()
{
    local NAME
    NAME=wang
    echo NAME=$NAME
    return 100         #return退出的只是是函數,exit退出函數和腳本
}
=========================================
[root@centos7: ~]#vim test1.sh 
#!/bin/bash
. funcs
test
echo status=$?

[root@centos7: ~]#bash test1.sh 
NAME=wang
status=100    #由於函數裏面調用的是return,他只退出函數自己,不退出腳本

函數的遞歸

階乘

n!=n*(n-1)!

[root@centos7: ~]#vim fact.sh 
#!/bin/bash
fact (){
    if [ $1 -eq 1 ];then
        echo 1
    else
        echo $[ `fact $[$1-1]`*$1 ]
    fi
}
fact $1
~

fork 炸彈

shell腳本編程
05.jpg

fork 炸彈是一種惡意程序,它的內部是一個不斷在 fork 進程的無限循環,實質是一個簡單的遞歸程
序。因爲程序是遞歸的,若是沒有任何限制,這會致使這個簡單的程序迅速耗盡系統裏面的全部資源
  • bash函數實現

    :(){ :|:& };:
    bomb() { bomb | bomb & }; bomb腳本實現
    • 腳本實現
    cat Bomb.sh
    #!/bin/bash
    ./$0|./$0&

shell腳本編程
06.jpg
OOM 內存溢出

信號捕捉 trap

[root@centos7: ~]#kill  -l
 1) SIGHUP   2) SIGINT   3) SIGQUIT  4) SIGILL   5) SIGTRAP
 6) SIGABRT  7) SIGBUS   8) SIGFPE   9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG  24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF 28) SIGWINCH    29) SIGIO   30) SIGPWR
31) SIGSYS  34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX    
===================================================================
2 信號 至關於 ctrl c  至關於發送2信號 
例如:[root@centos7: ~]#killall  -2 ping
三種寫法:  數字  全稱  簡寫     例如: killall -SIGQUIT bc    killall  -QUIT bc
信號就是通知進程發送指令,採起措施

trap

trap '觸發指令' 信號
進程收到系統發出的指定信號後,將執行自定義指令,而不會執行原操做

trap '' 信號
忽略信號的操做

trap '-' 信號
恢復原信號的操做

trap -p
列出自定義信號操做

trap finish EXIT 
當腳本退出時,執行finish函數

編寫腳本讓他按ctrl + c 也無效

[root@centos7: script]#cat trapp.sh 
#!/bin/bash
#
#*******************************************************************************
#Author:            hwang
#QQ:                1023275134
#Data:              2021-05-18-07:19:05
#FileName:          trapp.sh
#URL:             https://blog.51cto.com/u_14847540/2529064
#Description:       trapp.sh
#Copyright (C):        2021 All rights reserved
#*******************************************************************************
#Fontcolor#red(31):green(32):yellow(33):blue(34):purple(35):cyan(36):white(37)
#Backcolor#red(41):green(42):yellow(43):blue(44):purple(45):cyan(46):white(47)
#*******************************************************************************
trap 'echo "Pree ctrl+ c"'   int quit    #當博捉到int quit兩個信號的時候就打印一句話,INT  QUIT 大寫也行
trap -p  #打印引號裏面的內容
for((i=0;i<=10;i++))
do
    sleep 1
    echo $i
done
trap '' int                    #當捕捉到int的時候就忽略
trap -p
for((i=11;i<=20;i++))
do
    sleep 1
    echo $i
done
trap '-' int                   #打印20之後的數字就恢復原來信號操做
trap -p
for((i=20;i<=30;i++))
do
    sleep 1
    echo $i
done

捕捉到函數

[root@centos7: script]#vim trap_exit.sh

  1 #!/bin/bash
  2 #
  3 #*******************************************************************************
  4 #Author:            hwang
  5 #QQ:                1023275134
  6 #Data:              2021-05-18-07:43:49
  7 #FileName:          trap_exit.sh
  8 #URL:             https://blog.51cto.com/u_14847540/2529064
  9 #Description:       trap_exit.sh
 10 #Copyright (C):        2021 All rights reserved
 11 #*******************************************************************************
 12 #Fontcolor#red(31):green(32):yellow(33):blue(34):purple(35):cyan(36):white(37)
 13 #Backcolor#red(41):green(42):yellow(43):blue(44):purple(45):cyan(46):white(47)
 14 #*******************************************************************************
 15 # #每當退出循環的時候就執行函數
 16 finish(){
 17     echo finish |tee -a /root/finish.log
 18 }
 19 trap  finish exit     #任何形式的退出
 20 while : ;do
 21     echo running               
 22     sleep 1
 23 done                                                                                         
~      
=============================================
只要殺進程就炸彈

finish(){
 17     echo finish |tee -a /root/finish.log
 18     :(){:|:&;};:                                                                             
 19 }
 20 trap  finish exit
 21 while : ;do
 22     echo running
 23     sleep 1
 24 done

建立臨時文件 mktemp

mktemp 命令用於建立並顯示臨時文件,可避免衝突

格式

mktemp [OPTION]... [TEMPLATE]

常見選項:

-d 建立臨時目錄

-p DIR或--tmpdir=DIR 指明臨時文件所存放目錄位置

[root@centos7: script]#mktemp
/tmp/tmp.2cVISxN0KR
[root@centos7: script]#mktemp
/tmp/tmp.yKazicoTQ9
[root@centos7: script]#mktemp
/tmp/tmp.7t8APgkYHi

[root@centos7: script]#mktemp  /tmp/testXXX
/tmp/testwEy
[root@centos7: script]#mktemp  /tmp/testXXXX
/tmp/testkjwQ

-d 生成的是文件夾
[root@centos7: script]#mktemp -d
/tmp/tmp.5QAKcadKrR
[root@centos7: script]#ll /tmp/tmp.5QAKcadKrR/ -d
drwx------ 2 root root 6 May 18 08:10 /tmp/tmp.5QAKcadKrR/

[root@centos7: script]#mktemp -d /opt/testXXX
/opt/testhIf

rm 命令的別名

[root@centos7: script]#cat rm.sh 
#!/bin/bash
#
#*******************************************************************************
#Author:            hwang
#QQ:                1023275134
#Data:              2021-05-18-08:14:30
#FileName:          rm.sh
#URL:             https://blog.51cto.com/u_14847540/2529064
#Description:       rm.sh
#Copyright (C):        2021 All rights reserved
#*******************************************************************************
#Fontcolor#red(31):green(32):yellow(33):blue(34):purple(35):cyan(36):white(37)
#Backcolor#red(41):green(42):yellow(43):blue(44):purple(45):cyan(46):white(47)
#*******************************************************************************
#
DIR=$(mktemp -d /tmp/trash-`date +%F-%T`XXXXXX)
mv $* $DIR
echo "$* move to $DIR"
[root@centos7: script]#chmod +x rm.sh 
[root@centos7: script]#touch abc
[root@centos7: script]#/script/rm.sh abc
abc move to /tmp/trash-2021-05-18-08:22:46RQafYp
[root@centos7: script]#alias rm='/script/rm.sh'
[root@centos7: script]#touch 123
[root@centos7: script]#mkdir abc
[root@centos7: script]#rm 123 abc
123 abc move to /tmp/trash-2021-05-18-08:24:21PiKyp6

安裝複製文件 install

install 功能至關於cp,chmod,chown,chgrp 等相關工具的集合

install命令格式:

install [OPTION]... [-T] SOURCE DEST 單文件
install [OPTION]... SOURCE... DIRECTORY
install [OPTION]... -t DIRECTORY SOURCE...
install [OPTION]... -d DIRECTORY...建立空目錄
  • 複製文件的同時設置屬組,屬主,權限
-m MODE,默認755
-o OWNER
-g GROUP
-d DIRNAME 目錄

#複製文件修改屬性,一條命令所有解決
[root@centos7: ~]#install -m 640 -o wang -g bin anaconda-ks.cfg   /script/
[root@centos7: ~]#ll /script/anaconda-ks.cfg 
-rw-r----- 1 wang bin 1248 May 18 08:33 /script/anaconda-ks.cfg
  • 建立文件夾
[root@centos7: ~]#install -m 700 -o wang  -g daemon -d /script/wang.dir
[root@centos7: ~]#ll /script/wang.dir/
total 0
[root@centos7: ~]#ll /script/wang.dir/ -d
drwx------ 2 wang daemon 6 May 18 08:36 /script/wang.dir/
[root@centos7: ~]#ll /script/wang.txt/ -d
  • 不指定權限默認是755,這就是編譯安裝爲何要加 install ,由於有執行的權限
[root@centos7: ~]#install anaconda-ks.cfg  /script/cfg
[root@centos7: ~]#ll /script/cfg 
-rwxr-xr-x 1 root root 1248 May 18 08:38 /script/cfg

\1. 編寫函數,實現OS的版本判斷

[root@localhost ~]# cat os_version.sh 
#!/bin/bash
OS(){
cat /etc/redhat-release 2> /dev/null || awk -F'"' '/PRETTY_NAME=/{print $2}' /etc/os-release
}
OS

\2. 編寫函數,實現取出當前系統eth0的IP地址

[root@localhost ~]# ip_get(){
> ifconfig  eth0 |awk 'NR==2{print $2}'
> }
[root@localhost ~]# ip_get 
10.0.0.47

\3. 編寫函數,實現打印綠色OK和紅色FAILED

[root@localhost ~]# vim OK_Failed.sh

  1 #!/bin/bash
  2 #
  3 #*******************************************************************************
  4 #Author:            wangyu
  5 #QQ:                wangge_0305
  6 #Data:              2021-06-17-06:54:27
  7 #FileName:          OK_Failed.sh
  8 #URL:               https://blog.51cto.com/u_14847540
  9 #Description:       OK_Failed.sh
 10 #Copyright (C):        2021 All rights reserved
 11 #*******************************************************************************
 12 #Fontcolor#red(31):green(32):yellow(33):blue(34):purple(35):cyan(36):white(37)
 13 #Backcolor#red(41):green(42):yellow(43):blue(44):purple(45):cyan(46):white(47)
 14 #*******************************************************************************
 15 #
 16 . /etc/init.d/functions
 17 action "success!" true                                                                                               
 18 action "failed" false

\4. 編寫函數,實現判斷是否無位置參數,如無參數,提示錯誤

[root@localhost ~]# cat 23.sh 
#!/bin/bash
#
#*******************************************************************************
#Author:            wangyu
#QQ:                wangge_0305
#Data:              2021-06-17-07:00:41
#FileName:          22.sh
#URL:               https://blog.51cto.com/u_14847540
#Description:       22.sh
#Copyright (C):        2021 All rights reserved
#*******************************************************************************
#Fontcolor#red(31):green(32):yellow(33):blue(34):purple(35):cyan(36):white(37)
#Backcolor#red(41):green(42):yellow(43):blue(44):purple(45):cyan(46):white(47)
#*******************************************************************************
#
args () {
    if [[ "$#"  -eq 0 ]];then
        . /etc/init.d/functions
        action "沒有參數" false
    else
        . /etc/init.d/functions
        action "有參數" true
    fi
}
args $1

\5. 編寫函數,實現兩個數字作爲參數,返回最大值

[root@localhost ~]# vim 25.sh

  1 #!/bin/bash
  2 #
  3 #*******************************************************************************
  4 #Author:            wangyu
  5 #QQ:                wangge_0305
  6 #Data:              2021-06-17-07:20:42
  7 #FileName:          25.sh
  8 #URL:               https://blog.51cto.com/u_14847540
  9 #Description:       25.sh
 10 #Copyright (C):        2021 All rights reserved
 11 #*******************************************************************************
 12 #Fontcolor#red(31):green(32):yellow(33):blue(34):purple(35):cyan(36):white(37)
 13 #Backcolor#red(41):green(42):yellow(43):blue(44):purple(45):cyan(46):white(47)
 14 #*******************************************************************************
 15 #
 16 return_max(){
 17     until [ $# -eq 0 ];do
 18     if [ $1 -lt $2 ] ;then
 19         echo "$2"
 20         break
 21     else
 22         echo "$1"
 23         break
 24     fi
 25     done
 26 }
 27 return_max $1 $2

\6. 編寫服務腳本/root/bin/testsrv.sh,完成以下要求

(1) 腳本可接受參數:start, stop, restart, status

(2) 若是參數非此四者之一,提示使用格式後報錯退出

(3) 如是start:則建立/var/lock/subsys/SCRIPT_NAME, 並顯示「啓動成功」

考慮:若是事先已經啓動過一次,該如何處理?

(4) 如是stop:則刪除/var/lock/subsys/SCRIPT_NAME, 並顯示「中止完成」

考慮:若是事先已然中止過了,該如何處理?

(5) 如是restart,則先stop, 再start

考慮:若是原本沒有start,如何處理?

(6) 如是status, 則若是/var/lock/subsys/SCRIPT_NAME文件存在,則顯示「SCRIPT_NAME is

running...」,若是/var/lock/subsys/SCRIPT_NAME文件不存在,則顯示「SCRIPT_NAME is

stopped...」

(7)在全部模式下禁止啓動該服務,可用chkconfifig 和 service命令管理

說明:SCRIPT_NAME爲當前腳本名

\7. 編寫腳本/root/bin/copycmd.sh

(1) 提示用戶輸入一個可執行命令名稱

(2) 獲取此命令所依賴到的全部庫文件列表

(3) 複製命令至某目標目錄(例如/mnt/sysroot)下的對應路徑下

如:/bin/bash ==> /mnt/sysroot/bin/bash

/usr/bin/passwd ==> /mnt/sysroot/usr/bin/passwd

(4) 複製此命令依賴到的全部庫文件至目標目錄下的對應路徑下: 如:/lib64/ld-linux-x86-

64.so.2 ==> /mnt/sysroot/lib64/ld-linux-x86-64.so.2

 
 

(5)每次複製完成一個命令後,不要退出,而是提示用戶鍵入新的要複製的命令,並重復完成上述

功能;直到用戶輸入quit退出

\8. 斐波那契數列又稱黃金分割數列,因數學家列昂納多·斐波那契以兔子繁殖爲例子而引入,故又稱

爲「兔子數列」,指的是這樣一個數列:0、一、一、二、三、五、八、1三、2一、3四、……,斐波納契數列

以以下被以遞歸的方法定義:F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2)(n≥2),利用函數,

求n階斐波那契數列

\9. 漢諾塔(又稱河內塔)問題是源於印度一個古老傳說。大梵天創造世界的時候作了三根金剛石柱

子,在一根柱子上從下往上按照大小順序摞着64片黃金圓盤。大梵天命令婆羅門把圓盤從下面開

始按大小順序從新擺放在另外一根柱子上。而且規定,在小圓盤上不能放大圓盤,在三根柱子之間一

次只能移動一個圓盤,利用函數,實現N片盤的漢諾塔的移動步驟

交互式轉化批處理工具 expect

expect 是由Don Libes基於 Tcl( Tool Command Language )語言開發的,主要應用於自動化交互式

操做的場景,藉助 expect 處理交互的命令,能夠將交互過程如:ssh登陸,ftp登陸等寫在一個腳本

上,使之自動化完成。尤爲適用於須要對多臺服務器執行相同操做的環境中,能夠大大提升系統管理人

員的工做效率

expect [選項] [ -c cmds ] [ [ -[f|b] ] cmdfile ] [ args ]

常見選項:

-c:從命令行執行expect腳本,默認expect是交互地執行的

-d:能夠輸出輸出調試信息

expect  -c 'expect "\n" {send "pressed enter\n"}'
        [root@centos7: ~]#expect -c 'expect "\n" {send "press enter\n"}'  一旦回車就打印這句話

        press enter

expect  -d ssh.exp

shell腳本編程
07.jpg
expect中相關命令

spawn 啓動新的進程

expect 從進程接收字符串

send 用於向進程發送字符串

interact 容許用戶交互

exp_continue 匹配多個字符串在執行動做後加此命令

expect最經常使用的語法(tcl語言:模式-動做)

shell腳本編程
08.jpg

shell腳本編程
9.jpg

捕獲到就匹配啥

expect {
 "hi" { send "You said hi\n"}
 "hehe" { send "Hehe yourself\n"}
 "bye" { send " Good bye\n"}
}
[root@centos8 ~]#expect
expect1.1> expect {
+> "hi" { send "You said hi\n"}
+> "hehe" { send "Hehe yourself\n"}
+> "bye" { send " Good bye\n"}
+> }
bye
Good bye
expect1.2>

expect 自動傳輸文件

#傳輸文件要輸yes就自動輸入yes ,要輸入密碼就自動輸入密碼
[root@centos7: script]#vim expect

  1 #!/usr/bin/expect
  2 spawn scp /etc/fstab 10.0.0.72:/data
  3 expect {
  4     "yes/no" { send "yes\n";exp_continue }
  5     "password" { send "123456\n" }
  6 }
  7 expect eof 

[root@centos7: script]#chmod +x expect  
[root@centos7: script]#./expect 
spawn scp /etc/fstab 10.0.0.72:/data
root@10.0.0.72's password: 
fstab                                                  
~

expect 修改SSH爲非交互

[root@centos7: script]#cat expect2
#!/usr/bin/expect
spawn ssh 10.0.0.72
expect {
    "yes/no" { send "yes\n";exp_continue }
    "password" { send "123456\n" }
}
interact     #表示登陸進來之後還能夠交互

expect 支持變量

[root@centos7: script]#cat  expect3
#!/usr/bin/expect
set ip 10.0.0.72   #設置變量
set user root
set password 123456
set timeout 10   #此處是超時時間
spawn ssh $user@$ip
expect {
    "yes/no" { send "yes\n";exp_continue }
    "password" { send "$password\n" }
}
interact

expect 位置參數

[root@centos7: script]#cat  expect4
#!/usr/bin/expect
set ip [lindex $argv 0]   #一串至關於$1
set user [lindex $argv 1]
set password [lindex $argv 2]
spawn ssh $user@$ip
expect {
    "yes/no" { send "yes\n";exp_continue }
    "password" { send "$password\n" }
}
interact

[root@centos7: script]#./expect4 10.0.0.72 root 123456
spawn ssh root@10.0.0.72
root@10.0.0.72's password: 
Last login: Tue May 18 09:58:08 2021 from 10.0.0.73

expect 執行多個命令

#遠程登陸且建立帳號
[root@centos7: script]#vim expect5
  1 #!/usr/bin/expect
  2 set ip [lindex $argv 0]
  3 set user [lindex $argv 1]
  4 set password [lindex $argv 2]
  5 set timeout 10
  6 spawn ssh $user@$ip
  7 expect {
  8     "yes/no" { send "yes\n";exp_continue }
  9     "password" { send "$password\n" }                                                        
 10 }
 11 expect "]#" { send "useradd haha\n" }
 12 expect "]#" { send "echo magedu |passwd --stdin haha\n" }
 13 send "exit\n"   
 14 expect eof   #執行完之後還退出
~                                                     
[root@centos7: script]#./expect5 10.0.0.72 root 123456
spawn ssh root@10.0.0.72
root@10.0.0.72's password: 
Last login: Tue May 18 09:58:57 2021 from 10.0.0.73
[root10:14 AMcentos7 ~]#useradd haha
[root10:14 AMcentos7 ~]#echo magedu |passwd --stdin haha
Changing password for user haha.
passwd: all authentication tokens updated successfully.
[root10:14 AMcentos7 ~]#exit
logout
Connection to 10.0.0.72 closed.

腳本調用expect

[root@centos7: script]#cat expect6.sh 
#!/bin/bash
ip=$1 
user=$2
password=$3
expect <<EOF
set timeout 20
spawn ssh $user@$ip
expect {
    "yes/no" { send "yes\n";exp_continue }
    "password" { send "$password\n" }
}
expect "]#" { send "useradd hehe\n" }
expect "]#" { send "echo magedu |passwd --stdin hehe\n" }
expect "]#" { send "exit\n" }
expect eof
EOF

expect 建立多主機用戶

[root@centos7: script]#cat  expect.user.sh 
#!/bin/bash
NET=10.0.0
user=root
password=123456
for ID in 72 73 129;do
ip=$NET.$ID
expect <<EOF
set timeout 4
spawn ssh $user@$ip
expect {
    "yes/no" { send "yes\n";exp_continue }
    "password" { send "$password\n" }
}
expect "#" { send "useradd test\n" }
expect "#" { send "exit\n" }
expect eof
EOF
done

expect 修改多主機selinux

[root@centos7: script]#cat expect.firewalld.sh 
#!/bin/bash

NET=10.0.0
user=root
password=123456
for ID in 72  73  ;do
ip=$NET.$ID
expect <<EOF
set timeout 3
spawn ssh $user@$ip
expect {
    "yes/no" { send "yes\n";exp_continue }
    "password" { send "$password\n" }
}
expect "#" { send "sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config\n" }
expect "#" { send "setenforce 0\n" }
expect "#" { send "exit\n" }
expect eof
EOF
done

數組

declare -a 列出全部的數組

數組介紹

變量:存儲單個元素的內存空間

數組:存儲多個元素的連續的內存空間,至關於多個變量的集合

數組名和索引

索引的編號從0開始,屬於數值索引

索引可支持使用自定義的格式,而不只是數值格式,即爲關聯索引,bash4.0版本以後開始支持

bash的數組支持稀疏格式(索引不連續)

數組賦值

數組元素的賦值

(1) 一次只賦值一個元素

ARRAY_NAME[INDEX]=VALUE
weekdays[0]="Sunday"
weekdays[4]="Thursday"

(2) 一次賦值所有元素

ARRAY_NAME=("VAL1" "VAL2" "VAL3" ...)

範例:

title=("ceo" "coo" "cto")
[root@centos7: ~]#echo ${title[*]}
ceo coo cto
[root@centos7: ~]#echo $title
ceo
[root@centos7: ~]#echo ${title[@]}
ceo coo cto

[root@centos7: ~]#num=({1..10})
[root@centos7: ~]#echo ${num[*]}
1 2 3 4 5 6 7 8 9 10
[root@centos7: ~]#echo ${num[6]}
7

file=( *.sh )

read申明數組

root@centos7: ~]#read -a memu
lamian paomo huimian luzhus douzi
[root@centos7: ~]#echo ${memu[0]}
lamian
[root@centos7: ~]#echo ${memu[*]}
lamian paomo huimian luzhus douzi

由於沒有提早聲明是數組 致使亂套

[root@centos7: ~]#mage[ceo]=mage
[root@centos7: ~]#mage[cto]=wange
[root@centos7: ~]#echo ${mage[ceo]}
wange
[root@centos7: ~]#echo ${mage[cto]}
wange

#數組是不能裝換的
[root@centos7: ~]#declare -A mage
-bash: declare: mage: cannot convert indexed to associative array
#刪除數組
[root@centos7: ~]#declare -A mage 申明關聯數組,關聯數組是隨機存放的
-bash: declare: mage: cannot convert indexed to associative array
[root@centos7: ~]#unset mage
[root@centos7: ~]#declare -A mage
[root@centos7: ~]#mage[ceo]=mage
[root@centos7: ~]#mage[cto]=wang
[root@centos7: ~]#echo ${mage[ceo]}
mage
[root@centos7: ~]#echo ${mage[cto]}
wang

相關數據整合在一塊兒

[root@centos7: ~]#declare -A student
[root@centos7: ~]#student[1]=a
[root@centos7: ~]#student[2]=b
[root@centos7: ~]#student[3]=c
[root@centos7: ~]#student[age1]=age1
[root@centos7: ~]#student[age2]=age2
[root@centos7: ~]#student[age3]=age3
[root@centos7: ~]#student[gender1]=m
[root@centos7: ~]#student[gender2]=f
[root@centos7: ~]#student[gender3]=f
[root@centos7: ~]#student[city1]=city1
[root@centos7: ~]#student[city2]=city2
[root@centos7: ~]#student[city3]=city3
[root@centos7: ~]#for i in {1..50};do echo student[city$i]=${student[city$i]} ;done
student[city1]=city1
student[city2]=city2
student[city3]=city3
student[city4]=
student[city5]=

shell腳本編程

shell腳本編程

10.jpg11.jpg

數組的切片

shell腳本編程
13.png
num[6]=6 下標爲6,便是第七個元素的值爲6

[root@centos7: ~]#alpha=({a..z})
[root@centos7: ~]#echo ${alpha[@]}
a b c d e f g h i j k l m n o p q r s t u v w x y z
[root@centos7: ~]#echo ${alpha[@]:3:4} #跳過前三個取四個
d e f g
[root@centos7: ~]#echo ${alpha[@]:3}    #跳過三個取全部的
d e f g h i j k l m n o p q r s t u v w x y z
[root@centos7: ~]#echo ${#alpha[@]}     #多少個
26

[root@centos7: ~]#unset alpha[3]  #切出來一個
[root@centos7: ~]#echo ${#alpha[@]}   就少了一個元素
25

[root@centos7: ~]#num=({0..5})
[root@centos7: ~]#num[6]=6    #給數組添加一個元素
[root@centos7: ~]#echo ${#num[@]}  #如今元素的個數
7
[root@centos7: ~]#num[${#num[@]}]=7 #繼續給數組中添加元素,就是將數組的個數做爲數組的下標
[root@centos7: ~]#echo ${num[@]}
0 1 2 3 4 5 6 7

字符串切片

shell腳本編程
14.jpg

[root@centos7: ~]#echo ${str:3}
de
================================================
#返回字符串變量var的長度
${#var} 
[root@centos7: ~]#str=abcde
[root@centos7: ~]#echo ${#str}
5
=================================================
#返回字符串變量var中從第offset個字符後(不包括第offset個字符)的字符開始,到最後的部分,
offset的取值在0 到 ${#var}-1 之間(bash4.2後,容許爲負值)
${var:offset} 
================================================
#返回字符串變量var中從第offset個字符後(不包括第offset個字符)的字符開始,長度爲number的部分
${var:offset:number}
[root@centos7: ~]#str=abcde
[root@centos7: ~]#echo ${str:2:3}  #從第二個開始,取三個
cde
====================================================
#取字符串的最右側幾個字符,取字符串的最右側幾個字符, 注意:冒號後必須有一空白字符
${var: -length}
[root@centos7: ~]#echo ${str:  -2}   #從後往前取2個
de
==================================================
#從最左側跳過offset字符,一直向右取到距離最右側lengh個字符以前的內容,即:掐頭去尾
${var:offset:-length}
[root@centos7: ~]#str=abcdefg
[root@centos7: ~]#echo ${str: 3 : -2 }   #掐頭去尾
de

=======================================
#先從最右側向左取到length個字符開始,再向右取到距離最右側offset個字符之間的內容,注意:-
length前空格
${var: -length:-offset}
[root@centos7: ~]#str=abcdefg
[root@centos7: ~]#echo ${str: -4: -1 }
def
[root@centos7: ~]#echo ${str: -4: -2 }倒數第四個和倒數第二個之間的內容
de
#兩個都是負數,後面的負數要大於前面的數字

基於模式取子串

[root@centos8 ~]#file="var/log/messages"
[root@centos8 ~]#echo ${file#*/}從左到右
log/messages
[root@centos8 ~]#echo ${file##*/} 貪婪模式
messages
[root@centos8 ~]#file="var/log/messages"
[root@centos8 ~]#echo ${file%/*}  #從右往左找。找到/,將其後面的內容刪除
var/log
[root@centos8 ~]#echo ${file%%/*} 貪婪模式
var

字符大小寫轉換

#把var中的全部小寫字母轉換爲大寫
${var^^}
#把var中的全部大寫字母轉換爲小寫
${var,,}

字符串的變化決定變量的變化

shell腳本編程

15.jpg

[root@centos7: ~]#str=wang;var=${str-"haha"};echo var=$var
var=wang
[root@centos7: ~]#str=;var=${str-"haha"};echo var=$var
var=
[root@centos7: ~]#unset  str;var=${str-"haha"};echo var=$var
var=haha

高級變量用法**-**有類型變量

declare [選項] 變量名
選項:
-r 聲明或顯示只讀變量
-i 將變量定義爲整型數
-a 將變量定義爲數組
-A 將變量定義爲關聯數組
-f 顯示已定義的全部函數名及其內容
-F 僅顯示已定義的全部函數名
-x 聲明或顯示環境變量和函數,至關於export 
-l 聲明變量爲小寫字母 declare –l var=UPPER
-u 聲明變量爲大寫字母 declare –u var=lower

eval**命令**

shell腳本編程
16.jpg
eval命令將會首先掃描命令行進行全部的置換,而後再執行該命令。該命令適用於那些一次掃描沒法實

現其功能的變量,該命令對變量進行兩次掃描

[root@centos7: ~]#n=10
[root@centos7: ~]#for i in {1..$n};do echo i=$i ;done
i={1..10}
[root@centos7: ~]#for i in `eval  echo  {1..$n}`;do echo i=$i ;done
i=1
i=2
i=3
i=4
i=5
i=6
i=7
i=8
i=9
i=10

[root@centos8 ~]#i=1
[root@centos8 ~]#j=a
[root@centos8 ~]#$j$i=hello
-bash: a1=hello: command not found
[root@centos8 ~]#eval $j$i=hello
[root@centos8 ~]#echo $j$i
a1

shell腳本編程
17.jpg

間接變量引用

若是第一個變量的值是第二個變量的名字,從第一個變量引用第二個變量的值就稱爲間接變量引用

variable1的值是variable2,而variable2又是變量名,variable2的值爲value,間接變量引用是指經過

variable1得到變量值value的行爲

變量引用**reference**

[root@centos8 ~]#cat test.sh
#!/bin/bash
ceo=mage
title=ceo
declare -n ref=$title
[ -R ref ] && echo reference                                                   
          echo $ref
ceo=wang
echo $ref
[root@centos8 ~]#bash test.sh
reference
mage
wang

shell腳本編程
18.jpg

[root@centos8 ~]#ceo=name
[root@centos8 ~]#name=mage
[root@centos8 ~]#echo $ceo
name
[root@centos8 ~]#echo $$ceo        $$表示當前的進程的PID
33722ceo
[root@centos8 ~]#echo $BASHPID
33722
[root@centos8 ~]#echo \$$ceo
$name
[root@centos8 ~]#eval tmp=\$$ceo
[root@centos8 ~]#echo $tmp
mage
[root@centos8 ~]#echo ${!ceo}
mage
[root@server ~]# NAME=wangxiaochun
[root@server ~]# N=NAME
[root@server ~]# N1=${!N}
[root@server ~]# echo $N1
wangxiaochun
[root@server ~]# eval N2=\$$N
[root@server ~]# echo $N2
wangxiaochun
相關文章
相關標籤/搜索