一、什么是shell
以前没有系统学习shell,只是在做pwn时一般是直接调用system(“/bin/sh”)实现root权限的获取,所以觉得/bin/sh就是getshell。
Shell脚本中很多开头有#!/bin/sh,#! 告诉系统其后路径所指定的程序即是解释此脚本文件的 Shell 程序。个人感觉shell有点像python,所以就着类比学习一下,
二、一般规则
1、变量命名和C差不多,赋值变量直接写名字赋值,使用变量用${变量名}的形式。
1 | skill = "king" |
2、使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。
1 |
|
3、删除变量
1 |
|
4、字符串
好用的字符串,一般是双引号为主可以转义和拼接
1 | aa="run" |
字符串拼接
1 | $string="runoob is a great site" |
计算字符串长度,用#,相当于len()
1 | king="victor" |
根据下标范围提取子串,可以类比python的写法
1 | string="runoob is a great site" |
查找字母第一次出现的位置
1 | string="runoob is a great site" |
5、shell的数组
在 Shell 中,用括号来表示数组,数组元素用”空格”符号分割开。可以看成python中的列表(*表示全部,#表示len())
1 | value=(1 "king" 3 4 5) |
6、注释方式:#、!、EOF、`均可
1 | # value=“king” |
7、脚本传递参数: @表示全部参数,*全部参数表示一行
1 | echo "$0 $1 $2" |
8、运算符表达式
表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。
完整的表达式要被 `包含,注意这个字符不是常用的单引号,在 Esc 键下边。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27#算术运算、逻辑运算、布尔运算、关系运算
val=`expr 100 % 2 + 2 - 6 \* 3 / 2`
echo $val
if [ $val == -7 ];then
echo "good!"
fi
if [[ $val -ne -10 && $val -lt -1 || $val -gt -12 || $val -eq -7 || $val -ge -7 ]];then
echo "this is good!!"
fi
if [ $val -ne -10 -a $val -lt -1 -o $val != -9 ];then
echo "yes"
fi
#字符串运算
if [ -z $a ]
then
echo "-z $a : 字符串长度为 0"
else
echo "-z $a : 字符串长度不为 0"
fi
if [ -n "$a" ] #记得加双引号
then
echo "-n $a : 字符串长度不为 0"
else
echo "-n $a : 字符串长度为 0"
fi关于文件运算符的描述:
-b file 检测文件是否是块设备文件,如果是,则返回 true。 [ -b $file ] block -c file 检测文件是否是字符设备文件,如果是,则返回 true。 [ -c $file ] char -d file 检测文件是否是目录,如果是,则返回 true。 [ -d $file ] diractory -f file 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 [ -f $file ] file -g file 检测文件是否设置了 SGID 位,如果是,则返回 true。 [ -g $file ] sgid -k file 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 [ -k $file ] 返回 false。 -p file 检测文件是否是有名管道,如果是,则返回 true。 [ -p $file ] pipe -u file 检测文件是否设置了 SUID 位,如果是,则返回 true。 [ -u $file ] -r file 检测文件是否可读,如果是,则返回 true。 [ -r $file ] 返回 true。 -w file 检测文件是否可写,如果是,则返回 true。 [ -w $file ] 返回 true。 -x file 检测文件是否可执行,如果是,则返回 true。 [ -x $file ] 返回 true。 -s file 检测文件是否为空(文件大小是否大于0),不为空返回 true。 [ -s $file ] sky -e file 检测文件(包括目录)是否存在,如果是,则返回 true。 [ -e $file ] exist
不如实践来的快:
1 | if [ -e 1.sh ];then |
9、echo、printf输出字符串总结
能否引用变量 | 能否引用转移符 | 能否引用文本格式符(如:换行符、制表符)
单引号 | 否 | 否 | 否
双引号 | 能 | 能 | 能
无引号 | 能 | 能 | 否
1 | read -p "Input name and pwd:" -n 10 -t 10 -s name password #-n表示长度,-t表示时间,-s表示隐藏 |
10、test命令的使用
和[]作用一样的,其中$[]中括号里面可以进行算术运算
1 | num1=100 |
11、流程控制的书写
其中还是(())最好用,类似c语言的写法
1 | #if的脚本书写的形式 |
12、函数调用
$# | 传递到脚本或函数的参数个数 |
---|---|
$* | 以一个单字符串显示所有向脚本传递的参数 |
$$ | 脚本运行的当前进程ID号 |
$! | 后台运行的最后一个进程的ID号 |
$@ | 与$*相同,但是使用时加引号,并在引号中返回每个参数。 |
$- | 显示Shell使用的当前选项,与set命令功能相同。 |
$? | 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误,存函数返回值 |
第11个参数起都要${11}这样。
1 | function1(){ |
函数与命令的执行结果可以作为条件语句使用。要注意的是,和 C 语言不同,shell 语言中 0 代表 true,0 以外的值代表 false。
13、关于输入输出的重定向
类 型 | 符 号 | 作 用 |
---|---|---|
标准输出重定向 | command >file | 以覆盖的方式,把 command 的正确输出结果输出到 file 文件中。 |
command >>file | 以追加的方式,把 command 的正确输出结果输出到 file 文件中。 | |
标准错误输出重定向 | command 2>file | 以覆盖的方式,把 command 的错误信息输出到 file 文件中。 |
command 2>>file | 以追加的方式,把 command 的错误信息输出到 file 文件中。 | |
正确输出和错误信息同时保存 | command >file 2>&1 | 以覆盖的方式,把正确输出和错误信息同时保存到同一个文件(file)中。 |
command >>file 2>&1 | 以追加的方式,把正确输出和错误信息同时保存到同一个文件(file)中。 | |
command >file1 2>file2 | 以覆盖的方式,把正确的输出结果输出到 file1 文件中,把错误信息输出到 file2 文件中。 | |
command >>file1 2>>file2 | 以追加的方式,把正确的输出结果输出到 file1 文件中,把错误信息输出到 file2 文件中。 |
直接上代码:
1 | echo "king" > name.txt |
14、关于代码复用、库的使用
1 | . ./7.sh #先声明一下需要使用到的文件,还可以用source命令 |
这里只要把文件载入进来了就可以直接用里面的值了。
三、变量类型
运行shell时,会同时存在三种变量:
- 1) 局部变量 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
- 2) 环境变量 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
- 3) shell变量 shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行
四、方法和易错点总结
在shell脚本要运行linux的命令的话,可以有三种方法:
1 | ls |
进行数值运算也有3种方法:
1 | #实现number=number+1的效果 |
进行条件判断有2种方法:
1 | if [[ $number -le 5 ]] #shell的正规军要求 |
之所以有些shell命令不能直接运行是因为:
/bin/sh链接到了dash而不是bash,所以脚本李敏#!后面写解析器时可以自己定义为bash。