bash脚本编程简介:
此文假定你没有任何关于脚本或一般程序的编程知识, 但是如果你具备相关的知识, 那么你将很容易就能够达到中高级的水平. . . 你可以把此文作为参考, 自学手册, 或者是关于shell脚本技术的文档。
介绍内容包括:
A:变量、变量类型
B:条件判断、算术运算
C:整数测试及特殊变量
D:字符串测试及for循环
E:使用脚本选项及组合条件测试
F:case语句及脚本选项进阶
G:脚本完成磁盘分区格式化
A.bash变量类型:
1)本地变量:(局部变量)
set VARNAME=VALUE: 作用域为整个bash进程;
2)局部变量:
local VARNAME=VALUE:作用域为当前代码段;
3)环境变量:作用域为当前shell进程及其子进程;
export VARNAME=VALUE
eg1:VARNAME=VALUE 赋值
export VARNAME “导出”
4)位置变量:
$1, $2, ...
5)特殊变量:
$?: 上一个命令的执行状态返回值;
程序执行,可能有两类返回值:
返回值1.程序执行结果
返回值2.程序状态返回代码(0-255)
0:正确执行
1-255:错误执行,1,2,127系统预留;
eg1: #ls /etc/ 执行命令
#$? :0 “执行状态返回值”
6)输出重定向:
> 覆盖重定向
>>追加重定向
2>错误重定向
2>>错误追加重定向
&>追加及错误同时重写向
eg1: #ls /etc/ >/dev/null | echo $? >/dev/null软件设备,数据黑洞
7)撤消变量:
unset x 撤消变量 unset $x 撤消变量中的值
unset VARNAME
eg1:[root@localhost ~]# NAME=Tom定义变量
[root@localhost ~]# echo $NAME显示变量
Tom
[root@localhost ~]# unset NAME
[root@localhost ~]# echo $NAME 撤消变量后变量不显示
[root@localhost ~]#
8)查看当shell中变量:set 包含所有环境变量和本地变量
eg1:查看当前shell中的环境变量:printenv 或env或export
eg2:
[root@localhost ~]# ANIMALS=pigs
[root@localhost ~]# ANIMALS=$ANIMALS:goat
[root@localhost ~]# echo $ANIMALS
pigs:goat
[root@localhost ~]# echo $PATH
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
[root@localhost ~]# echoPATH=$PATH:/usr/local/apache/bin
PATH=/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/usr/local/apache/bin
******************************************************************************************
B.条件判断:
1)命令格式:
if A; then
B
else
C
fi
2)判断条件
1.条件测试类型: 整数测试 字符测试 文件测试
2.条件测试的表达式:[expression ] `expression ` testexpression
3.整数比较:
-eq: 两个整数是否相等; equal
-ne: 两个整数是否不等;不等,为真;相等,为假;not equal
-gt: 一个数是否大于另一个数;大于,为真;否则,为假;greater than
-lt: 一个数是否小于另一个数;小于,为真;否则,为假;less than
-ge: 大于或等于 greater than or equal
-le: 小于或等于less than or equal
eg1: [ $A -eq $B ] 每个字符间必须有空格
3)语句的间逻辑关系:
逻辑与: &&
第一个条件为假时,第二个条件不用再判断,最终结果已经有;
第一个条件为真时,第二个条件必须得判断;
逻辑或: ||
第一个条件为真或为假时,第二个条件必须得判断;
eg1:如果用户user11不存在,就添加用户user11
! id user11 && useradd user11 或 id user11 || useradd user11
eg2:如果/etc/inittab文件的行数大于500,就显示好大的文件;
[ `wc -l /etc/inittab | cut -d' ' -f1` -gt500 ] && echo "Large files."
4)变量名称规则:
(4.1)只能包含字母、数字和下划线,并且不能数字开头;
(4.2)不应该跟系统中已有的环境变量重名;
(4.3)最好做到见名知义;
如果用户不存在,添加并且给密码;否则,显示其已经存在;
! id user1 &> /dev/null && useradd user1&& echo "user1" | passwd --stdin user1 || echo "user1 exists."
5)算术运算:
(5.1)let 算术运算表达式
A=1
B=2
letC=$A+$B
(5.2)$[算术运算表达式]
C=$[$A+$B]
(5.3)$((算术运算表达式))
C=$(($A+$B))
(5.4)expr 算术运算表达式,表达式中各操作数及运算符之间要有空格且要使用命令引用
C=`expr$A + $B`
实例B一:添加3个用户user1, user2,user3;但要先判断用户存在否,不存在则再添加;
添加完成后,显示系統中总共有几个用户;
#!/bin/bash
! id user1 &> /dev/null && useradd user1 || echo "user1 exists."
! id user2 &> /dev/null && useradd user2 || echo "user2 exists."
! id user3 &> /dev/null && useradd user3 || echo "user3 exists."
USERS=`wc -l /etc/passwd | cut -d: -f1`
echo "$USERS users."
以下使用IF语句:
#!/bin/bash
NAME=user110
if id $NAME &> /dev/null;then 使用命令执行状态结果,要直接执行此命令,一定不能引用
echo "$NAME exists."
else
useradd $NAME
echo $NAME | passwd --stdin $NAME &> /dev/null
echo "Add $NAME finished."
fi
echo "`wc -l /etc/passwd | cut -d: -f1`users."
提示:
1.“引用”一个命令的执行结果,要使用命令引用;
比如: RESAULTS=`wc -l /etc/passwd | cut -d: -f1`;
2.使用一个命令的执行状态结果,要直接执行此命令,一定不能引用;
比如: if id user1一句中的id命令就一定不能加引号;
3.想把一个命令的执行结果赋值给某变量,要使用命令引用,
比如USERID=`id -u user1`;
4.想把一个命令的执行状态结果保存下来,并作为命令执行成功与否的判断条件,则需要先执行此命令,而后引用其状态结果,如
id-u user1
RETVAL=$?
此句绝对不可以写为:RETVAL=`id -u user1`;
实例B二:给定一个用户:
1、如果其UID为0,就显示此为管理员;
2、否则,就显示其为普通用户;
#!/bin/bash
NAME=user1
USERID=`id -u $NAME`
# USERID=`grep "user1:" /etc/passwd | cut -d: -f3` 与上条语句同样功能
if [ $USERID -eq 0 ]; then* then为同行前面要有;若then在下一行可不加;
echo"Adminuser."
else
echo"common user."
fi
实例B三:if语句条件差异
`id -u$NAME` 命令执行的结果: if [ `id -u $NAME` -eq0 ]; then *
id $NAME 命令状态的结果,即执行是否成功: if id $NAME; then *
实例B四:给定一个用户,获取其密码警告期限;再判断用户密码使用期限是否已小于警告期限;
提示:计算方法,最长使用期限减去已经使用的天数即为剩余使用期限;
如果小于,则显示“Warning”;否则,就显示“OK”。
圆整:丢弃小数点后的所有内容
#!/bin/bash
#
WARNING=`grep "user1:"/etc/shadow | cut -d: -f6` *密码警告期限
S=`date +%s`
T=`expr $S/86400`
LONG=`grep"^student" /etc/shadow | cut -d: -f5` *最长使用期限
N=`grep"^student" /etc/shadow | cut -d: -f3`
LOSS=$[$L-$[$T-$N]]
if [ $LOSS -lt $W ];then
echo 'Warning'
else
echo 'OK'
fi
实例B五:判定命令历史中历史命令的总条目是否大于1000;
如果大于,则显示“Some command will gone.”;否则显示“OK”。
#!/bin/bash
#
SUM=`history | tail -l | cut -d' ' -f2`
if [ $SUM -gt 1000 ];then
echo “Some command will gone.”
else
echo “OK”
fi
******************************************************************************************
C.整数测试及特殊变量:
1)测试方法:
[ expression ]
` expression `
test expression
2)bash中常用的条件测试有三种:
(2.1)整数测试:> : -gt >= : -ge <: :>
INT1=11
INT2=22
[ $INT1 -eq $INI2 ]
[[ $INT1 -eq $INT2 ]]
test $INT1 -eq $INT2
(2.2)文件测试:
-e FILE: 测试文件是否存在
-f FILE: 测试文件是否为普通文件
-d FILE: 测试指定路径是否为目录
-r FILE: 测试当前用户对指定文件是否有读取权限;
-w FILE: ..写权限;
-xFILE: ..执行权限;
eg1. 文件是否存在[ -e /etc/inittab ]
eg2. 当前用户对此文件是否有执行权限[ -x /etc/rc.d/rc.sysinit ]
if [ grep “^$USERNAME\>” /etc/passwd ]; then 不可用
if grep “^$USERNAME\>”/etc/passwd ; then 判断命令执行状态 可用
if `grep “^$USERNAME\>” /etc/passwd `; then 不可用
if [`grep “^$USERNAME\>” /etc/passwd | cut –d:-f3 ` -eq 0 ]; -eq比较 可用
if `grep “^$USERNAME\>” /etc/passwd | cut –d:-f3 ` ; 非零值 不建议用
(2.3)字符串测试:
3)定义脚本退出状态码
exit: 退出脚本
exit #: exit 3
如脚本没有明确定义退出状态码,那么,最后执行的一条命令的退出码即为脚本的退出状态码;
4)测试脚本是否有语法错误:
bash -n 脚本
bash -x 脚本:单步执行
5)bash变量的类型:
5.1.本地变量(局部变量) 环境变量
5.2.位置变量:
$1,$2, ...
shift
eg1:#!/bin/bash
echo $1
shift
echo $1 $1消失,$2变为$1
shift
echo $1 $1.$2消失,$3变为$1
#./shift.sh 1 2 3
1
2
3
5.3.特殊变量:
$?
$#:参数的个数
$*: 参数列表
$@:参数列表
eg2:#vi ./filetest.sh
#!/bin/bash
echo $# 参数的个数
if [ -e $1 ];then
echo "OK"
else
echo "No such file."
fi
#./filetest.sh /etc/fstab /etc/inittab
$1: /etc/fstab
$2: /etc/inittab
实例C一:给脚本传递两个参数(整数);显示此两者之和,之乘积;
#!/bin/bash
#
if [ $# -lt 2 ]; then
echo"Usage: cacl.sh ARG1 ARG2"
exit 8
fi
echo "The sum is: $[$1+$2]."
echo "The prod is: $[$1*$2]."
练习:写一个脚本,完成以下任务
1、使用一个变量保存一个用户名;
2、删除此变量中的用户,且一并删除其家目录;
3、显示“用户删除完成”类的信息;