网络安全自学笔记08 - Linux之shell

一、shell基本概述

  • 什么是shell脚本?到底能解决什么问题?shell脚本其实就是把一批命令集合在一起,解决一些复杂的问题,有点类似于程序设计(在shell中,变量、分支、循环、函数、数组等与程序设计完全类似的功能),但是本质上来说不是程序设计。shell的程序复杂程度是无法真正与编程语言相提并论的,但是由于与操作系统集合在一起的,所以能够执行一些更加底层的命令组合,且效率很高
  • linux系统中的shell是一个特殊的应用程序,它介于操作系统内核与用户之间,充当了一个“命令解释器”的角色,负责接收用户输入的操作指令并进行解释,将需要执行的操作传递给内核执行,并输出执行结果
  • 常见的shell解释器程序有很多种,使用不用的shell脚本是,其内部指令、命令行提示等方面会存在一些区别,通过/etcshells文件可以了解当前操作系统支持的shell脚本种类
    #列出系统中所有的shell
    cat /etc/shells
    # 查看当前环境变量$shell的值
    echo $shell
    

二、shell的类型

  • Bourne Shell:是贝尔实验室开发的,unix普遍使用的shell,在编程方面比较优秀,但在用户交互方面没有其他shell优秀
  • Korn Shell:是针对Bourne Shell的发展,在大部分内容上与Bourne Shell兼容,继承了C Shell和Bourne Shell有点。
  • BASH:是GNU的Bourne Again Shell,是GNU操作系统上默认的shell,在Bourne Shell基础上增强了很多特性,如命令补全,命令历史表
  • C Shell:是SUN公司的BSD版本,语法与C语言相似,比Bourne shell跟适合编程

三、创建一个shell并执行

  • 新建shell文件并编写内容

    vi first.sh
    cd /boot
    pwd
    ls -lh vml*
    
  • 添加执行权限

    chmod +x first.sh
    
  • 执行shell脚本(3种执行方法)

    # 当前目录下使用 ./ ,需要添加执行权限
    ./first.sh
    # sh . source执行不需要执行权限
    sh first.sh
    . first.sh
    source first.sh
    

四、重定向与管道操作

1、重定向操作

  • 标准输入:默认的设备是键盘,文件编号为0,命令将从标准输入文件中读取在执行过程中需要的输入数据,使用 < 操作符
  • 标准输出:默认的设备是显示器,文件编号为1,命令执行后的输出结果发送到标准输出文件。使用 > 覆盖或 >> 追加文件
  • 标准错误:默认的设备是显示器,文件编号为2,使用 2> 或 2>> 用来将错误信息覆盖或追加到文件中(在标准输入、标准输出重定向时,实际上省略了1、0编号)
  • 混合输出:使用 &> 将错误和标准信息一同保存到文件中

2、管道操作

  • 管道操作为不同命令之间的协同工作提供了一种机制,位于管道符号“ | ” 左侧的命令输出的结果,将作为右侧命令的输入,同一行命令中可以使用多个管道

五、shell变量

1、定义并输出一个变量

# 定义一个变量
home=jilin
# 打印这个变量的值
echo $home
# 使用read命令定义变量,手动输入,-p选项来设置提示信息
read -p "请输入家乡:"school
echo $school

2、{},“”,‘’,``,的作用

# {}大括号的作用,用于包括变量名,以免与后面相连导致变量名错误
echo ${home}1.2
# ""双引号赋值时的作用,赋值变量时出现括号时使用,是为一整个变量
home="jilin baicheng"
# ""双引号也可以通过$符合引用其他变量的值
home=jilin
home1=baicheng
homes="$home $home1"
echo $homes
# ''单引号的作用,禁止引用其他变量的值,$视为普通字符
homes='$home $home1'
echo $homes
# ``反撇号的作用,命令替换,提取命令执行后的输出结果
ls -lh`which useradd`

3、变量的作用范围

  • 默认为局部变量
  • 可以使用内部命令 export 将指定的变量导出为全局变量

4、变量的运算

  • 在bash shell 环境中,只能进行简单的整数运算,不支持小数运算,整数值的运算主要通过内部命令 expr 进行,运算符与变量之间至少有一个空格
    • + :加法运算
    • - :减法运算
    • \* :乘法运算,不能仅使用 * 不然会被当成文件通配符
    • / :除法运算
    • % :取模运算
X=35
Y=16
expr $X + $Y
expr $X - $Y
expr $X \* $Y
expr $X / $Y
expr $X % $Y

5、环境变量

  • 环境变量由系统维护,用于设置用户的工作环境,包括用户的宿主目录,命令查找路径, 用户当前目录,登录终端等
  • 使用env命令可以查看到当前工作环境下的环境变量
  • 环境变量的全局配置文件为 /etc/profile(此文件会在用户第一次登录时读取) ,初次之外,每个用户还有自己的独立配置文件 ~ /.bash_profile(此文件会在登录时以及每次运行新shell时读取) ,修改用户的配置文件只会针对用户生效
    • linux中自动启动脚本
      • /etc/rc.d/rc.local:系统在启动时进行加载,/erc/rc.local是本文件的软链接文件
      • /etc/profile :此文件为系统的每一个用户设置环境信息,当用户第一次登录时该文件被执行
      • /etc/bashrc:为每一个运行bash shell的用户执行此文件,当bash shell被打开时,该文件被读取
      • ~/.bash_profile:每个用户都可以使用该文件输出专用于自己的shell信息,当用户登录时该文件仅仅执行一次
      • ~/.bashrc:该文件包含专用于你用户的bash shell的bash信息,当登录时以及每次打开新的shell时,该文件倍读取
      • ~/.bash_logout:每当退出系统(退出bash shell)时,执行该文件

6、位置变量

  • 通过命令行给脚本程序传递参数
  • 位置变量:也成为位置参数,使用$1、$2、$3、。。。$9、${11}、。。。表示。如当执行命令行 ls -lh /boot/时,其中第一个位置变量为 -lh ,以 $1 表示,第二个位置变量为 /boot/,以 $2表示,命令或脚本本身的名称使用 $0 表示,虽然 $0与位置变量的格式相同,但是 $0属于预定义变量而不是位置变量
  • 预定义变量:bash中内置的一类变量,不能直接修改
    • $#:表示命令行中位置参数的个数
    • $*:表示所有位置参数的内容
    • $?:表示前一条命令执行后的返回状态,0表示正确,非0表示执行出现异常,用于判断
    • $0:表示当前执行的脚本或程序的名称
    • $@:返回每个参数,所有参数是一个字符串
    • $!:后台允许的最后一个进程的id号
    • $_:代表上一个命令的最后一个参数
    • $$:脚本允许的ID号

7、shell 结构语句

(1)test条件测试语句

  • test 条件表达式 或 [ 条件表达式 ]
  • 参数
    • -d : 测试是否为目录
    • -e:测试目录或文件是否存在
    • -f:测试是否是文件
    • -r:测试当前用户是否有读取权限
    • -w:测试当前用户是否有权限写入
    • -x:测试是否设置有可执行权限
test -d /media/
[ -d /media/ ]
echo $?
# 再shell中一切皆命令,[ ] 判断是test的另一种写法,当$?查看上一条结果为0时,则条件成立
# 测试条件成立,并直接输出yes
[ -d /media/cdrom ] && echo "yes"

(2)整数值比较符号(-eq、-ne、-gt、-lt、-le、-ge)

  • -eq:第一个数等于第二个数
  • -ne:第一个数不等于第二个数
  • -gt:第一个数大于第二个数
  • -lt:第一个数小于第二个数
  • -le:第一个数小于或等于第二个数
  • -ge:第一个数大于或等于第二个数
users=`who | wc -l |uniq`
[ $suers -gt 5 ] && echo "当前用户登录过多  "

(3)字符串比较符号(=、!=、-z)

  • =:第一个字符串与第二个字符串相同
  • !=:第一个字符串与第二个字符串不相同
  • -z:检查字符串是否为空,对与未定义和赋予空值的变量将是为空字符串
# 判断是否安装中文
[ $LANG != "zh_CN" && ehco "没有安装中文"
# 经常需要用户输入"yes"或"no"来确认某个任务,还需要根据变量"ACK"的取值分别执行进一步的操作
read -p "是否覆盖现有文件(yes/no)?" ACK
[ $ACK = "yes" ] && echo "覆盖"

(4)逻辑判断符号(&&、||、!)

  • &&:逻辑与,表示并且,只有当前后两个条件都成立时,真个测试命令的返回值为0,使用test命令测试时,“&&“可改为”-a”
  • ||:逻辑或,表示或者,只要前后两个条件中有一个成立,整个测试命令的返回值为0,使用test命令测试时,“||“可改为”-o”
  • !:逻辑否,表示不,只有条件不成立时,整个测试命令的返回值为0
# 测试当前Linux系统的内核版本是否大于3.4
uname -r
Munm=$(uname -r | awk -F . '{print $1}')
Snum=$(uname -r | awk -F . '{print $2}')
[ $Mnum -ge 3 ] && [$Snum -gt 4] && echo "符合要求"

(5)if结构语句 与 case分支语句

1)if结构语句

  • 语法

    # 单分支if语句
    if 条件测试操作
    then
    	命令序列
    if
    
    # 双分支if语句
    if 条件测试操作
    then
    	命令序列1
    else
    	命令序列2
    if
    
    # 多分支if语句
    if 条件测试操作
    then
    	命令序列1
    elif
    	命令序列2
    else
    	命令序列3
    if
    

2)case分支语句

  • 语法

    case 变量值 in
    	模式 1)
    		命令序列1
    		;;
    	模式 2)
    		命令序列2
    		;;
    	*)
    		默认命令序列
    esac
    

3)if 结构语句 与 case 分支语句示例

  • 编写控制sleep进程脚本,通过位置变量$1指定start、stop、restart、status控制参数,分别来启动、停止、重启sleep进程。
    case "$1" in
    	start)
    		echo -n "正在启动sleep服务..."
    		if sleep 7200 & ; then
    			echo "OK"
    		fi
    		;;
    	stop)
    		echo -n "正在停止sleep服务..."
    		pkill "sleep" &> /dev/null
    		echo "OK"
    		;;
    	status)
    		if pgrep "sleep" &> /dev/null ; then
    			echo "sleep"
    		else
    			echo "sleep"
    		fi
    		;;
    	restart)
    		$0 stop
    		$0 start
    		;;
    	*)
    		echo "用法:$0 {start|stop|staus|restart}"
    	esac	
    

(6)循环语句

1)for循环语句

  • 语法
    for 变量名 in 取值列表
    do
    	命令序列
    done	
    
  • for循环批量添加用户的脚本示例
    # users.txt内容需每行为一个用户名
    ULIST=$(cat /root/users.txt)
    for UNAME in $ULIST ; do
    	useradd $UNAME
    	echo "123456" | passwd -stdin $UNAME &>/dec/null
    done
    

2)while 循环语句

  • 语法

    while 条件测试操作 ; do
    	命令序列
    done
    
  • 批量添加规律编号的用户示例

    PREFIX="stu"
    i=1
    while [$i -le 20 ] ; do
    	useradd ${PREFIX}$i
    	echo "123456" | passwd --stdin ${PREFIX}$i &> /dev/null
    	let i++
    done
    

3)until 循环语句

  • 语法

    until 条件测试操作 ; do
    	命令序列
    done
    
  • 示例

    i=0 ; s=0
    until [$i -eq 50 ] ;do 
    	let "i=$i+1"
    	let "s=$s+$i"
    done
    

4)select循环语句

  • 语法

    select 变量名 in 值列表 ; do
    	命令序列
    done
    
  • 示例

    select item in "CPU" "IP" "MEM" "exit" ; do
    	case $itme in 
    		"CPU")
    			UPTIME;;
    		"IP")
    			ip add;;
    		"MEM")
    			free;;
    		"ecit")
    			exit;;
    		*)
    			echo error;;
    	esac
    done
    

(7)中断与退出控制

  • continue :结束单词循环
  • break :结束整个循环体
  • exit :直接结束整个脚本

六、shell数组与函数

1、数组

(1)基本语法

  • shell数组用括号来表示,元素用空格分隔,元素的下标与大部分编程语言类似由0开始

    # 定义1
    数组名=(value0 value1 value2 ...)
    # 定义2
    数组名=([0]=value [1]=value [2]=value ...)
    # 定义3
    列表名="value0 value1 value2 ..."
    数组名=($列表名)
    数组名[0]="value"
    数组名[1]="value"
    数组名[2]="value"
    
  • 获取数组长度

    arr_number=(1 2 3 4 5)
    arr_length=${#arr_number[*]}
    echo $arr_length
    
  • 读取某下标值

    arr_index2=${arr_number[2]}
    
  • 数组遍历

    arr_number=(1 2 3 4 5)
    for i in ${arr_number} ; do
    	echo $i
    done
    
  • 对数组中某个索引重新赋值

    arr_number=[1 2 3 4 5)
    $arr_number[2]=5
    

(2)关联数组

  • 需要使用书 “ declare -A 数组名称 ” 才能定义一个关联数组

    declare -A woman 
    woman=([name]=xiaoming [age]=22 [addr]=chengdu)
    echo $woman[name]
    

2、函数

  • 语法

    # 关键字function 可以省略
    function 函数名(){
    	命令序列
    	[return 0] #可选项
    }
    # 调用函数
    函数名
    
    
  • 多进程ping测试主机是否存活示例

    net="192.168.1"
    multi_ping(){
    	ping -c 2 -i 0.2 -W 1 $1 &> /dev/null
    	if [ $? -eq 0 ] ; then
    		echo "$1 is up"
    	else
    		echo "$1 is down"
    	fi
    }
    for i in {1..254} ; do
    	multi_ping $net.$i
    done
    

你可能感兴趣的:(网络安全自学笔记,linux,bash,unix)