Linux SHELL 脚本编程详解


Linux SHELL 脚本编程

  • 脚本编程详解
    • 名词解释
    • shell 脚本
    • 脚本中的条件测试
    • bash 测试分类
    • 脚本的状态返回值
    • 脚本语法检测和调试执行
    • 编程脚本之用户交互
  • 脚本执行方式
    • 1、选择执行
      • if 语句
      • case 语句
    • 2、循环执行
      • 2.1 for 循环
        • LIST 列表的生成方式
        • for 循环 示例
        • for 循环的特殊用法
      • 2.2 while 循环
      • 2.3 until 循环
  • 脚本示例
    • 1、vim 如何定制自动缩进四个字符。
    • 2、实现自动添加三个用户,并计算这三个用户的 uid 之和。
    • 3、通过命令传递两个文本文件路径给脚本,计算其空白行数之和。
    • 4、通过参数传递一个用户名给脚本,此用户不存时,则添加之。
    • 5、通过命令行参数给定两个数字,输出其中较大的数值。
    • 6、脚本参数传递一个文件路径给脚本,判断此文件的类型。
    • 7、传递一个参数给脚本,此参数为用户名;根据其ID号来判断用户类型。
    • 8、写一个脚本,要求如下:
    • 9、分别求100以内所有偶数之和,以及所有奇数之和。
    • 10、计算当前系统上的所有用的id之和。
    • 11、通过脚本参数传递一个目录给脚本,而后计算此目录下所有文本文件的行数之和;并说明此类文件的总数。
    • 12、计算/etc/passwd文件中的第10个用户和第20个用户的id号之和。
    • 13、计算/etc/rc.d/init.d/functions和/etc/inittab文件的空白行数之和。
    • 14、编写一个脚本,找出172.16.141.X网络中哪些主机地址被使用,哪些未被使用,并把结果保存至相应的文件中。
    • 15、写一个脚本,实现:能探测C类、B类或A类网络中的所有主机是否在线。
    • 16、编写脚本,通过命令行参数传入一个用户名,判断ID是偶数还是奇数。
    • 17、分别用while、for循环检测10.0.0.1/24网段存活的IP地址
【Linux SHELL 脚本编程详解】
脚本编程详解
编程语言的分类:根据运行方式 1、编译运行:源代码 --> 编译器 (编译)--> 程序文件 2、解释运行:源代码 --> 运行时启动解释器,由解释器边解释边运行

根据其编程过程中功能的实现是调用库还是调用外部的程序文件: 1、shell脚本编程:利用系统上的命令及编程组件进行编程 2、完整编程:利用库或编程组件进行编程

编程模型:过程式编程语言,面向对象的编程语言 程序=指令+数据 1、过程式:以指令为中心来组织代码,数据是服务于代码; 顺序执行 选择执行 循环执行 代表:C,bash 2、对象式:以数据为中心来组织代码,围绕数据来组织指令; 类(class):实例化对象,method; 代表:Java, C++, Python

名词解释
变量: 1、局部变量 2、本地变量 3、环境变量 4、位置参数变量 5、特殊变量具体参考: https://blog.csdn.net/weixin_44983653/article/details/95232625

  • 位置参数变量
位置参数变量 :主要是向脚本传递参数。# myscript.shargu1 argu2引用方式: argu1 argu2 $1,$2, ..., ${10},${11}, ...轮替: shift[n]:位置参数轮替示例: root@LeeMumu:~# cat echo.sh# 通过此脚本,了解位置参数变量 #!/bin/bashecho $1 echo $2root@LeeMumu:~# ./echo.sh "The line 1." "The line 2." The line 1. The line 2.

  • 特殊变量
$0:脚本文件路径本身 $#:脚本参数的个数 $*:所有参数 $@:所有参数

  • 算术运算和赋值
常用的算术运算符号: 1、+加 2、-减 3、*乘 4、/除 5、**次方 6、%余数 算术运算格式: 1、letVAR=算术运算表达式 2、VAR=$[算术运算表达式] 3、VAR=$((算术运算表达式)) # 给变量空间赋值时一定要使用 $[ ] 或者 $(( )) 4、VAR=$(expr $ARG1 $OP $ARG2) # (): 括号内部是运行命令,直接取命令运行结果# 注意:乘法符号在有些场景中需要使用转义符。增强型赋值: 变量做某种算术运算后回存至此变量中,如下两种赋值方式表示同一个意思: let i=$i+# let i+=# 常用的增强型赋值: +=,-=,*=, /=, %= 自增: VAR=$[$VAR+1] # 前面的 VAR 是变量空间,后面的 $VAR 是直接取变量空间里的值,注意区分 letVAR+=1 letVAR++ 自减: VAR=$[$VAR-1] letVAR-=1 letVAR--

%(余数) 示例: root@LeeMumu:~# yushu=$((9%2)) root@LeeMumu:~# echo $yushu 1 root@LeeMumu:~# yushu=$((8%2)) root@LeeMumu:~# echo $yushu 0

shell 脚本
1、什么是 shell 脚本? 1、shell 脚本是过程式编程,解释运行,依赖于外部程序文件运行。 2、shell 脚本是命令的堆积。 # 很多命令不具有幂等性,需要用程序逻辑来判断运行条件是否满足,以避免其运行中发生错误。2、如何编写 shell 脚本? 脚本文件的第一行,顶格位置需要给出: shebang,解释器路径,用于指明解释执行当前脚本的解释器程序文件。 常见的解释器: #!/bin/bash #!/usr/bin/python #!/usr/bin/perl 同时,在脚本顶部还可以加入版本、作者和描述等信息,如下: #!/bin/bash # Version: 0.0.1 # Author: LeeMumu # Description: XXX3、如何运行 shell 脚本? (1) 赋予执行权限,并直接运行此程序文件 chmod +x /PATH/TO/SCRIPT_FILE source /PATH/TO/SCRIPT_FILE (2) 直接运行解释器,将脚本以命令行参数传递给解释器程序 bash /PATH/TO/SCRIPT_FILE4、shell 脚本注意事项: (1) 脚本中的空白行会被解释器忽略 (2) 脚本中,除了shebang,余下所有以#开头的行,都会被视作注释行而被忽略;此即为注释行 (3) shell 脚本的运行是通过运行一个子shell进程实现的

脚本中的条件测试
条件测试:判断某需求是否满足,需要由测试机制来实现。如何编写测试表达式以实现所需的测试: (1) 执行命令,并利用命令状态返回值来判断; 0:成功 1-255:失败 (2) 测试表达式 testEXPRESSION [ EXPRESSION ] [[ EXPRESSION ]]# 注意:EXPRESSION两端必须有空白字符,否则为语法错误。

bash 测试分类
bash 的测试类型: 1、数值测试 2、字符串测试 3、文件测试 4、组合条件测试

  • 1、数值测试
数值测试:数值比较 -eq:是否等于 # [ $num1 -eq $num2 ],注意空格 -ne:是否不等于 -gt:是否大于 -ge:是否大于等于 -lt:是否小于 -le:是否小于等于

示例: root@LeeMumu:~# [ 2 -eq 2 ]# 命令执行成功 root@LeeMumu:~# echo $? 0 root@LeeMumu:~# [ 2 -gt 2 ]# 命令执行失败 root@LeeMumu:~# echo $? 1

  • 2、字符串测试
字符串测试: ==:是否等于 # [ STRING1 == STRING2 ],注意空格 > :是否大于 < :是否小于 !=:是否不等于 =~:左侧字符串是否能够被右侧的PATTERN所匹配 -z "STRING":判断指定的字串是否为空;空则为真,不空则假 # [[ -z “STRING” ]] -n "STRING":判断指定的字符串是否不空;不空则真,空则为假 # 注意: (1) 字符串要加引用 (2) 要使用 [[ ]]

示例: root@LeeMumu:~# [ a == b ]# 命令执行失败 root@LeeMumu:~# echo $? 1 root@LeeMumu:~# [ aba == baa ]# 命令执行失败 root@LeeMumu:~# echo $? 1 root@LeeMumu:~# [ a == a ]# 命令执行成功 root@LeeMumu:~# echo $? 0 root@LeeMumu:~# [[ -z "" ]]# 命令执行成功,字符串为空则为真 root@LeeMumu:~# echo $? 0 root@LeeMumu:~# [[ -z "aaa" ]]# 命令执行失败,字符串非空则为假 root@LeeMumu:~# echo $? 1

  • 3、文件测试
文件测试: 1、存在性测试 -aFILE -eFILE 文件的存在性测试,存在则为真,否则则为假2、存在性及类型测试 -bFILE:是否存在并且为 块设备文件 -cFILE:是否存在并且为 字符设备文件 -dFILE:是否存在并且为 目录文件 -fFILE:是否存在并且为 普通文件 -hFILE:是否存在并且为 符号链接文件 -LFILE:是否存在并且为 符号链接文件 -pFILE:是否存在且为 命名管道文件 -SFILE:是否存在且为 套接字文件3、文件权限测试: -rFILE:是否存在并且 对当前用户可读 -wFILE:是否存在并且 对当前用户可写 -xFILE:是否存在并且 对当前用户可执行4、特殊权限测试: -uFILE:是否存在并且 拥有suid权限 -gFILE:是否存在并且 拥有sgid权限 -kFILE:是否存在并且 拥有sticky权限5、文件是否有内容: -sFILE:是否有内容,有内容为真,没内容为假6、时间戳: -NFILE:文件自从上一次读操作后是否被修改过7、从属关系测试: -OFILE:当前用户是否为文件的属主 -GFILE:当前用户是否属于文件的属组8、双目测试: FILE1-efFILE2:FILE1与FILE2是否指向同一个文件系统的相同inode的硬链接; FILE1-ntFILE2:FILE1是否新于FILE2,新为真,否则为假 FILE1-otFILE2:FILE1是否旧于FILE2,旧为真,否则为假

示例: root@LeeMumu:~# touch space.txt# 创建空文件 root@LeeMumu:~# cat space.txt root@LeeMumu:~# [[ -s space.txt ]]# 有内容为真,没内容为假 root@LeeMumu:~# echo $? 1 root@LeeMumu:~# echo 1 > space.txt root@LeeMumu:~# [[ -s space.txt ]] root@LeeMumu:~# echo $? 0 root@LeeMumu:~# [[ -e space.backup.txt ]]# 存在为真,不存在为假 root@LeeMumu:~# echo $? 1 root@LeeMumu:~# touch space.backup.txt root@LeeMumu:~# [[ -e space.backup.txt ]] root@LeeMumu:~# echo $? 0

  • 4、组合条件测试
逻辑运算: 第一种方式: 1、与运算:COMMAND1 && COMMAND2 # && 前面为真时, && 后面就继续执行 # && 前面为假时, && 后面就不执行 2、或运算:COMMAND1 || COMMAND2 # 常用于判断此用户是否存在,如果不存在就对用户进行添加。 # id user1 &> /dev/null || useradd user1 # || 前面为真时, || 后面就不执行 # || 前面为假时, || 后面就继续执行 3、非运算:! COMMAND 例如: # [ -O FILE ] && [ -r FILE ]第二种方式: 1、与运算:EXPRESSION1-aEXPRESSION2 2、或运算:EXPRESSION1-oEXPRESSION2 3、非运算:! EXPRESSION 例如: # [ -O FILE -a -x FILE ]

示例: root@LeeMumu:~# [ 1 -eq 2 ] && echo 2 root@LeeMumu:~# [ 1 -lt 2 ] && echo 2 2 root@LeeMumu:~# [ 1 -eq 2 ] || echo 2 2 root@LeeMumu:~# [ 1 -lt 2 ] || echo 2

脚本的状态返回值
脚本的状态返回值:默认是脚本中执行的最后一条件命令的状态返回值。可用如下命令自定义状态退出状态码 # exit [n]:n为指定的状态码,一般制定为 1~255 结束脚本执行。注意:shell进程遇到exit时,即会终止,因此,整个脚本执行即为结束。

脚本语法检测和调试执行
1、检测脚本中的语法错误: # bash -n /path/to/some_script2、对脚本进行调试执行: # bash -x /path/to/some_script

编程脚本之用户交互 用户交互时,会使用到 read 命令。
该命令是从键盘读取变量的值,通常用在shell脚本中与用户进行交互的场合。该命令可以一次读取多个变量的值,变量和输入的值都需要使用空格隔开。
注意:在用户交互过程中,如果对输入的内容进行删除,需要同时使用 Ctrl + Delete 组合键。
read:从键盘读取变量值使用格式: read[option]... [name ...] -p 'PROMPT'# 指定读取值时的提示符 -t TIMEOUT# 指定读取值时等待的时间(秒)

示例: root@LeeMumu:~# cat read.sh #!/bin/bash # read -p "Please input what you want:" aBa# 输入的信息赋值给了变量 aBa echo "You input the $aBa!" root@LeeMumu:~# ./read.sh Please input what you want:This is a new line You input the This is a new line!

脚本执行方式 shell 脚本是过程式编程语言,代码的执行顺序分为:
1、顺序执行 # 逐条运行脚本代码 2、选择执行 # 代码有一个分支:条件满足时才会执行 # 两个或以上的分支:只会执行其中一个满足条件的分支 3、循环执行 # 代码片断(循环体)要执行0、1或多个来回

1、选择执行 if 语句
单分支的if语句 格式: if测试条件 then 代码分支 fi

双分支的if语句 格式: if测试条件; then 条件为真时执行的分支 else 条件为假时执行的分支 fi

多分支的if语句 ifCONDITION1; then 条件1为真 分支 elifCONDITION2; then 条件2为真 分支 elifCONDITION3; then 条件3为真 分支 ... ... elifCONDITIONn; then 条件n为真 分支 else 所有条件均不满足时的分支 fi注意:即便多个条件可能同时都能满足,分支只会执行中其中一个,首先测试为“真”的条件。

case 语句
语法格式: case$VARAIBLEin PAT1) 分支1 ; ; PAT2) 分支2 ; ; ... *) 分支n ; ; esac

对如上 case 语法格式进行说明: # case关键字 # in关键字 # PAT1)仅支持 glob 风格的通配符号 # VARDIBLE变量 # *)相当于 else # esac结束关键字(与 case 相反) # ; ; 双分号 # 适用于变量值同多个字符串进行等值或不等值比较的情形,仅能替代部分多分支 if 语句

# case 支持 glob 风格的通配符 *# 任意长度的任意字符; ?# 任意单个字符; []# 范围内任意单个字符; a|b# a或b

示例:写一个服务框架脚本。要求如下:
$lockfile,值/var/lock/subsys/SCRIPT_NAME(1) 此脚本可接受start, stop, restart, status四个参数之一; (2) 如果参数非此四者,则提示使用帮助后退出; (3) start,则创建lockfile,并显示启动; stop,则删除lockfile,并显示停止; restart,则先删除此文件再创建此文件,而后显示重启完成; status,如果lockfile存在,则显示running,否则,则显示为stopped。

脚本如下: #!/bin/bash # # chkconfig: - 50 50 # description: test service script # prog=$(basename $0) lockfile=/var/lock/subsys/$progcase $1in start) if [ -f $lockfile ]; then echo "$prog is running yet." else touch $lockfile [ $? -eq 0 ] && echo "start $prog finshed." fi ; ; stop) if [ -f $lockfile ]; then rm -f $lockfile [ $? -eq 0 ] && echo "stop $prog finished." else echo "$prog is not running." fi ; ; restart) if [ -f $lockfile ]; then rm -f $lockfile touch $lockfile echo "restart $prog finished." else touch -f $lockfile echo "start $prog finished." fi ; ; status) if [ -f $lockfile ]; then echo "$prog is running" else echo "$prog is stopped." fi ; ; *) echo "Usage: $prog {start|stop|restart|status}" exit 1 esac

命令执行: # cp testservice /etc/init.d/ # chkconfig --add testservice # chkconfig --list testservice # service testservice start # ls /var/lock/subsys/# 启动服务后都会在这个目录下进行文件创建

2、循环执行
循环执行:是指将一段代码重复执行0、1或多次。 进入条件:条件满足时才进入循环。 退出条件:每个循环都应该有退出条件,以有机会退出循环。

循环分为三种: 1、for循环 2、while循环 3、until循环

进入条件: for:列表元素非空 while:条件测试结果为“真” unitl:条件测试结果为“假” 退出条件: for:列表元素遍历完成 while:条件测试结果为“假” until:条件测试结果为“真”

循环控制语句: # continue:提前结束本轮循环,不会执行后面的命令,直接进入下一轮循环判断。 whileCONDITION1; do CMD1 ... ifCONDITION2; then continue fi CMDn ... done# break:提前跳出循环 whileCONDITION1; do CMD1 ... ifCONDITION2; then break fi done

创建死循环: while true; do 循环体 done 退出方式: 某个测试条件满足时,让循环体执行break命令。

示例:求100以内所有偶数之和; #!/bin/bash # declare -i evensum=0 declare -i i=0while [ $i -le 100 ]; do let i++ if [ $[$i%2] -eq 1 ]; then continue fi let evensum+=$i doneecho "Even sum: $evensum"

示例:求100以内所奇数之和 #!/bin/bash # declare -i oddsum=0 declare -i i=1while true; do let oddsum+=$i let i+=2 if [ $i -gt 100 ]; then break fi done

sleep 命令说明:
sleep 命令: - delay for a specified amount of time 命令格式: # sleep NUMBER

sleep 示例:每隔3秒钟到系统上获取已经登录用户的用户的信息;其中,如果logstash用户登录了系统,则记录于日志中,并退出。
#!/bin/bash # while true; do if who | grep "^logstash\>" &> /dev/null; then break fi sleep 3 doneecho "$(date +"%F %T") logstash logged on" >> /tmp/users.log #!/bin/bash # until who | grep "^logstash\>" &> /dev/null; do sleep 3 doneecho "$(date +"%F %T") logstash logged on" >> /tmp/users.log

2.1 for 循环
for 循环包括以下两种 1、遍历列表 2、控制变量

遍历列表:语法格式: forVARAIBLEinLIST; do 循环体 done参数解释: 1、for 是 关键字 2、VARAIBLE 是 变量 3、in 是 关健字 4、LIST 是 赋值列表 5、do 和 done 是 关键字VARAIBLE 赋值的三种形式: 1、VARAIBLE = VALUE 2、read 语句 3、for 语句进入和退出条件: 1、进入条件:只要列表有元素,即可进入循环 2、退出条件:列表中的元素遍历完成

LIST 列表的生成方式 一般有如下五种:
  • 1、直接给出
root@LeeMumu:~# echo 1 2 3 4 5 1 2 3 4 5

  • 2、整数列表
(1)、{start..end} root@LeeMumu:~# echo {1..5} 1 2 3 4 5(2)、seq [start[incremtal]]last# 中间参数是 步长 root@LeeMumu:~# seq 1 3 1 2 3 root@LeeMumu:~# seq 3 1 2 3 root@LeeMumu:~# seq 3 3 9 3 6 9

  • 3、返回列表参数
ls:返回列表 一行一个 cat:查看文件的返回列表参数# 只要结果能输出字串的

  • 4、glob
匹配符合条件的列表: # ls -d /etc/p*

  • 5、变量引用
$@ :参数传递 $* :参数传递

root@LeeMumu:~# passwd_Lines=`wc -l /etc/passwd | cut -d' ' -f1` # 注意:以上命令是 反引号,作命令引用 root@LeeMumu:~# echo $passwd_Lines 33 root@LeeMumu:~# seq 1 $passwd_Lines 1 2 ... 32 33 root@LeeMumu:~#echo {1.."$passwd_Lines"} {1..33} # 注意:使用花括号时引用变量时,不会生效,可用 seq root@LeeMumu:~# echo {1..$passwd_Lines} {1..33} root@LeeMumu:~# echo {1..33} 1 2 3 4 5 6 ... ...32 33 root@LeeMumu:~# echo '$passwd_Lines' $passwd_Lines

for 循环 示例 1、求 100 以内的正整数之和。
#!/bin/bash # declare -i sum=0for i in {1..100}; do echo "\$sum is $sum, \$i is $i" sum=$[$sum+$i] doneecho $sum

2、判断/var/log目录下的每一个文件的内容类型。
#!/bin/bash # for filename in /var/log/*; do if [ -f $filename ]; then echo "Common file." elif [ -d $filename ]; then echo "Directory." elif [ -L $filename ]; then echo "Symbolic link." elif [ -b $filename ]; then echo "block special file." elif [ -c $filename ]; then echo "character special file." elif [ -S $filename ]; then echo "Socket file." else echo "Unkown." fi done

3、打印 九九乘法表
#外循环控制乘数,内循环控制被乘数; #!/bin/bash # for j in {1..9}; do for i in $(seq 1 $j); do echo -n -e "${i}X${j}=$[${i}*${j}]\t" done echo done

for 循环的特殊用法
语法格式; for((控制变量初始化; 条件判断表达式; 控制变量的修正语句)); do 循环体 done控制变量初始化:仅在循环代码开始运行时执行一次 控制变量的修正语句:每轮循环结束会先进行控制变量修正运算,而后再做条件判断

示例:求100以内所有正整数之和 #!/bin/bash # declare -i sum=0for ((i=1; i<=100; i++)); do let sum+=$i doneecho "Sum: $sum."示例:打印九九乘法表 #!/bin/bash # for ((j=1; j<=9; j++)); do for ((i=1; i<=j; i++)); do echo -e -n "${i}X${j}=$[${i}*${j}]\t" done echo done

2.2 while 循环
语法格式: whileCONDITION; do 循环体 循环控制变量修正表达式 done进入条件:CONDITION测试为 真 退出条件:CONDITION测试为 假

示例:求100以内的正整数之和 #!/bin/bash # declare -i sum=0 declare -i i=1while [ $i -le 100 ]; do let sum+=$i let i++ doneecho $sum

  • while 循环的特殊用法(遍历文件的行):
whilereadVARIABLE; do 循环体; done

示例:找出ID号为偶数的用户,显示其用户名、ID及默认shell #!/bin/bash # while read line; do userid=$(echo $line | cut -d: -f3) username=$(echo $line | cut -d: -f1) usershell=$(echo $line | cut -d: -f7) if [ $[$userid%2] -eq 0 ]; then echo "$username, $userid, $usershell." fi done < /etc/passwd

2.3 until 循环
untilCONDITION; do 循环体 循环控制变量修正表达式 done进入条件:CONDITION测试为 假 退出条件:CONDITION测试为 真

示例:求100以内的正整数之和 #!/bin/bash # declare -i sum=0 declare -i i=1until [ $i -gt 100 ]; do let sum+=$i let i++ doneecho $sum

脚本示例 1、vim 如何定制自动缩进四个字符。
vim 的配置文件是:/etc/vimrc 可以对此配置文件进行编辑,添加配置: set tabstop=4 ,重读配置,使文件生效即可。如下: [root@LeeMumu ~]# vi /etc/vimrc# 编辑 vim 的配置文件 set tabstop=4 [root@LeeMumu ~]# source /etc/vimrc# 重读配置文件。使文件生效

2、实现自动添加三个用户,并计算这三个用户的 uid 之和。
[root@LeeMumu ~]# ./sUMID.sh Add user user21 successfully. The user user21 ID is:1004. Add user user22 successfully. The user user22 ID is:1005. Add user user33 successfully. The user user33 ID is:1006. The sum of these UserID is:3015. [root@LeeMumu ~]# tail -n 3 /etc/passwd user21:x:1004:1017::/home/user21:/bin/bash user22:x:1005:1018::/home/user22:/bin/bash user33:x:1006:1019::/home/user33:/bin/bash [root@LeeMumu ~]# cat sUMID.sh #!/bin/bash # declare -i sum=0for i in user21 user22 user33; do if id $i &> /dev/null ; then echo "The user $i exists." else useradd $i echo "Add user $i successfully." fi ID=`grep "^$i" /etc/passwd | cut -d":" -f3` #ID=$(grep "^$i" /etc/passwd | cut -d":" -f3)# 用 $() 或 `` 都可以 echo "The user $i ID is:$ID. " sum=$[$sum+$ID] done echo "The sum of these UserID is:$sum."

3、通过命令传递两个文本文件路径给脚本,计算其空白行数之和。
#!/bin/bash # file1_lines=$(grep "^$" $1 | wc -l) file2_lines=$(grep "^$" $2 | wc -l)echo "Total blank lines: $[$file1_lines+$file2_lines]"

4、通过参数传递一个用户名给脚本,此用户不存时,则添加之。
第一种: #!/bin/bash # if ! grep "^$1\>" /etc/passwd &> /dev/null; then useradd $1 echo $1 | passwd --stdin $1 &> /dev/null echo "Add user $1 finished." fi 第二种: #!/bin/bash # if [ $# -lt 1 ]; then echo "At least one username." exit 2 fiif ! grep "^$1\>" /etc/passwd &> /dev/null; then useradd $1 echo $1 | passwd --stdin $1 &> /dev/null echo "Add user $1 finished." fi第三种: #!/bin/bash # if [ $# -lt 1 ]; then echo "At least one username." exit 2 fiif grep "^$1\>" /etc/passwd &> /dev/null; then echo "User $1 exists." else useradd $1 echo $1 | passwd --stdin $1 &> /dev/null echo "Add user $1 finished." fi

5、通过命令行参数给定两个数字,输出其中较大的数值。
第一种: #!/bin/bash # if [ $# -lt 2 ]; then echo "Two integers." exit 2 fiif [ $1 -ge $2 ]; then echo "Max number: $1." else echo "Max number: $2." fi第二种:(相对于第一种来说,第二种是代码优化) #!/bin/bash # if [ $# -lt 2 ]; then echo "Two integers." exit 2 fideclare -i max=$1if [ $1 -lt $2 ]; then max=$2 fiecho "Max number: $max."第三种:(if 语句可嵌套) #!/bin/bash # if [ $# -lt 2 ]; then echo "TWO INTEGERS!" exit 1 else if [ $1 -lt $2 ]; then echo "The $2 is bigger than $1." elif [ $1 -eq $2 ]; then echo "The $1 is equal than $1." else echo "The $1 is bigger than $1." fi fi

6、脚本参数传递一个文件路径给脚本,判断此文件的类型。
#!/bin/bash # if [ $# -lt 1 ]; then echo "At least on path." exit 1 fiif ! [ -e $1 ]; then echo "No such file." exit 2 fiif [ -f $1 ]; then echo "Common file." elif [ -d $1 ]; then echo "Directory." elif [ -L $1 ]; then echo "Symbolic link." elif [ -b $1 ]; then echo "block special file." elif [ -c $1 ]; then echo "character special file." elif [ -S $1 ]; then echo "Socket file." else echo "Unkown." fi

7、传递一个参数给脚本,此参数为用户名;根据其ID号来判断用户类型。 (0: 管理员;1-999:系统用户;1000+:登录用户)
#!/bin/bash # [ $# -lt 1 ] && echo "At least on user name." && exit 1! id $1 &> /dev/null && echo "No such user." && exit 2userid=$(id -u $1)if [ $userid -eq 0 ]; then echo "root" elif [ $userid -ge 1000 ]; then echo "login user." else echo "System user." fi

8、写一个脚本,要求如下:
(1) 列出如下菜单给用户: disk) show disks info; mem) show memory info; cpu) show cpu info; *) quit; (2) 提示用户给出自己的选择,而后显示对应其选择的相应系统信息。

#!/bin/bash # cat << EOF cpu) display cpu information mem) display memory infomation disk) display disks information quit) quit =============================== EOFread -p "Enter your option: " optionwhile [ "$option" != "cpu" -a "$option" != "mem" -a "$option" != "disk" -a "$option" != "quit" ]; do echo "cpu, mem, disk, quit" read -p "Enter your option again: " option doneif [ "$option" == "cpu" ]; then lscpu elif [ "$option" == "mem" ]; then free -m elif [ "$option" == "disk" ]; then fdisk -l /dev/[hs]d[a-z] else echo "quit" exit 0 fi

9、分别求100以内所有偶数之和,以及所有奇数之和。
第一个脚本: #!/bin/bash #计算100以内所有奇数的和以及所有偶数的和;分别显示之 #奇数和变量 let SUM1=0 #偶数和变量 let SUM2=0 for I in {1..100}; do if [ $[$I%2] -eq 0 ]; then SUM1=$[$SUM1+$I] else SUM2=$[$SUM2+$I] fi doneecho -e "SUM1=$SUM1\nSUM2=$SUM2"第二个脚本: #!/bin/bash # declare -i even=0 declare -i odd=0for i in {1..100}; do if [ $[$i%2] -eq 0 ]; then even=$[$even+$i] else odd=$[$odd+$i] fi doneecho "The sum of the even_number between 1 and 100 is: $even" echo "The sum of the odd_number between 1 and 100 is: $odd" echo "The sum of the integer between 1 and 100 is: $[$even+$odd]"

10、计算当前系统上的所有用的id之和。
#!/bin/bash #declare -i passwd_Lines=`wc -l /etc/passwd | cut -d' ' -f1` declare -i sum_UID=0for i in `cat /etc/passwd | cut -d':' -f3`; do sum_UID=$[$sum_UID+$i] doneecho "The sum of the user-ID is:$sum_UID"

11、通过脚本参数传递一个目录给脚本,而后计算此目录下所有文本文件的行数之和;并说明此类文件的总数。
#!/bin/bash #declare -i count=0 declare -i line_count=0if [ $# -eq 1 ]; then if [ -d $1 ]; then for filename in $1* ; do if [ -f $filename ]; then line_count=$[$line_count+`wc -l $filename | cut -d' ' -f1`] count=$[$count+1] echo "The Common_File $filename has $line_count lines." else exit 1 fi done else echo -e "Please Input Correct Directory.\nFor Example: /path/path/" exit 2 fi else echo "Please Input One Directory!" exit 3 fi echo " " echo "The Number of Common_File is:$count" echo "The Total Lines of Common_File is:$line_count"

12、计算/etc/passwd文件中的第10个用户和第20个用户的id号之和。
[root@LeeMumu ~]# bash sum1020.sh The UID OF the tenth user is: 11. The UID OF the twentith user is: 59. The UID_SUM OF the tenth user and the twentith user is: 70. [root@LeeMumu ~]# cat sum1020.sh #!/bin/bash # ID10=$(head -10 /etc/passwd | tail -1 | cut -d":" -f3) ID20=$(head -20 /etc/passwd | tail -1 | cut -d":" -f3)sum1020=$[$ID10+$ID20]echo "The UID OF the tenth user is: $ID10." echo "The UID OF the twentith user is: $ID20." echo "The UID_SUM OF the tenth user and the twentith user is: $sum1020."

13、计算/etc/rc.d/init.d/functions和/etc/inittab文件的空白行数之和。
[root@LeeMumu ~]# bash sumSPACElines.sh The /etc/rc.d/init.d/functions has 91 space-lines. The /etc/inittab has 0 space-lines. The /etc/rc.d/init.d/functions and /etc/inittab totally have 91 space-lines. [root@LeeMumu ~]# cat sumSPACElines.sh #!/bin/bash # ID10=$(grep "^[[:space:]]*$"/etc/rc.d/init.d/functions | wc -l) ID20=$(grep "^[[:space:]]*$"/etc/inittab | wc -l)sum1020=$[$ID10+$ID20]echo "The /etc/rc.d/init.d/functions has $ID10 space-lines." echo "The /etc/inittab has $ID20 space-lines." echo "The /etc/rc.d/init.d/functions and /etc/inittab totally have $sum1020 space-lines."

14、编写一个脚本,找出172.16.141.X网络中哪些主机地址被使用,哪些未被使用,并把结果保存至相应的文件中。
[root@LEEMUMU ~]# cat ping.sh #!/bin/bash #declare -i upnum=0 declare -i downnum=0 declare -i i=1pinghost() { if ping $1 -c 1 -W 1 &>/dev/null; then echo -e "\033[1; 32m$1 is up.\033[0m"| tee -a up20190717.txt upnum=$[$upnum+1] else echo -e "\033[1; 31m$1 is down.\033[0m"| tee -a down20190717.txt downnum=$[$downnum+1] fi }while [ $i -le 254 ]; do pinghost 172.16.141.$i let i++ doneecho "Uphost is $upnum." echo "Downhost is $downnum."

15、写一个脚本,实现:能探测C类、B类或A类网络中的所有主机是否在线。
#!/bin/bash #cping() { local i=1 while [ $i -le 5 ]; do if ping -W 1 -c 1 $1.$i &> /dev/null; then echo "$1.$i is up" else echo "$1.$i is down." fi let i++ done }bping() { local j=0 while [ $j -le 5 ]; do cping $1.$j let j++ done }aping() { local x=0 while [ $x -le 255 ]; do bping $1.$x let x++ done }

16、编写脚本,通过命令行参数传入一个用户名,判断ID是偶数还是奇数。
[root@LeeMumu ~]# ./evenorodd.sh Please Input One UserName:JC9 The UserID Of JC9 is even! [root@LeeMumu ~]# ./evenorodd.sh Please Input One UserName:jc8 The jc8 Not Exist! Please Input Another UserName! [root@LeeMumu ~]# ./evenorodd.sh Please Input One UserName:JC6 The UserID Of JC6 is odd!

[root@LeeMumu ~]# cat evenorodd.sh #!/bin/bash # read -p "Please Input One UserName:" UserNameif ! id $UserName &> /dev/null; then echo -e "\e[1; 31mThe $UserName Not Exist!\e[0m" echo -e "\e[1; 32mPlease Input Another UserName!\e[0m" exit 1 else if [ $[`id -u $UserName`%2] -eq 0 ]; then echo -e "\e[1; 33mThe UserID Of $UserName is even!\e[0m" else echo -e "\e[1; 34mThe UserID Of $UserName is odd!\e[0m" fi fi

17、分别用while、for循环检测10.0.0.1/24网段存活的IP地址 第一种:
#!/bin/bash # 先定义函数,再引用函数 while_ping(){ local i=1 while [ $i -le 255 ]; do ping -W 1 -c 1 $1.$i &> /dev/null if [ $? == 0 ]; then echo "$1.$i is up" else echo "$1.$i is down" fi let i++ done }########################################################for_ping(){for i in {1..255}; do ping -W 1 -c 1 $1.$i &> /dev/null if [ $? == 0 ]; then echo "$1.$i is up" else echo "$1.$i is down" fi done }########################################################if [ $# -lt 2 ]; then echo "Usage sh $0 {for_ping|while_ping} Network" echo "Such as :for_ping 192.168.1 OR while_ping 192.168.1" exit 1 elif [[ $1 == "for_ping" ]]; then echo "for_ping" for_ping $2 elif [[ $1 == "while_ping" ]]; then echo "while_ping" while_ping $2 fi

第二种:
#!/bin/bash for ip in {1..255};do ping -c 1 10.0.0.$ip > /dev/null 2>&1 if [ $? -eq 0 ]; then echo 10.0.0.$ip is UP else echo 10.0.0.$ip is DOWN fi done##############################################declare -i ip=1 while [ $ip -le 255 ]; do ping -c 1 10.0.0.$ip > /dev/null 2>&1 if [ $? -eq 0 ]; then echo 10.0.0.$ip UP else echo 10.0.0.$ip DOWN fi let ip++ done

    推荐阅读