渗透测试-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 不需要可执行权限

posted @ 2022-03-19 12:30  toki-plus  阅读(99)  评论(0编辑  收藏  举报