shell编程:
编译器,解释器编程语言:机器语言、汇编语言、高级语言静态语言:编译型语言 强类型(变量) 事先转换成可执行格式 C、C++、JAVA、C# 动态语言:解释型语言, on the fly 弱类型 边解释边执行 PHP、SHELL、python、perl 面向过程:Shell, C面向对象: JAVA, Python, perl, C++变量:内存空间,命名内存:编址的存储单元进程:1+100:1+10000001变量类型:事先确定数据的存储格式和长度 字符 数值 整型 浮点型: 11.23, 1.123*10^1, 0.1123*10^2 2013/10/10, 64bit 99999: 24bit, 真、假 逻辑:1+1>2逻辑运算:与、或、非、异或1: 真0: 假1 & 0 = 00 & 1 = 00 & 0 = 01 & 1 = 1或:非:! 真 = 假! 假 = 真shell: 弱类型编程语言强:变量在使用前,必须事先声明,甚至还需要初始化;弱:变量用时声明,甚至不区分类型;变量赋值:VAR_NAME=VALUEbash变量类型: 环境变量 本地变量(局部变量) 位置变量 特殊变量 本地变量:set VARNAME=VALUE: 作用域为整个bash进程;局部变量:local VARNAME=VALUE:作用域为当前代码段;环境变量:作用域为当前shell进程及其子进程;export VARNAME=VALUEVARNAME=VALUEexport VARNAME “导出”位置变量:$1, $2, ...特殊变量:$?: 上一个命令的执行状态返回值;程序执行,可能有两类返回值: 程序执行结果 程序状态返回代码(0-255) 0: 正确执行 1-255:错误执行,1,2,127系统预留; 输出重定向:>>>2>2>>&>撤消变量:unset VARNAME查看当shell中变量:set查看当前shell中的环境变量:printenvenvexport脚本:命令的堆砌,按实际需要,结合命令流程控制机制实现的源程序shebang: 魔数#!/bin/bash# 注释行,不执行/dev/null: 软件设备, bit bucket,数据黑洞 脚本在执行时会启动一个子shell进程; 命令行中启动的脚本会继承当前shell环境变量; 系统自动执行的脚本(非命令行启动)就需要自我定义需要各环境变量; 练习:写一个脚本,完成以下任务1、添加5个用户, user1,..., user52、每个用户的密码同用户名,而且要求,添加密码完成后不显示passwd命令的执行结果信息;3、每个用户添加完成后,都要显示用户某某已经成功添加;useradd user1echo "user1" | passwd --stdin user1 &> /dev/nullecho "Add user1 successfully."条件判断: 如果用户不存在 添加用户,给密码并显示添加成功; 否则 显示如果已经没在,没有添加;bash中如何实现条件判断?条件测试类型: 整数测试 字符测试 文件测试条件测试的表达式: [ expression ] [[ expression ]] test expression 整数比较: -eq: 测试两个整数是否相等;比如 $A -eq $B -ne: 测试两个整数是否不等;不等,为真;相等,为假; -gt: 测试一个数是否大于另一个数;大于,为真;否则,为假; -lt: 测试一个数是否小于另一个数;小于,为真;否则,为假; -ge: 大于或等于 -le:小于或等于 命令的间逻辑关系: 逻辑与: && 第一个条件为假时,第二条件不用再判断,最终结果已经有; 第一个条件为真时,第二条件必须得判断; 逻辑或: || 如果用户user6不存在,就添加用户user6! id user6 && useradd user6id user6 || useradd user6如果/etc/inittab文件的行数大于100,就显示好大的文件;[ `wc -l /etc/inittab | cut -d' ' -f1` -gt 100 ] && echo "Large file."变量名称: 1、只能包含字母、数字和下划线,并且不能数字开头; 2、不应该跟系统中已有的环境变量重名; 3、最好做到见名知义;如果用户存在,就显示用户已存在;否则,就添加此用户;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、最后显示当前系统上共有多少个用户;练习,写一个脚本,完成以下要求:给定一个用户: 1、如果其UID为0,就显示此为管理员; 2、否则,就显示其为普通用户;如果 UID为0;那么 显示为管理员否则 显示为普通用户 NAME=user16USERID=`id -u $NAME`if [ $USERID -eq 0 ]; then echo "Admin"else echo "common user."fiNAME=user16if [ `id -u $NAME` -eq 0 ]; then echo "Admin"else echo "common user."fiif id $NAME; then 练习:写一个脚本判断当前系统上是否有用户的默认shell为bash; 如果有,就显示有多少个这类用户;否则,就显示没有这类用户;grep "bash$" /etc/passwd &> /dev/nullRETVAL=$?if [ $RETVAL -eq 0 ]; then if grep "bash$" /etc/passwd &> /dev/null; then 提示:“引用”一个命令的执行结果,要使用命令引用;比如: RESAULTS=`wc -l /etc/passwd | cut -d: -f1`; 使用一个命令的执行状态结果,要直接执行此命令,一定不能引用;比如: if id user1一句中的id命令就一定不能加引号; 如果想把一个命令的执行结果赋值给某变量,要使用命令引用,比如USERID=`id -u user1`; 如果想把一个命令的执行状态结果保存下来,并作为命令执行成功与否的判断条件,则需要先执行此命令,而后引用其状态结果,如 id -u user1 RETVAL=$? 此句绝对不可以写为RETVAL=`id -u user1`; 练习:写一个脚本判断当前系统上是否有用户的默认shell为bash; 如果有,就显示其中一个的用户名;否则,就显示没有这类用户;练习:写一个脚本给定一个文件,比如/etc/inittab判断这个文件中是否有空白行;如果有,则显示其空白行数;否则,显示没有空白行。#!/bin/bashA=`grep '^$' /etc/inittab | wc -l`if [ $A -gt 0 ]; then echo "$A"else echo "meiyoukongbaihang"fi —— by 张帅 #!/bin/bashFILE=/etc/inittabif [ ! -e $FILE ]; then echo "No $FILE." exit 8fiif grep "^$" $FILE &> /dev/null; then echo "Total blank lines: `grep "^$" $FILE | wc -l`."else echo "No blank line."fi练习:写一个脚本给定一个用户,判断其UID与GID是否一样如果一样,就显示此用户为“good guy”;否则,就显示此用户为“bad guy”。#!/bin/bashUSERNAME=user1USERID=`id -u $USERNAME`GROUPID=`id -g $USERNAME`if [ $USERID -eq $GROUPID ]; then echo "Good guy."else echo "Bad guy."fi进一步要求:不使用id命令获得其id号;#!/bin/bash#USERNAME=user1if ! grep "^$USERNAME\>" /etc/passwd &> /dev/null; then echo "No such user: $USERNAME." exit 1fiUSERID=`grep "^$USERNAME\>" /etc/passwd | cut -d: -f3`GROUPID=`grep "^$USERNAME\>" /etc/passwd | cut -d: -f4`if [ $USERID -eq $GROUPID ]; then echo "Good guy."else echo "Bad guy."fi练习:写一个脚本给定一个用户,获取其密码警告期限;而后判断用户密码使用期限是否已经小于警告期限; 提示:计算方法,最长使用期限减去已经使用的天数即为剩余使用期限; 如果小于,则显示“Warning”;否则,就显示“OK”。圆整:丢弃小数点后的所有内容#!/bin/bashW=`grep "student" /etc/shadow | cut -d: -f6`S=`date +%s`T=`expr $S/86400`L=`grep "^student" /etc/shadow | cut -d: -f5`N=`grep "^student" /etc/shadow | cut -d: -f3`SY=$[$L-$[$T-$N]]if [ $SY -lt $W ]; then echo 'Warning'else echo 'OK'fi —— by 董利东练习:写一个脚本判定命令历史中历史命令的总条目是否大于1000;如果大于,则显示“Some command will gone.”;否则显示“OK”。shell中如何进行算术运算:A=3B=61、let 算术运算表达式 let C=$A+$B2、$[算术运算表达式] C=$[$A+$B]3、$((算术运算表达式)) C=$(($A+$B))4、expr 算术运算表达式,表达式中各操作数及运算符之间要有空格,而且要使用命令引用 C=`expr $A + $B` 条件判断,控制结构:单分支if语句if 判断条件; then statement1 statement2 ...fi双分支的if语句:if 判断条件; then statement1 statement2 ...else statement3 statement4 ...fi多分支的if语句:if 判断条件1; then statement1 ...elif 判断条件2; then statement2 ...elif 判断条件3; then statement3 ...else statement4 ...fi测试方法:[ expression ][[ expression ]]test expressionbash中常用的条件测试有三种:整数测试: -gt -le -ne -eq -ge: -lt:INT1=63INT2=77[ $INT1 -eq $INI2 ][[ $INT1 -eq $INT2 ]]test $INT1 -eq $INT2 文件测试: -e FILE:测试文件是否存在-f FILE: 测试文件是否为普通文件-d FILE: 测试指定路径是否为目录-r FILE: 测试当前用户对指定文件是否有读取权限;-w-x [ -e /etc/inittab ][ -x /etc/rc.d/rc.sysinit ] 练习:写一个脚本给定一个文件:如果是一个普通文件,就显示之;如果是一个目录,亦显示之;否则,此为无法识别之文件;定义脚本退出状态码exit: 退出脚本exit #如果脚本没有明确定义退出状态码,那么,最后执行的一条命令的退出码即为脚本的退出状态码;测试脚本是否有语法错误:bash -n 脚本bash -x 脚本:单步执行 bash变量的类型: 本地变量(局部变量) 环境变量 位置变量: $1, $2, ... shift:踢掉参数 特殊变量: $? $#:参数的个数 $*: 参数列表 $@:参数列表shift 一次踢掉多个
./filetest.sh /etc/fstab /etc/inittab$1: /etc/fstab$2: /etc/inittab练习:写一脚本能接受一个参数(文件路径)判定:此参数如果是一个存在的文件,就显示“OK.”;否则就显示"No such file."练习:写一个脚本给脚本传递两个参数(整数);显示此两者之和,之乘积;#!/bin/bash#if [ $# -lt 2 ]; then echo "Usage: cacl.sh ARG1 ARG2" exit 8fiecho "The sum is: $[$1+$2]."echo "The prod is: $[$1*$2]." 练习:写一个脚本,完成以下任务1、使用一个变量保存一个用户名;2、删除此变量中的用户,且一并删除其家目录;3、显示“用户删除完成”类的信息; bash: 引用变量:${VARNAME}, 括号有时可省略。整型,8bit: 2560-255, 溢出 变量:1,1000010:16bit10: 1010, 8bit