滲透測試-07:Shell
語法特點
- 指令碼頂部宣告解釋當前指令碼所用的工具,
#!/bin/sh
或#!/bin/bash
- 語句末尾不加分號
;
- 註釋:單行註釋
#
,多行註釋:<<! 被註釋的內容 !
- 變數名和等號之間不能有空格
- 對變數進行操作時不加
$
符,使用變數時加$
符,如:$name
、${name}
-
""
不會解釋$name
,只會解釋${name}
;''會原樣解釋${name}
- 字串可以用單引號,也可以用雙引號,也可以不用引號
- 字串拼接直接不用任何符號,如:
"name:""Toki"
- 條件表示式要放在方括號之間,並且要有空格,例如:
[$a==$b]
是錯誤的,必須寫成[ $a == $b ]
變數
用語句給變數賦值
for file in `ls /etc`
# 或
for file in $(ls /etc)
只讀變數
普通變數名可以被覆蓋,只讀變數的值不能被改變
myUrl="https://www.google.com"
readonly myUrl
刪除變數
unset myUrl
變數作用域
-
區域性變數
:區域性變數在 指令碼或命令中定義,僅在當前shell例項中有效,其他shell啟動的程式不能訪問區域性變數 -
環境變數
:所有的程式,包括shell啟動的程式,都能訪問環境變數,有些程式需要環境變數來保證其正常執行。必要的時候shell指令碼也可以定義環境變數 -
shell變數
字串
獲取字串長度
echo ${#name}
# 或
${#string[0]}
字串擷取
echo ${string:0:4}
查詢子字串位置
string="runoob is a great site"
echo `expr index "$string" io` # 輸出 4
陣列
bash 只支援一維陣列(不支援多維陣列),用 括號
來表示陣列,陣列元素用 空格
隔開,如:
name=(value0 value1 value2 value3) # 或 name=( value0 value1 value2 value3 )
陣列讀取
${陣列名[下標]}
使用 @ 符號可以獲取陣列中的所有元素,如:echo ${name[@]}
獲取陣列的長度
# 取得陣列元素的個數
length=${#name[@]}
# 或
length=${#name[*]}
# 取得陣列單個元素的長度
lengthn=${#name[n]}
傳遞引數
#!/bin/bash
echo "Shell 傳遞引數例項!";
echo "執行的檔名:$0";
echo "第一個引數為:$1";
echo "第二個引數為:$2";
echo "第三個引數為:$3";
$ chmod +x test.sh
$ ./test.sh 1 2 3
Shell 傳遞引數例項!
執行的檔名:./test.sh
第一個引數為:1
第二個引數為:2
第三個引數為:3
$*
與 $@
區別:
相同點:都是引用所有引數
不同點:只有在雙引號中體現出來。假設在指令碼執行時寫了三個引數 1、2、3,則 " * " 等價於 "1 2 3"(傳遞了一個引數),而 "@" 等價於 "1" "2" "3"(傳遞了三個引數)
表示式和運算子
-
表示式和運算子之間要有空格,例如
2+2
是不對的,必須寫成2 + 2
-
完整的表示式要用反引號包含
-
乘號
*
前邊必須加反斜槓\
才能實現乘法運算
#!/bin/bash
a=10
b=20
val=`expr $a \* $b`
echo "a * b : $val"
關係運算符
-eq (==) [ $a -eq $b ]
-ne (!=) [ $a -ne $b ]
-gt (>) [ $a -gt $b ]
-lt (<) [ $a -lt $b ]
-ge (>=) [ $a -ge $b ]
-le (<=) [ $a -le $b ]
布林運算子
! (非) [ ! false ] 返回 true。
-o (或) [ $a -lt 20 -o $b -gt 100 ]
-a (與) [ $a -lt 20 -a $b -gt 100 ]
邏輯運算子
&& (and) [[ $a -lt 100 && $b -gt 100 ]]
|| (or) [[ $a -lt 100 || $b -gt 100 ]]
字串運算子
= 檢測兩個字串是否相等,相等返回 true。 [ $a = $b ]
!= 檢測兩個字串是否不相等,不相等返回 true。 [ $a != $b ]
-z 檢測字串長度是否為0,為0返回 true。 [ -z $a ]
-n 檢測字串長度是否不為 0,不為 0 返回 true。 [ -n "$a" ]
$ 檢測字串是否為空,不為空返回 true。 [ $a ]
檔案測試運算子
-b file 檢測檔案是否是塊裝置檔案,如果是,則返回 true。 [ -b $file ]
-c file 檢測檔案是否是字元裝置檔案,如果是,則返回 true。 [ -c $file ]
-d file 檢測檔案是否是目錄,如果是,則返回 true。 [ -d $file ]
-f file 檢測檔案是否是普通檔案(既不是目錄,也不是裝置檔案),如果是,則返回 true。 [ -f $file ]
-g file 檢測檔案是否設定了 SGID 位,如果是,則返回 true。 [ -g $file ]
-k file 檢測檔案是否設定了粘著位(Sticky Bit),如果是,則返回 true。 [ -k $file ]
-p file 檢測檔案是否是有名管道,如果是,則返回 true。 [ -p $file ]
-u file 檢測檔案是否設定了 SUID 位,如果是,則返回 true。 [ -u $file ]
-r file 檢測檔案是否可讀,如果是,則返回 true。 [ -r $file ]
-w file 檢測檔案是否可寫,如果是,則返回 true。 [ -w $file ]
-x file 檢測檔案是否可執行,如果是,則返回 true。 [ -x $file ]
-s file 檢測檔案是否為空(檔案大小是否大於0),不為空返回 true。 [ -s $file ]
-e file 檢測檔案(包括目錄)是否存在,如果是,則返回 true。 [ -e $file ]
-S: 判斷某檔案是否 socket。
-L: 檢測檔案是否存在並且是一個符號連結。
輸入輸出
read 命令,從輸入中讀取一行,並把輸入行的每個欄位的值指定給 shell 變數
#!/bin/sh
read name
echo "$name It is a test"
[root@www ~]# sh test.sh
OK #輸入
OK It is a test #輸出
顯示換行
#!/bin/sh
echo -e "OK! \n" # -e 開啟轉義
echo "It is a test"
顯示不換行
#!/bin/sh
echo -e "OK! \c" # -e 開啟轉義 \c 不換行
echo "It is a test"
顯示結果定向至檔案
echo "It is a test" > myfile
顯示命令執行結果
注意反引號
echo `date`
printf
預設的 printf
不會像 echo
自動新增換行符,我們可以手動新增 \n
,如:
printf "Hello, Shell\n"
佔位符
#!/bin/bash
printf "%-10s %-8s %-4s\n" 姓名 性別 體重kg
printf "%-10s %-8s %-4.2f\n" 張三 男 66.1234
printf "%-10s %-8s %-4.2f\n" 李四 男 48.6543
printf "%-10s %-8s %-4.2f\n" 王五 女 47.9876
姓名 性別 體重kg
張三 男 66.12
李四 男 48.65
王五 女 47.99
%-10s 指一個寬度為 10 個字元(- 表示左對齊,沒有則表示右對齊),任何字元都會被顯示在 10 個字元寬的字元內,
如果不足則自動以空格填充,超過也會將內容全部顯示出來。%-4.2f 指格式化為小數,其中 .2 指保留2位小數。
邏輯運算
-eq 等於則為真
-ne 不等於則為真
-gt 大於則為真
-ge 大於等於則為真
-lt 小於則為真
-le 小於等於則為真
#!/bin/bash
a=100
b=100
if test $[a] -eq $[b]
then
echo '兩個數相等!'
else
echo '兩個數不相等!'
fi
result=$[a+b] # 注意等號兩邊不能有空格
echo "result 為: $result" # result 為: 200
= 等於則為真
!= 不相等則為真
-z 字串 字串的長度為零則為真
-n 字串 字串的長度不為零則為真
#!/bin/bash
a="a"
b="b"
if test $a = $b
then
echo '兩個字串相等!'
else
echo '兩個字串不相等!'
fi
檔案操作
-e 檔名 如果檔案存在則為真
-r 檔名 如果檔案存在且可讀則為真
-w 檔名 如果檔案存在且可寫則為真
-x 檔名 如果檔案存在且可執行則為真
-s 檔名 如果檔案存在且至少有一個字元則為真
-d 檔名 如果檔案存在且為目錄則為真
-f 檔名 如果檔案存在且為普通檔案則為真
-c 檔名 如果檔案存在且為字元型特殊檔案則為真
-b 檔名 如果檔案存在且為塊特殊檔案則為真
test
#!/bin/bash
cd /bin
if test -e ./bash
then
echo '檔案已存在!'
else
echo '檔案不存在!'
fi
與或非優先順序:非( ! )>與( -a )>或( -o )
#!/bin/bash
cd /bin
if test -e ./notFile -o -e ./bash
then
echo '至少有一個檔案存在!'
else
echo '兩個檔案都不存在'
fi
判斷語句
單行
if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "true"; fi
多行
if condition1
then
command1
elif condition2
then
command2
else
commandN
fi
迴圈語句
for 迴圈
單行
for var in item1 item2 ... itemN; do command1; command2… done;
多行
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
while 迴圈
#!/bin/bash
int=1
while(( $int<=5 ))
do
echo $int
let "int++"
done
無限迴圈
while :
do
command
done
while true
do
command
done
for (( ; ; ))
until 迴圈
until 迴圈執行一系列命令直至條件為 true 時停止。
until 迴圈與 while 迴圈在處理方式上剛好相反。
一般 while 迴圈優於 until 迴圈,但在某些時候—也只是極少數情況下,until 迴圈更加有用。
until condition
do
command
done
跳出迴圈
break
、continue
case 語句
每個 case 分支用右圓括號開始,用兩個分號 ;;
表示 break
,即執行結束,跳出整個 case ... esac
語句,esac(就是 case 反過來)作為結束標記。
取值可以為變數或常數
echo '輸入 1 到 4 之間的數字:'
echo '你輸入的數字為:'
read aNum
case $aNum in
1) echo '你選擇了 1'
;;
2) echo '你選擇了 2'
;;
3) echo '你選擇了 3'
;;
4) echo '你選擇了 4'
;;
*) echo '你沒有輸入 1 到 4 之間的數字'
;;
esac
函式
[ function ] funname [()]
{
action;
[return int;]
}
1、可以帶 function fun()
定義,也可以直接 fun()
定義,不帶任何引數
2、引數返回,可以顯示加 return
返回,如果不加,將以最後一條命令執行結果,作為返回值。 return
後跟數值 n(0-255)
#!/bin/bash
funWithParam(){
echo "第一個引數為 $1 !"
echo "第二個引數為 $2 !"
echo "第十個引數為 $10 !"
echo "第十個引數為 ${10} !"
echo "第十一個引數為 ${11} !"
echo "引數總數有 $# 個!"
echo "作為一個字串輸出所有引數 $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73
注意,$10
不能獲取第十個引數,獲取第十個引數需要 ${10}
。當 n>=10
時,需要使用 ${n}
來獲取引數
$# 傳遞到指令碼或函式的引數個數
$* 以一個單字串顯示所有向指令碼傳遞的引數
$$ 指令碼執行的當前程序ID號
$! 後臺執行的最後一個程序的ID號
$@ 與$*相同,但是使用時加引號,並在引號中返回每個引數。
$- 顯示Shell使用的當前選項,與set命令功能相同。
$? 顯示最後命令的退出狀態。0表示沒有錯誤,其他任何值表明有錯誤。
輸入/輸出重定向
command > file 將輸出重定向到 file。
command < file 將輸入重定向到 file。
command >> file 將輸出以追加的方式重定向到 file。
n > file 將檔案描述符為 n 的檔案重定向到 file。
n >> file 將檔案描述符為 n 的檔案以追加的方式重定向到 file。
n >& m 將輸出檔案 m 和 n 合併。
n <& m 將輸入檔案 m 和 n 合併。
<< tag 將開始標記 tag 和結束標記 tag 之間的內容作為輸入。
檔案描述符 0
通常是標準輸入(STDIN),1
是標準輸出(STDOUT),2
是標準錯誤輸出(STDERR)2
和 >
之間不可以有空格,2>
是一體的時候才表示錯誤輸出
command < infile > outfile
執行 command
,從檔案 infile
讀取內容,然後將輸出寫入到 outfile
中。
檔案包含
. filename # 注意點號(.)和檔名中間有一空格
# 或
source filename
被包含的檔案 test.sh
不需要可執行許可權