============================================================================
shell脚本基础
============================================================================
一、Shell特性回顾
内壳
1、命令历史、命令补全
1000条命令历史
命令历史的使用技巧:
!n:执行第n条历史命令
!-n:执行倒数第n条历史命令
!!:上一条命令
!string:最近和string匹配历史命令
!$:上一条命令的最后一个参数
Esc,. 先按esc,然后按.
Alt+. 同时按住alt和.
补全:tab
命令补全
路径补全
2、管道,重定向
| < > << >>
3、命令别名
alias
4、命令行编辑
5、命令行展开
6、文件名通配 globbing
*:匹配任意字符,0个或多个
?:匹配任意单个字符
[]:匹配指定范围内的任意单个字符
[abc],[a-m],[a-z],[0-9],[a-zA-Z]
[[:space:]] 空白字符
[[:punct:]] 标点符号
[[:lower:]] 小写字母
[[:upper:]] 大写字母
[[:alpha:]] 大小写字母
[[:digit:]] 数字 [0-9]
[[:alnum:]] 数字和大小写字母
可以使用 man 7 glob获取帮助
[^]:匹配指定范围外的任意单个字符 [^0-9]
1、创建a123, cd6, c78m, c1 my, m.z, k 67, 8yu, 789等文件;
注意,以上文件是以逗号隔开的,其它符号都是文件名的组成部分
2、显示所有以a或m开头的文件
ls [am]*
3、显示所有文件名中包含了数字的文件;
ls *[0-9]*
ls *[[:digit:]]*
4、显示所有以小写字母开头后面跟两个字符的文件:
ls [a-z]??
ls [[:lower:]]??
5、显示文件名开头中包含了非字母(大小写字母)文件;
ls [^a-zA-Z]*
ls [^[:alpha:]]*
7、变量
8、编程
用户登录shell类型:
bash的配置文件:
全局配置:
/etc/profile,/etc/profile.d/*.sh,/etc/bashrc
个人配置:
~/.bash_profile,~/.bashrc
profile类的文件:
设定环境变量
运行命令或脚本
bashrc类的文件:
设定本地变量
定义命令别名
登录式shell如何读取配置文件?
/etc/profile-->/etc/profile.d/*.sh-->~/.bash_profile-->~/.bashrc-->/etc/bashrc
非登录式shell如何读取配置文件?
~./.bashrc-->/etc/bashrc-->/etc/profile.d/*.sh
登出的时候影响的文件:
~/.bash_history 用户级 退出bash时执行
~/.bash_logout 用户级 退出bash时执行
影响bash shell的其它文件
bash登录和欢迎信息
/etc/issue 登录前显示的信息(本地登录)
/etc/issue.net 登录前显示的信息(网络登录)
/etc/motd 登录后显示的信息
Shell编程特点
shell脚本:命令的堆砌,按实际需要,结合命令流程控制机制实现的源程序
Shell脚本规范
1、 开头指定脚本解释器
#!/bin/sh或#!/bin/bash
其他行#表示注释
名称见名知义 backup_mysql.sh,以sh结尾
2、 开头加版本版权等信息
#Date:创建日期
#Author:作者
#Mail:联系方式
#Function:功能
#Version:版本
3、 脚本中尽量不用中文注释
别吝啬添加注释,必要的注释方便自己别人理解脚本逻辑和功能;
尽量用英文注释,防止本机或切换系统环境后中文乱码的困扰;
单行注释,可以放在代码行的尾部或代码行的上部;
多行注释,用于注解复杂的功能说明,可以放在程序体中,也可以放在代码块的开始部分
代码修改时,对修改的内容
5、 多使用内部命令
内部命令可以在性能方面为你节省很多。
6、 没有必要使用cat命令
eg:cat /etc/passwd | grep guru
使用以下方式即可
eg:grep guru etc/passwd
7、 仔细阅读出错信息
有时候我们修改了某个错误并再次运行后,系统依旧会报错。然后我们再次修改,但系统再次报错。这可能会持续很长时间。但实际上,旧的错误可能已经被纠正,只是由于出现了其它一些新错误才导致系统再次报错
8、 脚本以.sh为扩展名
eg:script-name.sh
Shell脚本运行
方法一:切换到shell脚本所在的目录(此时,称为工作目录)执行shell脚本
方法二:以绝对路径的方式去执行bash shell脚本:
方法三:直接使用bash 或sh 来执行bash shell脚本:
方法四:在当前的shell环境中执行bash shell脚本:source或.
区别:
1、方法三:可以在脚本中不指定解释器,脚本可以没有执行权限
2、方法一和方法二脚本需要有执行权限,./script_name.sh 或/path/script_name.sh
3、方法四:当前shell执行,方法1-3开启子shell
-----------------------------------------------------------------------------------------------
变量
-----------------------------------------------------------------------------------------------
1、变量基础
命名
变量名称:
1、只能包含字母、数字和下划线,并且不能数字开头;
2、不应该跟系统中已有的环境变量重名;
3、最好做到见名知义;
变量名=变量值
变量值=前面不能有空格,变量值本身有空格等要用引号
file_path
FilePath
echo $var_name
shell:弱类型编程语言
强:变量在使用前,必须事先声明,甚至还需初始化;
弱:变量用时声明,甚至不区分类型;
declare -i 定义整形变量
设定
查看 set env
取消与清空变量:
unset VAR_NAME
若不加任何选项,首先尝试取消变量,若失败,再试着取消与该变量同名的函数。
unset -v VAR_NAME #取消变量
unset -f FUNCTION_NAME #取消函数
清空变量方法:
VAR_NAME=
引号:
'':单引号,所见及所得
"":引号内变量替换
``:反撇号。引用命令 $()
2、变量分类
环境变量
HOME:家目录位置
LANG:系统语言变量
PATH:命令搜索路径
PS1:提示符
HOSTNAME:主机名称
SHELL:当前用户shell类型
MAIL:当前用户的邮件存放目录
RANDOM:随机数变量
示例:设置java环境变量
#配置环境变量/etc/profile
export JAVA_HOME=/usr/java/jdk1.6.0_45
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$PATH:$JAVA_HOME/bin
#使配置生效 #source /etc/profile
#检测: # java –version
java version "1.6.0_45"
Java(TM) SE Runtime Environment (build 1.6.0_45-b06)
Java HotSpot(TM) 64-Bit Server VM (build 20.45-b01, mixed mode
#也可以脚本形式(比如java.sh)定义在/etc/profile.d/下面
输出成全局变量使用 export
方法1:先定义,在输出
JAVA_HOME=/usr/java/jdk1.6.0_45
export JAVA_HOME
方法2:export JAVA_HOME=/usr/java/jdk1.6.0_45
生产环境定义oracle用户环境变量
[oracle@oracle11G ~]$ cat .bash_profile
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/bin
export PATH
umask 022
export ORACLE_BASE=/u01/app/oracle
export ORACLE_SID=orcl
export ORACLE_HOME="$ORACLE_BASE/product/11.2.0.1.0/dbhome_1"
export PATH="$ORACLE_HOME/bin:$PATH"
export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK
特殊变量
$# :参数个数
$* :参数列表
$? :返回上一条命令执行结果,0和非0
$$ :
$@ :参数列表
$n :位置参数 $1 $2
$0 :脚本名称
预定义变量:$$、$*、$@、$#、$?
示例:
脱义
# cat var2.sh
#!/bin/sh
echo "script name($0): $0"
echo "all parameters numbers($#): $#"
echo "all parameters($*): $*"
echo "all parameters($@): $@"
echo "PID of the script($$): $$"
echo "success of the previous command($?): $?"
$* 与$@ 区别:仅仅在加双引号时区别
$* 获取当前shell的所有参数,将所有命令行参数视为单个字符串,相当于”$1$2$3”
$@ 将所有参数以”$1” “$2” “$3”形式,每个参数作为个体
# set -- "I am" test command
[root@localhost Scripts]# for i in "$*";do echo $i;done
I am test command
[root@localhost Scripts]# for i in "$@";do echo $i;done
I am
test
command
[root@localhost Scripts]# for i;do echo $i;done
I am
test
command
只读变量
将变量配置成为 readonly 类型,该变量不可被更改内容,也不能 unset
定义方法:
方法一:
readonly [-fap] [变量定义]
-f 定义只读函数
-a 定义只读数组变量
-p 显示系统中全部的变量列表
方法二:
declare –r 变量定义
readonly
read -p
read命令行中也可以不指定变量.如果不指定变量,那么read命令会将接收到的数据放置在环境变量REPLY中。
3.变量运算
算术扩展 $((算术式)) r=$((2+5*8))
外部程序expr expr 算术式 r=`expr 4 + 2`
$[] $[算术式] r=$[1+2]
内置命令declare declare –i 变量=算术式 declare –i r=2+3
内置命令let let算术式 let r=3+4
bc
expr:运算符左右必须要有空格
+ 加法 `expr $a + $b` 结果为 30。
- 减法 `expr $a - $b` 结果为 10。
* 乘法 `expr $a * $b` 结果为 200。
/ 除法 `expr $b / $a` 结果为 2。
% 取余 `expr $b % $a` 结果为 0。
= 赋值 a=$b 将把变量 b 的值赋给 a。
== 相等则返回 true [ $a == $b ] 返回 false。
!= 不相等则返回 true [ $a != $b ] 返回 true。
示例:编写一个 Shell 程序,从键盘读入两个整数,然后做加减乘除,并输出结果。
4.变量扩展
取字符串
规则1:${变量名:位置起点}
含义:由指定的位置起点开始,截取子字符串到字符串结束,起点由0开始
规则2:${变量名:位置起点:长度}
含义:由指定的位置起点开始,截取指定长度的字符串,起点由0开始
计算子串长度
规则:${#变量名称}
含义:表示返回变量名称的字符串长度
对比样式:
${变量#关键词} 最短匹配,从左到右
${变量##关键词} 最长匹配,从左到右
${变量%关键词}
${变量%%关键词}
变量替换:
${var:-word}:表示如果 var 已经被赋值,则取它的值,否则取word 的值,但var不改变。
${var:=word}:表示如果 var 已经被赋值,则取它的值,否则取word 的值,同时将 word 赋给 var 。
${var:+word}:表示如果 var 已经被赋值,则取它的值,否则var 变量置为空。
${变量/旧字符串/新字符串}
${变量//旧字符串/新字符串}
截取:
由字符串前面开始对比删除最短的相符者
语法:${待测变量#样式}
说明:从待测变量的值的左边开始对比,删除最短符合样式的字符串
${待测变量##样式}
${待测变量%样式}
${待测变量%%样式}
-----------------------------------------------------------------------
条件测试
-----------------------------------------------------------------------
条件判定的依据:判定一条命令是否执行成功 $?
判断方法:命令执行的返回码, 0:TRUE( 成功 ) ,非 0:FALSE( 失败 )
条件测试的语法:
格式1:[ expression ]
格式2:test expression
格式3:[[ expression ]]
格式1与格式2等效
1、整数测试
-eq 等于
-ne 不等
-gt 大于
-lt 小于
-ge 大于等于
-le 小于等于
2、文件测试
-e FILE:存在
-f FILE:文件
-d PATH:目录
-r FILE:只读权限
-w FILE:写权限
-x FILE:执行权限
3、字符串比较
==
!=
-n string:
-z string:
示例:
从键盘输入两个字符串,判断这两个字符串是否相等,如相等输出。
比较字符串长度是否大于零
4、逻辑操作符
[ ]中使用 [[ ]]中使用 说明
-a && 与,两端都为真,则真
-o || 或,两端有一个为真则为真
! ! 非,相反则为真
示例:分别给两个字符变量赋值,一个变量赋予一定的值,另一个变量为空,求两者的与、或操作
5、命令执行顺序
; --命令的顺序执行# date ; ls -l /etc/passwd
&& --前面命令执行不成功,后面的命令不执行# mkdir /mnt/iso && mount /dev/sr0 /mnt/iso
|| --如果前面命令成功,后面就不执行,如果前面不成功后面就执行
命令1 && 命令2
1、命令1执行结果为假,命令2不会执行
2、命令1执行结果为真,接着执行命令2
命令1 || 命令2
1、命令1执行结果为真,命令2不会执行
2、命令1执行结果为假,接着执行命令2
示例:
如果用户user6不存在,就添加用户user6;
如果用户存在,就显示用户已存在;否则,就添加此用户;
如果用户不存在,就添加;否则,显示其已存在;
如果目录/abc存在给出提示信息目录已存在,否则创建目录