shell学习
发表于:2024-11-25 作者:热门IT资讯网编辑
编辑最后更新 2024年11月25日,我的自学shell过程,中间参考过鸟哥,马哥,老男孩等各方的学习方法和过程!shellshell编程之变量语言转换的设备或软件:编译器,解释器编程语言:机器语言、汇编语言、高级语言高级语言:静态语言:
我的自学shell过程,中间参考过鸟哥,马哥,老男孩等各方的学习方法和过程!shellshell编程之变量语言转换的设备或软件:编译器,解释器编程语言:机器语言、汇编语言、高级语言高级语言:静态语言:编译型语言有开发环境,不需要借助额外的二进制程序,写完代码后,通过编译器直接转换成二进制后再独立执行特征:强类型(变量)事先转换成可执行格式语言类型:C、C++、JAVA、C#动态语言:解释型语言特征:弱类型边解释边执行语言类型:PHP、SHELL、Python、perl编程模型面向过程:SEHLL,C编程重点在问题解决过程本身适合开发小型面向对象:JAVA,Python把要实现的项目抽象成一个个对象,定义对象之间的动作适合开发大型应用程序变量:内存空间,命名的内存空间内存:编址的存储单元变量类型(定义存储数据的格式和长度):字符数值整型浮点型时间布尔型(逻辑型、真假型)逻辑运算:与,或,非,异或与 运算:两者为真才为真,只要有一个假就是假或 运算:只要有一个为真,结果即为真非 运算:取反异或 运算:操作数相反为真,相同为假强类型变量:变量在使用前,必须事先声明,甚至还需要初始化初始化:数值初始化默认为0,字符默认初始化为空(NULL)弱类型变量:变量使用时声明,不区分类型,默认为字符串变量赋值:VAR_NAME=VALUE说明:变量名(VAR_NAME)=值(VALUE)bash变量类型:环境变量:本地变量:(局部变量)位置变量:特殊变量:本地变量:VARNAME(变量名)=VALUE(值)作用域整个bash进程局部变量local VARNAME(变量名)=VALUE(值)作用域当前代码段环境变量:作用域为当前shell进程及其子进程export VARNAME(变量名)=VALUE(值)export 意为"导出",即为导出一个环境变量脚本在执行时会启动一个子shell进程命令行中启动的脚本会继承当前shell环境变量系统自动执行的脚本(非命令行启动),就需要自我定义需要各环境变量位置变量:$n 第n个位置变量特殊变量:$?上一个命令的执行状态返回值示例:echo $?程序执行,两类返回值程序执行结果程序状态返回代码(0-255)0:正确执行1-255:错误执行撤销变量unset VARNAME(变量名)查看当前shell中的变量set查看当前shell中的环境变量printenvenvexport脚本:命令的堆砌,按实际需要,结合命令流程控制机制实现的源程序第一个脚本cat fisrt.sh #!/bin/bash# 注释行,不执行cat /etc/fstabla /var保存退出chmod +x fisrt.sh/dev/null软件设备,bit bucket数据黑洞引用变量:${VARNAME},括号可以省略单引号,强引用,不作变量替换双引号:弱引用,内部变量做替换变量名规则字母、数字、下划线,不能以数字开头不能同系统中已有的变量名重名最好见名知意练习练习1:写一个脚本1、条件5个用户,user1....user52、每个用户的密码同用户名,而且要求,添加密码完成后不显示passwd命令的执行结果信息3、每个用户添加完成后,显示用户某某已经完成添加#!/bin/bash# 说明:键盘输入需创建的用户名,执行时自动生成与用户名相同的密码,但不显示passwd的执行过程信息# 说明:添加完成后,显示用户某某已经完成添加# read命令读取键盘输入# 验证密码是否创建成功,用 su - read -p "input a user:" valuseradd $valecho "$val" | passwd --stdin $val &> /dev/nullecho "Add $val successfully!~"id $val练习2:写一个脚本1、使用一个变量保存一个用户名2、删除此变量中的用户,并且一并删除其家目录3、显示"用户删除完成"信息#!/bin/bash#echo "查看有哪些用户: 'cat /etc/passwd |cut -f1 -d:'"echo -e "查看有哪些用户: \n$(cat /etc/passwd |cut -f1 -d:)"read -p "Delete a user:" valuserdel -r $valecho "Del $val successfully!~"shell编程之条件判断shell -n检查shell语法是否错误shell -x检查shell执行过程 实现条件判断条件测试类型整数测试:等于不等于字符测试:是不是文件测试:存不存在条件测试的表达式(expression指表达式)[ expression ]中括号两端必须有空格[[ expression ]]test expression整数比较(整数测试)-eq测试两个整数是否相等,比如:$A -eq $B-ne测试连个整数是否不等,不等为真,相等为假-gt测试一个数是否大于另一个数:大于为真,否则为假-lt测试一个数是否小于另一个数:小于为真,否则为假-ge大于或等于-le小于或等于命令间的逻辑关系逻辑与:&&第一条件为真时,第二条件不用再判断,最终结果已经有第一条件为真时,第二条件必须判断示例:! id user6 && useradd user6说明:如果 ! id user6 为真,就执行 useradd user6如果 ! id user6 为假,就不执行 useradd user6示例:! id user6 && useradd user6说明:用户存在就不创建,用户不存在就创建逻辑或:||示例:id user6 || useradd user6说明:用户存在就不创建,用户不存在就创建条件判断,控制结构但分支if语句if 判断条件;thenstatement1(语句1)statement2(语句2)...fi双分支if语句if 判断条件;thenstatement1(语句1)statement2(语句2)...elsestatement3(语句3)statement4(语句4)...fiexit n 表示退出 (n)示例:判断用户是否存在,如果不存在就创建用户和密码,并提示创建成功!#!/bin/bash#read -p "please input:" NAMEif id $NAME &> /dev/null;then echo "$NAME 用户已经存在"else useradd $NAME echo $NAME | passwd --stdin $NAME &> /dev/null echo "用户 $NAME 添加成功。"fi示例:如果/etc/passwd 文件的行数大于100,就显示好大的文件#!/bin/bashLINES=`wc -l /etc/passwd`FINLINES=`echo $LINES | cut -d' ' -f1`[ $FINLINES -gt 50 ] && echo "/etc/passwd is a big file." || echo "/etc/passwd is a small file."示例:用户存在,就显示用户已存在,否则,就添加此用户id user1 && echo "user1 exists" || useradd user1示例:如果用户不存在,就添加;否则,显示其已经存在! id user1 && useradd user1 || echo "user1 exists."示例:如果用户不存在,添加并且给密码;否则,表示其以已经存在! id user1 && useradd user1 && echo "user1" | passwd --stdin user1 || echo "user1 exists"练习:写一个脚本1、添加3个用户user1,user2,user3.但要先判断用户是否存在,不存在而后添加2、添加完成后,显示一共添加了几个用户,当然,不能包括因为事先存在而没有添加的3、最后显示当前系统上共有多少个用户#!/bin/bash# 创建用户! id user1 &> /dev/null && useradd user1 && echo "user1" | passwd --stdin user1 &> /dev/null || echo "user1 exists"! id user2 &> /dev/null && useradd user2 && echo "user2" | passwd --stdin user2 &> /dev/null || echo "user2 exists"! id user3 &> /dev/null && useradd user3 && echo "user3" | passwd --stdin user3 &> /dev/null || echo "user3 exists"# 显示当前用户数USERS=`wc -l /etc/passwd | cut -d: -f1`echo "$USERS users."练习:添加用户,并判断是否存在,存在就显示"已经存在",不存在就创建,并创建与用户同名的密码,并在创建成功后显示"Add $val successfully!~"#!/bin/bashread -p "input a user:" val! id $val && useradd $val && echo "$val" | passwd --stdin $val && echo "Add $val successfully!~" || echo "$val 已经存在"练习:写一个脚本,给定一个用户1、如果其UID为0,就显示此为管理员2、否则,就显示其为普通用户第一种方法#!/bin/bashread -p "请输入用户名: " NAMEUSERID=`id -u $NAME`if ! id $NAME &> /dev/null ;then echo "................ "else if [ $USERID -eq 0 ];thenecho "................ "echo "$NAME为管理员." elseecho "................ "echo "$NAME为普通用户" fi echo "................ "fi第二种方法:#!/bin/bash# 需完善read -p "请输入用户名:" NAME#NAME=fanUSERID=`id -u $NAME`! id $NAME && echo "用户不存在!" || [ $USERID -eq 0 ] && echo "admin" || echo "Common user."练习:判断当前系统是否有用户的默认shell为bash,如果有,就显示有多少个这类用户,否则,就显示没这类用户#!/bin/bash#grep "\/dev/nullRETVAL=$?if [ $RETVAL -eq 0 ];then USERS=`grep "\ /dev/nullRETVAL=$?if [ $RETVAL -eq 0 ];then USERS=`grep "\ /dev/null;thenecho "文件有 `grep '^$' $FILE | wc -l` 行空白行!"elseecho "文件没有空白行!"fi练习:写一个脚本,判断其UID和GID是否一样,如果一样,此用户为"good";否则,为"bad"第一种方法:#!/bin/bashread -p "请输入用户:" IDUid=`id -u $ID`Gid=`id -g $ID`if [ $Uid -eq $Gid ];then echo "good!~"else echo "bad!~"fi第二种方法:#!/bin/bashread -p "请输入用户:" IDif ! grep "^$ID\>" /etc/passwd $> /dev/null;thenecho "用户不存在"exit 1fiUserID=`grep "^$ID\>" /etc/passwd | cut -d: -f3`GroupID=`grep "^$ID\>" /etc/passwd | cut -d: -f4`if [ $UserID -eq $GroupID ];thenecho "good!~(UID和GID相同)"elseecho "bad!~(UID和GID不同)"fishell条件判断和算术运算1、let 算术运算表达式let C=$A+$B2、$[算术运算表达式]C=$[$A+$B]3、$((算术运算表达式))C=$(($A+$B))4、exprC=`EXPR $A + $B`练习:给定一个用户,获取其密码警告期限,而后判断用户最近一次修改时间距是否已经小于警告期限小于,则显示"warning",否则,显示"find"一方法:#!/bin/bashread -p "请输入用户:" IDTIMESTAMP=`date +%s`TODAY=`let today=$TIMESTAMP/86400`UserID=`grep "^$ID\>" /etc/passwd | cut -d: -f3`ti2=`let Ti1=$TODAY-$UserID`ti3=`grep "^$ID\>" /etc/passwd | cut -d: -f6`if [ $ti2 < $ti3 ];thenecho " warning!!! "elseecho "find!!! "fi二方法:#!/bin/bashread -p "请输入用户:" IDW=`grep "^$ID\>" /etc/passwd | cut -d: -f6`S=`date +%s`T=`expr $s/86400`L=`grep "^$ID\>" /etc/passwd | cut -d: -f5`N=`grep "^$ID\>" /etc/passwd | cut -d: -f3`SY=$[$L-$[$T-$N]]if [ $SY-lt $W ];thenecho " warning!!! "elseecho "find!!! "fishell 整数测试和特殊变量整数测试-eq测试两个整数是否相等,比如:$A -eq $B-ne测试连个整数是否不等,不等为真,相等为假-gt测试一个数是否大于另一个数:大于为真,否则为假-lt测试一个数是否小于另一个数:小于为真,否则为假-ge大于或等于-le小于或等于整数测试方法:[ expression ]命令测试法[[ expression ]]关键字测试法test expression示例:比较两个数值[ $Num1 -eq $Num2 ][[ $Num1 -eq $Num2 ]]test $Num1 -eq $Num2 文件测试:-e file测试文件是否存在-f file测试文件是否为普通文件-d file测试指定路径是否为目录-r file测试当前用户对指定文件是否有读权限-w file测试当前用户对指定文件是否有写权限-x file测试当前用户对指定文件是否有执行权限示例:测试文件是否存在[ -e filename ]多分支if语句if 判断条件1;thenstatement1...elif 判断条件2;thenstatement2...elif 判断条件3;thenstatement3...elsestatement4...fi定义脚本退出码:exit 退出脚本exit #测试脚本是否有语法错误bash -n 脚本脚本单步执行bash -x 脚本bash变量类型:环境变量:本地变量:(局部变量)位置变量:特殊变量:位置变量:$1,$2,...shift轮替(默认为1)特殊变量:$?上一条命令的退出状态码$#参数的个数$*参数列表$@参数列表练习:vim shift.sh#!/bin/bashecho $1shift 2echo $1shift 2echo $1练习:写脚本,给脚本传递两个参数(整数);显示两者之和,之积#!/bin/bashif [ $# -lt 2 ];thenecho "Usge: ./.sh ARG1,ARG2."exit 8fiecho "The sum is: $[$1+$2]."echo "the pro is: $[$1*$2]." 练习:写一个脚本,接受参数,判定,此参数如果是一个存在的文件,就显示"OK",否则就显示"No such file。"#!/bin/bash#说明:参数不能为空,否则会显示帮助"Usge: ./fan3.sh ARG1...[ARG2,ARG3,...]"if [ $# -lt 1 ];then echo "Usge: ./fan3.sh ARG1...[ARG2,ARG3,...]" exit 7fiif [ -e $1 ];then echo "OK"else echo "No such file."fishell字符串测试和for循环字符串比较== 等值比较,等则为真,不等为假(等号两端必须是空格)!=不等比较,不等为真,等则为假-n string测试字符串是否为空,空为真,不空为假-z string测试字符串是否为不空,不空为真,空为假循环:进入条件,退出条件forwhileuntilfor循环for 变量 in 列表;do循环体done遍历完成后,退出生成列表{1..100}表示起始为1,结束为100`seq [起始数[步进长度]] 结束数`循环示例:示例:1加到100#!/bin/bash#declare -i SUM=0for I in {1..100};do let SUM=$[$SUM+$I]doneecho "sum is :$SUM"字符串比较示例:示例:传递一个用户名参数给脚本,判断此用户名跟基本组的组名是否一致#!/bin/bash#if ! id $1 &> /dev/null;thenecho "No such user."exit 10fiif [ $1 == 'id -n -g $1' ];thenecho "ok"elseecho "No"fi示例:传一个参数(单字符),参数为q,就退出脚本,否则显示用户的参数示例:传一个参数(单字符),参数为q、Q、quit,就退出脚本,否则显示用户的参数#!/bin/bash#if [ $1 = 'q' ];thenecho "Quiting..."exit 1elif [ $1 = 'Q' ];thenecho "Quiting..."exit 2elif [ $1 = 'quit' ];thenecho "Quiting..."exit 3elif [ $1 = 'Quit' ];thenecho "Quiting..."exit 4elseecho $1fi字符串练习:传递三个参数,第一个为整数,第二个为运算符,第三个为整数,显示计算结果,要求保留两位精度bc用法echo " scale=2;a/b" | bsbc <<< "scale=2;a/b"字符串练习:比较三个整数的大小练习:判断当前主机的CPU生产商,其信息在/proc/cpuinfo文件中vendor id 一行中如果其生产商为AuthenticAMD,就显示其为AMD公司如果其生产商为GenuineIntel,就显示其为Intel公司否则,就为非主流公司#!/bin/bash#I=vendor_idN=`grep $I /proc/cpuinfo | sed -r 's#[[:space:]]+##g' | cut -d: -f2`if [ $N == GenuineIntel ];then echo "该CPU生产商为:Intel 公司"elif [ $N == AuthenticAMD ];then echo "该CPU生产商为 AMD 公司"else echo "该CPU生产商为非主流公司!" fi字符串练习:传递3个参数,参数均为用户名。将此用户的账号信息提取出来后放置于filename 中,行号一行首有行号#!/bin/bash#A=rootB=mailC=ntpecho `grep -n ^$A /etc/passwd` >>file.txtecho `grep -n ^$B /etc/passwd` >>file.txtecho `grep -n ^$C /etc/passwd` >>file.txtfor循环练习题遍历/etc/passwd中的用户,并问好!并显示对方的shell提示:LINES=`wc -l /etc/passwd | cut -d' ' -f1`for I in `seq 1 $LINES`;do echo "hello,`head -n $I /etc/passwd | tail -l | cut -d: -f1`";done#!/bin/bash#LI=`wc -l /etc/passwd | cut -d' ' -f1`#echo "$LI" for I in `seq 1 $LI`;doecho "hello, `head -n $I /etc/passwd | tail -1 | cut -d: -f1`, 该用户对于的shell是:`head -n $I /etc/passwd | tail -1 | cut -d: -f7`";donefor循环练习题添加10个用户user1到user10,密码同用户名;但要求只有用户不存在才能创建#!/bin/bashfor I in {1..10};do let N=$I U=user$N if id $U &>/dev/null;thenecho "$U 已经存在!~" elseuseradd $Uecho $U | passwd --stdin $U &> /dev/nullecho "$U 已经添加成功!~" fidone扩展:删除用户user1...user10#!/bin/bashfor I in {1..10};do let N=$I U=user$N if id $U &>/dev/null;thenuserdel -r $Uecho "$U 已经删除成功!~" elseecho "$U 不存在!~" fidone扩展:接受参数:add:添加用户user1...user10del:删除用户user1...user10#!/bin/bashif [ $# -lt 1 ];thenecho "input add or del:"exit 7fiif [ $1 == 'add' ];thenfor I in {1..10};doif id user$I &> /dev/null;thenecho "user$I 已存在"elseuseradd user$Iecho user$I | passwd --stdin user$I &> /dev/nullecho "user$I 添加成功!~"fidoneelif [ $1 == 'del' ];thenfor I in {1..10};doif id user$I &> /dev/null;thenuserdel -r user$Iecho "user$I 删除成功"elseecho "user$I 不存在"fidoneelseecho "Unknown ARG"exit 8fi执行:.sh add 添加用户.sh del 删除用户扩展:输入 .sh user1,user2,user3 添加#!/bin/bashecho $1for I in `echo $1 | sed 's/,/ /g'`;doif id $I &>/dev/null;thenecho "$I 存在"elseuseradd $Iecho $I | passwd --stdin $I >/dev/nullecho "$I 添加成功"fidone扩展:输入 .sh --add user1,user2,user3.sh --del user1,user2,user3#!/bin/bashif [ $1 == '--add' ];thenfor I in `echo $2 | sed 's/,/ /g'`;doif id $I &>/dev/null;thenecho "$I 存在"elseuseradd $Iecho $I | passwd --stdin $I >/dev/nullecho "$I 添加成功"fidoneelif [ $1 == '--del' ];thenfor I in `echo $2 | sed 's/,/ /g'`;doif id $I &>/dev/null;thenuserdel -r $Iecho "$I 删除成功"elseecho "$I 不存在"fidoneelif [ $1 == '--help' ];thenecho "(1).命令格式:./ sh --[options] username!~"echo "(2).--add username | --del username | --help 不能同时出现"elseecho "Unknown options"fi缺点(待完善):无法判断参数数无法判断没有参数(忘记给参数)无法判断参数错误(--add和--del同时使用)for循环练习题计算100以内所有能被3整除的正整数提示:取模,取余#!/bin/bashlet "sum=0"for i in {1..10}dolet "m=i%3"if [ "$m" -eq 0 ]thenlet "sum=sum+i"fidoneecho "the sum is :$sum"for循环练习题计算100以内所有奇数的和以及所有偶数的和,分别显示之#!/bin/bashdeclare "sum1=0"declare "sum2=0"for i in {1..100}dolet "m=i%2"if [ "$m" -eq 0 ];thenlet "sum1=sum1+i"elif [ "$m" -eq 1 ];thenlet "sum2=sum2+i"fidoneecho " 1-100以内的偶数和为: $sum1"echo " 1-100以内的奇数和为: $sum2"练习题分别显示默认shell为bash的用户和/sbin/nologin的用户,并统计各类shell下的用户总数#!/bin/bash#FILE=/etc/passwdecho "默认shell为bash的用户有: `grep 'bash' $FILE | wc -l` 个!分别为:"B=`sed -n '/bash/p' $FILE | cut -d: -f1`BB=`echo $B|sed 's@[[:spqce:]]@,@g'`echo "$BB"echo "默认shell为nologin的用户有 `grep 'nologin' $FILE | wc -l` 个!分别为:"A=`sed -n '/nologin/p' $FILE | cut -d: -f1`AA=`echo $A|sed 's@[[:spqce:]]@,@g'`echo "$AA"脚本选项·和组合条件测试回顾:整数测试:-eq测试两个整数是否相等,比如:$A -eq $B-ne测试连个整数是否不等,不等为真,相等为假-gt测试一个数是否大于另一个数:大于为真,否则为假-lt测试一个数是否小于另一个数:小于为真,否则为假-ge大于或等于-le小于或等于字符测试==等于!=不等于>大于<小于-n字符串是否为空-z字符串是否为不空文件测试-e file测试文件是否存在-f file测试文件是否为普通文件-d file测试指定路径是否为目录-r file测试当前用户对指定文件是否有读权限-w file测试当前用户对指定文件是否有写权限-x file测试当前用户对指定文件是否有执行权限组合测试-o逻辑或-a逻辑与!逻辑非添加10个用户user1到user10,密码同用户名;但要求只有用户不存在才能创建#!/bin/bashfor I in {1..10};do let N=$I U=user$N if id $U &>/dev/null;thenecho "$U 已经存在!~" elseuseradd $Uecho $U | passwd --stdin $U &> /dev/nullecho "$U 已经添加成功!~" fidone扩展:删除用户user1...user10#!/bin/bashfor I in {1..10};do let N=$I U=user$N if id $U &>/dev/null;thenuserdel -r $Uecho "$U 已经删除成功!~" elseecho "$U 不存在!~" fidone扩展:接受参数:add:添加用户user1...user10del:删除用户user1...user10#!/bin/bashif [ $# -lt 1 ];thenecho "input add or del:"exit 7fiif [ $1 == 'add' ];thenfor I in {1..10};doif id user$I &> /dev/null;thenecho "user$I 已存在"elseuseradd user$Iecho user$I | passwd --stdin user$I &> /dev/nullecho "user$I 添加成功!~"fidoneelif [ $1 == 'del' ];thenfor I in {1..10};doif id user$I &> /dev/null;thenuserdel -r user$Iecho "user$I 删除成功"elseecho "user$I 不存在"fidoneelseecho "Unknown ARG"exit 8fi执行:.sh add 添加用户.sh del 删除用户扩展:输入 .sh user1,user2,user3 添加#!/bin/bashecho $1for I in `echo $1 | sed 's/,/ /g'`;doif id $I &>/dev/null;thenecho "$I 存在"elseuseradd $Iecho $I | passwd --stdin $I >/dev/nullecho "$I 添加成功"fidone扩展:输入 .sh --add user1,user2,user3.sh --del user1,user2,user3#!/bin/bashif [ $1 == '--add' ];thenfor I in `echo $2 | sed 's/,/ /g'`;doif id $I &>/dev/null;thenecho "$I 存在"elseuseradd $Iecho $I | passwd --stdin $I >/dev/nullecho "$I 添加成功"fidoneelif [ $1 == '--del' ];thenfor I in `echo $2 | sed 's/,/ /g'`;doif id $I &>/dev/null;thenuserdel -r $Iecho "$I 删除成功"elseecho "$I 不存在"fidoneelif [ $1 == '--help' ];thenecho "(1).命令格式:./ sh --[options] username!~"echo "(2).--add username | --del username | --help 不能同时出现"elseecho "Unknown options"fi缺点(待完善):无法判断参数数无法判断没有参数(忘记给参数)无法判断参数错误(--add和--del同时使用)shell编程case语句和脚本选项进阶面向过程控制接口顺序结构选择结构if..slif..else..fi循环结构case语句:选择结构case SWITCH invalue1)statement...;;#每一个选择条件必须两个;结束value2)statement...;;*)statement...;;esac#case字母反过来写表示结尾示例:写一个脚本,只接受参数start,stop,restart,status其中之一#!/bin/bash#read -p "iuput:" Ncase $N in'start') echo "start server...";;'stop') echo "stop server...";;'restaer') echo "restart server...";;'status') echo "Running..."*) echo "`basename $0` {start|stop|restart|status}";;esac示例:写一个脚本,可以接受选项及参数,而后获取每一个选项及参数,并能根据选项及参数作出特定的操作比如:admin.sh --add tom,jer --del tom,jer --v|--verbose --h|--helo选项可同时使用例如:./test.sh -v --add tom,jer #!/bin/bash#DEBUG=0ADD=0DEL=0for I in `seq 1 $#`;doif [ $# -gt 0 ]; thencase $1 in-v|--verbose) DEBUG=1 shift ;;-h|--help) echo "Usage:`basename $0` --add UAERNAM --del USERNAME -v|--verbose -h|--help" exit 0 ;;--add) ADD=1 ADDUSERS=$2 shift 2 ;;--del) DEL=1 DELUSERS=$2 shift 2 ;;*) echo "Usage:`basename $0` --add UAERNAM --del USERNAME -v|--verbose -h|--help" exit 7 ;;esacfidoneif [ $ADD -eq 1 ]; then for USER in `echo $ADDUSERS | sed 's@,@ @g'`; doif id $USER &> /dev/null; then[ $DEBUG -eq 1 ] && echo "$USER exists."elseuseradd $USER[ $DEBUG -eq 1 ] && echo "Add user $USER finished." fi donefiif [ $DEL -eq 1 ]; then for USER in `echo $DELUSERS | sed 's@,@ @g'`; doif id $USER &> /dev/null; thenuserdel -r $USER[ $DEBUG -eq 1 ] && echo "Delete $USER finished."else[ $DEBUG -eq 1 ] && echo "$USER not exist."fi donefi写一个脚本利用RANDOM生成10个随机数,并找出其中的最大值和最小值#!/bin/bashdeclare -i MAX=0declare -i MIN=0for I in {1..10};domyrand=$RANDOM[ $I -eq 1 ] && MIN=$myrandif [ $I -le 9 ];thenecho -n "$myrand,"elseecho "$myrand"fi [ $myrand -gt $MAX ] && MAX=$myrand [ $myrand -lt $MIN ] && MIN=$myranddoneecho "max = $MAX"echo "min = $MIN"示例:写一个脚本:showlog.sh用法为:showlog.sh -v -c -h|--help其中:-h选项单独使用,用于显示帮助信息,-c显示当前登陆的所有用户,如果同时使用-v,极限是同时登陆的用户数,又显示登陆用户的相关信息#!/bin/bash#declare -i SHOWNUM=0declare -i SHOWUSERS=0for I in `seq 1 $#`;do if [ $# -gt 0 ]; thencase $1 in-h|--help) echo "Usage:`basename $0` -h|--help -c|-counts -v|--verbose" exit 0 ;;-v|--verbose) let SHOWUSERS=1 shift ;;-c|--count) let SHOWNUM=1 shift ;;*) echo "Usage:`basename $0` -h|--help -c|-counts -v|--verbose" exit 8 ;;esac fidoneif [ $SHOWNUM -eq 1 ];then echo "log users:`who | wc -l`." if [ $SHOWUSERS -eq 1 ];thenecho "They are:"who fifishell编程 while循环while循环适用于循环次数未知的场景必须要有退出条件语法格式while CONDITON;dostatement...done进入循环,条件满足退出循环,条件不满足循环的控制方法break提前退出循环continue提前进入下一循环while特殊用法之一:死循环while :;dodonewhile特殊用法之二:while read LINE;dodone < FILENAME说明:whlie 循环读取FILENAME中的每一行,放在变量LINE中,然后再循环中处理LINE中的行示例:(待完善)判断/etc/passwd中的那个用户的shell是bash,如果是bash就显示用户名,否则不显示名字#!/bin/bash#FILE=/etc/passwdlet I=0while read LINE;do [ `echo $LINE | awk -F : '{prinf $3}'` -le 505 ] && continue #用户ID大于505就不在判断,提前进入下一循环 [ `echo $LINE | awk -F : '{prinf $7}'` == '/bin/bash' ] && echo $LINE | awk -F : '{print $1}' && let I++ [ $I -eq 6 ] && break #只读取前6个用户done < $FILEcontinue示例:计算100以内所有偶数和#!/bin/bash#let SUM=0let I=0while [ $I -lt 100 ];do let I++ if [ $[$I%2] -eq 0 ];thencontinue fi let SUM+=$Idoneecho $SUM break示例:从1加到1000,知道和为5000就退出循环不再相加#!/bin/bash#declare -i SUM=0for I in {1..1000};do let SUM+=$I if [ $SUM -gt 5000 ];thenbreak fidoneecho "I=$I"echo "SUM=$SUM"break示例:判断一个文件是否存在,用户输入quit就退出#!/bin/bash#while :;do read -p "input filename:"FILENAME [ $FILENAME=='quit' ] && break if [ -e $FILENAME ];then echo "$FILENAME exists." else echo "No $FILENAME" fidoneecho "Quit." 写一个脚本:说明:此脚本能于同一个repo文件中创建多个yum源的指向1、接受一个文件名作为参数,此文件存放至/etc/yum.repos.d目录中,且文件名以.repo为后缀,要求此文件不能事先存,否则,报错2、在脚本中,提醒用户输出repo id ,如果为quit,则退出脚本,否则,继续完成下面的步骤3、repo name以及baseurl的路径,而后以repo文件的格式将其保存到指定的文件中4、enabled默认为1,而gpgcheck默认为05、此脚本会循环多次,除非用户为repo id指定为quit#!/bin/bash#REPOFILE=/etc/yum.repos.d/$1if [ -e $REPODILE ];then echo "$1 exists." exit 3firead -p "input ID:" REPOIDuntil [ $REPOID == 'quit' ];do echo "[$REPOID]" >> $REPOFILE read -p "input name: " REPONAME echo "name=$REPONAME" >> $REPOFILE read -p "input Baseurl:" REPOURL echo -e 'enabled-1\ngpgcheck=0' >> $REPOFILE read -p "input ID:" REPOIDdone示例:计算100以内所有正整数的和#!/bin/bash#declare -i I=1declare -i SUM=0while [ $I -le 100 ];do let SUM+=$I let I++doneecho "$SUM"示例:用户输入字符串,就转换成大写,输入'quit'就退出#!/bin/bash#read -p "input something:" STRINGwhile [ $STRING != 'quit' ];do echo $STRING | tr 'a-z' 'A-Z' read -p "input something:" STRINGdone示例:练习: 每隔5秒就来查看hadoop是否已经登陆,如登陆,显示其已经登陆,就退出提示:sleepsleep 3 延迟3秒#!/bin/bash#who | grep "hadoop" &> /dev/nullRETVAL=$?while [ $RETVAL -ne 0 ];do echo "`date`,hadoop not is log!" sleep 5 who | grep "hadoop" &> /dev/null RETVAL=$?doneecho "`date` hadoop is logged!"示例:1.显示一个菜单给用户d|D) show disk usagesm|M) show menory usagess|S) show swap usages*) quit2.当用户给定选项后显示响应的内容#!/bin/bashcat << EOFd|D) show disk usagesm|M) show menory usagess|S) show swap usages*) quitEOFread -p "Your choice:" CHcase $CH ind|D) echo "Disk usages:" df -h ;;m|M) echo "Memory usages;" free -m | grep "Mem" ;;s|S) echo "Swap usages:" free -m | grep "Swap" ;;*) echo "Unknow.." exit 9 ;;esac~ 扩展:当用户选择完成,显示响应信息后,不退出,而让用户再一次选择,再次显示响应内容,除了用户使用quit#!/bin/bashcat << EOF d|D) show disk usages m|M) show menory usages s|S) show swap usages *) quitEOFread -p "Your choice:" CHwhile [ $CH != 'quit' ];do case $CH in d|D)echo "Disk usages:"df -h;; m|M)echo "Memory usages;"free -m | grep "Mem";; s|S)echo "Swap usages:"free -m | grep "Swap";; *)echo "Unknow..";; esacread -p "Again,your choice:" CHdone写一个脚本:1、提示用户输入一个用户名2、显示一个菜单给用户。形如U|u show UIDG|g show GIDS|s show SHELLQ|q quit3、提醒用户选择一个选项,并显示其所有选择的内容如果用户给一个错误的选项,则提醒用户选项错误,请其重新选择#!/bin/bash# echo "* * * * * * * * * * * * *"read -p "Please enter your user name: " USuntil [ $US == 'quit' ];doif id -u $US &> /dev/null;thenecho "$US is OK!Please select"echo "=======options======="cat << EOFU|u) show UIDG|g) show GIDS|s) show SHELLq|Q) quitEOFecho "=====================" read -p "Please select options: " SHecho "=====================" while : ;do case $SH in U|u)echo "$US uid=`grep "^$US" /etc/passwd | cut -d: -f4`" ;; G|g)echo "$US gid=`grep "^$US" /etc/passwd | cut -d: -f3`" ;; S|s)echo "$US shell=`grep "^$US" /etc/passwd | cut -d: -f7`" ;; Q|q)echo "******quiting...******"exit ;; *)echo "Wrong option.Please again"echo "=======options======="cat << EOFU|u) show UIDG|g) show GIDS|s) show SHELLq|Q) quitEOFecho "=====================" ;; esacread -p "Please choose again: " SHdoneelse echo "-------------------------------------" echo "The user name wrong.." echo "* * * * * * * * * * * * *" read -p "Please enter the username again : " US fidoneshell编程until循环until CONDITION;进入循环,条件不满足退出循环,条件满足for循环for ((expr1 ; expr2 ; expr3)); do循环体done示例:100以内的正整数相加#!/bin/bash#declare -i SUM2=0for ((J=1;J<=100;J++));do let SUM2+=$Jdoneecho $SUM2until循环示例:示例:#!/bin/bash#read -p "input something:" STuntil [ $ST== 'quit' ];do echo $ST | tr 'a-z' 'A-Z' read -p "input something:" STdone示例:练习: 每隔5秒就来查看hadoop是否已经登陆,如登陆,显示其已经登陆,就退出第一种方法#!/bin/bash#who | grep "hadoop" &> /dev/nullRETVAL=$?until [ $RETVAL -eq 0 ];do echo "hadoop is not come." sleep 5 who | grep "hadoop" &> /dev/null RETVAL=$?doneecho "hadoop is logged in."第二种方法#!/bin/bash#until who | grep "hadoop" &> /dev/null;do echo "hadoop is not come." sleep 5doneecho "hadoop is logged in."测试:通过ping命令测试192.168.0.151到192.168.0.254直接所有主机是否在线如果在线,就显示ip is up,其ip要换为真正的IP动作,且显示为绿色如果不在线,就显示"ip is down",其中的IP换为真正的IP地址,且红色显示分别用while,until for(两种形式)循环实现for循环第一种方法:for ((i=99;i<=120;i++));do if ping -c 1 -W 1 192.168.0.$i &> /dev/null;thenecho "192.168.0.$i 在线" elseecho "192.168.0.$i 不在线" fidonefor循环第二种方法:for i in {99..120};do if ping -c 1 -W 1 192.168.0.$i &> /dev/null;thenecho "192.168.0.$i 在线" elseecho "192.168.0.$i 不在线" fidonewhile循环#!/bin/bash#declare -i I=151while [ $I -le 254 ];do let I++ if ping -c 1 -W 1 192.168.3.$I &> /dev/null;thenecho "192.168.3.$I 在线" elseecho "192.168.3.$I 不在线" fidoneuntil循环#!/bin/bash#declare -i I=191until [ $I -gt 254 ];do let I++ if ping -c 1 -W 1 192.168.3.$I &> /dev/null;thenecho "192.168.3.$I 在线" elseecho "192.168.3.$I 不在线" fidoneshell编程之:函数、功能function代码重用,结构化编程,不能独立运行,需要调用时执行,可以多次被调用定义函数方法一function FUNCNAME {command}定义函数方法二FUNCNAME() {command}自定义执行状态返回值return ##的值:0-255接受参数的函数FUNCNAM n1 n2$1 n1$2 n2示例:多次显示菜单#!/bin/bash#function SHOWM {#定义函数SHOWMcat << EOF d|D) show disk usages m|M) show menory usages s|S) show swap usages *) quitEOF}SHOWM#调用函数return示例添加用户test#!/bin/bash#ADDUSER() {USERNAME=testif ! id -u $USERNAME &> /dev/null;thenuseradd $USERNAMEecho $USERNAME | passwd --stdin $USERNAME &> /dev/nullreturn 0elsereturn 1fi}ADDUSERecho $?if [ $? -eq 0 ];thenecho "add user finished."elseecho "Failuer."fi扩展:添加多个用户#!/bin/bash#ADDUSER() {USERNAME=$1if ! id -u $USERNAME &> /dev/null;thenuseradd $USERNAMEecho $USERNAME | passwd --stdin $USERNAME &> /dev/nullreturn 0elsereturn 1fi}for I in {1..10};doADDUSER user$Iif [ $? -eq 0 ];thenecho "add user$I finished."elseecho "add user$I Failuer."fidone函数接受参数示例#!/bin/bash#TWOSUM() {echo $[$1+$2]}TWOSUM 5 6SUM=`TWOSUM 5 6`#保存函数的执行结果至一个变量,可做进一步操作echo $SUM示例:10以内相邻两个数相加#!/bin/bash#TWOSUM() {echo $[$1+$2]}for I in {1..10};dolet J=$[$I+1]TWOSUM $I $Jecho "$I + $J = `TWOSUM $I $J`"done示例:写一个脚本,判定192.168.0.200-192.168.0.254之间的主机哪些在线。要求:1、使用函数来实现一台主机的判定过程2、在主程序中来调用此函数判定指定范围内的所有主机的在线情况第一种方法:#!/bin/bash#PING() { if ping -c 1 -W 1 $1 &> /dev/null;thenecho "$1 在线" elseecho "$1 不在线" fi}for I in {200..254};do PING 192.168.0.$Idone#for I in{200..254};do#ping另一个网段# PING 192.168.2.$I#done第二种方法:#!/bin/bash#PING() { if ping -c 1 -W 1 $1 &> /dev/null;thenreturn 0 elsereturn 1 fi}for I in {200..254};do PING 192.168.0.$I if [ $? -eq 0 ];thenecho "192.168.0.$I 在线" elseecho "192.168.0.$I 不在线" fidone写一个脚本1、函数接受一个参数,参数为用户名判定一个用户是否存在如果存在,就返回此用户的shell和UID,并返回正常状态值如果不存在,就说此用户不存在,并返回错误状态值2、在主程序中调用函数扩展1:在主程序中,让用户自己输入用户名后,传递给函数来进行判断扩展2:在主程序中输入用户名判断后不退出脚本,而是提示用户继续输入下一个用户名,但如果用户输入的是q或Q就退出#!/bin/bash#ADDUSER() {USERNAME=$1if id -u $USERNAME &> /dev/null;thenreturn 0elsereturn 1fi}read -p "input : " Uecho "==================================="until [ $U == q -o $U == Q ];doADDUSER $Uif [ $? == 0 ];then# echo "$U 存在" sh=`grep "^$U" /etc/passwd | awk -F : '{print $7}'` ui=`grep "^$U" /etc/passwd | awk -F : '{print $4}'` echo "$U 的 shell = $sh, UID = $ui" echo "===================================" read -p "input again: " U echo "==================================="else echo "$U 不存在" echo "===================================" read -p "input again: " U echo "==================================="fidoneecho "quit..."echo "==================================="