bash脚本编程
编程语言:
编译器,解释器
编程语言:机器语言,汇编语言、高级语言
静态语言:编译型语言
强类型(变量)
关键字:
事先转换成可执行格式
c,c++,JAVA,C#
动态语言:解释型语言 on the fly
弱类型
边解释变执行
php,shell,python,perl(面向过程)
面向对象:shell,c
面向对象:JAVA,Python,perl,C++
bash:脚本解释器
编程能力:
脚本编程
变量:内存空间,命名的内存空间(可以回收)
内存:编址的存储单元
进程:临时存储数据要用到变量
映射表:变量名和物理地址的映射
变量类型:
事先确定数据的存储格式和长度
字符
数值
整型
浮点型:11.23(1.12310^1)(0.112310^2)
2013/10/10
布尔型:真假型 逻辑
逻辑运算:与、或,非、异或(相同为假,不同为真)
&, !
短路逻辑运算
与:其中一个为假,结果为假
或:其中一个为真,结果为真。
shell:弱类型编程语言
强:变量在使用前,必须事先声明,甚至还需要初始化:
弱类型编程语言:变量用时声明,甚至不区分类型:(默认为字符)
显式转换,隐式转换
1+c=(ASCII)
10:16bit
10:1010,8bit
整型:8bit,256
0-255;溢出
缓冲区溢出:攻击(填入数据前,先判断)
变量赋值:var_name=value
bash变量类型:
环境变量
本地变量(局部变量)
位置变量
特殊变量
本地变量:(作用域当前bash)
变量声明: varname=value
局部变量(作用域为当前代码)
local varname=value
bash:进程的变量
echo $VAR_name
引用变量:${VARNMAE} $varname(防止混淆要用{})
''强引用
“” 弱引用
环境变量(作用域为当前shell进程及其子进程)
export varname=value
“导出”
varname=value
export varname
脚本在执行时会启动一个子shell进程,
命令行中启动的脚本就会继承当前shell环境变量
系统自动执行的脚本(非命令行启动)就需要自我定义需要各环境变量。
位置变量:
$1,$2,$3,......
特殊变量:
$?:上一个命令的执行状态返回值(回传码)
程序执行结果
程序状态返回代码(0-255)
0:表示正确
1-255:表示错误 1,2,127系统预留
id 用户
echo $?
输出重定向:
<
2>
2>>
&>
/dev/null:设备,软件设备(软件模拟) ,bit bucket,数据黑洞
id student &> /dev/null
echo $?
撤销变量:
set (省略)
unset varname
查看当前shell的变量:(本地变量,环境变量)
set (所有变量)
查看当前shell中的环境变量
printenv
env
export
变量添加
animal=$animal:goat
animal=$animal:shell
export PATH=$PATH:/usr/local/apache/bin
export PATH=/usr/local/apache/bin/:$PATH
默认为字符串
脚本:命令的堆砌,按实际需求,结合命令流程控制机制实现的源程序。
ELF:可执行的链接的二进制文件。
shebang:魔数
#!/bin/bash(可执行程序的路径)
#:注释行,不执行
chmod +x *.sh
./*.sh(独立执行)
bash *.sh (可以没有执行权限)
练习:写一个脚本:
1.添加5个用户,user1,user5
2.每个用户的密码同用户名,而且,添加密码完成后不显示passwd命令的执行结果
3.每个用户添加完成后,都要显示用户某某已完成。
练习:写一个脚本:
1.使用一个变量保存一个用户名
2.删除此变量中的用户,且一并删除其家目录
3.显示“用户删除完成”类的信息。
条件判断:
如果用户不存在
添加用户,给密码并显示添加成功。
否则
显示已经存在,不添加。
bash中如何实现条件判断:
条件测试类型:
整数测试
字符测试
文件测试
条件测试的表达式:
[ expression ] (注意空格)
[[ expression ]]
test expression
整数比较:
-eq:测试两个整数是否相等:比如 [ $A -eq $B ] echo $?
-ne:测试两个整数是否不等,不等为真,相等为假
-gt:测试一个数是否大于一个数:大于为真,小于为假
-lt:测试一个数是否小于 一个数。
-ge:测试一个数是否大于等于一个数
-le:小于等于
命令间逻辑关系:
逻辑与: &&
第一个条件为假时,第二个条件不用再判断了,最终结果已经有了
第一个条件为真时,第二个条件必须判断。
逻辑或:|| 第一个条件为假时,第二个条件判断
第二个条件为真时,第二个条件不判断
(短路操作)
id user01 && echo "hello,user1"
id user1 || useradd user1
变量名称:
1.只能包含字母、数字、下划线、并且不能数字开头
2.变量名不能和系统变量同名
3.最好做到见名知义。
! id user2 && useradd user2
[ $FINELINE -gt 100 ] && echo "/etc/inittab is a big file " || echo "/etc/inittab is a small file"
id user1 && echo "user is exists" || useradd user
! id user && useradd user && echo "user exits"
! id userr && useradd user && echo "nihao" | passwd --stdin user || echo "user is exits"
如果用户存在,就显示用户已存在;否则,就添加此用户;
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."
条件判断:控制结构:
单分支if语句:
if 判断条件 ; then (如果then 和 if 不在一行 可以省略;)
statement1
statement2
....
fi
双分支的if语句:
if 判断条件 ; then
statement1
statement2
....
else
statememt3
...
fi
userid=`id -u $username`
if [ $userid -eq 0] ;then
echo "it is admin"
else
echo "it is not admin"
fi
if id $name ;then
判断用户是否存在
#!/bin/bash
username=user1
userid=`id -u $useranme`
groupid=`id -g $useranm`
if [ $userid -eq $groupid ] ;then
echo "good guy"
else
echo "bad guy"
fi
shell中进行算术运算:
a=1
b=2
let: 让字符转换成数值进行算术运算
1.let 算术运算表达式
let c=$a+$b
2.$[算术运算表达式]
c=[$a+$b]
3.$((算术运算表达式))
c=(($a+$b)
4.expr 算术运算表达式 (注意表达式中各操作数及运算符之间要有空格)
c=`expr $a + $b`
提前结束脚本
exit:退出脚本。可以自定义回传码(命令执行状态码),没有跟数字,默认最后一次执行的状态码。
exit 数值#
测试方法:
[ expression ]命令
[[ expression ]] 关键字
test expresión
bash常见的测试有三种:
整数测试:
-gt
-le;
-ne
-eq
-lt
-ge:
[ $a -eq 4b ]
[[ $a -eq $b ]]
test $a -eq $b
文件测试:
-e file :测试文件是否存在
-f file 测试文件是否为普通文件
-d file 测试文件是否为目录
-r file 测试当前用户对指定文件是否有读取的权限
-w file
-x file
[ -e /etc/inittab ]
[ -w /etc/rc.d/rc/sysconfig ]
if [ ! -e $FILE ];then
echo ""
exit 0
圆整:丢弃小数点后的数。
多分支的if语句
if 判断条件1; then
statement1
.......
elif 判断条件2;then
statement2
......
elif 判断条件3;then
statement3
...
else
statement4
....
fi
测试脚本是否有语法错误:
bash -n file.sh
bash -x 脚本 单步执行命令
编写一个脚本
给定一个文件,如果是普通文件,就显示
如果是目录,就显示目录,否则此为不能识别。
#!/bin/bash
FILE=/etc/rc.d/rc.sysconfig
if [ ! -e $FILE ];then
echo "NO such file"
fi
if [ -f $FILE ];then
echo "common file"
elif [ -d $FILE ];then
echo "$FILE is directory "
else
echo "UNknown"
fi
定义退出状态码
exit:退出脚本
exit #
如果脚本没有明确定义退出状态码,那么执行最后一条命令的的状态码即为脚本的退出状态码。
bash变量的类型:
本地变量(局部变量):作用域只是当前shell
环境变量:作用域是当前shell,及其子shell
位置变量:$1,$2,$3....
shift:轮替 位置参数的轮替。
#!/bin/bash
echo $1
shift
echo $
shift
echo $1
shift
shift #:一下轮替n个
./filetest.sh /etc/fstab /etc/inittab
$1: /etc/fstab
$2: /etc/inittab
特殊变量:
$?:
$#:参数的个数
$*:参数列表
$@:参数列表
练习:写一个脚本
能接受一个参数(文件路径)
判定:此参数
#!/bin/bash
if [ $# -eq 0 ];then
echo""
exit 0
if [ ! -e $1 ];then
echo "NO such file"
fi
if [ -f $1 ];then
echo "common file"
elif [ -d $1 ];then
echo "$1 is directory "
else
echo "UNknown"
fi
特殊变量:
$?:
$#:参数的个数
$*:参数列表
$@:参数列表
字符串测试:
==或=: [ $a == $b ] (等号两端要有空格)
!=:测试是否不等,不等为真,相等为假。
>
<
=>
<=
-n string :测试指定字符串是否为空,空为真,不空为假。
-s string :测试指定字符串是否为空,空为假,不空为真。
#!/bin/bash
if ! id $1 &> /dev/null;then
echo "no user"
exit 1
fi
if [ `id -n -u $1` == `id -n -g $1` ];then
echo "yiyang"
else
"buyiyang"
fi
if [ $1 == "q" ];then
echo "quiting..."
exit 1
elif [ $1 == 'Q' ];then
echo "quiting.."
exit 2
esle
exit 3
fi
echo "scale=2;111/22;" | bc
bc <<< "scale=2;111/22;"(注意3个小于号)
循环:进入条件,退出条件
for
while
until
for 变量 in 列表;do
循环体
done
for i in 1 2 3 4 5 6 7 8 9 10;do
加法运算
done
遍历完成后,退出。
如何生成列表:
{1..100}
seq 起始数 步进长度 结束数
#!/bin/bash
let sum=0
for i in {1..100};do
let sum=$sum+$i
done
echo "$sum"
decalre -i sum
declare
-i:整型
-x :声明为环境变量
取模,取余 %
测试:
整数测试:
-le
-lt
-ge
-gt
-eq
-ne
字符测试:
==
!=
>
<
-n
-z
文件测试:
-f
-d
-r
-x
-w
-e
if [ $# -gt 1 ];then
组合测试条件:
-a:与关系
-o:或关系
!:非关系
if [ $# -gt 1 -a $# -le 3 ]
if [ $# -gt 1 ] && [ $# -le 3 ]
Q,q,quit
if [ $1 == q -o $1 == Q -o $1 == quit -o $1 == Quit ];then
echo "quiting"
exit 1
fi
let i=$[$i+1]
let sum=$[$sum+$i]
let sum+=$i
let i+=1
let i++
-= i--
*=
/=
%=
++i,--i
面向过程:
控制结构:
顺序结构
选择结构
循环结构
选择结构:
if:单分支、双分支的,多分支
if condaiction;then
statment
.....
fi
if condation;then
statment
....
else
....
fi
if condation;then
statment
..
elif condation;then
statment;
....
fi
case语句:选择结构
case switch in
value)
statment
....
;;
value2)
statment
....
;;
*)
statment
.....
;;
esac
由键盘输入一个字符,给出判断?
case.sh
#!/bin/bash
case $1 in
[0-9])
echo "a digtal";;
[a-z])
echo "lower";;
[A-Z])
echo "upper";;
*)
echo "unknown";;
esac
只接受参数,start,stop,restart,status
#!/bin/bash
case $1 in
'stat')
echo "start server...";;
'restart')
echo "restart server...";;
'stauts')
echo "stuts service...";;
*)
echo "`basename $0` {start |stop |restart |status}";;
esac
#!/bin/bash
case $1 in
-y|--verbose)
debug=1
;;
*)
脚本编程:
顺序结构
选择结构
if:单分支、双分支的,多分支
case
循环结构:
for
while
until
while循环:适用于循环次数未知的情况下,必须要有退出条件。
语法:
while condition ; do
statemant
....
done
计算100以内正整数的和:
#!/bin/bash
declare -i i=1
declare -i sum=0
while [ $i -le 100 ];do
let sum+=$1
let $i+=1
done
read -p "please input string" string
while [ $string != 'quit' ];do
echo $string |tr 'a-z' 'A-Z'
read -p "please input string "string
done
while [ 1 -eq 1 ]
or
while true
or
while ((1))
or
while [[ 1 ]]
or
while :
while循环
while ,until,for
break:提前退出循环
continue:退出本次循环,进行下一次循环。
while的特殊用法一:
while : ;do
done
while的特殊用法二:
while read LINE;do
done </path/to/somefile
函数:功能 function
代码重用:
库:so
函数:就是把其中某个特定的功能的代码封装起来,进行调用。
定义函数:
function FUCname {
command
}
FUncname() {
command
}
function showmenu {
}
函数不能直接执行,必须调用才行。
showmenu
自定义状态返回值
return #
#!/bin/bash
ADD() {
a=9
b=7
let c=$a+$b`
echo $c
}
ADD
sum=`ADD`
echo $sum
let m=1
sm=$[$m+`ADD`] #函数执行结果引用 ``
ADD
echo $? 执行状态结果
bash -x *.sh 逐步执行显示
注意:执行结果,状态结果
函数的执行状态结果是最后一条命令的执行结果的状态返回值。
自定义状态返回值
return #
0--255
if [ $? -eq 0 ];then
echo ""
else
fi
根据返回结果判断程序执行成功与否
接受参数的函数:
./a.sh aa bb cc
位置参数:
$1:
$2:
函数的参数:
ADD 5 6
$1
$2 :函数参数
ADD(){
echo $[$1+$2]
}
ADD 5 6
sum=`ADD 5 6`
echo $sum
echo "$i+$j=`ADD $i $j`"
#!/bin/bash
PING() {
if ping -c 1 -W 1 $1 &> /dev/null; then
return 0
else
return 1
fi
}
for i in {200..254};do
PING 192.168.0.$i
if [ $? -eq 0 ];then
echo "192.168.0.$i is up"
else
echo "192.168.0.$i is down"
fi
done
for i in {220..254};do
PING 172.16.0.$i
done
if ping 192.168.0.$i ;then
返回执行状态结果。
``:引用echo结果