Linux shell腳本數值計算與條件執行

變量的數值計算實踐

1 算術運算符

如果要執行算術運算,就會離不開各種運算符號,和其他編程語言類似,Shell 也有很多算術運算符。

下面就給大家介紹一下常見的 Shell 算術運算符:

  • +、-一元正號和負號。
  • +、-,加法和減法。
  • *、/、%,乘法、除法、取余(取模)。
  • **,冪運算。
  • ++、–,增加及減少,可前置也可放在變量結尾。
  • !、&&、||,邏輯非(取反)、邏輯與(and)、邏輯或(or)。
  • <、<=、>、>=,比較符號(小于、小于等于、大于、大于等于)。
  • ==、!=、=,比較符號(相等、不相等,對于字符串也可以表示相當于)。
  • <<、>>,向左移位、向右移位。
  • ~、|、&、^,按位取反、按位異或、按位與、按位。
  • =、+=、-=、*=、/=、%=,賦值運算符,例如 a+=1 相當于 a=a+1a-=1 相當于 a=a-1

Shell 中常見的算術運算命令:

  • (()),用于整數運算的常用運算符,效率很高。
  • let,用于整數運算,類似于(())
  • expr,可用于整數運算,但還有很多其他的額外功能。
  • bc,Linux下的一個計算器程序(適合整數及小數運算)。
  • $[],用于整數運算。
  • awk,awk 既可以用于整數運算,也可以用于小數運算。
  • declare,定義變量值和屬性,-i參數可以用于定義整形變量,做運算。

2 (()) 雙小括號數值運算命令

雙小括號 (()) 的作用是進行數值運算與數值比較,它的效率很高,用法靈活,是企業場景運維人員經常采用的運算操作符。

2.1 (()) 雙小括號數值運算的基礎語法

雙小括號 (()) 的操作方法:

  • ((i=i+1)),此種書寫方法為運算后賦值法,即將i+1的運算結果賦值給變量i。

    注意:不能用 echo ((i=i+l))輸出表達式的值,可以用echo $((i=i+l))輸出其值。

  • **i=((i+1))??,可以在‘(())‘前加‘((i+1))**,可以在 `(())` 前加 `((i+1))??,可以在(())前加` 符,表示將表達式運算后賦值給i。

  • (( 8>7 && 5==5)),可以進行比較操作,還可以加入邏輯與和邏輯或,用于條件判斷。

  • **echo ((2+1))??,需要直接輸出運算表達式的運算結果時,可以在‘(())‘前加‘((2+1))**,需要直接輸出運算表達式的運算結果時,可以在 `(())` 前加 `((2+1))??,需要直接輸出運算表達式的運算結果時,可以在(())前加` 符。

2.2 (()) 雙小括號數運算實踐

**示例1:**簡單的數值計算。

[wsh@test ~ ?]$ echo $((1+1))
2
[wsh@test ~ ?]$ echo $((6*3))
18
[wsh@test ~ ?]$ ((i=5))
[wsh@test ~ ?]$ ((i=i*2))
[wsh@test ~ ?]$ echo $i
10

**示例2:**復雜的數值計算。

[wsh@test ~ ?]$ ((a=1+2**3-4%3))
[wsh@test ~ ?]$ echo $a
8[wsh@test ~ ?]$ b=$((a=1+2**3-4%3))
[wsh@test ~ ?]$ echo $b
8
[wsh@test ~ ?]$ echo $((a=1+2**3-4%3))
8[wsh@test ~ ?]$ a=$((100*(100+1)/2))
[wsh@test ~ ?]$ echo $a
5050
[wsh@test ~ ?]$ echo $((100*(100+1)/2))
5050

**示例3:**特殊運算符號

[wsh@test ~ ?]$ a=8;echo $((a+=1))
9
[wsh@test ~ ?]$ echo $((a**2))
81

**示例4:**比較和判斷

[wsh@test ~ ?]$ ((3<8))
[wsh@test ~ ?]$ echo $?
0
[wsh@test ~ ?]$ echo $((3<8))
1[wsh@test ~ ?]$ ((3>8))
[wsh@test ~ ?]$ echo $?
1
[wsh@test ~ ?]$ echo $((3>8))
0[wsh@test ~ ?]$ echo $((3==3))
1[wsh@test ~ ?]$ if ((8>7 && 5==5));then echo yes;fi
yes

**示例5:**變量前后使用–和++特殊運算符的表達式

[wsh@test ~ ?]$ a=10
[wsh@test ~ ?]$ echo $((a++))
10
[wsh@test ~ ?]$ echo $a
11[wsh@test ~ ?]$ echo $((--a))
10
[wsh@test ~ ?]$ echo $a
10

總結:

  • 執行 echo $((a++))echo $((a--)) 命令輸出整個表達式時,輸出的值即為 a 的值,表達式執行完畢后,會對a進行++--的運算
  • 執行 echo $((++a))echo $((--a)) 命令輸出整個表達式時,會先對a進行++--的運算,然后再輸出表達式的值,即為a運算后的值。

**示例6:**通過 (())運算后賦值給變量

[wsh@test ~ ?]$ num=99
[wsh@test ~ ?]$ echo $((num+1))
100
[wsh@test ~ ?]$ num=$((num+1))
[wsh@test ~ ?]$ echo $num
100

3 let 命令

let運算命令的語法格式為:let 表達式

let表達式的功能等同于:((表達式))

示例:

[wsh@test ~ ?]$ i=2
[wsh@test ~ ?]$ i=i+8
[wsh@test ~ ?]$ echo $i
i+8[wsh@test ~ ?]$ i=2
[wsh@test ~ ?]$ let i=i+8
[wsh@test ~ ?]$ echo $i
10

4 expr 命令

expr(evaluate(求值)expressions(表達式))命令既可以用于整數運算,也可以用于相關字符串長度、匹配等的運算處理。

4.1 expr 命令的基本用法示例
[wsh@test ~ ?]$ expr 2+2
2+2
[wsh@test ~ ?]$ expr 2 + 2
4[wsh@test ~ ?]$ expr 2 * 2
expr: syntax error
[wsh@test ~ ?]$ expr 2 \* 2
4

在使用 expr 時:

  • 運算符及用于計算的數字左右都至少有一個空格,否則會報錯。
  • 使用乘號時,必須用反斜線屏蔽其特定含義,因為 Shell 可能會誤解星號的含義。
4.2 expr 的企業級實戰案例詳解

**示例1:**判斷一個變量值是否為整數

在 Shell 編程里,由于函數庫很少,所以判斷字符串是否為整數就不是一件很容易的事情。在這里,我們為讀者介紹一種簡單的可以判斷一個字符串是否為整數的方法。

實現原理是,利用以 expr 做計算時變量或字符串必須是整數的規則,把一個變量或字符串和一個已知的整數(非0)相加,看命令返回的值是否為 0。如果為 0,就認為做加法的變量或字符串為整數,否則就不是整數。

[wsh@test ~ ?]$ i=5
[wsh@test ~ ?]$ expr $i + 5
10
[wsh@test ~ ?]$ echo $?
0[wsh@test ~ ?]$ i=a
[wsh@test ~ ?]$ expr $i + 5
expr: non-integer argument
[wsh@test ~ ?]$ echo $?
2

此外,用 expr match 功能進行整數判斷時,可執行 man expr 命令獲得幫助。

# 變量值為非整數,返回值為0
[wsh@test ~ ?]$ i=a
[wsh@test ~ ?]$ expr match "$i" "^[1-9][0-9]*$"
0# 變量值為整數,返回值為1
[wsh@test ~ ?]$ i=5
[wsh@test ~ ?]$ expr match "$i" "^[0-9][0-9]*$"
1

**示例2:**判斷文件擴展命名是否符合要求

[wsh@test ~ ?]$ file=stu-202212.jpg# 匹配擴展名,返回值為0,忽略輸出結果
[wsh@test ~ ?]$ expr "$file" : ".*\.jpg$"
14
[wsh@test ~ ?]$ echo $?
0# 未匹配擴展名,返回值為1,忽略輸出結果
[wsh@test ~ ?]$ expr "$file" : ".*\.pub$"
0
[wsh@test ~ ?]$ echo $?
1

**示例3:**計算字符串的長度

[wsh@test ~ ?]$ str="abc123abc123"
[wsh@test ~ ?]$ expr length "$str"
12

**示例4:**打印下面語句中字符數不大于6 的單詞

#!/bin/bash
strings="This is Linux World  Welcome to our classroom"
for word in $strings
doif [ $(expr length "$word") -le 6 ];thenecho $wordfi
done

執行結果如下:

[wsh@test ~ ?]$ bash str.sh
This
is
Linux
World
to
our

5 bc 命令

bc 是UNIX/Linux下的計算器,因此,除了可以作為計算器來使用,還可以作為命令行計算工具使用。

示例:

[wsh@test ~ ?]$ bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
1+3*4-6/3^3%4
13
scale=4
1/3
.3333
quit[wsh@test ~ ?]$ echo '1+3*4-6/3^3%4' | bc
13
[wsh@test ~ ?]$ echo 'scale=4;1/3' | bc
.3333

6 awk 命令實現計算

利用awk進行運算的效果也很好,適合小數和整數,特別是命令行計算,尤其是小數,運算很精確,好用。

[wsh@test ~ ?]$ echo 7.7 3.8 | awk '{ print $1-$2 }'
3.9
[wsh@test ~ ?]$ echo 358 113 | awk '{ print ($1-3)/$2 }'
3.14159

7 $[] 符號的運算

示例1:

[wsh@test ~ ?]$ echo $[1+1]
2
[wsh@test ~ ?]$ echo $[4-2]
2
[wsh@test ~ ?]$ echo $[2*2]
4
[wsh@test ~ ?]$ echo $[4/2]
2
[wsh@test ~ ?]$ echo $[5/2]
2
[wsh@test ~ ?]$ echo $[5%2]
1
[wsh@test ~ ?]$ count=3;echo $[(count+1)*3]
12
[wsh@test ~ ?]$ count=3;echo $[ ++count + 3 ]
7
[wsh@test ~ ?]$ count=3;echo $[ count++ + 3 ]
6
[wsh@test ~ ?]$ count=3;echo $[ --count + 3 ]
5
[wsh@test ~ ?]$ count=3;echo $[ count-- + 3 ]
6

**示例2:**通過一條命令計算輸出 1+2+3+...+10 的表達式,并計算出結果,請使用bc命令計算。輸出內容如1+2+3+4+5+6+7+8+9+10=55

[wsh@test ~ ?]$ echo $(seq -s + 10) | bc[wsh@test ~ ?]$ echo $(( $(echo {1..10} | tr ' ' '+' ) ))[wsh@test ~ ?]$ echo $[ $(echo {1..10} | tr ' ' '+' ) ]

Shell 腳本的條件測試

1 Shell 腳本的條件測試

1.1 條件測試方法綜述

通常,在 bash 的各種條件結構和流程控制結構中都要進行各種測試,然后根據測試結果執行不同的操作,有時也會與if等條件語句相結合,來完成測試判斷,以減少程序運行的錯誤。

執行條件判斷表達式后通常會返回"真"或"假",就像執行命令后的返回值為0,表示真;非0,表示假。

在 bash 編程里,條件測試常用的語法如下:

  • 語法1:test <判斷表達式>,test命令和"<判斷表達式>"之間至少有一個空格。
  • 語法2:[ <判斷表達式> ],和test命令的用法相同,這是推薦方法。[]的邊界和內容之間至少有一個空格。
  • 語法3:[[ <判斷表達式> ]],是比test和[]更新的語法格式。[[]]的邊界和內容之間至少有一個空格。
  • 語法4:(( <判斷表達式> )),一般用于 if 語句。(())(雙小括號)兩端不需要有空格。
  • 語法5:comand,命令的返回值確定表達式的真值或假值。

有幾個注意事項需要說明一下:

  • 語法1中的test命令語法2中的[]是等價的,語法3中的[[]]為擴展的test命令,語法4中的(())常用于計算。建議使用相對友好的語法2,即中括號[]的語法格式。
  • [[ ]](雙中括號)中可以使用通配符等進行模式匹配,這是其區別于其他幾種語法格式的地方。
  • &&、||、>、<等操作符可以應用于[[]]中,但不能應用于[]中,在[]中一般用-a、-o、-gt(用于整數)、-lt(用于整數)代替上述操作符。
  • 對于整數的關系運算,也可以使用 Shell 的算術運算符(())
1.2 test 條件測試的簡單語法及示例

test條件測試的語法格式為: test <判斷表達式>

[wsh@test ~ ?]$ help test
test: test [expr]Evaluate conditional expression.Exits with a status of 0 (true) or 1 (false) depending onthe evaluation of EXPR.  Expressions may be unary or binary.  Unaryexpressions are often used to examine the status of a file.  Thereare string operators and numeric comparison operators as well.The behavior of test depends on the number of arguments.  Read thebash manual page for the complete specification.File operators:-a FILE        True if file exists.-b FILE        True if file is block special.-c FILE        True if file is character special.-d FILE        True if file is a directory.-e FILE        True if file exists.-f FILE        True if file exists and is a regular file.-g FILE        True if file is set-group-id.-h FILE        True if file is a symbolic link.-L FILE        True if file is a symbolic link.-k FILE        True if file has its `sticky' bit set.-p FILE        True if file is a named pipe.-r FILE        True if file is readable by you.-s FILE        True if file exists and is not empty.-S FILE        True if file is a socket.-t FD          True if FD is opened on a terminal.-u FILE        True if the file is set-user-id.-w FILE        True if the file is writable by you.-x FILE        True if the file is executable by you.-O FILE        True if the file is effectively owned by you.-G FILE        True if the file is effectively owned by your group.-N FILE        True if the file has been modified since it was last read.FILE1 -nt FILE2  True if file1 is newer than file2 (according tomodification date).FILE1 -ot FILE2  True if file1 is older than file2.FILE1 -ef FILE2  True if file1 is a hard link to file2.String operators:-z STRING      True if string is empty.-n STRINGSTRING      True if string is not empty.STRING1 = STRING2True if the strings are equal.STRING1 != STRING2True if the strings are not equal.STRING1 < STRING2True if STRING1 sorts before STRING2 lexicographically.STRING1 > STRING2True if STRING1 sorts after STRING2 lexicographically.Other operators:-o OPTION      True if the shell option OPTION is enabled.-v VAR	 True if the shell variable VAR is set! EXPR         True if expr is false.EXPR1 -a EXPR2 True if both expr1 AND expr2 are true.EXPR1 -o EXPR2 True if either expr1 OR expr2 is true.arg1 OP arg2   Arithmetic tests.  OP is one of -eq, -ne,-lt, -le, -gt, or -ge.Arithmetic binary operators return true if ARG1 is equal, not-equal,less-than, less-than-or-equal, greater-than, or greater-than-or-equalthan ARG2.Exit Status:Returns success if EXPR evaluates to true; fails if EXPR evaluates tofalse or an invalid argument is given.

**示例1:**判斷文件是否存在

[wsh@test ~ ?]$ test -f file && echo true || echo false  

該語句表示如果file文件存在,則輸出true,否則輸出false。這里的&&是邏輯與,||是邏輯或。test的-f參數用于測試文件是否為普通文件,test命令若執行成功(為真),則執行&&后面的命令,而||后面的命令是test命令執行失敗之后(為假)所執行的命令。

test命令判斷表達式的邏輯也可以用上述表達形式的一半邏輯(即僅有一個&&或||)來測試,示例如下。

[wsh@test ~ ?]$ test -f file && echo true
[wsh@test ~ ?]$ test -f file || echo false

另外,邏輯操作符&&||的兩端既可以有空格,也可以無空格。帶空格看起來會更美觀一些,建議使用帶空格的格式。

示例2:-z 選項判斷變量值是否為空,如果為空,則為真值,反之為假值。

[wsh@test ~ ?]$ unset string
[wsh@test ~ ?]$ test -z "$string" && echo null string || echo $string
null string[wsh@test ~ ?]$ string="hello world"
[wsh@test ~ ?]$ test -z "$string" && echo null string || echo $string
hello world

結論:test命令測試的功能很強大,但是和[][[]]的功能有所重合,因此,在實際工作中選擇一種適合自己的語法就好了。對于其他的語法,能讀懂別人寫的腳本就可以了。

1.3 [](中括號)條件測試語法及示例

[]條件測試的語法格式為:[ < 判斷表達式> ]

注意:中括號內部的兩端要有空格,[]和test等價,即test的所有判斷選項都可以直接在[]里使用。

**示例1:**判斷文件是否存在

[wsh@test ~ ?]$ [ -f file ] && echo true || echo false  

該語句表示如果file文件存在,則輸出true,否則輸出false。這里的&&是邏輯與,||是邏輯或。test的-f參數用于測試文件是否為普通文件,test命令若執行成功(為真),則執行&&后面的命令,而||后面的命令是test命令執行失敗之后(為假)所執行的命令。

[]條件判斷表達式的邏輯也可以用上述表達形式的一半邏輯(即僅有一個&&或||)來測試,示例如下。

[wsh@test ~ ?]$ [ -f file ] && echo true
[wsh@test ~ ?]$ [ -f file ] || echo false

邏輯操作符 &&|| 的兩端既可以有空格,也可以無空格。帶空格看起來會更美觀一些,建議使用帶空格的格式。

1.4 [[]](雙中括號)條件測試語法及示例

[[]]條件測試的語法格式為: [[ < 判斷表達式> ]]

注意:雙中括號里的兩端也要有空格。

**示例1:**判斷文件是否存在

[wsh@test ~ ?]$ [[ -f file ]] && echo true || echo false  

該語句表示如果file文件存在,則輸出true,否則輸出false。這里的&&是邏輯與,||是邏輯或。test的-f參數用于測試文件是否為普通文件,test命令若執行成功(為真),則執行&&后面的命令,而||后面的命令是test命令執行失敗之后(為假)所執行的命令。

[]條件判斷表達式的邏輯也可以用上述表達形式的一半邏輯(即僅有一個&&或||)來測試,示例如下。

[wsh@test ~ ?]$ [[ -f file ]] && echo true
[wsh@test ~ ?]$ [[ -f file ]] || echo false

邏輯操作符 &&|| 的兩端既可以有空格,也可以無空格。帶空格看起來會更美觀一些,建議使用帶空格的格式。

2 文件判斷表達式

2.1 文件判斷表達式的用法

文件測試常用選項:

  • -d 文件,d的全拼為directory文件存在且為目錄則為真,即判斷表達式成立。
  • -f 文件,f的全拼為file文件存在且為普通文件則為真,即判斷表達式成立。
  • -e 文件,e的全拼為exist文件存在則為真,即判斷表達式成立。區別于"-f",-e不辨別是目錄還是文件。
  • -r 文件,r的全拼為read文件存在且可讀則為真,即判斷表達式成立。
  • -s 文件,s的全拼為size文件存在且文件size不為0則為真,即判斷表達式成立。
  • -w 文件,w的全拼為write文件存在且可寫則為真,即判斷表達式成立。
  • -x 文件,x的全拼為executable文件存在且可執行則為真,即判斷表達式成立。
  • -L 文件,L的全拼為link文件存在且為鏈接文件則為真,即判斷表達式成立。
  • f1 -nt f2,nt的全拼為newer than,文件fl比文件f2新則為真,即判斷表達式成立。根據文件的修改時間來計算。
  • f1 -ot f2,ot的全拼為older than,文件fl比文件f2舊則為真,即判斷表達式成立。根據文件的修改時間來計算。
2.2 文件判斷表達式舉例
[wsh@test ~ ?]$ data_path=/tmp/wsh
[wsh@test ~ ?]$ mkdir ${data_path}
[wsh@test ~ ?]$ [ -d ${data_path} ] && echo ${data_path} is exist
${data_path} is exist[wsh@test ~ ?]$ rmdir ${data_path}
[wsh@test ~ ?]$ [ -d ${data_path} ] || echo ${data_path} is not exist
/tmp/wsh is not exist[wsh@test ~ ?]$ [ -r /etc/shadow ] && cat /etc/shadow || echo hello
hello[wsh@test ~ ?]$ [ -w ~/.bashrc ] && echo "alias pa='ps axu'" >> ~/.bashrc
[wsh@test ~ ?]$ tail -1 ~/.bashrc
alias pa='ps axu'
2.3 特殊條件判斷表達式案例

以下寫法適用于所有的條件判斷表達式,是工作中比較常用的替代if語句的方法。判斷條件判斷表達式的條件成立或不成立后,還需要繼續執行多條命令語句的語法。

例如,當條件1成立時,同時執行命令1、命令2、命令3。

# 格式1
[ 條件1 ] && {
命令1
命令2
命令3
}# 格式2
[[ 條件1 ]] && {
命令1
命令2
命令3
}# 格式3
test 條件1 && {
命令1
命令2
命令3
}

示例:

[wsh@test ~ ?]$ [ -w ~/.bashrc ] && {
echo "alias sa='ssh root@servera'" >> ~/.bashrc
echo "alias sb='ssh root@serverb'" >> ~/.bashrc
echo "alias sc='ssh root@serverc'" >> ~/.bashrc
}[wsh@test ~ ?]$ tail -3 ~/.bashrc
alias sa='ssh root@servera'
alias sb='ssh root@serverb'
alias sc='ssh root@serverc'# 一行寫法
[wsh@test ~ ?]$ [ -r /etc/passwd ] && { echo ha; echo ha; echo ha; }
ha
ha
ha

3 字符串判斷表達式

3.1 字符串測試操作符

字符串測試操作符的作用包括:比較兩個字符串是否相同、測試字符串的長度是否為零、字符串是否為NULL等。

常用字符串測試操作符:

  • -n “字符串”,若字符串的長度不為0,則為真,即判斷表達式成立,n可以理解為no zero。
  • -z “字符串”,若字符串的長度為0,則為真,即判斷表達式成立,z可以理解為zero的縮寫。
  • “串1” = “串2”,若字符串1等于字符串2,則為真,即判斷表達式成立,可使用"==“代替”="。
  • “串1” != “串2”,若字符串1不等于字符串2,則為真,即判斷表達式成立,但不能用"!==“代替”!="。

以下是針對字符串測試操作符的提示:

  • 對于字符串的測試,一定要將字符串加雙引號之后再進行比較,如 [ -n "$myvar" ],特別是使用[] 的場景。
  • 比較符號(例如=和!=)的兩端一定要有空格。

示例1:-z 選項,判斷變量值是否為空,如果為空,則為真值,反之為假值。

[wsh@test ~ ?]$ unset string
[wsh@test ~ ?]$ [ -z "$string" ] && echo null string || echo $string
null string[wsh@test ~ ?]$ string="hello world"
[wsh@test ~ ?]$ [ -z "$string" ] && echo null string || echo $string
hello world

示例2:-n 選項,判斷變量值是否為非空,如果為非空,則為真值,反之為假值。

[wsh@test ~ ?]$ unset string
[wsh@test ~ ?]$ [ -n "$string" ] && echo $string || echo null string
null string[wsh@test ~ ?]$ string="hello world"
[wsh@test ~ ?]$ [ -n "$string" ] && echo $string || echo null string
hello world

**示例3:**判斷是否相對

[wsh@test ~ ?]$ [ "$string" = "hi" ] && echo hi
hi
[wsh@test ~ ?]$ [ "$string" = "ha" ] && echo ha[wsh@test ~ ?]$ [ "$string" != "hi" ] && echo no hi
[wsh@test ~ ?]$ [ "$string" != "ha" ] && echo ha
ha
3.2 字符串測試生產案例

示例: /etc/init.d/network 部分內容

[wsh@test ~ ?]$ sed -n '30,31p' /etc/init.d/network
# Check that networking is up.
[ "${NETWORKING}" = "no" ] && exit 6
3.3 [[]]中=~操作符

語法:[[ "$str" =~ pattern ]]

**作用:**使用 =~ 操作符時,其右邊的字符串被認為是一個擴展正則表達式。擴展之后跟左邊字符串進行比較,看左邊字符串是否包含右邊模式,也就是判斷右邊的模式是否為左邊字符串的子字符串,而不是判斷右邊的模式是否完全等于左邊字符串。

=~ 操作符右邊的字符串不能使用引號括起來,無論是雙引號、還是單引號,否則表示匹配這個字符串自身的內容,不再解析成正則表達式。

示例:

# 判斷變量值是否包涵數字
[wsh@test ~ ?]$ str=123abc
[wsh@test ~ ?]$ [[ "$str" =~ [0-9]+ ]] && echo str is a string with num || echo str is a string without any num
str is a string with num
[wsh@test ~ ?]$ str=abcdef
[wsh@test ~ ?]$ [[ "$str" =~ [0-9]+ ]] && echo str is a string with num || echo str is a string without any num
str is a string without any num# 判斷變量值是否只包涵數字
[wsh@test ~ ?]$ str=123;[[ "$str" =~ ^[0-9]+$ ]] && echo str is a num || echo str is not a num
str is a num# 加引號對比
[wsh@test ~ ?]$ str=123;[[ "$str" =~ [0-9]+ ]] && echo true || echo false 
true
[wsh@test ~ ?]$ str=123;[[ "$str" =~ "[0-9]+" ]] && echo true||echo false 
false

4 整數二元比較操作符

4.1 整數二元比較操作符介紹

整數二元比較操作符使用說明如下:

[]和test中比較符號(())和[[]]中比較符號說明
-eq==或=相等,全拼為 equal
-ne!=不相等,全拼為 not equal
-gt>大于,全拼為 greater than
-ge>=大于等于,全拼為 greater equal
-It<小于,全拼為less than
-le<=小于等于,全拼為 less equal

以下是針對上述符號的特別說明:

  • =!= 也可在[]中做比較使用,但在[]中使用包含 >< 的符號時,需要用反斜線轉義,有時不轉義雖然語法不會報錯,但是結果可能會不對。
  • 也可以在[[]]中使用包含-gt-lt 的符號,但是不建議這樣使用。
  • 比較符號兩端也要有空格。

示例1:

[wsh@test ~ ?]$ [ 2 -lt 3 ] && echo true || echo false
true
[wsh@test ~ ?]$ [ 2 -gt 3 ] && echo true || echo false
false
[wsh@test ~ ?]$ [ 2 -le 3 ] && echo true || echo false
true
[wsh@test ~ ?]$ [ 4 -ge 3 ] && echo true || echo false
true

示例2: 錯誤的示例

[wsh@test ~ ?]$ [ 2 > 1 ] && echo true
true# 事實是2<3
[wsh@test ~ ?]$ [ 2 > 3 ] && echo true
true# 轉義>符號
[wsh@test ~ ?]$ [ 2 \> 3 ] && echo true || echo false
false

[]、[[]]、(())用法的小結:

  • 整數加雙引號的比較是對的。
  • [[]]中用類似-eq等的寫法是對的,[[]]中用類似>、<的寫法也可能不對,有可能會只比較第一位,邏輯結果不對。
  • []中用類似>、<的寫法在語法上雖然可能沒錯,但邏輯結果不對,可以使用=、!=正確比較。
  • (())中不能使用類似-eq等的寫法,可以使用類似>、<的寫法。
4.2 整數變量測試實踐示例

示例1:

[wsh@test ~ ?]$ a=98;b=99
[wsh@test ~ ?]$ [ $a -eq $b ] && echo true || echo false
false
[wsh@test ~ ?]$ [ $a -ne $b ] && echo true || echo false
true[wsh@test ~ ?]$ [ $a -gt $b ] && echo true || echo false
false
[wsh@test ~ ?]$ [ $a -lt $b ] && echo true || echo false
true

示例2:

[wsh@test ~ ?]$ a=98;b=99
[wsh@test ~ ?]$ [[ $a = $b ]] && echo true || echo false
false
[wsh@test ~ ?]$ [[ $a != $b ]] && echo true || echo false
true[wsh@test ~ ?]$ (( $a >= $b )) && echo true || echo false
false
[wsh@test ~ ?]$ (( $a <= $b )) && echo true || echo false
true

5 邏輯操作符

5.1 邏輯操作符介紹

表達式中邏輯操作符使用說明如下:

[]和test中邏輯操作符[[]]和(())中邏輯操作符說明
-a&&and,與,兩端都為真,則結果為真
-oIIor,或 ,兩端有一個為真,則結果為真
!!not,非,兩端相反,則結果為真

對于上述操作符,有如下提示:

  • 邏輯操作符前后的表達式是否成立,一般用真假來表示。
  • "!"的中文意思是反,即與一個邏輯值相反的邏輯值。
  • -a的中文意思是“與”(and或&&),前后兩個邏輯值都為“真”,綜合返回值才為“真”,反之為“假”。
  • -o的中文意思是“或”(or或||),前后兩個邏輯值只要有一個為“真”,返回值就為“真”。

表達式外:&&或||可用于連接兩個含[]、test或[[]]的表達式:

  • 使用&&表達式時:

    • 當左邊為真,右邊表達式才會執行。

    • 當左邊為假,右邊表達式不會執行。

  • 使用||的表達式時:

    • 當左邊為真,右邊表達式不會執行。

    • 當左邊為假,右邊表達式才會執行。

5.2 邏輯操作符實踐示例
# 判斷表達式內部:邏輯與
[wsh@test ~ ?]$ file=/etc/passwd
[wsh@test ~ ?]$ [ -f $file -a -r $file ] && head -1 $file
root:x:0:0:root:/root:/bin/bash[wsh@test ~ ?]$ [[ -f $file && -r $file ]] && head -1 $file
root:x:0:0:root:/root:/bin/bash# 判斷表達式內部:邏輯或
[wsh@test ~ ?]$ num=10
[wsh@test ~ ?]$ [ $num -lt 20 -o $num -gt 1 ] && echo $num is between 1 and 20. 
10 is between 1 and 20.[wsh@test ~ ?]$ [[ $num -lt 20 || $num -gt 1 ]] && echo $num is between 1 and 20. 
is between 1 and 20.# 判斷表達式內部:邏輯非
[wsh@test ~ ?]$ [ ! 6 -eq 5 ] && echo 6!=5
6!=5
[wsh@test ~ ?]$ [[ ! 6 -eq 5 ]] && echo 6!=5
6!=5
5.3 邏輯操作符企業案例
[wsh@test ~ ?]$ data_path=/tmp/wsh
[wsh@test ~ ?]$ mkdir ${data_path}
[wsh@test ~ ?]$ [ -d ${data_path} ] && echo ${data_path} is exist
/tmp/wsh is exist[wsh@test ~ ?]$ rmdir ${data_path}
[wsh@test ~ ?]$ [ -d ${data_path} ] && echo ${data_path} is not exist
[wsh@test ~ ?]$ [ -d ${data_path} ] || mkdir ${data_path}
[wsh@test ~ ?]$ ls -d ${data_path}
/tmp/wsh

6 判斷表達式 test、[]、[[]]、(())的區別總結

判斷表達式符號[]test[[]](())
邊界是否需要空格需要需要需要不需要
邏輯操作符!、-a、-o!、 -a、 -o!、&&、||!、&&、||
整數比較操作符-eq、-ne、-gt、-ge、-lt、-le-eq、-ne、-gt、-ge、-lt、-le-eq、-ne、-gt、-ge、-lt、-le=、!=、>、>=、<、<=
字符串比較操作符=、== 、!==、== 、!==、== 、!=== 、!=
是否支持通配符匹配不支持不支持支持(=~)不支持

if 條件語句的知識與實踐

1 if 條件語句

if條件語句是Linux運維人員在實際生產工作中使用得最頻繁也是最重要的語句,因此,請務必重視if條件語句的知識,并牢固掌握。

1.1 if 條件語句的語法

if條件語句,其語義類似于漢語里的“如果…那么”。

1. 單分支結構

第一種語法:

if <條件表達式>then 指令
fi

第二種語法:

if <條件表達式>;then指令
fi

上文的“<條件表達式>”部分可以是test、口、[[]]、(())等條件表達式,甚至可以直接使用命令作為條件表達式。每個if條件語句都以if開頭,并帶有then,最后以fi結尾。

第二種語法中的分號相當于命令換行,上面的兩種語法含義是相同的,讀者可根據習慣自行選擇。

本書主要使用第二種語法格式。

在所有編程語言里,if條件語句幾乎是最簡單的語句格式,且用途最廣。當if后面的<條件
表達式>成立時(真),就會執行then后面的指令或語句;否則,就會忽略then后面的指令或語句,
轉而執行fi下面的程序。

if單分支語句執行流程邏輯圖如下:

在這里插入圖片描述

條件語句還可以嵌套(即if條件語句里面還有if條件語句),注意每個if條件語句中都要有一個與之對應的fi(if反過來寫),每個if和它下面最近的fi成對搭配,語法示例如下:

if <條件表達式>;thenif <條件表達式>;then指令fi
fi

提示:通常在書寫Shell條件語句時,要讓成對的條件語句關鍵字的縮進相對應,以便于閱讀瀏覽。

前文曾講解過的文件條件表達式:

[ ! -d /tmp/wsh ] && mkdir /tmp/wsh

等價于下面的if條件語句:

if [ ! -d /tmp/wsh ];thenmkdir /tmp/wsh
fi

記憶小技巧:女孩對男孩說。

如果 你有房;那么
我就嫁給你
果如
2. 雙分支結構

if條件語句的雙分支結構主體則為:“如果…,那么…,否則…”。

if條件語句的雙分支結構語法為:

if <條件表達式>;then指令集1
else指令集2
fi

if 雙分支語句執行流程邏輯圖如下:

在這里插入圖片描述

前文的文件測試條件表達式

[ -d /tmp/wsh ] && echo /tmp/wsh is exist || mkdir /tmp/wsh

就相當于下面的雙分支的if條件語句:

if [ -d /tmp/wsh ];thenecho /tmp/wsh is exist
elsemkdir /tmp/wsh
fi

記憶小技巧:女孩對男孩說。

如果 你有房;那么
我就嫁給你
否則
我再考慮考慮
果如
3. 多分支結構

if條件語句多分支結構的主體為:“如果…,那么…,否則如果…,那么,否則如果…,那么…,否則…”。

if條件語句多分支語法為:

if <條件表達式1>;then指令1
elif <條件表達式2>;then指令2
else指令3
fi

多個elif

if <條件表達式1>;then指令
elif <條件表達式2>;then指令
elif <條件表達式3>;then指令
else指令
fi

提示:

  1. 注意多分支elif的寫法,每個elif都要帶有then。
  2. 最后結尾的else后面沒有then。

if多分支語句執行流程對應的邏輯圖如下:

在這里插入圖片描述

記憶小技巧:女孩對男孩說。

如果 你有房;那么
我就嫁給你
或者 你有錢;那么
我也可以嫁給你
否則
我再考慮考慮
果如
1.2 if 條件語句多種條件表達式語法

if條件語句(包括雙多分支if)的“<條件表達式>”部分可以是test、[]、[[]]、(())等條件表達式,甚至還可以直接使用命令作為條件表達式,具體的語法如下。

1. test條件表達式
if test 表達式;then指令
fi
2. []條件表達式
if [ 字符串 或 算術表達式 ];then指令
fi
3. [[]]條件表達式
if [[ 字符串 或 算術表達式 ]];then指令
fi
4. (())條件表達式
if ((算術表達式));then指令
fi
5. 命令表達式
if 命令;then指令
fi

說明:以上表達式除了語法不同之外,具體的應用是一致的,實際工作場景中,讀者只需選擇一種適合自己習慣的表達式就好。

1.3 if 條件語句實踐

示例1:檢測sshd服務是否運行,如果未運行則啟動sshd服務。

#!/bin/bash
systemctl is-active sshd &>/dev/null
if [ $? -ne 0 ];thenecho "sshd is not running, I'll start sshd."systemctl start sshd
fi

示例2:檢測sshd服務是否運行,如果未運行則啟動sshd服務;如果運行,輸出 “Running”。

#!/bin/bash
systemctl is-active sshd &>/dev/null
if [ $? -ne 0 ];thenecho "sshd is not running."echo -n "Starting sshd ... ..."systemctl start sshd && echo DONE
elseecho "sshd is running"
fi

示例3:通過傳參控制sshd服務。

#!/bin/bash
if [ "$1" == "start" ];thensystemctl start sshd
elif [ "$1" == "stop" ];thensystemctl stop sshd
elif [ "$1" == "status" ];thensystemctl status sshd
elif [ "$1" == "restart" ];thensystemctl restart sshd
elseecho "Usage: $0 start|stop|status|restart "
fi

或者

#!/bin/bash
if [ "$1" = "start" -o "$1" = "stop" -o "$1" = "status" -o "$1" = "restart" ];thensystemctl $1 sshd
elseecho "Usage: $0 start|stop|status|restart"
fi

示例4:任意給三個整數,對三個數進行從大到小排序并輸出。

#!/bin/bash
a=10
b=20
c=30
# 如果a小于b,交換值,此時a大b小
if [ $a -lt $b ];thennum=$b;b=$a;a=$num
fi
# 比較后兩個值大小并交換,此時c值最小
if [ $b -lt $c ];thennum=$c;c=$b;b=$num;
fi
# 比較前兩個值大小并交換,此時a值最大
if [ $a -lt $b ];thennum=$b;b=$a;a=$num;
fi
echo "$a>$b>$c"

示例5:每3分鐘檢查一次系統可用內存,如果空閑內存低于100M時給root用戶發郵件。

對于開發程序而言,一般來說應該遵循下面的3步法則。

  1. 分析需求

    明白開發需求,是完成程序的大前提,因此,分析需求至關重要,一切不以需求為主的程序開發,都是不倡導的!

  2. 設計思路

    設計思路就是根據需求,把需求進行拆解,分模塊逐步實現,例如本題可以分為如下幾步:

    1. 獲取當前系統剩余內存的值(先在命令行實現)。
    2. 配置郵件報警(可采用第三方郵件服務器)。
    3. 判斷取到的值是否小于100MB,如果小于100MB,就報警(采用if語句)。
    4. 編碼實現Shell腳本。
    5. 加入crond定時任務,每三分鐘檢查一次。
  3. 編碼實現

    編碼實現就是具體的編碼及調試過程,工作中很可能需要先在測試環境下調試,調試好了,再發布到生產環境中。

本例的最終實現過程如下:

  1. 獲取可用內存大小。

    [wsh@test ~ ?]$ free -mtotal     used      free      shared  buff/cache   available
    Mem:           3931      327      3419          11         184        3388
    Swap:          3967        0      3967[wsh@test ~ ?]$ free -m | awk 'NR==2 { print $4}'
    3419
    
  2. 發郵件的客戶端常見的有mail或mutt;服務端有sendmail服務(CentOS5下默認的)、postfix服務(CentOS6下默認的)。這里不使用本地的郵件服務。

  3. 編寫Shell腳本:monitor_mem.sh。

    #!/bin/bash
    FreeMem=$(free -m | awk 'NR==2 { print $4}')
    if [ $FreeMem -lt 100 ];thenecho  "Mem is lower than 100M" | mail -s "FreeMem is ${FreeMem}M" root@localhost
    fi
    
  4. 加入到計劃任務

    [wsh@test ~ ?]$ chmod +x monitor_mem.sh
    [wsh@test ~ ?]$ crontab -e 
    no crontab for wsh - using an empty one
    crontab: installing new crontab
    [wsh@test ~ ?]$ crontab -l
    */3 * * * * /home/wsh/monitor_mem.sh
    

2 if 條件語句企業案例精講

2.1 監控 Web 和數據庫

用if條件語句針對Nginx Web服務或MySQL數據庫服務是否正常進行檢測,如果服務未啟動,則啟動相應的服務。

這是企業級運維實戰綜合題,需要讀者對NginxWeb服務或MySQL數據庫服務很熟悉才行,本例同樣適用于其他的Web服務和數據庫服務。

大家還記得前面說過的開發程序前的三部曲吧?這里就采用這種方式來解答此題。

(1) 分析問題

監控Web服務和MySQL數據庫服務是否異常的方法:

  • 端口監控

    1. 在服務器本地監控服務端口的常見命令有 netstat、ss、lsof
    2. 從遠端監控服務器本地端口的命令有 telnet、nmap、nc
  • 監控服務進程或進程數,此方法適合本地服務器,注意,過濾的是進程的名字。命令為:

    ps -ef | grep nginx | wc -1
    ps -ef | grep mysql | wc -1
    
  • 客戶端模擬用戶訪問

    • 使用wget或curl命令進行測試(如果監測數據庫,則需要轉為通過Web服務器去訪問數據庫),并對測試結果做三種判斷:

      • 利用返回值($?)進行判斷
      • 獲取特殊字符串以進行判斷(需要事先開發好程序)
      • 根據HTTP響應header的情況進行判斷
    • 登錄MySQL數據庫判斷

      • 通過MySQL客戶端連接數據庫,根據返回值或返回內容判斷。例如:

        mysql -u root -pwsh -e "select version();" &>/dev/null;echo$?
        

此外,對端口進程等進行判斷時,盡量先通過grep過濾端口和進程特殊標記字符串,然后結合wc將過濾到的結果轉成行數再比較,這樣相對簡單有效,且經過wc-1命令處理之后的結果一定是數字,這樣再進行判斷就會比較簡便。如果單純地根據具體的列取具體的值判斷會很麻煩,如果確實想采用取值判斷的方法,那就盡量用字符串比較的語法。

提示: 掌握技術思想比解決問題本身更重要。

(2) 監測 MySQL 數據庫異常
  1. MySQL 數據庫環境準備

    [wsh@test ~ ?]$ sudo yum install -y mariadb-server
    [wsh@test ~ ?]$ sudo systemctl enable mariadb --now
    [wsh@test ~ ?]$ sudo ss -lnt|grep 3306
    LISTEN     0      50           *:3306                     *:*
    # 關閉防火墻
    [wsh@test ~ ?]$ sudo systemctl disable firewalld.service --now
    
  2. 通過命令行檢測數據庫服務是否正常,只有先確定命令行是正確的,才能確保將它放到腳本里也是正確的。

    • 首先采用端口監控的方式。

      在服務器本地監控端口的命令有netstat、ss、lsof,這里使用ss:

      [wsh@test ~ ?]$ ss -lnt|grep ':3306'|wc -l
      1
      

      從遠端監控服務器監控本地端口的命令有telnet、nmap、nc,這里使用nmap:

      [wsh@test ~ ?]$ sudo yum install -y nmap nc telnet
      [wsh@test ~ ?]$ nmap 127.0.0.1 -p 3306|grep open
      3306/tcp open  mysql
      [wsh@test ~ ?]$ nmap 127.0.0.1 -p 3306|grep open|wc -l
      1
      

      本例為了統一IP地址,因此使用的都是同一個IP,即127.0.0.1,在實際工作中,應該用自己服務器的IP來替代。

    • 以下是在客戶端模擬用戶訪問的方式進行監控。

      使用mysql連接數據庫,根據執行命令的返回值判斷成功與否。

      [wsh@test ~ ?]$ mysql -uroot -h 127.0.0.1 -e 'select version();' &>/dev/null
      [wsh@test ~ ?]$ echo $?
      0
      
  3. 開發監控MySQL數據庫的腳本。

    #!/bin/bash
    if ss -lnt|grep -q ':3306';thenecho "MySQL is Running."
    elseecho "MySQL is Not Running."
    fi
    
(3) 監測 Web 服務器異常
  1. Web 服務器準備

    [wsh@test ~ ?]$ sudo yum install -y httpd
    [wsh@test ~ ?]$ sudo systemctl enable httpd --now
    [wsh@test ~ ?]$ sudo ss -lnt|grep ':80 '
    LISTEN     0      128       [::]:80                    [::]:* 
    # 關閉防火墻
    [wsh@test ~ ?]$ sudo systemctl disable firewalld.service --now
    
  2. 通過命令行檢測數據庫服務是否正常,只有先確定命令行是正確的,才能確保將它放到腳本里也是正確的。

    • 首先采用端口監控的方式。

      在服務器本地監控端口的命令有netstat、ss、lsof,這里使用ss:

      [wsh@test ~ ?]$ ss -lnt|grep ':80'|wc -l
      1
      

      從遠端監控服務器監控本地端口的命令有telnet、nmap、nc,這里使用nmap:

      [wsh@test ~ ?]$ sudo yum install -y nmap nc telnet
      [wsh@test ~ ?]$ nmap 127.0.0.1 -p 80|grep open
      3306/tcp open  mysql
      [wsh@test ~ ?]$ nmap 127.0.0.1 -p 80|grep open|wc -l
      1
      

      本例為了統一IP地址,因此使用的都是同一個IP,即127.0.0.1,在實際工作中,應該用自己服務器的IP來替代。

    • 以下是在客戶端模擬用戶訪問的方式進行監控。

      使用wget或curl命令訪問URL地址來測試。根據執行命令的返回值判斷成功與否,本例的URL使用了網上的地址,在實際工作中應使用開發人員提供給我們的訪問數據庫的程序地址。

      # 方式1
      [wsh@test ~ ?]$ wget --timeout=10 --tries=2 www.redhat.com 2>/dev/null
      [wsh@test ~ ?]$ echo $?
      0# 方式2
      [wsh@test ~ ?]$ wget --timeout=10 --tries=2 www.redhat.com -q
      [wsh@test ~ ?]$ echo $?
      0# 方式3
      [wsh@test ~ ?]$ curl -s www.redhat.com
      [wsh@test ~ ?]$ echo $?
      0
      
    1. 開發監控Web服務器的腳本

      #!/bin/bash
      if wget --timeout=10 --tries=2 www.redhat.com &>/dev/null;thenecho "Apache is Running."
      elseecho "Apache is Not Running."
      fi
      
2.2 比較大小的經典拓展案例

使用if條件語句比較兩個整數的大小。使用傳參方法時,需要對傳參個數及傳入的參數是否為整數進行判斷。

示例1:

#!/bin/bash# 判斷參數個數
if [ $# -ne 2 ];thenecho "USAGE: $0 numl num2"exit 1
fi# 賦值
a=$1
b=$2# 判斷參數是否為整數
expr $a + 1 &>/dev/null
RETVAL1=$?
expr $b + 1 &>/dev/null
RETVAL2=$?
if [ $RETVAL1 -ne 0 -o $RETVAL2 -ne 0 ];thenecho "please provide two int number"exit 2
fi# 比較
if [ $a -lt $b ];thenecho "$a<$b"
elif [ $a -eq $b ];thenecho "$a=$b"
elseecho "$a>$b"
fi

示例2:

#!/bin/sh
read -p "Pls input two num:" a b
expr $a + 0 & >/dev/null
RETVAL1=$?
expr $b + 0 & >/dev/null
RETVAL2=$?
if [ -z "$a" ] || [ -z "$b" ];thenecho "Pls input two num again.exit 1
elif test $RETVAL1 -ne 0 -o $RETVAL2 -ne 0;thenecho "Pls input two int num again.exit 2
elif [ $a -lt $b ];thenecho "$a < $b"
elif [ $a -eq $b ];thenecho "$a = $b"
elseecho "$a > $b"
fi
exit 0
2.3 判斷字符串是否為數字的多種思路

示例1: 刪除字符串中的所有數字,看字符串的長度是否為0 , 如果不為0,則說明不是整數。

sed替換:

[wsh@test ~ ?]$ [ -n "$(echo wsh123|sed 's/[0-9]//g')" ] && echo char || echo int
char[wsh@test ~ ?]$ [ -n "$(echo 123|sed 's/[0-9]//g')" ] && echo char || echo int
int[wsh@test ~ ?]$ [ -z "$(echo 123|sed 's/[0-9]//g')" ] && echo int || echo char
int[wsh@test ~ ?]$ [ -z "$(echo wsh123|sed 's/[0-9]//g')" ] && echo int || echo char
char

使用變量的子串替換

[wsh@test ~ ?]$ string=wsh123
[wsh@test ~ ?]$ [ -n "${string//[0-9]/}" ] && echo char || echo int
char[wsh@test ~ ?]$ string=123
[wsh@test ~ ?]$ [ -n "${string//[0-9]/}" ] && echo char || echo int
int

使用tr替換:

[wsh@test ~ ?]$ string=123
[wsh@test ~ ?]$ [ -z "$(echo $string | tr -d 0-9)" ] && echo int || echo char
int[wsh@test ~ ?]$ string=abc123
[wsh@test ~ ?]$ [ -z "$(echo $string | tr -d 0-9)" ] && echo int || echo char
char

示例2: 如果num的長度不為0,并且把num中的非數字部分刪除,然后再看結果是不是等于num本身,如果兩者都成立,則num就是數字。

[wsh@test ~ ?]$ num=abc123
[wsh@test ~ ?]$ [ -n "$num" -a  "$num" = "${num//[^0-9]/}" ] && echo int || echo char
char
[wsh@test ~ ?]$ num=123
[wsh@test ~ ?]$ [ -n "$num" -a  "$num" = "${num//[^0-9]/}" ] && echo int || echo char
int

示例3: 通過 expr 計算判斷

[wsh@test ~ ?]$ expr abc + 1 &>/dev/null
[wsh@test ~ ?]$ echo $?
2[wsh@test ~ ?]$ expr 1 + 1 &>/dev/null
[wsh@test ~ ?]$ echo $?
0

示例4: 通過“=~”符號判斷

[wsh@test ~ ?]$ [[ 123 =~ ^[0-9]+$ ]] && echo int || echo char
int
[wsh@test ~ ?]$ [[ abc123 =~ ^[0-9]+$ ]] && echo int || echo char
char
2.4 判斷字符串長度是否為0的多種思路

示例1: 使用字符串條件表達式判斷

[wsh@test ~ ?]$ [ -z "wsh" ] && echo true || echo false
false
[wsh@test ~ ?]$ [ -n "wsh" ] && echo false || echo true
false

示例2: 使用變量子串判斷

[wsh@test ~ ?]$ str=wsh
[wsh@test ~ ?]$ [ ${#str} -eq 0 ] && echo true || echo false
false

示例3: 使用 expr length 函數判斷

[wsh@test ~ ?]$ [ $(expr length "wsh") -eq 0 ] && echo true || echo false
false

示例4: 使用wc -L命令統計判斷

[wsh@test ~ ?]$ [ $(echo "wsh"|wc -L) -eq 0 ] && echo true || echo false 
false

示例5: 使用 awk length 函數判斷

[wsh@test ~ ?]$ [ $(echo "wsh"|awk '{print length}') -eq 0 ] && echo true || echo false
false
2.5 監控 memcached 服務是否正常

監控memcached服務是否正常,模擬用戶(Web客戶端)檢測。

此題需要讀者了解并可以搭建memcached服務(memcached是運維場景中常用的內存緩存軟件),且可以用nc或telnet命令訪問memcached服務,加上用set/get來模擬檢測。

  1. 環境準備

    [root@test ~ ?]# yum install -y nc memcached
    [root@test opt ?]# systemctl enable memcached.service --now
    
  2. 參考解答

    [wsh@test scripts ?]$ cat check_memcache.sh
    #!/bin/bash
    # Author: wsh
    # Time: 2022-12-10 14:21:37
    # Name: check_memcache.sh
    systemctl is-active memcached.service &>/dev/null
    RetVal=$?if [ $RetVal -ne 0 ];thenecho "Memcached is not running."
    else# 刪除緩存中的 key 及對應的值printf "del key\r\n"|nc 127.0.0.1 11211  &>/dev/null# 添加新值printf "set key 0 0 10 \r\nwsh1234\r\n"|nc 127.0.0.1 11211 &>/dev/null# 查詢新值McCount=$(printf "get key\r\n"|nc 127.0.0.1 11211|wc -l)[ $McCount -eq 1 ] && \echo "Memcached status is ok." || \echo "Memcached status is error."
    fi
    
2.6 開發 rsync 服務的啟動腳本

rsync是運維場景中最常用的數據同步軟件,本例就是要完成一個類似系統的啟動rsync服務的方法,即使用/etc/init.d/rsyncd{start|stop|restart}即可啟動和停止rsync服務,這里是用if條件語句來實現相應效果的,其實通過case語句來實現效果最佳,不過由于還沒講解到case語句,因此這里主要練習if語句。

  1. 分析問題。要想開發出rsync服務的啟動腳本,就需要熟悉rsync服務的配置,以及rsync服務是如何啟動,以及如何停止的。

  2. 要實現/etc/init.d/rsyncd{start|stop|restart}的操作語法,就需要用到腳本的傳參。根據傳入的參數,進行判斷,然后執行對應的啟動和停止命令。

    實現過程如下:

    • 第1步,rsync 服務準備。
    # 安裝軟件
    [wsh@test ~ ?]$ sudo yum install -y rsync# 啟動服務
    [wsh@test ~ ?]$ sudo rsync --daemon# 檢測端口
    [wsh@test ~ ?]$ ss -lnt|grep ':873'
    LISTEN     0      5            *:873                      *:*              
    LISTEN     0      5         [::]:873                   [::]:*  
    
    • 第2步,rsync服務停止和端口檢測。
    [wsh@test ~ ?]$ sudo pkill rsync
    [wsh@test ~ ?]$ ss -lnt|grep ':873'
    
    • 第3步,判斷rsync服務是否啟動的方法。

      • 常規方法有檢測端口以及進程是否存在
      • 還可以當服務啟動時,創建一個鎖文件(/var/lock/rsync/locker),而當服務停止時,就刪除這個鎖文件,這樣就可以通過判斷這個文件有無,來確定服務是否是啟動狀態,這是一些系統腳本常用的手法。
    • 第4步,開發rsync服務的啟動腳本。

      [wsh@test ~ ?]$ sudo vim /etc/init.d/rsyncd
      #!/bin/bash
      # Author: wsh
      # Time: 2022-12-12 18:10:15
      # Name: rsyncd# 判斷參數個數
      if [ $# -ne 1 ];thenecho "Usage: $0 [ start | stop | restart | status ]"exit 1
      fi# 根據參數1做出相應動作
      if [ "$1" = "start" ];thenrsync --daemonsleep 2# 判斷當前狀態if ss -lnt|grep -q ':873';thenecho "rsyncd is started."exit 0fi
      elif [ "$1" = "stop" ];thenpkill rsync &>/dev/nullsleep 2# 判斷當前狀態if ! ss -lnt|grep -q ':873';thenecho "rsyncd is stoped."exit 0fi
      elif [ "$1" = "status" ];then# 判斷當前狀態if ! ss -lnt|grep -q ':873';thenecho "rsyncd is stoped."elseecho "rsyncd is started."fi
      elif [ "$1" = "restart" ];thenpkill rsync &>/dev/nullretval_1=$?sleep 1rsync --daemonretval_2=$?sleep 1# 判斷停止和啟動狀態if [ $retval_1 -eq 0 -a $retval_2 -eq 0 ];thenecho "rsyncd is restarted."exit 0fi
      elseecho "Usage: $0 [ start | stop | restart | status ]"exit 1
      fi
      

    執行結果:

    [wsh@test ~ ?]$ sudo bash /etc/init.d/rsyncd start
    rsyncd is started.
    [wsh@test ~ ?]$ sudo bash /etc/init.d/rsyncd status
    rsyncd is started.
    [wsh@test ~ ?]$ sudo bash /etc/init.d/rsyncd stop
    rsyncd is stoped.
    [wsh@test ~ ?]$ sudo bash /etc/init.d/rsyncd status
    rsyncd is stoped.
    [wsh@test ~ ?]$ sudo bash /etc/init.d/rsyncd restart
    [wsh@test ~ ?]$ sudo bash /etc/init.d/rsyncd status
    rsyncd is started.[wsh@test ~ ?]$ sudo bash /etc/init.d/rsyncd hello
    Usage: /etc/init.d/rsyncd [ start | stop | restart | status ]
    [wsh@test ~ ?]$ echo $?
    1
    

Shell 函數的知識與實踐

1 Shell 函數介紹

在講解Shell 函數之前,先來回顧Linux系統中 alias 的作用。

[wsh@test ~ ?]$ ls -l --color=auto /home
total 0
drwx------. 2 wsh wsh 125 Aug 24 16:24 wsh
[wsh@test ~ ?]$ alias ll='ls -l --color=auto'
[wsh@test ~ ?]$ ll /home/
total 0
drwx------. 2 wsh wsh 125 Aug 24 16:24 wsh

函數也有類似于別名的作用,例如可簡化程序的代碼量,讓程序更易讀、易改、易用。

簡單地說,函數的作用就是將程序里多次被調用的相同代碼組合起來(函數體),并為其取一個名字(即函數名),其他所有想重復調用這部分代碼的地方都只需要調用這個名字就可以了。當需要修改這部分重復代碼時,只需要改變函數體內的一份代碼即可實現對所有調用的修改,也可以把函數獨立地寫到文件里,當需要調用函數時,再加載進來使用。

使用 Shell 函數的優勢整理如下:

  • 把相同的程序段定義成函數,可以減少整個程序的代碼量,提升開發效率。
  • 增加程序的可讀性、易讀性,提升管理效率。
  • 可以實現程序功能模塊化,使得程序具備通用性(可移植性)。

對于Shell來說,Linux系統里的近2000個命令可以說都是Shell的函數,所以,Shell的函數也是很多的,這一點需要讀者注意。

2 Shell 函數的語法

下面是Shell 函數的常見語法格式。

標準寫法

function 函數名 () {指令...return n
}

簡化寫法1:不寫()

function 函數名 {指令...return n
}

簡化寫法2:不寫function

函數名 () {指令...return n
}

3 Shell 函數的執行

Shell的函數分為最基本的函數和可以傳參的函數兩種,其執行方式分別說明如下。

  1. 執行不帶參數的函數時,直接輸人函數名即可(注意不帶小括號)。

    格式如下:函數名

    有關執行函數的重要說明:

    • 執行Shell 函數時,函數名前的function和函數后的小括號都不要帶。
    • 函數的定義必須在要執行的程序前面定義或加載。
    • Shell執行系統中各種程序的執行順序為:系統別名->函數->系統命令->可執行文件
    • 函數執行時,會和調用它的腳本共用變量,也可以為函數設定局部變量及特殊位置參數。
    • 在Shell 函數里面,return命令的功能與exit類似,return的作用是退出函數,而exit是退出腳本文件。
    • return語句會返回一個退出值(即返回值)給調用函數的當前程序,而exit會返回一個退出值(即返回值)給執行程序的當前Shell。
    • 如果將函數存放在獨立的文件中,被腳本加載使用時,需要使用source或來加載。
    • 在函數內一般使用local定義局部變量,這些變量離開函數后就會消失。
  2. 帶參數的函數執行方法,格式如下:

    函數名 參數1 參數2
    

    函數后接參數的說明:

    • Shell 的位置參數($1、2…、2…、2#、?、*、??及$@)都可以作為函數的參數來使用。
    • 此時父腳本的參數臨時地被函數參數所掩蓋或隱藏。
    • $0 比較特殊,它仍然是父腳本的名稱。
    • 當函數執行完成時,原來的命令行腳本的參數即可恢復。
    • 函數的參數變量是在函數體里面定義的。

4 Shell 函數的基礎實踐

示例1: hello函數

[wsh@test ~ ?]$ cat fun1.sh 
#!/bin/bash
function hello () {echo "Hello World !"
}
hello
[wsh@test ~ ?]$ bash fun1.sh 
Hello World !# 函數必須先定義,后調用
[wsh@test ~ ?]$ cat fun2.sh 
#!/bin/bash
hello
function hello () {echo "Hello World !"
}
[wsh@test ~ ?]$ bash fun2.sh
fun2.sh: line 2: hello: command not found

示例2: 調用外部函數

[wsh@test ~ ?]$ cat >> mylib << 'EOF'
function hello () {echo "Hello World !"
}
EOF[wsh@test ~ ?]$ cat fun3.sh 
#!/bin/bash
if [ -r mylib ];thensource mylib
elseecho mylib is not exist exit 1
fi
hello[wsh@test ~ ?]$ bash fun3.sh 
Hello World !

示例3: 帶參數的函數

[wsh@test ~ ?]$ cat fun4.sh 
#!/bin/bash
function print () {if [ "$1" == "PASS" ];thenecho -e '\033[1;32mPASS\033[0;39m'elif [ "$1" == "FAIL" ];thenecho -e '\033[1;31mFAIL\033[0;39m'elif [ "$1" == "DONE" ];thenecho -e '\033[1;35mDONE\033[0;39m'elseecho "Usage: print PASS|FAIL|DONE"fi
}
read -p "請輸入你想要打印的內容:" str
print $str[wsh@test ~ ?]$ bash fun4.sh 
請輸入你想要打印的內容:`PASS`
PASS
[wsh@test ~ ?]$ bash fun4.sh 
請輸入你想要打印的內容:hello
Usage: print PASS|FAIL|DONE

示例4: hello函數

[wsh@test ~ ?]$ cat fun5.sh 
#!/bin/bash
function print () {if [ "$1" == "PASS" ];thenecho -e '\033[1;32mPASS\033[0;39m'elif [ "$1" == "FAIL" ];thenecho -e '\033[1;31mFAIL\033[0;39m'elif [ "$1" == "DONE" ];thenecho -e '\033[1;35mDONE\033[0;39m'elseecho "Usage: $0 PASS|FAIL|DONE"
fi
}
str=$2
print $str# 結果表明,腳本的第一個參數并沒有傳遞給腳本內部函數。
[wsh@test ~ ?]$ bash fun5.sh PASS FAIL
FAIL# 結果表明,$0 仍然使用腳本名,而非函數名。
[wsh@test ~ ?]$ bash fun5.sh 
Usage: fun5.sh PASS|FAIL|DONE

5 利用 Shell 函數開發企業級URL檢測腳本

[wsh@test ~ ?]$ cat check_url.sh 
#!/bin/bash
function usage () {echo "usage: $0 url"exit 1
}function check_url () {wget --spider -q -o /dev/null --tries=1 -T 5 $1[ $? -eq 0 ] && echo $1 is accessable || echo $1 is not accessable
}function main () {[ $# -ne 1 ] && usagecheck_url $1
}main $*# 測試結果如下:
[wsh@test ~ ?]$ bash check_url.sh www.baidu.com
www.baidu.com is accessable
[wsh@test ~ ?]$ bash check_url.sh www.wsh.com
www.wsh.com is not accessable

6 函數的遞歸調用

示例1:求1+2+3+…+10 的和
#!/bin/bash
function sum_out() {if [ $1 -eq 1 ];thensum=1elsesum=$[ $1 + $(sum_out $[ $1 - 1 ] ) ]fiecho $sum
}
read -p "輸入一個你想計算和的整數:" num
sum_out $num
示例2:求1*2*3*…*10 的階乘
#!/bin/bash
function fact_out() {if [ $1 -eq 1 ];thensum=1elsesum=$[ $1 * $(fact_out $[ $1 - 1 ] ) ]fiecho $sum
}
read -p "輸入一個你想計算和的整數:" num
fact_out $num
示例3:fork 炸彈
:(){ :|:& };:

解釋如下:

:()   # 定義函數,函數名為":",即每當輸入":"時就會自動調用{}內代碼
{        # ":"函數起始字元:    # 用遞歸方式調用":"函數本身|    # 使用管道一次產生兩個函數調用:    # 另一次遞歸調用的":"函數&    # 放后臺運行,以便產生更多的子進程
}        # ":"函數終止
;        # ":"函數定義結束后將要進行的操作...
:        # 調用":"函數,"引爆"fork炸彈

fork 炸彈原因:無限制的啟用新進程,直到消耗完所有計算資源。

解決辦法:限制用戶進程數量。

例如:限制100個進程

[wsh@test ~ ?]$ ulimit -u 100

case 條件語句的應用實踐

case 條件語句相當于多分支的if/elif/else條件語句,但是它比這些條件語句看起來更規范更工整,常被應用于實現系統服務啟動腳本等企業應用場景中。

在case語句中,程序會將case獲取的變量的值與表達式部分的值1、值2、值3等逐個進行比較:

  • 如果獲取的變量值和某個值(例如值1)相匹配,就會執行值(例如值1)后面對應的指令(例如指令1,其可能是一組指令),直到執行到雙分號(;;)才停止,然后再跳出case語句主體,執行case語句(即esac字符)后面的其他命令。
  • 如果沒有找到匹配變量的任何值,則執行“*)”后面的指令(通常是給使用者的使用提示),直到遇到雙分號(此處的雙分號可以省略)或esac結束,這部分相當于if多分支語句中最后的else語句部分。
  • 另外,case語句中表達式對應值的部分,還可以使用管道等更多功能來匹配。

1 case 條件語句的語法

case 條件語句的語法格式為:

case "變量值" in值1)指令1...;;值2)指令2...;;*)指令3...;;
esac

為了便于記憶,下面是某女生寫的case 條件語句的中文形象描述:

case "找老公條件" in資產大于1千萬)嫁給你;;資產介于1百萬和1千萬之間)再考慮以下;;資產小于1百萬)再見;;其他情況)視情況而定;;
esac

case 條件語句的執行流程邏輯圖如下:
在這里插入圖片描述

2 case 條件語句實踐

示例:判斷用戶輸入的數字是否是1、2、3。

[wsh@test ~ ?]$ cat case1.sh 
#!/bin/bash
read -p "請輸入一個1-3之間數字:" num
case $num in1)echo "您輸入的數字是:$num";;2)echo "您輸入的數字是:$num";;3)echo "您輸入的數字是:$num";;*)echo "請輸入一個1-3之間數字。";;
esac# 執行驗證
[wsh@test ~ ?]$ bash case1.sh 
請輸入一個1-3之間數字:1
您輸入的數字是:1[wsh@test ~ ?]$ bash case1.sh 
請輸入一個1-3之間數字:4
請輸入一個1-3之間數字。

3 實踐:給輸出的字符串加顏色

[wsh@test ~ ?]$ cat case2.sh 
#!/bin/bash
case $1 inPASS)echo -e '\033[1;32mPASS\033[0;39m';;FAIL)echo -e '\033[1;31mFAIL\033[0;39m';;DONE)echo -e '\033[1;35mDONE\033[0;39m';;*)echo "Usage: $0 PASS|FAIL|DONE";;
esac

執行效果:

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

4 case 條件語句的 Linux 系統腳本范例

/etc/init.d/network

提示:network-scripts 軟件包 提供以上腳本。

5 case小結

  1. case 語句比較適合變量值較少且為固定的數字或字符串集合的情況,如果變量的值是已知固定的start/stop/restart 等元素,那么采用case語句來實現就比較適合。
  2. case語句和if條件語句的常見應用場景
    • case主要是寫服務的啟動腳本,一般情況下,傳參不同且具有少量的字符串,其適用范圍較窄。
    • if就是取值判斷、比較,應用面比case更廣。幾乎所有的case語句都可以用if條件語句來實現。
  3. case語句就相當于多分支的if/elif/else語句,但是case語句的優勢是更規范、易讀。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/94724.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/94724.shtml
英文地址,請注明出處:http://en.pswp.cn/web/94724.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C#實戰:基于iTextSharp實現PDF加密小工具

目錄 1、技術框架 2、代碼實戰 2.1 創建窗體 2.2 后臺代碼邏輯 2.3 PDF加密用戶類型 2.4 PDF加密權限列表 3、運行效果 4、總結 大家日常辦公中有時候為了文檔資料的安全需要對文檔進行加密,尤其是針對PDF文檔這個場景還是非常廣泛的。今天給大家分享使用C#來實現PDF…

基于Labview的旋轉機械AI智能診斷系統

1.摘要本文基于 CWRU 公開軸承數據集提出了一套“AI 輕量級模型 LabVIEW 智能診斷系統”。首先&#xff0c;LabVIEW 端構建了可視化、可交互的智能診斷平臺。系統能夠加載本地振動信號數據&#xff0c;調用訓練好的深度學習模型進行故障識別與狀態判斷。界面集成信號時域監測、…

Qt從qmake遷移到cmake的記錄

文章目錄1.UI程序[開啟/關閉]控制臺2.增加宏定義3.在主項目中引入子項目4.使用C語言文件1.UI程序[開啟/關閉]控制臺 qmake&#xff1a; CONFIG console DEFINES QT_MESSAGELOGCONTEXTcmake&#xff1a; set(CMAKE_WIN32_EXECUTABLE OFF) # ON為關閉控制臺 OFF為開啟控制臺2…

LangChain4J-(3)-模型參數配置

LangChain4j 提供了靈活的模型參數配置方式&#xff0c;允許你根據不同的 AI 模型&#xff08;如 OpenAI、GPT-4、Anthropic 等&#xff09;設置各種參數來控制生成結果。后面手擼代碼繼續在之前章節的代碼上拓展一、日志配置&#xff08;Logging&#xff09;在 LangChain4j 中…

LangGraph - API多種訪問方式

本文介紹了Langgraph服務的四種調用方式&#xff1a;1. 通過LangGraph Studio UI界面手動測試&#xff1b;2. 使用Python SDK進行同步/異步調用&#xff1b;3. 通過REST API測試&#xff1b;4. 使用JavaScript SDK接入。Langgraph 服務端代碼 graph.pyfrom langchain_openai im…

HEI-612 HART/EtherNet/IPModbus TCP 網關:打通工業通信壁壘

在工業自動化領域&#xff0c;HART 協議設備的廣泛應用與以太網網絡的高效管理常面臨 “協議孤島” 難題 —— 老舊 HART 傳感器、變送器難以接入 EtherNet/IP 或 Modbus TCP 系統&#xff0c;數據雙向交互卡頓、調試復雜、兼容性差等問題&#xff0c;嚴重制約生產效率提升。上…

OSPF 的工作過程、Router ID 機制、報文結構

視頻版講解>>>>>>>>>>>>>>路由協議深度解析&#xff1a;從靜態路由到 OSPF 實戰 一、回顧靜態路由&#xff1a;拓撲與核心邏輯 我們先回到上周講解的拓撲圖&#xff0c;這張圖是理解靜態路由的核心載體 —— 路由器作為網段分割的…

Qt 6 與 Qt 5 存在的兼容性差異

之前有提到。我的是Qt5&#xff0c;我朋友的是Qt 6&#xff0c;由于版本不兼容問題&#xff0c;在遷移時會有問題。所以這一我們說說這兩個的區別。&#xff08; 正文開始嘍&#xff01; 總結來說&#xff1a;Qt5遷移至 Qt 6 需&#xff1a;1. 破壞性變更&#xff08;必須修改…

本地windows電腦部署html網頁到互聯網:html+node.js+ngrok/natapp

目錄 核心概念&#xff1a;為什么不能直接分享HTML文件&#xff1f; 1&#xff0c;html文件修改 2&#xff0c;安裝設置node.js 3&#xff0c;路由器虛擬服務器 4&#xff0c;采用ngrok工具進行內網穿透&#xff08;國外工具&#xff09; 5&#xff0c;采用natapp工具進行…

electron離線開發核心環境變量npm_config_cache

npm_config_cache 這個環境變量。它在離線環境配置中扮演著核心角色。什么是 npm_config_cache&#xff1f;npm_config_cache 是一個環境變量&#xff0c;用于直接設置 npm 的緩存目錄的絕對路徑。npm 在安裝包時&#xff0c;會遵循一個特定的工作流程&#xff1a;檢查緩存&…

CTFshow系列——命令執行web57-60

本篇文章介紹命令執行的另一種情況&#xff0c;CTFshow的Web57-60關的講解解析&#xff1b;要想了解其它關卡可查看我以往的文章&#xff0c;感謝關注。 文章目錄Web57&#xff08;新方法&#xff09;Web58&#xff08;POST型&#xff09;不可用函數可用函數Web59第二種方法&am…

域名、ip、DSN、URL

目錄 1、ip 2、域名 3、DSN 4、URL 1、ip 每個連接到Internet上的主機都會分配一個IP地址&#xff0c;此ip是該計算機在互聯網上的邏輯地址的唯一標識&#xff0c;計算機之間的訪問就是通過IP地址來進行的。寫法&#xff1a;十進制的形式&#xff0c;用“.”分開&#xff0…

【JAVA實現websocket】

JAVA實現websocket背景依賴問題代碼實現測試背景 近期項目中需要用到websocket&#xff0c;實現即時通信。 依賴 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></depen…

2.6 提示詞調優編碼實戰(一)

目錄 寫在前面 一,需求定義 二,簡單提示詞 2.1 代碼示例 2.2 輸出結果 三,提示詞模版 3.1 提示詞 3.1.1 任務描述 3.1.2 用戶輸入 3.1.3 模型輸出格式 3.1.4 Prompt模版 3.2 輸出結果 寫在前面 前面我們總結了提示詞對于模型的意義,接下來我們來通過向模型輸入…

使用Stone 3D快速制作第一人稱視角在線小游戲

首先得有個怪物模型&#xff0c;怪物帶有idle, attack動作 然后有個場景模型&#xff0c;把怪物&#xff08;如果模型較大&#xff0c;建議使用remote-mesh來加載&#xff09;擺放到想放的位置。 給相機加上fps-controls和character組件 給所有怪物加上character組件 可以在…

嵌入式第三十七課!!!TCP機制與HTTP協議

TCP的其他機制TCP頭部標志位SYN&#xff1a;請求建立連接標志位 ACK&#xff1a;響應報文標志位 PSH&#xff1a;攜帶數據標志位&#xff0c;通知接收方該從緩沖區讀數據 FIN&#xff1a; 請求斷開連接標志位 RST&#xff1a;復位標志位 URG: 緊急數據標志…

【測試】pytest測試環境搭建

使用pytest進行API測試&#xff0c;vscode運行 創建虛擬環境&#xff0c;安裝pytest&#xff0c;httpx&#xff0c;requests&#xff0c;dotenvvscode中ctrlshiftp&#xff0c;選擇python: Configure Tests&#xff0c;選擇pytest&#xff0c;目錄左側插件testing里面可以看到有…

javaweb開發筆記——微頭條項目開發

第八章 微頭條項目開發 一 項目簡介 1.1 微頭條業務簡介 微頭條新聞發布和瀏覽平臺,主要包含業務如下 用戶功能 注冊功能 登錄功能 頭條新聞 新聞的分頁瀏覽 通過標題關鍵字搜索新聞 查看新聞詳情 新聞的修改和刪除 權限控制 用戶只能修改和自己發布的頭條新聞 1.…

Linux(二十二)——服務器初始化指南

文章目錄前言一、配置國內 Yum 源&#xff08;加速軟件安裝&#xff09;二、更新系統與安裝必備工具三、網絡連接驗證四、配置主機名五、同步時間六、配置防火墻6.1 使用 iptables6.1.1 整體思路6.1.2 詳細步驟6.1.3 完整配置腳本示例6.1.4 常用管理命令6.2 使用 firewalld總結…

我用Photoshop Firefly+Blender,拯救被環境毀掉的人像大片

今日陽光正好。這樣的天氣對于攝影師來說是種饋贈&#xff0c;但也讓我想起了這個行業最普遍也最無奈的痛點&#xff1a;我們精心策劃了一場拍攝&#xff0c;模特的表現、光線的質感都近乎完美&#xff0c;但最終卻因為一個平淡的陰天、一處雜亂的背景&#xff0c;或是一個無法…