作者主页

目录

为什么要学习Shell?

shell变量概述

变量使用

变量定义方式

截取

查看变量

清除变量

变量嵌套

开启新shell 全局变量

系统环境变量

位置参数

预定义变量

shell变量赋值

if比较

for循环

脚本题

变量替换

shell变量运算

流程控制语句

单分支语句

双分支语句

多分支语句

文件比较

与或非格式

流程控制语句-整数比对

流程控制语句-字符对比

正则表达式

流程控制语句-正则比对

case语句

循环语句

批量创建用户

批量探测主机是否存活

随机点名

随机猜数

程序语句

函数与数组

为什么要学习Shell?

1、什么是Shell

Shell是一种用户使用的解释型程序,它是操作系统的一部分,派生自多种不同的系统。它是一种命令解释器,它可以读取用户的输入,解释该输入,并执行相应的命令。 Linux的Shell有很多种,如bash,csh,ksh等。当前常用的为bash

2、Shell 的特性

(1)交互式:用户可以通过Shell的界面实现与计算机的交互,以便用户和计算机之间的信息交换。

(2)自动化: Shell 可以将用户编写的一系列命令,保存为脚本,并在需要的时候自.动执行,以减少用户的工作量。

(3)扩展性: Shell 可以实现过滤和管道功能,可以与其他应用程序和编程语言结合使用,实现不同应用程序、不同编程语言之间的信息传递

#!/bin/bash #shell脚本应以此开头

chmod +x test.sh #新脚本完成后需要给予运行权限

#脚本运行方法

./test.sh #用户身份执行

/sh/test.sh #用户身份执行

sh test.sh #管理员身份执行

source test.sh #管理员身份执行

. test.sh #管理员身份执行

shell变量概述

变量是shell传递数据的一种方法,即用一个固定的字符串去表示不固定的值,便于后期引用

变量使用

a=34 #将固定字符a表示为34

echo $a #返回a

34 #返回的执行结果

name="zhangsan" #定义变量

age=19 #定义变量

score=90 #定义变量

id=1 #定义变量

info="ID:$id Name:$name Age:$age Score:$score" #在变量中引用变量

eccho $info #返回info

ID:1 Name:zhangsan Age:19 Score:90 #返回结果

time=$(date +%F) #变量中套用命令

echo $time #返回time

2023-07-25 #返回的执行结果

变量定义方式

用户自定义变量:人为定义变量

系统环境变量:系统操作环境相对自带的

位置参数变量:向脚本传递参数的变量

预定义变量:bash定义好的变量

变量名不能出现"-",有空格时需要用引号括起来

var=“hello word”

2.引用变量,$+变量名或者${变量名}

id=1 #定义变量

info="ID:$id" #引用id变量

name=zhangsan #定义name变量

echo "${name}_is" #引用name变量时后缀加_is

zhangsan_is #返回结果

例:

id=1

name=zhangsan

age=19

score=90

student="ID:${id}姓名:${name}年龄:${age}成绩:${score}"

echo $student

ID:1姓名:zhangsan年龄:19成绩:90

截取

ifconfig ens33|head -2|tail -1|awk '{print $2}' #截取ip

df -hT|head -7|tail -1|awk '{print $6}' #截取硬盘使用百分比

used *100 / buff/cache #内存占比公式定义为变量时双嵌套

mem=$((used *100 / buff/cache)) #计算

查看变量

set |grep ip

清除变量

unset ip

引用变量,双引号属于弱引用取变量的值,单引号属于强引用原封不动引用变量

echo "$var hello china" #需要引用变量值

echo '$var hello china' #只想引用变量名,不执行$特殊符号

echo "$var hello china \$SHELL" #部分变量执行,部分变量不执行

变量嵌套

aa=$(rpm -e $(rpm -qa|grep java)) #将由里向外运行命令

开启新shell 全局变量

bash #开启一个新的shell,之前设定的所有局部变量将清空

export ip=$(ifconfig ens33|head -2|tail -1|awk '{print $2}')

#变量前加export时变量变为全局变量可在多个shell中使用,不加时默认为局部变量

系统环境变量

echo $PATH #PATH路径,系统命令查找路径

/usr/local/bin:/usr/local/sbin:/usr/bin:usr/sbin #PATH返回结果

export PATH=${PATH}:/sh #在PATH中添加路径(重启丢失)

echo "export PATH=${PATH}:/sh" >> /etc/profile #永久追加路径

echo "宿主目录: $HOME"

echo "当前目录: $PWD"

echo "主机名: $HOSTNAME"

echo "客户端地址和端口: $SSH_CONNECTION"

位置参数

vim variable.sh

#!/bin/bash

echo "当前shell脚本的文件名:$0"

echo "第1个shell脚本位置参数:$1"

echo "第2个shell脚本位置参数:$2"

echo "第3个shell脚本位置参数:$3"

echo "第10个shell脚本位置参数:${10}"

例:

vi test.sh

#!/bin/bash

echo $(($1 + $2))

#

./test.sh 34 56 #34即为$1 56即为$2

90 #返回的值

vi test.sh

#!/bin/bash

​echo $1

echo $2

echo $3

echo $4

echo $5

#

./test.sh 23 34 45

23 #返回的值

34 #返回的值

45 #返回的值

预定义变量

echo $* #所有传递的位置参数:

echo $@ #所有传递的位置参数:

echo $# #共传递的参数数量

echo $$ #当前程序运行的PID:

echo $? #返回上一个命令执行的返回结果为0时代表上一个命令成功其他为错误

vi test.sh

#!/bin/bash

echo $*

echo $@

#

./test.sh 2 34 535 54 35 345

2 34 535 54 35 345 #返回的值所有传递的位置参数

2 34 535 54 35 345 #返回的值所有传递的位置参数

vi test.sh

#!/bin/bash

echo $#

#

./test.sh 2 34 535 54 35 345

6 #返回的值总共传递的参数数量

vi test.sh

#!/bin/bash

echo $$

#

./test.sh

6667 #返回的值脚本本身pid

shell变量赋值

例:read -p 交互方式变量赋值

vi test.sh

#!/bin/bash

read -p "请输入第一个值:" num1

read -p "请输入第二个值:" num2

sum=$((num1 + num2))

echo "$num1 + $num2 = $sum"

#执行以上脚本

./test.sh

请输入第一个值:4 #返回结果

请输入第二个值:8 #返回结果

4 + 8 = 12 #返回结果

&> #混合输出将覆盖原文件的信息,&>>将追加至源文件信息后

ping -w1 -c1 baidu.com &> file

cat file

PING baidu.com (110.242.68.66) 56(84) bytes of data. #file文件信息

64 bytes from 110.242.68.66 (110.242.68.66): icmp_seq=1 ttl=128 time=21.5 ms #file文件信息

#file文件信息

--- baidu.com ping statistics --- #file文件信息

1 packets transmitted, 1 received, 0% packet loss, time 0ms #file文件信息

rtt min/avg/max/mdev = 21.571/21.571/21.571/0.000 ms #file文件信息

ping -c1 -w1 www.baidu.com &> /dev/null #/dev/null为系统自带垃圾箱,放此后会删除

echo $? #返回上一个命令执行的返回结果 0 0为真其他为假

if比较

-e 文件名 如果文件存在则为真

-r 文件名 如果文件存在且可读则为真

-w 文件名 如果文件存在且可写则为真

-x 文件名 如果文件存在且可执行则为真

-s 文件名 如果文件存在且至少有一个字符则为真

-d 文件名 如果文件存在且为目录则为真

-f 文件名 如果文件存在且为普通文件则为真

-c 文件名 如果文件存在且为字符型特殊文件则为真

-b 文件名 如果文件存在且为块特殊文件则为真

= 等于则为真

!= 不相等则为真

-z 字符串 字符串的长度为零则为真

-n 字符串 字符串的长度不为零则为真

-eq 等于则为真

-ne 不等于则为真

-gt 大于则为真

-ge 大于等于则为真

-lt 小于则为真

-le 小于等于则为真

vi read3.sh

#!/bin/bash

read -p "请输入需要检测的ip地址:"IP

ping -w1 -c1 ${IP} &> /dev/null #-c指定包的数量,-w为等待时间秒为单位 &>:混合输出至 #/dev/null:系统自带垃圾箱

if [ $? -eq 0 ];then #if [];then 条件,then满足时返回

#$? -eq 0 $?返回的值等于0

echo "${IP} 可以通信" #满足$? -eq 0时返回

else #不满足上面条件时

echo "${IP} 无法通信"

fi

for循环

for 将要使用的变量名 in 一个数列

do

要做的事情

done

#!/bin/bash

read -p "请输入网段:" IP

for i in {1..254}

do

ping -c 1 -w 1 ${IP}.${i} &> /dev/null

if [ $? -eq 0 ];then

echo -e "\033[32m ${IP}.${i}可以通信 \033[0m"

else

echo -e "\033[31m ${IP}.${i}无法通信 \033[0m"

fi

done

脚本题

在每月第一天备份并压缩/etc目录的所有内容,放到/backup,备份文件以时间戳命名。 (1) 备份目录在哪,/backup (2) 备份目标是谁,/etc (3) 命令,tar (4) 时间戳命名,$(date +%F)

变量替换

url="www.baidu.com"

echo $url

www.baidu.com #返回的值

echo ${url#*.}

baidu.com #返回的值

${变量#匹配规则} #从头开始匹配,最短删除

${变量##匹配规则} #从头开始匹配,最长删除

${变量%匹配规则} #从尾开始匹配,最短删除

${变量%%匹配规则} #从尾开始匹配,最长删除

${变量/旧字符串/新字符串} #替换字符串,仅替换第一个

${变量//旧字符串/新字符串} #替换字符串,替换全部

例1:从前往后删变量内容

Qh_url=mirrors.tuna.tsinghua.edu.cn

echo $Qh_url #直接返回变量

echo ${Qh_url#*.} #删除.分隔的第一个字段

echo ${Qh_url##*.} #仅保留最后一个字段

例2:从后往前删变量内容

Qh_url=mirrors.tuna.tsinghua.edu.cn

echo $Qh_url

echo ${Qh_url%.*} #删除最后一个字段

echo ${Qh_url%%.*} #仅保留第一个字段

例3:变量内容替换

Qh_url=mirrors.tuna.tsinghua.edu.cn

echo $Qh_url

echo ${Qh_url/u/U} #替换从左往右第一个

echo ${Qh_url//u/U} #替换所有

shell变量运算

1.整数运算,expr、$(())、$[],不支持小数运算

a+b 加 a-b 减 a*b 乘(expr计算时,用 \ *) a/b 除 a%b 余

例1:

#只能进行整数之间的运算

a=20

b=10

#运算方式

expr $a + $b

echo $(( $a + $b ))

echo $[ $a + $b ]

例2:递增和递减

#每运行一次对应的数值就加1

echo $((a++))

echo $((a--))

echo $((++b))

echo $((--b))

echo $((100*(1+100)/2)) 求1到100之和

脚本题: 例:查看内存使用率,仅保留整数

#!/bin/bash

Mem_use=$(free -m |grep ^M |awk '{print $3/$2*100}')

if [ ${Mem_use%.*} -ge 80 ];then # -ge 大于等于

echo "memory is overfull: ${Mem_use%.*}%"

else

echo "memory is OK: ${Mem_use%.*}%"

fi

例:查看磁盘使用状态,使用率超出80%就报警 思路: 怎么查看磁盘 怎么提取使用率 整数判断

#!/bin/bash

Disk=$(df -h |grep /$ |awk '{print $(NF-1)}') #NF代表列的数量

if [ ${Disk%\%} -ge 80 ];then

echo "你的磁盘使用率过高:$Disk"

else

echo "你的磁盘使用率正常:$Disk"

fi

流程控制语句

单分支语句

if [ 满足条件 ];then

执行代码

fi

#!/bin/bash

if [ while 1>0 ];then #如果1>0

echo "ok"

fi

双分支语句

if [ 满足条件 ];then

执行代码

else #如果上面条件不满足

执行另一条代码

fi

#!/bin/bash

if grep "$1" /etc/passwd;then

echo "ok"

else

echo "error"

fi

多分支语句

if [ 满足条件1 ];then

执行代码1

elif [ 满足条件2 ];then

执行代码2

else #如果以上条件都不满足

执行最后代码

fi

例:

#!/bin/bash

read -p "请输入用户名:" User

if grep $User /etc/passwd &> /dev/null;then

echo "用户$User存在"

elif ls -d /home/$User &> /dev/null;then

echo "用户$User不存在"

echo "但是$User宿主目录存在"

else

echo "用户$User不存在"

echo "$User宿主目录也不存在"

fi

文件比较

-e 文件或目录是否存在 [ -e file ]

-s 文件存在且至少有一个字符则为真 [ -s file ]

-d 目录是否存在 [ -d file ]

-f 文件是否存在 [ -f file ]

-r 文件存在且可读 [ -r file ]

-w 文件存在且可写 [ -w file ]

-x 文件存在且可执行 [ -x file ]

#!/bin/bash

if [ -e /etc/passwd ];then

echo "/etc/passwd存在"

else

echo "/etc/passwd不存在"

fi

#判断/etc/passwd是否存在

与或非格式

&& #与 1 && 1 = 1 0 && ? = 0 两者同时满足

|| #或 1 || ? = 1 0 || 1 = 1 两者满足其一

! #非 取反 !真 = 假 反之则为真

流程控制语句-整数比对

-eq #等于则为真 [ $? -eq 0 ]

-ne #不等则为真 [ $? -ne 0 ]

-gt #大于则为真 [ 1 -gt 2 ]

-lt #小于则为真 [ 1 -lt 2 ]

-ge #大于等于则为真 [ 1 -ge 2 ]

-le #小于等于则为真 [ 1 -le 2 ]

例1:监控nginx状态,nginx故障则停止keepalived服务

#!/bin/bash

killall -0 nginx

if [ $? -ne 0 ];then

systemctl stop keepalived

fi

例2:判断服务是否运行

#!/bin/bash

if [ $# -ne 1 ];then

echo "请在运行代码后输入一个服务名称"

exit

fi

systemctl status "$1" &> /dev/null

if [ $? -eq 0 ];then

echo "$1 服务正在运行"

else

echo "$1 服务没有运行"

systemctl restart $1

echo "$1 服务已重新启动"

fi

流程控制语句-字符对比

= 等于则为真 [ "$a" == "$b" ]

!= 不等则为真 [ ! "$b" == "$a" ]

-z 字符长度为零则为真 [ -z "$a" ]

-n 字符长度不为零则为真 [ -n "$a" ]

str1>str2 str1大于str2则为真 [ str1>str2 ]

str1

#!/bin/bash

read -p "请输入yes/no:" n

if [ ${n} = "yes" ];then

echo "this is ok"

else

echo "this is no"

fi

#!/bin/bash

read -p "请输入你的分数" fs

expr $fs + 1 &> /dev/null

if [ $? -ne 0 ];then

echo "请输入一个数字"

exit

fi

if [ $fs -ge 0 -a $fs -le 60 ];then

echo "成绩不及格,请补考"

elif [ $fs -gt 60 -a $fs -le 80 ];then

echo "成绩合格"

elif [ $fs -gt 80 -a $fs -le 100 ];then

echo "成绩优秀,恭喜"

else

echo "成绩应在0-100之间"

fi

正则表达式

$ #匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符本身,请使用 \$。

( ) #标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 \( 和 \)。

* #匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 \*。

+ #匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 \+。

. #匹配除换行符 \n 之外的任何单字符。要匹配 . ,请使用 \. 。

? #匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 \?。

\ #将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, 'n' 匹配字符 'n'。'\n' 匹配换行符。序列 '\\' 匹配 "\",而 '\(' 则匹配 "("。

^ #匹配输入字符串的开始位置,除非在方括号表达式中使用,当该符号在方括号表达式中使用时,表示不接受该方括号表达式中的字符集合。要匹配 ^ 字符本身,请使用 \^。

{ #标记限定符表达式的开始。要匹配 {,请使用 \{。

| #指明两项之间的一个选择。要匹配 |,请使用 \|。

限定符:

* #匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于 {0,}。

+ #匹配前面的子表达式一次或多次。例如,zo+ 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。

? #匹配前面的子表达式零次或一次。例如,do(es)? 可以匹配 "do" 、 "does"、 "doxy" 中的 "do" 。? 等价于 {0,1}。

{n} #n 是一个非负整数。匹配确定的 n 次。例如,o{2} 不能匹配 "Bob" 中的 o,但是能匹配 "food" 中的两个 o。

{n,} #n 是一个非负整数。至少匹配n 次。例如,o{2,} 不能匹配 "Bob" 中的 o,但能匹配 "foooood" 中的所有 o。o{1,} 等价于 o+。o{0,} 则等价于 o*。

{n,m} #m 和 n 均为非负整数,其中 n <= m。最少匹配 n 次且最多匹配 m 次。例如,o{1,3} 将匹配 "fooooood" 中的前三个 o。o{0,1} 等价于 o?。请注意在逗号和两个数之间不能有空格。

x|y #匹配 x 或 y。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 则匹配 "zood" 或 "food"

[xyz] #字符集合。匹配所包含的任意一个字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。

#注意!在中括号里面包含 ^ 表示"排除"

[^xyz]#负值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain" 中的'p'、'l'、'i'、'n'。

[a-z] #字符范围。匹配指定范围内的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z' 范围内的任意小写字母字符。

\b #匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。

\B #匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。

\d #匹配一个数字字符。等价于 [0-9]。

\D #匹配一个非数字字符。等价于 [^0-9]。

\s #匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。

\S #匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。

\w #匹配字母、数字、下划线。等价于'[A-Za-z0-9_]'。

\W #匹配非字母、数字、下划线。等价于 '[^A-Za-z0-9_]'。

举例

^[a-z][0-9]$ #匹配以字母开头,以数字结尾

^[^0-9][0-9]$ #匹配以非数字开头,以数字结尾

[^a-z] #除了小写字母以外的所有字符

[^\\\/\^] #除了(\)(/)(^)之外的所有字符

[^\"\'] #除了双引号(")和单引号(')之外的所有字符

^[a-zA-Z_]$ #所有的字母和下划线 _

^a$ #字母a

^a{4}$ #aaaa

^a{2,4}$ #aa,aaa或aaaa

^a{1,3}$ #a,aa或aaa

^a{2,}$ #包含多于两个a的字符串

^a{2,} #如:aardvark和aaab,但apple不行

a{2,} #如:baad和aaa,但Nantucket不行

^[a-zA-Z0-9_]{1,}$ # 所有包含一个以上的字母、数字或下划线的字符串

^[1-9][0-9]{0,}$ # 所有的正整数

^\-{0,1}[0-9]{1,}$ # 所有的整数

^[-]?[0-9]+\.?[0-9]+$ # 所有的浮点数

流程控制语句-正则比对

#判断当前用户是否r开头

[[ "$USER" =~ ^r ]] && echo $?

#判断num变量是否为多个数字

[[ $num =~ ^[0-9]+$ ]]&& echo "成立"||echo "不成立"

脚本创建用户

#!/bin/bash

read -p "请输入用户名前缀:" q

if [[ ! ${q} =~ ^[a-Z]+$ ]];then

echo "前缀应为字母组合"

quit

fi

read -p "请输入用户名后缀(应为数字):" w

if [[ ${w} =~ ^[0-9]+$ ]];then

user=${q}${w}

useradd $user

echo "123456" | passwd --stdin ${user} &> /dev/null

echo "您当前指定的用户名为${user},初始密码为123456"

fi

同时创建多个用户

seq 100 #生成100个序列

#!/bin/bash

read -p "请输入要创建的用户名" name

if [[ $name =~ ^[0-9]+$ ]];then

echo "用户名必须是数字"

exit

fi

read -p "请输入要创建的个数" num

if [[ $num =~ ^[^0-9]+$ ]];then

echo "用户数量必须是数字"

exit

fi

for i in $(seq $num)

do

user=${name}${i}

useradd ${user} &> /dev/null

echo '123' |passwd -stdin ${user} &> /dev/null

done

echo "创建完成,初始密码为123"

read -p "请输入要删除的用户名" name

read -p "请输入数量" num

for i in $(seq ${num})

do

user=${name}${i}

userdel -r ${user} &> /dev/null

done

echo "删除完成"

case语句

主要用在对菜单的处理。比if更简单明了,if适合针对一个范围进行判断。case适合等值判断

cat << END

------选项菜单-------

1.----copy-----------

2.----mv-------------

3.----backup---------

---------------------

END

read -p "请输入您的选择" n

case ${n} in

1)

echo "copy"

;;

2)

echo "mv"

;;

3)

echo "backup"

;;

*)

echo "不在菜单内"

;;

esac

案例:服务启动停止脚本

#!/bin/bash

if [ $1 == "start" ];then

rsync --daemon

echo "rsync已启动"

elif [ $1 == "stop" ];then

killall rsync

echo "rsync已关闭"

else

echo "请配合start|stop"

exit

fi

#/var/run/ #程序pid日志文件存储目录

sed -i 's/# pid file/pid file/' /etc/rsyncd.conf #启动rsync的pid配置文件

. /etc/init.d/functions

case $1 in

start)

if [ ! -f /var/run/rsyncd.pid ];then

rsync --daemon

action "rsync running.." /bin/true

else

action "rsync 已启动" /bin/false

fi

;;

stop)

killall rsync

;;

status)

echo "状态"

;;

*)

echo "不在选项内"

;;

esac

举例

case启停nginx

#!/bin/bash

. /etc/init.d/functions

case $1 in

start)

if [ -f /var/run/nginx.pid ];then

action "nginx已在运行状态无法重复运行" /bin/false

else

sudo systemctl start nginx

if [ $? -eq 0 ];then

action "nginx启动成功" /bin/true

else

action "nginx启动失败请检查原因" /bin/false

fi

fi

;;

stop)

if [ -f /var/run/nginx.pid ];then

sudo systemctl stop nginx

if [ $? -eq 0 ];then

action "nginx关闭成功" /bin/true

else

action "nginx关闭失败" /bin/false

fi

else

action "nginx并未在运行" /bin/false

fi

;;

reload)

if [ -f /var/run/nginx.pid ];then

sudo systemctl restart nginx

if [ $? -eq 0 ];then

action "nginx重启成功" /bin/true

else

action "nginx重启失败" /bin/false

fi

else

action "nginx未在运行中,无法进行重启" /bin/false

fi

;;

status)

if [ -f /var/run/nginx.pid ];then

echo "nginx正处于运行状态"

else

echo "nginx现在未在运行"

fi

;;

*)

echo "请输入start|stop|reload|status"

;;

esac

循环语句

#重新定义分隔符

IFS=

#累加

((i=1;i<=100;i++)) #i的初始值为1,当i小于等于一百,i做累加

#结构

for 变量名 in

do

循环命令语句

done

read -p "请输入最大值" n

for i in $(seq ${n})

do

echo ${i}

done

a=1

b=9

for i in {1..9}

do

let a++

let b--

echo $a:$b

done

批量创建用户

echo $((RANDOM)) #生成随机数

echo $((RANDOM))|md5sum #无序乱码随机数

echo $((RANDOM))|md5sum|cut -c 2-10 #截取第二位到第十位

#!/bin/bash

if [! $UID -eq 0 ];then

echo "非管理员无权访问"

exit

fi

read -p "请输入用户前缀" name

read -p "请输入创建数量" num

echo "创建用户${name}1到${name}-${num}"

read -p "确认创建(y/n)" m

case $m in

y)

for i in $(seq $num)

do

user=${name}${i}

id ${user} &> /dev/null

if [ $? -eq 0 ];then

echo "${user}已存在"

else

useradd ${user}

pass=$(echo $((RANDOM))|md5sum|cut -c 2-10)

echo ${pass}|passwd --stdin ${user} $> /dev/null

echo "用户名:${user} 密码:${pass}" >> /sh/user.txt

fi

done

echo "用户已创建完成,信息存放在/sh/user.txt中"

;;

n)

exit

;;

*)

echo "请输入y或n"

;;

esac

批量探测主机是否存活

#!/bin/bash

for i in $(seq 10)

do

ip=192.168.154.${i}

ping -c 1 -w 1 ${ip} &> /dev/null

if [ $? -eq 0 ];then

echo "${ip} 可到达"

else

echo "${ip}无法到达"

fi

echo ${ip} >> /tmp/ip.txt

done

wait

echo "ping 测试结束,端口测试开始"

for i in $(cat /tmp/ip.txt)

do

nmap ${i} |grep 22 &> /dev/null

if [ $? -eq 0 ];then

echo "${i} 22端口正常"

else

echo "${i} 22端口未检出"

fi

done

echo "测试完成"

随机点名

#!/bin/bash

#随机数公式,得到1-n范围的随机数

#RANDOM%n+1

#sed -n "1p" student.txt #打印student.txt中的第一行

num=$(wc -l /sh/student.txt|awk '{print $1}')

for i in $(seq ${num})

do

n=$((RANDOM%${num}+1))

sed -n "${n}p" student.txt

sleep 1 #暂停一秒

done

s=$(sed -n "${n}p" student.txt)

echo -e "就是你了:\033[32m $s \033[0m"

随机猜数

while true #无限循环

continue #继续上一次操作

break #退出循环到done后

#!/bin/bash

i=0

num=$((RANDOM%100+1))

while true

do

read -p "请猜一个1-100的数字" s

if [[ $s =~ ^[^0-9]+$ ]];then

echo "输入错误,请输入1-100的纯数字"

continue

fi

if [ $s -gt $num ];then

echo "你猜大了"

elif [ $s -lt $num ];then

echo "你猜小了"

else

echo "你真厉害,猜对了"

break

fi

let i++

done

echo "你总共猜了$(( $i + 1 ))次"

程序语句

exit #退出程序

break #打断循环执行循环之后的代码

continue #重新开始循环

最后给大家带上函数简单应用以便大家自己去进行拓展

函数与数组

定义函数 命令的集合,用来完成特定的功能; 提前定义函数,在脚本中任意调用函数名。 使用函数使代码模块化,便于重复使用,增加可读性。

#!/bin/bash

#函数定义格式:

#函数名(){

# shell命令

#}

#

#或

# ​

#function 函数名 {

# shell命令

#}

#定义menu函数内容

#menu(){

#定义菜单时,应贴着左侧写

#cat << END

#1.创建用户

#2.删除用户

#3.退出程序

#END

#}

#调用menu

#menu

menu(){

cat << END

1.创建用户

2.删除用户

3.退出程序

END

}

input(){

while true

do

read -p "请输入用户前缀:" name

if [[ $name =~ [0-9]+ ]];then

echo "前缀不能包含数字"

continue

fi

break

done

while true

do

read -p "请输入用户数量" num

if [[ $num =~ ^[^0-9]+$ ]];then

echo "数量应为数字"

continue

fi

break

done

}

function create {

input

read -p "将创建${name}1~${name}${num} {y/n}" m

case ${m} in

y)

for i in $(seq $num)

do

user=${name}${i}

id ${user} &> /dev/null

if [ $? -eq 0 ];then

echo "用户:${user}已存在"

else

useradd ${user} &> /dev/null

pass=$(echo $((RANDOM))|md5sum|cut -c 2-10)

echo ${pass}|passwd --stdin ${user} &> /dev/null

echo "用户名:${user} 密码:${pass}" >> /tmp/user.txt

echo "${user}创建成功"

fi

sleep 1

done

;;

n)

;;

*)

echo "输入无效应为 y|n"

create

;;

esac

}

while true

do

menu

read -p "请对菜单进行选择(1-3)" y

case $y in

1)

create

;;

2)

echo 删除用户

;;

3)

;;

*)

echo "选择无效,请选择 1|2|3"

;;

esac

done