1. 程式人生 > 其它 >滲透測試-07:Shell

滲透測試-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

變數作用域

  1. 區域性變數:區域性變數在 指令碼或命令中定義,僅在當前shell例項中有效,其他shell啟動的程式不能訪問區域性變數
  2. 環境變數:所有的程式,包括shell啟動的程式,都能訪問環境變數,有些程式需要環境變數來保證其正常執行。必要的時候shell指令碼也可以定義環境變數
  3. 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

跳出迴圈

breakcontinue

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 不需要可執行許可權