shell脚本编程
编程基础
程序:
程序的构成:指令 + 数据
程序的编程风格:
过程式:以指令为中心,数据服务于指令
对象式:以数据为中心,指令服务于数据
shell程序:提供了编程能力,解释执行
shell,perl,python语言均为高级编程语言
编程的逻辑处理方式:
顺序执行
循环执行
选择执行
shell编程:过程式、解释执行
脚本基本格式
shell脚本是包含一些命令或声明,并符合一定格式的文本文件
格式要求:首行shabanng机制
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl
shell脚本用途:
自动化常用命令
执行系统管理和故障排除
创建简单的应用程序
处理文本或文件
如何创建shell脚本
第一步:使用文本编辑器来创建文本文件
第一行必须为shell声明序列,即shebang
例如:#!/bin/bash
添加注释:
注释以#开头(以#开头的行不会被执行)
第二步:运行脚本
给予执行权限,在命令执行上指定脚本的绝对或相对路径
运行解释器,将脚本作为解释器程序的参数运行
#!/bin/bash
#author: wang
#Version: 1.0
#Description:This script displays some information about your# environment echo "Greetings. The date and time are $(date)" echo "Your working directory is: $(pwd)"
脚本调试:
bash –n /path/to/some_script:检测脚本中的语法错误
bash –x /path/to/some_script:调试执行
变量
变量即是命名的内存空间
bash变量为弱类型变量
即无需指定类型,默认均为字符型;参与运算会自动进行隐式类型转换,变量无需实现定义,可直接调用
变量命名法则:
1、不能使用程序中保留字,如if,for…
2、只能使用数字、字母及下划线,且不能以数字开头
3、见名知义
4、统一命名法则:驼峰命名法
根据变量的生效范围等标准可做以下归类:
本地变量:生效范围为当前shell进程
环境变量:生效范围为当前shell进程及其子进程
局部变量:生效范围为当前shell进程中某代码片段(通常为函数)
位置变量:$1、$2…,用于表示脚本代码中调用命令行的参数
特殊变量:$?à 前一条命令的执行结果,0表示成功,1-255表示失败
$0à 命令本身
$#à 参数的数量
本地变量:
变量赋值:name=‘value’,
可以使用引用value:
(1) 可以是直接字串; name=“root"
(2) 变量引用:name="$USER"
(3) 命令引用:name=`COMMAND`, name=$(COMMAND)
变量引用:${name}, $name
"":弱引用,其中的变量引用会被替换为变量值
'':强引用,其中的变量引用不会被替换为变量值,而保持原字符串
显示已定义的所有变量:set
删除变量:unset name
环境变量:
变量声明、赋值:
export name=VALUE
declare -x name=VALUE
变量引用: $name, ${name}
显示所有环境变量:
export
env
printenv
删除: unset name
bash有许多内建的环境变量: PATH, SHELL, USRE,UID,HISTSIZE, HOME, PWD, OLDPWD, HISTFILE, PS1
只读和位置变量:
只读和位置变量
只读变量:只能声时,但不能修改和删除
readonly name
declare -r name
一般是常量中会使用
declare –rx name 表示既是一个常量又是一个环境变量
但是随shell进程终止而终止
位置变量:在脚本代码中调用通过命令行传递给脚本的参数
$1, $2, …:对应第1、第2等参数,shift [n]换位置
$0: 命令本身
$*: 传递给脚本的所有参数,全部参数合为一个字符串
$@: 传递给脚本的所有参数,每个参数为独立字符串
$#: 传递给脚本的参数的个数
$@ $* 只在被双引号包起来的时候才会有差异
运算
算术运算:
+, -, *, /, %取模(取余), **(乘方)
实现算术运算:
(1) let var=算术表达式
(2) var=$[算术表达式]
(3) var=$((算术表达式))
(4) var=$(expr arg1 arg2 arg3 …)
(5) declare –i var= 数值
(6) echo ‘算术表达式’ | bc
乘法符号有些场景中需要转义,如*
bash有内建的随机数生成器:$RANDOM(1-32767)
echo $[$RANDOM%50] :0-49之间随机数
如果要表示2-51:echo $[$RANDOM%50+2]
表示1-n: echo $[$RANDOM%N+1]
赋值
增强型赋值:
+=, -=, *=, /=, %=
let varOPERvalue
例如:let count+=3
自加3后自赋值
自增,自减:
let var+=1
let var++
let var-=1
let var–
逻辑运算
true, false
1 0
与:
1 与 1 = 1
1 与 0 = 0
0 与 1 = 0
0 与 0 = 0
或:
1 或 1 = 1
1 或 0 = 1
0 或 1 = 1
0 或 0 = 0
非:!
! 1 = 0
! 0 = 1
短路运算:
短路与:
第一个为0,结果必定为0;
第一个为1,第二个必须要参与运算;
短路或:
第一个为1,结果必定为1;
第一个为0,第二个必须要参与运算;
异或:^
异或的两个值,相同为假,不同为真
例如:
#command1 && command2
command1为“假”,则command2 不会再执行
否则,command1为“真”,则command2必须执行
#command1 || command2
command1为“假”,则command2 必须执行
否则,command1为“真”,则command2不会再执行
要实现user1用户不存在就添加用户user1
id user1 || useradd user1
退出状态
进程使用退出状态来报告成功或失败
0 代表成功,1-255代表失败
$? 变量保存最近的命令退出状态
例如:
ping-c1-W1hostdown&>/dev/null
echo$?
退出状态码
bash自定义退出状态码
exit [n]:自定义退出状态码;
注意:脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字
注意:如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码
条件测试
判断某需求是否满足,需要由测试机制来实现;
专用的测试表达式需要由测试命令辅助完成测试过程;
评估布尔声明,以便用在条件性执行中
若真,则返回0
若假,则返回1
测试命令:
test EXPRESSION
[ EXPRESSION ]
[[ EXPRESSION ]]
注意:EXPRESSION前后必须有空白字符
条件性的执行操作符
根据退出状态而定,命令可以有条件地运行
&& 代表条件性的AND THEN
|| 代表条件性的OR ELSE
例如:
grep-qno_such_user/etc/passwd ||echo'Nosuchuser'
Nosuchuser
ping-c1-W2station1&>/dev/null >&& echo"station1isup" || (echo'station1isunreachable';exit1)
station1isup
test命令
长格式的例子:
test "$A"=="$B" && echo "Stringsareequal"
test "$A" -eq "$B" && echo "Integersareequal"
简写格式的例子:
[ "$A" == "$B" ] && echo "Stringsareequal"
[ "$A" -eq "$B" ] && echo "Integersareequal"
数值测试:
-gt:是否大于;
-ge:是否大于等于;
-eq:是否等于;
-ne:是否不等于;
-lt:是否小于;
-le:是否小于等于;
字符串测试:
==:是否等于;
>:ascii码是否大于ascii码
<:是否小于
!=:是否不等于
=~:左侧字符串是否能够被右侧的PATTERN所匹配
注意:此表达式一般用于[[ ]]中;
-z "STRING":字符串是否为空,空为真,不空为假
-n "STRING":字符串是否不空,不空为真,空为假
注意:用于字符串比较时的用到的操作数都应该使用引号
文件测试
存在性测试
-a FILE:同-es
-e FILE: 文件存在性测试,存在为真,否则为假;
存在性及类别测试
-b FILE:是否存在且为块设备文件;
-c FILE:是否存在且为字符设备文件;
-d FILE:是否存在且为目录文件;
-f FILE:是否存在且为普通文件;(存在为真)
-h FILE 或-L FILE:存在且为符号链接文件;
-p FILE:是否存在且为命名管道文件;
-S FILE:是否存在且为套接字文件;
文件权限测试:
-r FILE:是否存在且可读
-w FILE: 是否存在且可写
-x FILE: 是否存在且可执行
文件特殊权限测试:
-g FILE:是否存在且拥有sgid权限;
-u FILE:是否存在且拥有suid权限;
-k FILE:是否存在且拥有sticky权限;
文件大小测试:
-s FILE:是否存在且非空;
非空为真,空为假
文件是否打开:
-t fd:fd表示文件描述符是否已经打开且与某终端相关
-N FILE:文件自上一次被读取之后是否被修改过(读先发生,写后发生)
就是读的时间比较旧
双目测试:
FILE1 –ef FILE2: FILE1与FILE2是否指向同一个设备上的相同inode(硬链接)
FILE1 –nt FILE2: FILE1是否新于FILE2;(修改的时间)
FILE1 –ot FILE2: FILE1是否旧于FILE2;(修改的时间)
组合测试条件
第一种方式:
COMMAND1 && COMMAND2 并且
COMMAND1 || COMMAND2 或者
! COMMAND 非
如:[ -e FILE ] && [ -r FILE ]
第二种方式:
EXPRESSION1 -a EXPRESSION2 并且
EXPRESSION1 -o EXPRESSION2 或者
! EXPRESSION
必须使用测试命令进行,即进行test或者[ ];
意思是只要主机名没有定义或者主机名为默认就改为www.magedu.com
# [ -z “$HOSTNAME” -o $HOSTNAME "== "localhost.localdomain" ] && hostname www.magedu.com
判断/bin/cat是否为可执行文件,如果是就调用
# [ -f /bin/cat -a -x /bin/cat ] && cat /etc/fstab
使用read命令来接受输入
使用read来把输入值分配给一个或多个shell变量:
-p:指定要显示的提示
-t:TIMEOUT
read从标准输入中读取值,给每个单词分配一个变量
所有剩余单词都被分配给最后一个变量
read -p “Enter a filename:“ FILE
条件选择if语句
选择执行
注意:if语句可嵌套
单分支
if 判断条件:then
条件为真的分支代码
fi
双分支
if 判断条件; then
条件为真的分支代码
else
条件为假的分支代码
fi
多分支
if CONDITION1; then
if-true
elifCONDITION2; then
if-ture
elifCONDITION3; then
if-ture
…
else
all-false
fi
逐条件进行判断,第一次遇为“真”条件时,执行其分支,而后结束整个if语句
条件判断:case语句
case 变量引用in
PAT1)
分支1
;;
PAT2)
分支2
;;
…
*)
默认分支
;;
esac
case支持glob风格的通配符:
*:任意长度任意字符
?:任意单个字符
[]:指定范围内的任意单个字符
a|b:a或b
练习:
1、写一个脚本/root/bin/createuser.sh,实现如下功能:使用一个用户名做为参数,如果指定参数的用户存在,就显示其存在,否则添加之;显示添加的用户的id号等信息
代码:
[root@localhost bin]# cat creatuser.sh
#!/bin/bash
echo "Please input a username:"
read username
id $username &> /dev/null
if [[ $? -eq 0 ]];then
echo "用户已存在"
else
useradd $username;echo "用户$username添加成功"
id $username
fi
测试:
[root@localhost bin]# creatuser.sh
Please input a username:
wang
用户已存在
[root@localhost bin]# creatuser.sh
Please input a username:
li
用户li添加成功
uid=1007(li) gid=1007(li) groups=1007(li)
2、写一个脚本/root/bin/yesorno.sh,提示用户输入yes或no,并判断用户输入的是yes还是no,或是其它信息
代码:
[root@localhost bin]# cat yesorno.sh
#!/bin/bash
read -p "Please input yes or no:" x
case $x in
[Yy][Ee][Ss]|[Yy])
echo you have inputde yes
;;
[Nn][Oo]|[Nn])
echo you have inputed no
;;
*)
echo illegal input
;;
esac
测试:
[root@localhost bin]# yesorno.sh
Please input yes or no:yes
you have inputde yes
[root@localhost bin]# yesorno.sh
Please input yes or no:Yes
you have inputde yes
[root@localhost bin]# yesorno.sh
Please input yes or no:no
you have inputed no
[root@localhost bin]# yesorno.sh
Please input yes or no:No
you have inputed no
[root@localhost bin]# yesorno.sh
Please input yes or no:aa
illegal input
3、写一个脚本/root/bin/filetype.sh,判断用户输入文件路径,显示其文件类型(普通,目录,链接,其它文件类型)
代码:
[root@localhost bin]# cat filetype.sh
#!/bin/bash
echo "请输入一个文件路径"
read file
if [[ -L $file ]];then
echo $file 是一个符号链接文件
elif [[ -f $file ]];then
echo $file 是一个普通文件
elif [[ -b $file ]];then
echo $file 是一个块设备文件
elif [[ -c $file ]];then
echo $file 是一个字符设备文件
elif [[ -d $file ]];then
echo $file 是一个目录文件
elif [[ -p $file ]];then
echo $file 是一个管道文件
elif [[ -S $file ]];then
echo $file 是一个套接字文件
else
echo No such file
fi
测试:
[root@localhost bin]# filetype.sh
请输入一个文件路径
/etc/rc1.d
/etc/rc1.d 是一个符号链接文件
[root@localhost bin]# filetype.sh
请输入一个文件路径
/etc/issue
/etc/issue 是一个普通文件
[root@localhost bin]# filetype.sh
请输入一个文件路径
/testdir
/testdir 是一个目录文件
[root@localhost bin]# filetype.sh
请输入一个文件路径
/run/systemd/notify
/run/systemd/notify 是一个套接字文件
[root@localhost bin]# filetype.sh
请输入一个文件路径
/dev/sda
/dev/sda 是一个块设备文件
[root@localhost bin]# filetype.sh
请输入一个文件路径
/dev/null
/dev/null 是一个字符设备文件
[root@localhost bin]# filetype.sh
请输入一个文件路径
/dev/zero
/dev/zero 是一个字符设备文件
4、写一个脚本/root/bin/checkint.sh,判断用户输入的参数是否为正整数
[root@localhost bin]# cat checkini.sh
代码:
#!/bin/bash
echo "Please input a number"
read num
if [[ -z $num ]];then
echo "至少要输入一个数值"
exit
fi
NUM=$(echo $num |egrep -o '^\-?[[:digit:]]+$')
if [[ $num == $NUM ]];then
if [[ $num -gt 0 ]];then
echo $num 是一个正整数
elif [[ $num -eq 0 ]];then
echo 输入的是0
else
echo $num 是一个负整数
fi
else
echo $num 不是一个整数
fi
测试:
[root@localhost bin]# checkini.sh
Please input a number
0
输入的是0
[root@localhost bin]# checkini.sh
Please input a number
1
1 是一个正整数
[root@localhost bin]# checkini.sh
Please input a number
-8
-8 是一个负整数
[root@localhost bin]# checkini.sh
Please input a number
sss
sss 不是一个整数
原创文章,作者:Mr.Lee,如若转载,请注明出处:http://www.178linux.com/36625
评论列表(1条)
博客作业要按时完成,压得太多,你就越不想写了。