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