shell脚本——学习笔记(包含应用案例)

Posted 0611#

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了shell脚本——学习笔记(包含应用案例)相关的知识,希望对你有一定的参考价值。

题头为本人编写shell脚本格式^v^

#!/bin/bash
#****************
#Author: Pakho
#Date: 2021-00-00
#FileName: .sh
#****************

循环

Expect命令
  • 我们通过Shell可以实现简单的控制流功能,如:循环、判断等。但是对于需要交互的场合则必须通过人工来干预,有时候我们可能会需要实现和交互程序如telnet服务器等进行交互的功能。而expect就使用来实现这种功能的工具。
  • expect是一个免费的编程工具语言,用来实现自动和交互式任务进行通信,而无需人的干预。expect是不断发展的,随着时间的流逝,其功能越来越强大,已经成为系统管理员的的一个强大助手。expect需要Tcl编程语言的支持,要在系统上运行expect必须首先安装Tcl。

一、安装

[root@pakho ~]#  yum -y install tcl expect tclx tcl-devel

二、Expect工作原理

  • 从最简单的层次来说,Expect的工作方式象一个通用化的Chat脚本工具。Chat脚本最早用于UUCP网络内,以用来实现计算机之间需要建立连接时进行特定的登录会话的自动化。
  • Chat脚本由一系列expect-send对组成:expect等待输出中输出特定的字符,通常是一个提示符,然后发送特定的响应。例如下面的
    Chat脚本实现等待标准输出出现Login:字符串,然后发送somebody作为用户名;然后等待Password:提示符,并发出响应
    sillyme。

实例

  • 例1:通过expect实现远程发送免密对系统登陆
#!/bin/bash
#****************
#Author:Pakho
#Date:2021.5.12
#Filename:ssh.sh
#****************
>ip.txt
for i in {2..245}
do
        {
                ip=192.168.100.$i
                ping -c1 -W1 $ip &>/dev/null
                        if [ $? -eq 0 ]
                                then
                                        echo "$ip" >>ip.txt
/usr/bin/expect <<-EOF
spawn ssh-copy-id $ip
expect {
        "yes/no" { send "yes\\r";exp_continue }
        "password:" { send "11111111\\r" }
        }
expect eof
EOF
                         fi
        }
done
        wait
                echo "完成!"

数组

  • 例1:使用数组统计用户shell的类型和数量
#!/bin/bash
declare -A shells   #声明数组
while read ll       #通过交互定义变量读取文件的内容定义给ll变量
        do
                type=`echo $ll | awk -F: '{print $7}'` #输出文件内容 -F:指定冒号分隔符
                let shells[$type]++  #let变量运算 shells数组名称 $type 索引
done  < /etc/passwd   #使用文件里面的内容

for i in {!shelle[*]}    #!取反 使用索引进行循环         #使用循环遍历数组
do
        echo "shell类型/索引 $i ; shell数量 ${shells[$i]}" #数组名称加索引看值
done
  • 例2:while脚本快速定义数组
#!/bin/bash
while read line
do
#hosts:数组名
#[++i]:索引递增,++i是1开始,i++是0开始
#$line:值,即文件中的内容
        hosts[++i]=$line
done < /etc/hosts

#输出索引每一行
for i in ${!hosts[*]}
do
        echo "hosts数组的索引是 $i,值是 ${hosts[$i]}"
done
  • 例3:for脚本快速定义数组
#!/bin/bash
OLD_IFS=$IFS            #将旧的分隔符备份
IFS=$'\\n'               #定义for循环的分隔符为换行符
for i in `cat /etc/hosts`
do
        hosts[++x]=$i
done

for bb in ${!hosts[*]}
do
        echo "hosts数组的索引是 $bb ,值是 ${hosts[$bb]}"
done
IFS=$OLD_IFS           #将分隔符还原便于脚本后方的for使用

for循环使用空格和回车作为分隔符
while循环使用回车作为分隔符
系统默认的分隔符变量为IFS 例:IFS=$'\\n' 将换行符定义为换行 \\r:回车

函数

- Shell 函数的本质是一段可以重复使用的脚本代码,这段代码被提前编写好了,放在了指定的位置,使用时直接调取即可。 - Shell 中的函数和C++、Java、Python、C# 等其它编程语言中的函数类似,只是在语法细节有所差别 - Shell 函数定义的语法格式如下:
function name() {
    statements
    [return value]
   }

对各个部分的说明:

  • function是 Shell 中的关键字,专门用来定义函数;
  • name是函数名;
  • statements是函数要执行的代码,也就是一组语句;
  • return value表示函数的返回值,其中 return 是 Shell 关键字,专门用在函数中返回一个值;这一部分可以写也可以不写。

由{ }包围的部分称为函数体,调用一个函数,实际上就是执行函数体中的代码。

一、定义函数

方法一:

函数名(){
	函数要实现的功能代码
	}

方法二:

 function 函数名 {
 	函数要实现的功能代码
 }

二、调用函数

函数名
函数名 参数1 参数2

函数存在的意义在于反复调用 以上只是举例

示例:

  • 例1:通过shell脚本,编写工具箱,引用函数并调用函数
需求:通过shell脚本,编写工具箱,引用函数并调用函数

思路:

  • 1、编写菜单和判断
  • 2、添加循环
  • 3、添加函数
#!bin/bash
#打印出工具箱菜单
yesorno () { read -p "继续按y,退出程序按n:" yn    #定义函数yesorno
        if [ "$yn" = y ]
                then
                 		clear                  #清屏 类似于Crtl+l键
                else
                        exit
        fi
        }

menu () {                                     #定义函数menu
cat <<EOF
-------系统工具箱-------
|    1.查看磁盘信息    |
|    2.查看内存信息    |
|    3.查看CPU信息     |
|    4.查看网络信息    |
|    5.查看进程信息    |
|    6.退出工具箱      |
-------系统工具箱-------
EOF
}

while : 													#使用whlie循环
do
	menu                                                    #调用函数menu
	read -p "请输入你的选择[1..6]" number                      #使用交互定义变量

	case $number in                                         #使用case流控
		1)
			echo "===========磁盘信息=========="
			df -hT
			echo "===========磁盘信息=========="
			read -p "继续按y,退出程序按n:" yn
			yesorno                                         #调用函数yesorno
			;;
		2)
			echo "===========内存信息=========="
			free -m
			echo "===========内存信息=========="
			yesorno                                         #调用函数yesorno
			;;
		3)
			echo "============CPU信息==========="
			uptime
			echo "============CPU信息==========="
			yesorno                                         #调用函数yesorno
			;;
		4)
			echo "=========网络端口信息========"
			read -p "请输入您要查询的网络端口号" hao
			netstat -anpt | head -2
			netstat -anpt | grep $hao
			echo "=========网络端口信息========"
			yesorno                                         #调用函数yesorno
			;;
		5)
			echo "===========进程信息=========="
			read -p "请输入您要查询的进程名" ps
			ps aux | grep $ps
			echo "===========进程信息=========="
			yesorno                                         #调用函数yesorno
			;;
		6)
			echo "感谢使用系统工具箱"
			exit
			;;
		*)
			menu                                            #调用函数menu
			;;
	esac
done                                                        #Script结束

三、函数传参

  • 例1:传参,让函数能够自定义
#!/bin/bash
fun () {                        #定义函数名fun
	fff=1                       #定义阶乘元数
	for ((i=1;i<=$1;i++))       #使阶乘循环
		do
			fff=$[$fff * $i]  #阶乘公式
		done
			echo "$fff"         #输出阶乘结果
}
fun $1
fun $2
fun $3

测试:
[root@pakho ~]# bash fun1.sh  5 6 7
120     #5的阶乘是120
720     #6的阶乘是720
5040    #7的阶乘是5040
  • 例2:shell的写法和其他运算表达式
#!bin/bash
fun () {
	fff=1
	for i in `seq $1`     
		do
        	let fff*=$i      #fff等于   fff*$i=fff
		done
			echo "$fff"
}
fun $1
fun $2
fun $3
  • 例3:函数传参,数组传参
需求:制作一个简单的阶乘脚本,通过数组给函数传参
#!/bin/bash
num=(1 2 3) #定义数组

array () {  #定义函数
factorial=1
for i in $*
        do
                factorial=$[factorial * $i] #定义阶乘的公式
        done
                echo $factorial
}

array ${num[*]}      #位置变量中的所有变量

例4:函数结果,赋予数组

场景:用户获赠流量包(每人增加5G),结果运算
#!/bin/bash
num=(1 2 3)    #定义数组表示用户的初值

array () {
local g        #local 定义变量仅在函数中有效
for i in $*
        do
                outarray[g++]=$[$i+5]  #第二个数组表示计算之后的值
        done
                echo ${outarray[*]}    #输出新的数组
}

array ${num[*]}


四、影响shell程序的内置命令

:
true  #真
false #假
exit  #退出程序
break #退出循环
continuesh #跳出本次循环进行下一次循环
shift      #
———————————————————————————————————————————————————————————————————————————————————

shift使位置参数向左移动,默认移动一位,可以使用shift 2
exit 退出整个程序
break结束当前循环,或跳出本层循环
continue 忽略本次循环的代码,直接进行下一次的循环


  • 循环嵌套的的规则:外部循环一次,内部循环全部

实例

  • 例1:continue、break&exit
需求:跳出5的循环
环境:
[root@pakho ~]# bash for.sh
A123456789
B123456789
C123456789
D123456789
#!/bin/bash
for i in {A..D}
do
echo -n $i
        for j in {1..9}
        do
                if [ $j -eq 5 ]
                        then
                              # continue
                              # break 2  break可以添加参数 跟的数字决定跳出几个循环体
                              # exit    
                fi
        echo -n $j
        done
echo                #echo相当于回车
done

例2:shift参数移动

1)for循环不定义循环范围,循环取参数作为循环范围

#!/bin/bash
for i
do
        let sum+=$i  #+=    sum+$i等于sum 将结构赋值给sum
done
echo "总和:$sum"

2)使用while循环,发现停不下来

#!/bin/bash
while [ $# -ne 0 ]
do
        let sum+=$1
done
echo "总和:$sum"        #成为死循环 发现循环无法停止

3)使用shift移动参数的命令,结果得以实现

#!/bin/bash
while [ $# -ne 0 ]
do
        let sum+=$1
        shift          #本行添加
done
echo "总和:$sum"

参数位移
4)shift创建用户案例

#!/bin/bash
while [ $# -ne 0 ]
do
        useradd $1
        echo "$1 创建成功"
        shift
done

正则表达式

未完待续

以上是关于shell脚本——学习笔记(包含应用案例)的主要内容,如果未能解决你的问题,请参考以下文章

shell脚本学习-文件包含

shell脚本——sed详细介绍(包含应用案例)

shell脚本——awk详细介绍(包含应用案例)

Linux学习笔记-Shell教程

shell脚本——正则表达式(包含grep详细介绍及应用)

Shell脚本(学习笔记1)