Linux實戰教學筆記17:精簡shell基礎

第十七節 精簡shell基礎

標籤(空格分隔): Linux實戰教學筆記javascript


1,前言

1.1 爲何學習shell編程

Shell腳本語言是實現Linux/UNIX系統管理及自動化運維所必備的重要工具,Linux/UNIX系統的底層及基礎應用軟件的核心大部分涉及Shell腳本的內容。每個合格的Linux系統管理員或運維工程師,都須要熟練的編寫Shell腳本語言,並可以閱讀系統及各種軟件附帶的Shell腳本內容。只有這樣才能提高運維人員的工做效率,適應日益複雜的工做環境,減小沒必要要的重複工做,從而爲我的的職場發展奠基較好的基礎。html

1.2 學好Shell編程所需的基礎知識

  • 可以熟練使用vim編輯器,熟悉SSH終端
  • 有必定的Linux命令基礎,至少須要掌握80個以上Linux經常使用命令,並可以熟練使用它。
  • 要熟練掌握Linux正則表達式及三劍客命令(grep,sed,awk)

1.3 如何學好Shel編程

  • 學好Shel編程的核心:多練-->多思考-->再練-->再思考,堅持如此循環便可!
  • 新手大忌:不可拿來主義,能夠模仿,可是要本身嚼爛了吃下去,不然會鬧肚子。
  • 格言:你以爲會了並不必定會了,你認爲對的並不必定對的。

你們要勤動手,自行完成學習筆記和代碼的書寫。經過每個小目標培養本身的興趣以及成就感java

2,Shell腳本入門

2.1 什麼是Shell

  • Shell是一個命令解釋器,它在操做系統的最外層,負責直接與用戶對話,把用戶的輸入解釋給操做系統,並處理各類各樣的操做系統的輸出結果,輸出屏幕返回給用戶。
  • 這種對話方式能夠是:
    1)交互的方式:從鍵盤輸入命令,經過/bin/bash的解釋器,能夠當即獲得shell的迴應
    2)非交互的方式:腳本

下圖黃色部分就是命令解釋器shellpython

屏幕快照 2017-02-24 下午1.35.04.png-226.5kB

Shell的英文意思是貝殼的意思,命令解釋器Shell像一個貝殼同樣包住系統核心。linux

Shell執行命令分爲兩種方式:nginx

  • 內置命令:如講過的cd,pwd,exit和echo等命令,當用戶登陸系統後,shell以及內置命令就被系統載入內存,而且一直運行。
  • 通常命令:如ls,磁盤上的程序文件-->調入-->執行命令

2.2 什麼是Shell 腳本

當linux命令或語句不在命令行下執行(嚴格說,命令行也是shell),而是經過一個程序文件執行時,該程序就被稱爲Shell腳本或Shell程序
用戶能夠在Shell腳本中敲入一系列的命令及語句組合。這些命令,變量和流程控制語句等有機的結合起來就造成一個功能強大的Shell腳本。git

首先先帶領你們寫一個清空/var/log/messages日誌的腳本正則表達式

咱們須要先想明白幾個問題:
1)日誌文件在哪?
/var/log/messages
2)用什麼命令能夠清空文件?
> 重定向
3)寫一個簡單的shell腳本。redis

#!/bin/env bash # -*- coding:utf-8 -*- # author:Mr.chen cd /var/log/ >messages

4)怎樣執行腳本?
[root@chensiqi1 ~]# sh /server/scripts/chensiqi.shdocker

有沒有考慮到:

  • 有沒有腳本放在統一的目錄

/server/scripts目錄下

  • 權限:用哪一個用戶執行文件

須要對用戶作判斷

  • 清空錯文件怎麼辦,該如何辦?

  • 錯誤提示:有沒有成功知不知道?

  • 腳本的通用性

範例:包含命令,變量和流程控制的清空/var/log/messages日誌的shell腳本

[root@chensiqi1 ~]# mkdir -p /server/scripts #要有規範的存放腳本目錄 [root@chensiqi1 ~]# vim /server/scripts/chensiqi.sh [root@chensiqi1 ~]# cd /server/scripts/ [root@chensiqi1 scripts]# cat /server/scripts/clear_log.sh #!/bin/env bash # -*- coding:utf-8 -*- # author:Mr.chen LOG_DIR=/var/log if [ $UID -ne 0 ] #root用戶的UID是0 then echo "Must be root to run this script" exit 1 #退出腳本,返回值1 fi cd $LOG_DIR 2>/dev/null || { echo "Cannot chage to necessary directory." exit 1 } #若是第一個語句執行失敗,那麼執行||後邊的 cat /dev/null > messages && echo "Logs cleaned up." #打開一個空文件而後重定向日誌文件作爲清空處理 exit 0

清空日誌的三種方法:

echo >test.log >test.log cat /dev/null >test.log #清空內容,保留文件

小結:

  • Shell就是命令解釋器。==>翻譯官
  • Shell腳本==>命令放在腳本里

2.3,Shell腳本在運維工做中的做用地位

Shell腳本擅長處理純文本類型的數據,而Linux中幾乎全部的配置文件,日誌文件等都是純文本類型文件。

3,Shell腳本的創建和執行

3.1 Shell腳本的創建

推薦使用vim編輯器編輯腳本,能夠事先作個別名。

[root@chensiqi1 scripts]# echo "alias vi=vim">>/etc/profile [root@chensiqi1 scripts]# source /etc/profile

3.1.1腳本開頭第一行

規範的Shell腳本第一行會指出由哪一個程序(解釋器)來執行腳本中的內容。在linux bash編程中通常爲:

#!/bin/bash 或 #!/bin/sh

其中開頭的「#!」又稱爲幻數,在執行Shell腳本的時候,內核會根據「#!」後的解釋器來肯定哪一個程序解釋腳本中的內容。注意:這一行必須在每一個腳本頂端的第一行,若是不是第一行則爲腳本註釋行。

3.1.2 sh和bash的區別

[root@chensiqi1 scripts]# ll /bin/sh lrwxrwxrwx. 1 root root 4 Dec 23 20:25 /bin/sh -> bash #sh是bash的軟連接,推薦標準寫法#!/bin/bash

能夠看一下系統自帶的腳本的寫法

head -1 /etc/init.d/*

3.1.3 bash版本

[root@chensiqi1 scripts]# bash --version GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu) Copyright (C) 2009 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software; you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.

3.1.4 bash漏洞【破殼漏洞】

若是是比較老的系統,須要注意shell的版本過低,有漏洞,須要升級shell

[root@chensiqi1 scripts]# yum -y update bash #驗證方法 [root@chensiqi1 scripts]# env x='(){ :;};echo be careful' bash -c "echo this is a test" this is a test 若是返回2行 be careful this is a test 這樣的結果的話,請儘快升級

3.1.5 不一樣語言腳本的開頭寫法

#!/bin/sh #!/bin/bash #!/usr/bin/awk #!/bin/sed #!/usr/bin/tcl #!/usr/bin/expect #!/usr/bin/perl #!/usr/bin/env python

若是腳本開頭不指定解釋器,就要用對應的解釋器執行腳本。例如bash test.sh和python.test.py

要求:養成一個好習慣,開頭加上相應的解釋器標識。

3.1.6 腳本註釋

在Shell腳本中,跟在#後面的內容表示註釋。註釋部分不會被執行,僅給人看。註釋能夠自成一行,也能夠跟在命令後面,與命令同行。要養成寫註釋的習慣,方便本身與他人。

最好不用中文註釋,由於在不一樣字符集的系統會出現亂碼。

3.2 Shell腳本的執行

3.2.1 Shell腳本執行的四種方式

1)bash scripts-name或sh script-name(推薦使用)

這種方法是當腳本自己沒有可執行權限時常使用的方法。

2)path /script-name 或./scripts-name(全路徑或當前路徑執行腳本)
這種方法首先須要給腳本文件可執行權限。

3)source scripts-name或. scripts-name #注意「.」點號,且點號後有空格。
source 或.在執行這個腳本的同時,能夠將腳本中的函數和變量加載到當前Shell。不會產生子shell。又有點像nginx的include功能。

3.3 Shell腳本開發的規範和習慣

1)開頭指定腳本解釋器
2)開頭加版本版權等信息,可配置~/.vimrc文件自動添加
3)腳本不要用中文註釋,儘可能用英文註釋
4)腳本以.sh爲擴展名
5)放在統一的目錄
6)代碼書寫優秀習慣
a,成對的內容一次性寫出來,防止遺漏,如[],'',""等
b,[]兩端要有空格,先輸入[]退格,輸入2個空格,再退格寫。
c,
流程控制語句一次書寫完,再添加內容。

if 條件 then 內容 fi

d,經過縮進讓代碼易讀
f,腳本中的引號都是英文狀態下的引號,其餘字符也是英文狀態。

好的習慣可讓咱們避免不少沒必要要的麻煩,提升工做效率。

4,Shell環境變量

4.1 什麼是變量

變量就是用一個固定的字符串(也多是字符數字等的組合),替代更多更復雜的內容,這個內容裏可能還會包含變量和路徑,字符串等其餘內容。變量的定義是存在內存中。

x=1 y=2

4.2 變量類型

變量分爲兩類:
1)環境變量(也可稱爲全局變量);能夠在建立他們的Shell及派生出來的子shell中使用。環境變量又能夠分爲自定義環境變量和bash內置的環境變量。

2)局部變量(普通變量):只能在建立他們的shell函數或shell腳本中使用,還記得前面的$user?咱們建立的通常都是普通變量。

4.2.1 環境變量

  • 環境變量用於定義Shell的運行環境,保證Shell命令的正確執行,Shell經過環境變量來肯定登陸用戶名,命令路徑,終端類型,登陸目錄等,全部的環境變量都是全局變量,可用於全部子進程中,包括編輯器,shell腳本和各種應用。但crond計劃任務除外,還須要從新定義環境變量。
  • 環境變量能夠在命令行中設置,但用戶退出時這些變量值也會丟失,所以最好在用戶家目錄下的.bash_profile文件中或全局配置/etc/bashrc,/etc/profile文件或者/etc/profile.d/目錄中定義。將環境變量放入profile文件中,每次用戶登陸時這些變量值都將被初始化。
  • 一般,全部環境變量均爲大寫。環境變量應用於用戶進程前,都應該用export命令導出。例如:export chensiqi=1
  • 有一些環境變量,好比HOME,PATH,SHELL,UID,USER等,在用戶登陸以前就已經被/bin/login程序設置好了。一般環境變量定義並保存在用戶家目錄下的.bash_profile或/etc/profile文件中。
#顯示環境變量 [root@chensiqi1 scripts]# echo $HOME /root [root@chensiqi1 scripts]# echo $PATH /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin [root@chensiqi1 scripts]# echo $SHELL /bin/bash [root@chensiqi1 scripts]# echo $UID 0 [root@chensiqi1 scripts]# echo $USER root [root@chensiqi1 scripts]# env #查看系統環境變量 HOSTNAME=chensiqi1 SELINUX_ROLE_REQUESTED= TERM=xterm-256color SHELL=/bin/bash HISTSIZE=500 SSH_CLIENT=192.168.197.1 49592 22 SELINUX_USE_CURRENT_RANGE= OLDPWD=/root SSH_TTY=/dev/pts/1 LC_ALL=C USER=root #中間省略部份內容.... MAIL=/var/spool/mail/root PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin PWD=/server/scripts LANG=zh_CN.UTF-8 SELINUX_LEVEL_REQUESTED= HISTCONTROL=ignoredups SHLVL=1 HOME=/root LOGNAME=root CVS_RSH=ssh SSH_CONNECTION=192.168.197.1 49592 192.168.197.133 22 LESSOPEN=||/usr/bin/lesspipe.sh %s G_BROKEN_FILENAMES=1 _=/bin/env
#當前終端變量 [root@chensiqi1 scripts]# echo $PS1 [\u@\h \W]\$

4.2.1 局部變量

定義局部變量

局部變量在用戶當前的shell生存期的腳本中使用。例如,局部變量chensiqi取值爲chensiqi098,這個值只在用戶當前shell生存期中有意義。若是在shell中啓動另外一個進程或退出,局部變量chensiqi值將無效。

普通字符串變量定義

變量名=value 變量名=‘value’ 變量名=「value」

shell中變量名及變量內容的要求

  • 通常是字母,數字,下劃線組成,且以字母開頭。如chensiqi,chensiqi123,chensiqi-training。變量的內容,可使用單引號或雙引號印起來,或不加引號。

  • 雖然變量能夠如下劃線開頭,但相似這種變量都是比較特殊的,都是系統本身用的。咱們儘可能少用。

[root@chensiqi1 scripts]# _123=eeee [root@chensiqi1 scripts]# echo $_123 eeee

普通字符串變量定義測試

[root@chensiqi1 scripts]# a=192.168.1.2 [root@chensiqi1 scripts]# b='192.168.1.2' [root@chensiqi1 scripts]# c="192.168.1.2" [root@chensiqi1 scripts]# echo "a=$a" a=192.168.1.2 [root@chensiqi1 scripts]# echo "b=$b" b=192.168.1.2 [root@chensiqi1 scripts]# echo "c=${c}" c=192.168.1.2 [root@chensiqi1 scripts]# a=192.168.1.2-$a [root@chensiqi1 scripts]# b='192.168.1.2-$a' [root@chensiqi1 scripts]# c="192.168.1.2-$a" [root@chensiqi1 scripts]# echo "a=$a" a=192.168.1.2-192.168.1.2 [root@chensiqi1 scripts]# echo "b=$b" b=192.168.1.2-$a [root@chensiqi1 scripts]# echo "c=${c}" c=192.168.1.2-192.168.1.2-192.168.1.2

把一個命令作爲變量

[root@chensiqi1 scripts]# ls chensiqi.sh clear_log.sh [root@chensiqi1 scripts]# CMD=`ls` [root@chensiqi1 scripts]# echo $CMD chensiqi.sh clear_log.sh [root@chensiqi1 scripts]# CMD1=$(pwd) [root@chensiqi1 scripts]# echo $CMD1 /server/scripts
變量名=`ls` <==反引號 變量名=$(ls)

小結:

1)CMD=ls的ls兩側的符號是鍵盤tab鍵上面的,不是單引號。
2)在變量名前加$,能夠取得此變量的值,使用echo或printf命令能夠顯示變量的值,$A和$(A)寫法不一樣,效果同樣,推薦後面的寫法。
3)${WEEK}DAY若變量和其餘字符組成新的變量就必須給變量加上大括號{}.
4)養成將全部字符串變量用雙引號括起來使用的習慣,減小編程遇到的怪異錯誤。「$A」和「${A}」

4.3 變量名及變量內容定義小結

  1. 變量名只能由字母,數字,下劃線組成,且以字母開頭。

  2. 規範的變量名寫法定義:見名知意
    a,ChensiqiAge=1 <==每一個單詞首字母大寫
    b,chensiqi_age=1 <==每一個單詞之間用「-」
    c,chensiqiAgeSex=1 <==駝峯語法:首個單詞字母小寫,其他單詞首字母大寫

  3. =號的知識,a=1中的等號是賦值的意思,比較是否是相等爲「==」
  4. 打印變量,變量名前接$符號,變量名後接字符的時候,要用大括號括起來

[root@chensiqi1 ~]# word="big" [root@chensiqi1 ~]# echo ${word}ger bigger [root@chensiqi1 ~]# echo $wordger [root@chensiqi1 ~]# 
  1. 注意變量內容引用方法,通常爲雙引號,簡單連續字符能夠不加引號,但願原樣輸出,使用單引號。
  2. 變量內容是命令,要用反引號``或者$()把變量括起來使用

5,Shell特殊變量

5.1 位置變量

$0 獲取當前執行的shell腳本的文件名,若是執行腳本帶路徑那麼就包括腳本路徑。 $n 獲取當前執行的shell腳本的第n個參數值,n=1..9,當n爲0時表示腳本的文件名,若是n大於9用大括號括起來{10},參數以空格隔開。 $# 獲取當前執行的shell腳本後面接的參數的總個數
$0 獲取當前執行的shell腳本的文件名,包括路徑 [root@chensiqi1 scripts]# cat chensiqi.sh #!/bin/bash echo $0 [root@chensiqi1 scripts]# sh chensiqi.sh chensiqi.sh [root@chensiqi1 ~]# sh /server/scripts/chensiqi.sh /server/scripts/chensiqi.sh
#參觀系統腳本使用$0 [root@chensiqi1 ~]# grep -i usage /etc/init.d/crond echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}" [root@chensiqi1 ~]# /etc/init.d/crond Usage: /etc/init.d/crond {start|stop|status|restart|condrestart|try-restart|reload|force-reload}
$n $1 $2...$n命令腳本後面的參數的內容$1第一個參數$2是第二個參數.... [root@chensiqi1 scripts]# echo \${1..15} $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 $11 $12 $13 $14 $15 [root@chensiqi1 scripts]# cat chensiqi.sh #!/bin/bash echo $0 echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11} ${12} ${13} ${14} ${15} [root@chensiqi1 scripts]# sh chensiqi.sh {a..z} chensiqi.sh a b c d e f g h i j k l m n o
$# 獲取當前shell命令行中參數的總個數,用於判斷傳參的參數個數是否符合要求 [root@chensiqi1 scripts]# cat chensiqi.sh #!/bin/bash echo $0 echo $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11} ${12} ${13} ${14} ${15} echo $# [root@chensiqi1 scripts]# sh chensiqi.sh chensiqi.sh 0 [root@chensiqi1 scripts]# sh chensiqi.sh ee tt chensiqi.sh ee tt 2

5.2 進程狀態變量

$? 獲取執行上一個指令的返回值(0爲成功,非零爲失敗) 查找方法man bash,而後搜索Special Parameters

5.2.1 $?測試

[root@chensiqi1 scripts]# echo $? 0 [root@chensiqi1 scripts]# cd /rrr -bash: cd: /rrr: No such file or directory [root@chensiqi1 scripts]# echo $? 1 $?返回值參考 0 表示運行成功 2 權限拒絕 1~125 表示運行失敗,腳本命令,系統命令錯誤或參數傳遞錯誤; 126 找到該命令,但沒法執行 127 未找到要運行的命令 128 命令被系統強制結束

生產環境:
1)用於判斷命令,腳本或函數等程序是否執行成功。
2)若在腳本中調用執行「exit數字」,則會返回這個數字給「$?」變量
3)若是在函數中使用「return 數字」,則會以函數返回值的形式傳給「$?」.

#!/bin/bash /etc/init.d/network restart >/dev/null 2>&1 if [ $? -ne 0 ] then echo "Mynetwork is bad!" exit 1 fi

6,變量的數值計算

6.1 (())用法(經常使用於簡單的整數運算)

算數運算符號

運算符 意義
++ -- 增長及減小,可前置也可放在結尾
+ - ! ~ 一元運算的正負號,非,邏輯與位的取反
* / % 乘法,除法,取餘
+ - 加法,減法
< <= > >= 比較符號
== 1+= 相等,不相等
<< >> 向左移動,向右移動
& 位的AND
^ 位的異或
| 位的或
&& 位的AND
|| 位的OR
?: 條件表達式
= += -= *=等 賦值運算符
** 冪運算

使用方法:

[root@chensiqi1 scripts]# ((a=1+2**3-4%3)) [root@chensiqi1 scripts]# echo $a 8 [root@chensiqi1 scripts]# b=$((1+2**3-4%3)) [root@chensiqi1 scripts]# echo $b 8 [root@chensiqi1 scripts]# echo $((1+2**3-4%3)) 8 小結: 1)「(())」在命令行執行時不須要$符號,可是輸出須要$符號 2)「(())」裏全部字符之間有無或多個空格沒有任何影響

一個比較繞的知識點:

[root@chensiqi1 scripts]# a=8 [root@chensiqi1 scripts]# echo $a 8 [root@chensiqi1 scripts]# echo $((a+=1)) #至關於a=a+1 9 [root@chensiqi1 scripts]# echo $((a++)) #a在前,先輸出a的值,在加1 9 [root@chensiqi1 scripts]# echo $a 10 [root@chensiqi1 scripts]# echo $((a--)) 10 [root@chensiqi1 scripts]# echo $a 9 [root@chensiqi1 scripts]# echo $((++a)) 10 [root@chensiqi1 scripts]# echo $a 10 [root@chensiqi1 scripts]# echo $((--a)) 9 [root@chensiqi1 scripts]# echo $a 9

記憶方法:++,--

變量a在前,表達式的值爲a,而後a自增或自減,變量a在符號後,表達式值自增或自減,而後a值自增或自減。

數值判斷:

[root@chensiqi1 scripts]# echo $((3>2)) 1 [root@chensiqi1 scripts]# echo $((3<2)) 0

6.2 練習:實現一個計算器

結合前邊的知識:

方法一:

[root@chensiqi1 scripts]# cat calculator.sh #!/bin/env bash echo $(($1)) [root@chensiqi1 scripts]# sh calculator.sh 3+2 5 [root@chensiqi1 scripts]# sh calculator.sh 3**2 9 [root@chensiqi1 scripts]# cat calculator.sh #!/bin/env bash echo $(($1$2$3)) [root@chensiqi1 scripts]# sh calculator.sh 3 - 2 1

方法二:傳參並計算

[root@chensiqi1 scripts]# cat calculator.sh #!/bin/env 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))" [root@chensiqi1 scripts]# sh calculator.sh a-b =4 a+b =8 a*b =12 a/b =3 a**b =36 a%b =0 #傳參數 [root@chensiqi1 scripts]# cat calculator.sh #!/bin/env bash a=$1 #不須要把後面的$a,$b都改 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))" [root@chensiqi1 scripts]# sh calculator.sh 3 8 a-b =-5 a+b =11 a*b =24 a/b =0 a**b =6561 a%b =3

6.2 $[]的用法

[root@chensiqi1 scripts]# echo $[2+3] 5 [root@chensiqi1 scripts]# echo $[2*3] 6

7,腳本中定義變量

7.1 腳本中直接賦值

[root@chensiqi1 scripts]# cat calculator.sh #!/bin/env 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))"

7.2 命令行傳參

[root@chensiqi1 scripts]# cat calculator.sh #!/bin/env bash a=$1 #不須要把後面的$a,$b都改 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))"

8,條件測試

什麼是條件測試呢?
簡單理解,判斷某些條件是否成立,成立執行一種命令,不成立執行另一種命令。

8.1 條件測試語法

格式:[ <測試表達式> ] 你們要掌握着一種,注意測試表達式兩邊要留空格

8.2 測試表達式

好習慣:先敲一對[],而後退格輸入2個空格[],最後再回退一個空格開始輸入[ -f file ]

[root@chensiqi1 ~]# [ -f /etc/hosts ] && echo 1 || echo 1 [root@chensiqi1 ~]# [ -f /etc/hosts1 ] && echo 1 || echo 0 0 [root@chensiqi1 ~]# [ ! -f /etc/hosts1 ] && echo 1 || echo 0 1 #在作測試判斷時,不必定用上面的方法,用下面的寫一半方法更簡潔 [root@chensiqi1 ~]# [ -f /etc/hosts ] && echo 1 1 [root@chensiqi1 ~]# [ -f /etc/hosts1 ] || echo 0 0 #系統腳本 [root@chensiqi1 ~]# vi /etc/init.d/nfs .... [ -x /usr/sbin/rpc.nfsd ] || exit 5 [ -x /usr/sbin/rpc.mountd ] || exit 5 [ -x /usr/sbin/exportfs ] || exit 5

8.3 經常使用文件測試操做符號

經常使用文件測試操做符號 說明
-f文件,英文file 文件存在且爲普通文件則真,即測試表達式成立
-d文件,英文directory 文件存在且爲目錄文件則真,即測試表達式成立
-s文件,英文size 文件存在且文件大小不爲0則真,即測試表達式成立。
-e文件,英文exist 文件存在則真,即測試表達式成立。只要有文件就行,區別-f
-r文件,英文read 文件存在且可讀則真,即測試表達式成立
-w文件,英文write 文件存在且可寫則真,即測試表達式成立
-x文件,英文executable 文件存在且可執行則真,即測試表達式成立。
-L文件,英文link 文件存在且爲連接文件則真,即測試表達式成立
f1 -nt f2,英文newer than 文件f1比文件f2新則真,即測試表達式成立,根據文件修改時間計算。
f1 -ot f2,英文older than 文件f1比文件f2舊則真,即測試表達式成立,根據文件修改時間計算

8.4 字符串測試操做符

字符串測試操做符的做用:比較兩個字符串是否相同,字符串長度是否爲零,字符串是否爲NULL。Bash區分零長度字符串和空字符串。
|經常使用字符串測試操做符|說明|
|--|--|
|-z "字符串"|若串長度爲0則真,-z理解爲zero|
|-n 「字符串」|若串長度不爲0則真,-n理解爲no zero|
|「串1」=「串2」|若串1等於串2則真,可使用「==」代替「=」|
|「串1」!="串2"|若串1不等於串2則真,但不能使用「!==」代替「!=」|

特別注意,以上表格中的字符串測試操做符號務必要用「」引發來。[ -z "$string"]字符串比較,比較符號兩端最好有空格,參考系統腳本。

[ "$password" = "john" ] 提示: [,"password",=,"join",]之間必須存在空格
[root@chensiqi1 ~]# sed -n '30,31p' /etc/init.d/network # Check that networking is up. [ "${NETWORKING}" = "no" ] && exit 6

8.5 整數二元比較操做符

在[]中使用的比較符 說明
-eq equal等於
-ne not equal不等於
-gt greater than大於
-ge greater equal大於等於
-lt less than小於
-le less equal小於等於

在[]中能夠用>和<,但須要用\轉義,雖然不報錯,但結果不對。但仍是不要混用!

8.6 邏輯操做符

在[]中使用的邏輯操做符 說明
-a 與and,兩端都爲真則真
-o 或or,有一個真就真
非not,相反則爲真

小結:
1)多個[]之間的邏輯操做符是&&或||
2)&&前面成功執行後面
3)||前面不成功執行後面

8.7 其餘

有的時候用[]比if要簡單

[ -f "$file" ] && echo 1 || echo 0 if [ -f "file" ];then echo 1;else echo 0;fi

9,if條件語句

9.1 if單分支條件語句

if [ 條件 ] then 指令 fi 或 if [ 條件 ];then 指令 fi

提示:分號至關於命令換行,上面兩種語法等同

特殊寫法:if [ -f "$file1" ];then echo 1;fi 至關於[-f "$file1" ] && echo 1

9.1.1 輸入2個數字,比較大小

#!/bin/bash #no1 if [ $# -ne 2 ] then echo "USAGE $0 num1 num2" exit 1 fi a=$1 b=$2 if [ $a -lt $b ];then echo "yes,$a less than $b" exit fi if [ $a -eq $b ];then echo "yes,$a equal $b" exit fi if [ $a -gt $b ];then echo "yes,$a greater than $b" exit fi

9.1.2 若是/server2/scripts下面有if3.sh就輸出if3.sh到屏幕,若是沒有自動建立

[root@chensiqi1 scripts]# cat chensiqi.sh #!/bin/bash path=/server2/scripts file=if3.sh if [ ! -d $path ] then mkdir -p $path echo "directory is not exsist!" fi if [ ! -f $path/$file ] then touch $path/$file echo "file is not exsist!" else echo "file is exsist!" fi

9.2 if 雙分支條件語句

if [ 條件 ] then 指令 else 指令 fi
特殊寫法:if [ -f "$file1" ];then echo 1;else echo 0;fi 至關於[ -f "file1" ] && echo 1 ||echo 0

9.2.1 若是/server2/scripts下面有if3.sh就輸出if3.sh到屏幕,若是沒有就自動建立

[root@chensiqi1 scripts]# cat chensiqi.sh #!/bin/bash file=/server2/scripts/if3.sh path=`dirname $file` if [ -f $file ];then cat $file exit 0 else if [ ! -d $path ];then mkdir -p $path echo "$path is not exist,already created it." echo "1234" >> $file fi if [! -f $file ];then echo "1234" >> $file echo "$file is not exist,already created it." fi fi

9.3 多分支if語句

if [ 條件1 ];then 指令1 elif [ 條件2 ];then 指令2 elif [ 條件3 ];then 指令3 elif [ 條件4 ];then 指令4 else 指令n fi

9.3.1 判斷兩個整數大小

[root@chensiqi1 scripts]# cat chensiqi.sh #!/bin/bash if [ $# -ne 2 ];then echo "USAGE $0 num1 num2" exit 1 else num1=`echo $1 | sed 's#[0-9]##g'` num2=`echo $2 | sed 's#[0-9]##g'` fi if [ ${#num1} -eq 0 -a ${#num2} -eq 0 ];then if [ $1 -lt $2 ];then echo "$1 less than $2!" exit elif [ $1 -eq $2 ];then echo "$1 equal $2!" exit else echo "$1 great than $2!" exit fi else echo "num1 num2 must be digit!" fi 

10 case 結構條件句

10.1 case結構條件句語法

case "字符串變量" in 值1) 指令1 ;; 值2) 指令2 ;; *) 指令 esac 注意:case語句至關於一個if的多分支結構語句
值1的選項
apple)
    echo -e "@RED_COLOR apple $RES" ;; 也能夠這樣寫,輸入2種格式找同一個選項 apple|APPLE) echo -e "$RED_COLOR apple $RES" ;;

case 語句小結
1)case語句就至關於多分支的if語句。case語句的優點是更規範,易讀。
2)case語句適合變量的值少,且爲固定的數字或字符串集合。
3)系統服務啓動腳本傳參的判斷多用case語句

10.2 給指定文本加顏色

以傳參爲例,在腳本命令行傳2個參數,給指定內容(第一個參數)加指定顏色(第二個參數)

 
 

11 循環語句(while/for)

11.1 循環語句語法

11.1.1 while條件語句

while 條件 do 指令 done

11.1.2 for循環結構語法

for 變量名 in 變量取值列表 do 指令... done

11.2 while語句

休息命令:sleep 1 休息一秒,usleep 1000000休息1秒單位微妙

11.2.1 守護進程

[root@chensiqi1 scripts]# cat chensiqi.sh #!/bin/bash while true do uptime >> /var/log/uptime.log sleep 2 done #while true 表示條件永遠爲真,所以會一直運行,像死循環同樣。 [root@chensiqi1 scripts]# cat /var/log/uptime.log 23:01:57 up 8:33, 2 users, load average: 0.04, 0.03, 0.05 23:01:59 up 8:33, 2 users, load average: 0.04, 0.03, 0.05 23:02:01 up 8:33, 2 users, load average: 0.04, 0.03, 0.05

11.2.2 從1加到100

[root@chensiqi1 scripts]# cat chensiqi.sh #!/bin/bash i=1 sum=0 while [ $i -lt 100 ] do ((sum=sum+i)) ((i++)) done echo $sum

11.2.3 倒計時

[root@chensiqi1 scripts]# cat chensiqi.sh #!/bin/bash i=10 while [ $i -gt 0 ] do echo $i sleep 1 ((i--)) done

11.3 防止腳本執行中斷的方法

1)sh while01.sh & #放在後臺執行
2)screen 分離 ctrl+a+d 查看screen -ls進入screen -r num
3)nohup while01.sh &

11.4 for循環語句

11.4.1 打印列表元素

[root@chensiqi1 scripts]# cat chensiqi.sh #!/bin/bash for i in 5 4 3 2 1 #用空格隔開 do echo $i done [root@chensiqi1 scripts]# sh chensiqi.sh 5 4 3 2 1 [root@chensiqi1 scripts]# for i in {5..1};do echo $i;done 5 4 3 2 1 [root@chensiqi1 scripts]# echo 10.1.1.{1..10} 10.1.1.1 10.1.1.2 10.1.1.3 10.1.1.4 10.1.1.5 10.1.1.6 10.1.1.7 10.1.1.8 10.1.1.9 10.1.1.10 [root@chensiqi1 scripts]# for i in `seq 5 -1 1`;do echo $i;done 5 4 3 2 1 #循環執行命令n次 [root@chensiqi1 scripts]# for i in `seq 100`;do curl -I baidu.com;done

11.4.2 開機啓動項優化

[root@chensiqi1 scripts]# cat chensiqi.sh #!/bin/bash LANG=en for i in `chkconfig --list|grep "3:on"|awk '{print $1}'` do chkconfig $i off done for name in sshd rsyslog crond network sysstat do chkconfig $name on done 

11.4.3 在/chensiqi目錄批量建立文件

#!/bin/bash Path=/chensiqi [ -d "$Path" ] || mkdir -p $Path for i in `seq 10` do touch $Path/chensiqi_$i.html done

11.4.4 批量更名

[root@chensiqi1 scripts]# cat chensiqi.sh #!/bin/bash $Path=/chensiqi [ -d "$Path" ] || mkdir -p $Path for file in `ls $Path` do mv $file `echo $file|sed -r 's#chensiqi(.*).html#linux\1.HTML#g'` done

11.4.5 批量建立用戶並設置密碼

[root@chensiqi1 scripts]# cat chensiqi.sh #!/bin/bash User=chensiqi Path=/tmp for user in ${User}{01..10} do useradd $user >/dev/null 2>&1 if [ ! $? -eq 0 ];then echo "$user created faile!" echo "scripts begin to rollback!" for i in ${User}{01..10} do userdel -r $i >/dev/null 2>&1 [ $? -eq 0 ] || exit 1 done echo >$Path/user_passwd exit 1 else passWD=`echo $RANDOM|md5sum|cut -c1-8` [ -d $Path ] || mkdir $Path echo $passWD | passwd --stdin $user echo "$user:$passWD">>$Path/user_passwd fi done 

11.4.6 獲取當前目錄下的目錄名作爲變量列表打印輸出

[root@chensiqi1 ~]# cat /server/scripts/chensiqi.sh #!/bin/bash Path=`pwd` echo $Path for filename in `ls` do [ -d ${Path}/${filename} ] && echo $filename done

11.4.7 九九乘法表

[root@chensiqi1 ~]# cat /server/scripts/chensiqi.sh #!/bin/bash for ((i=1;i<10;i++)) do for ((j=1;j<=i;j++)) do echo -n "$i * $j = $((i*j))" echo -n " " done echo " " done [root@chensiqi1 ~]# sh /server/scripts/chensiqi.sh 1 * 1 = 1 2 * 1 = 2 2 * 2 = 4 3 * 1 = 3 3 * 2 = 6 3 * 3 = 9 4 * 1 = 4 4 * 2 = 8 4 * 3 = 12 4 * 4 = 16 5 * 1 = 5 5 * 2 = 10 5 * 3 = 15 5 * 4 = 20 5 * 5 = 25 6 * 1 = 6 6 * 2 = 12 6 * 3 = 18 6 * 4 = 24 6 * 5 = 30 6 * 6 = 36 7 * 1 = 7 7 * 2 = 14 7 * 3 = 21 7 * 4 = 28 7 * 5 = 35 7 * 6 = 42 7 * 7 = 49 8 * 1 = 8 8 * 2 = 16 8 * 3 = 24 8 * 4 = 32 8 * 5 = 40 8 * 6 = 48 8 * 7 = 56 8 * 8 = 64 9 * 1 = 9 9 * 2 = 18 9 * 3 = 27 9 * 4 = 36 9 * 5 = 45 9 * 6 = 54 9 * 7 = 63 9 * 8 = 72 9 * 9 = 81 

11.5 各類語句小結

1)while循環的特長是執行守護進程以及咱們但願循環不退出持續執行,用於頻率小於1分鐘循環處理(crond),其餘的while循環幾乎均可以被for循環替代。
2)case語句能夠被if語句替換,通常在系統啓動腳本傳入少許固定規則字符串用case語句,其餘普通判斷多用if
3)一句話,if,for語句最經常使用,其次while(守護進程),case(服務啓動腳本)

11.6 獲取隨機數的幾種方法。

11.6.1 經過系統環境變量$RANDOM

[root@chensiqi1 ~]# echo $RANDOM 6178 [root@chensiqi1 ~]# echo $RANDOM 30890 [root@chensiqi1 ~]# echo $((RANDOM%9)) #輸出0~9之間隨機數 2 [root@chensiqi1 ~]# echo $((RANDOM%9)) [root@chensiqi1 ~]# echo $((RANDOM%9))$((RANDOM%9)) #輸出00~99 隨機數 64 [root@chensiqi1 ~]# echo $((RANDOM%9))$((RANDOM%9)) #輸出00~99歲?隨機數 10 [root@chensiqi1 ~]# echo $((RANDOM%9))$((RANDOM%9)) #輸出00~99歲?隨機數 51 [root@chensiqi1 ~]# echo $RANDOM|md5sum #隨機數長短不一,能夠用md5sum命令統一格式化 599e328a94329684ce5c92b850d32f26 -

11.6.2 經過openssl產生

[root@chensiqi1 ~]# openssl rand -base64 8 aND8WMRM6vQ= [root@chensiqi1 ~]# openssl rand -base64 8 RsRdRq/9vi4= [root@chensiqi1 ~]# openssl rand -base64 8|md5sum b1108cafbc2291392e41d2c914360138 - [root@chensiqi1 ~]# openssl rand -base64 10 1frkA2kIJODxqQ==

11.6.3 經過時間得到隨機數

[root@chensiqi1 ~]# echo $(date +%N) 361599138 [root@chensiqi1 ~]# echo $(date +%N) 199271856 [root@chensiqi1 ~]# echo $(date +%t%N) 950526316 [root@chensiqi1 ~]# echo $(date +%t%N) 340140329

11.6.4 urandom

[root@chensiqi1 ~]# head /dev/urandom | cksum 621330951 2535 [root@chensiqi1 ~]# head /dev/urandom | cksum 404398617 2470

11.6.5 UUID

[root@chensiqi1 ~]# cat /proc/sys/kernel/random/uuid 8a6c5bbe-2d42-44ac-9ef1-3e7683a613e3 [root@chensiqi1 ~]# cat /proc/sys/kernel/random/uuid c828c209-5b5f-4bc7-917c-678ed4215988 [root@chensiqi1 ~]# uuidgen 961dc354-81b2-4564-9b85-6095ed4bc7b5

11.7 break continue exit return

11.7.1 break continue exit 對比

break continue exit用於循環結構中控制虛幻(for,while,if)的走向

命令 說明
break n n表示跳出循環的層數,若是省略n表示跳出整個循環
continue n n表示退出到第n層繼續循環,若是省略n表示跳過本次循環,忽略本次循環剩餘代碼,進入循環的下一次循環
exit n 退出當前shell程序,n爲返回值,n也能夠省略,在下一個shell裏經過$?接收這個n值
return n 用在函數裏,作爲函數的返回值,用於判斷函數執行是否正確。和exit同樣,若是函數裏有循環,也會直接退出循環,退出函數

11.7.2 break

[root@chensiqi1 ~]# cat /server/scripts/chensiqi.sh #!/bin/bash for ((i=0;i<=5;i++)) do [ $i -eq 3 ] && break echo $i done echo "ok" [root@chensiqi1 ~]# sh /server/scripts/chensiqi.sh 0 1 2 ok

11.7.3 continue

[root@chensiqi1 ~]# cat /server/scripts/chensiqi.sh #!/bin/bash for ((i=0;i<=5;i++)) do [ $i -eq 3 ] && continue echo $i done echo "ok" [root@chensiqi1 ~]# sh /server/scripts/chensiqi.sh 0 1 2 4 5 ok

11.7.4 exit

[root@chensiqi1 ~]# cat /server/scripts/chensiqi.sh #!/bin/bash for ((i=0;i<=5;i++)) do [ $i -eq 3 ] && exit 2 echo $i done echo "ok" [root@chensiqi1 ~]# sh /server/scripts/chensiqi.sh 0 1 2 [root@chensiqi1 ~]# echo $? 2

11.7.5 return

[root@chensiqi1 ~]# cat /server/scripts/chensiqi.sh #!/bin/bash function xxxx { for ((i=0;i<=5;i++)) do [ $i -eq 3 ] && return 7 echo $i done echo "ok" } xxxx echo $? [root@chensiqi1 ~]# sh /server/scripts/chensiqi.sh 0 1 2 7

12,shell腳本的調試

  1. 使用dos2unix處理腳本

從windows編輯的腳本到Linux下須要使用這個命令
dos2unix windows.sh

  1. 使用echo命令調試

在變量讀取或修改的先後假如echo $變量,也可在後面使用exit退出腳本,這樣能夠不用註釋後邊代碼

  1. 利用bash的參數調試

sh [-nvx]
-n:不會執行該腳本,僅查詢腳本語法是否有問題,並給出錯誤提示。可用於生產服務器那些只能執行一次不可逆的腳本。
-v:在執行腳本時,先將腳本的內容輸出到屏幕上而後執行腳本,若是有錯誤,也會給出錯誤提示。(通常不用)
-x:將執行的腳本內容及輸出顯示到屏幕上,經常使用

shell腳本調試技巧小結:
1)要記得首先用dos2unix對腳本格式化
2)直接執行腳本根據報錯來調試,有時報錯不許確。
3)sh -x調試整個腳本,顯示執行過程。
4)set -x和set +x調試部分腳本(在腳本中設置)
5)echo輸出變量及相關內容,而後緊跟着exit退出,不執行後面程序的方式,一步步跟蹤腳本,對於邏輯錯誤比較好用。
6)最關鍵的時語法熟練,編碼習慣,編程思想,將錯誤扼殺在萌芽中,減輕調試負擔,提升效率。

金牌IT職業再教育培訓機構,歡迎來校資源。QQ:215379068
相關文章
相關標籤/搜索