shell脚本
变量:
1、什么是变量?
变量即可以变化的量
[root@localhost ~]# a=10
[root@localhost ~]# echo $a //$表示引用
10
2、变量名称注意事项
- 只能包含字母、数字、下划线,并且不能以数字开头
- 不应该跟系统中已有的环境变量重名,尽量不要全部使用大写,尽量不要用“_”下划线开头
- 最好做到见名知义
- 不能使用程序中的保留字,例如if、for等(在脚本中,只有if判断,for循环这种用法)
问题:
如果发现路径不对
[root@localhost ~]# echo $PATH //查看路径
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@localhost ~]# PATH=123 //更改路径
[root@localhost ~]# bash //发现命令不能正常使用
-bash: bash: command not found
[root@localhost ~]# ls
-bash: ls: command not found
//解决
[root@localhost ~]# export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@localhost ~]# ls
anaconda-ks.cfg tt.s
变量类型
- 字符型 (字母)
- 数值型
- 整型 (整数)
- 浮点型 (包含小数,复数)
- 布尔型 ()
变量操作
-
设置变量
eg:PATH=123
-
引用变量
eg:echo $PATH
-
撤销变量
[root@localhost ~]# echo $c 5 [root@localhost ~]# unset c //unset表示撤销 [root@localhost ~]# echo $c //没有东西
单引号与双引号的区别
[root@localhost ~]# echo "$a"
10
[root@localhost ~]# echo '$a'
$a
[root@localhost ~]# echo "'$a'"
'10'
[root@localhost ~]# echo '"$a"'
"$a"
//双引号取值,单引号不取值
bash变量类型
- 环境变量
export VAR_NAME=VALUE //作用域为当前shell进程及其子进程
[root@localhost ~]# export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
- 本地变量(局部变量)
VAR_NAME=VALUE //本地变量,作用域为当前shell进程。对当前shell外的其它shell进程,包括当前shell的父shell、子shell进程均无效
local VAR_NAME=VALUE //局部变量,作用域为当前代码段,常用于函数
- 位置变量
$1,$2,$3,.... //用来引用脚本的参数
shift [num] //位置变量使用完以后退出,后面的参数向前推进
eg:
[root@localhost ~]# vim test.sh
[root@localhost ~]# chmod +x test.sh
[root@localhost ~]# ./test.sh 1 2 3 4 5 6 7 8 9
1 7 6 3 8
[root@localhost ~]# cat test.sh
#!/bin/bash
echo $1 $7 $6 $3 $8
- 特殊变量(bash内置的,用来保存某些特殊数据的变量,也称系统变量)
$# //是传给脚本的参数个数
[root@localhost ~]# vim test.sh
[root@localhost ~]# cat test.sh
#!/bin/bash
echo $#
[root@localhost ~]# ./test.sh
0
[root@localhost ~]# ./test.sh 1 2 3 4 5 6 7 8 9
9
[root@localhost ~]# ./test.sh 1 2 3 10
4
$0 //是脚本本身的名字
[root@localhost ~]# vim test.sh
[root@localhost ~]# cat test.sh
#!/bin/bash
echo $0
[root@localhost ~]# ./test.sh
./test.sh
[root@localhost ~]# bash test.sh
test.sh
$! //是shell最后运行的后台Process的PID
$@ //是传给脚本的所有参数的列表
[root@localhost ~]# vim test.sh
[root@localhost ~]# cat test.sh
#!/bin/bash
echo $@
[root@localhost ~]# ./test.sh xixi haha cici sisisi
xixi haha cici sisisi //输出的每个单词都是单独的一行
$* //是以一个单字符串显示所有向脚本传递的参数,与位置变量不同,参数可超过9个
[root@localhost ~]# vim test.sh
[root@localhost ~]# cat test.sh
#!/bin/bash
echo $*
[root@localhost ~]# ./test.sh xixi haha cici sisisi mimi snjwebd wehdb wjcfhbcre wejhfb hr hrfb
xixi haha cici sisisi mimi snjwebd wehdb wjcfhbcre wejhfb hr hrfb
//输出结果写在一行
$$ //是脚本运行的当前进程ID号
$? //是显示上条命令的退出状态,0表示没有错误,其他表示有错误(不能用来检测脚本)
[root@localhost ~]# ls bdhgwevc
ls: cannot access 'bdhgwevc': No such file or directory
[root@localhost ~]# echo $?
2 //表示此条命令输出有错误
bash内建环境变量
PATH
SHELL
UID //当前用户的id
HISTSIZE //命令历史长度
HOME //家目录
PWD //当前位置
HISTFILE //命令历史文件在哪
PS1 //如下
eg:
[root@localhost ~]# echo $PS1
[\u@\h \W]\$ // \u表示root \h表示localhost \w表示~ \$表示#
[root@localhost ~]# PS1='[\W]'
[~]
[~]
[~]
[~]ls
anaconda-ks.cfg test.sh tt.sh
[~]export PS1='[\u@\h \W]\$'
[root@localhost ~]#
只读变量(常量)
readonly VAR_NAME=VALUE //不能修改值,不能销毁,只能等shell进程终止时随之消亡(将shell环境关闭)
eg:
[root@localhost ~]#readonly b=3
[root@localhost ~]#echo $b
3
[root@localhost ~]#b=30
-bash: b: readonly variable
[root@localhost ~]#echo $b
3
[root@localhost ~]#unset b
-bash: unset: b: cannot unset: readonly variable
shell:
shell:处于操作系统的最外层,与用户直接对话,把用户的输入解释给操作系统,然后操作系统输出结果给用户
实现shell的软件: bash 以及其他的编程语言
shell作用:
1、解释执行用户的命令或者程序等
2、用户输入一条命令,shell就解释一条
shell脚本:
按实际需要,结合命令流程控制机制实现的源程序。说白点就是命令的堆砌。
1、执行shell脚本的方式称之为:非交互式
2、windows: .bat批处理脚本
linux: .sh 脚本文件
3、shell脚本规则
1》#:表示注释
2》shebang指文本文件中第一行的前两个字符:#!
在unix系统中: 程序会分析shebang后面的内容
如:以#!/bin/sh开头的文件,程序执行会调用/bin/sh(bash解释器)
以#!/usr/bin/python开头的文件,指定python解释器执行
以#!/usr/bin/env解释器名称,是一种在不同平台上都能正确找到解释器的办法
程序返回值
程序执行以后有两类返回值:
- 程序执行的结果
- 程序状态返回代码(0-255)
- 0:正确执行
- 1-255:错误执行,1、2、127系统预留,有特殊意义
脚本测试
bash -n scriptname //检查脚本是否有语法错误
bash -x scriptname //单步执行,检查脚本错在哪里
写脚本注意事项
- 禁止将未成功执行过的代码直接写进脚本
- 脚本中的命令一定要用绝对路径
shell算术运算
let C=$A+$B //let 算术运算表达式
eg:
[root@localhost ~]#vim test.sh
[root@localhost ~]#cat test.sh
#!/bin/bash
a=10
b=2
let c=$a+$b
echo $c
[root@localhost ~]#./test.sh
12
C=$[$A+$B] //$[算术运算表达式]
eg:
[root@localhost ~]#vim test.sh
[root@localhost ~]#cat test.sh
#!/bin/bash
a=10
b=2
c=$[$a+$b]
echo $c
[root@localhost ~]#./test.sh
12
C=$(($A+$B)) //$((算术运算表达式))
eg:
[root@localhost ~]#vim test.sh
[root@localhost ~]#cat test.sh
#!/bin/bash
a=10
b=2
c=$(($a+$b))
echo $c
[root@localhost ~]#./test.sh
12
C=`expr $A + $B` //expr 算术运算表达式,表达式中各操作数及运算符之间要有空隔,而且要使用命令引用
[root@localhost ~]#vim test.sh
[root@localhost ~]#cat test.sh
#!/bin/bash
a=10
b=2
c=`expr $a + $b`
echo $c
[root@localhost ~]#./test.sh
12
+ 加 -减 *乘 /除(不支持小数) **幂 %取余数
命令间的逻辑关系
逻辑与:&&
第一个条件为假时,第二个条件不用再判断,最终结果已经有
第一个条件为真时,第二个条件必须得判断
逻辑或:||
前一个命令的结果为真时,第二个命令就不执行
前一个命令的结果为假时,第二个命令必须执行
bash条件判断
1.1 条件测试类型
- 整数测试
- 字符测试
- 文件测试
1.2 条件测试的表达式
[ expression ]
[[ expression ]]
test expression
1.3 整数测试(双目)
-eq //测试两个整数是否相等
-ne //测试两个整数是否不等
-gt //测试一个数是否大于另一个数
-lt //测试一个数是否小于另一个数
-ge //大于或等于
-le //小于或等于
1.4 字符测试
== //等值比较,检查==两边的内容是否一致,==两边都要有空格
!= //检查两边内容是否不一致,不一致为真,一致为假
=~ //左侧字符串是否能够被右侧的PATTERN所匹配到。此表达式应用于双中括号[[]]中
-z "string" //测试指定字符串是否为空,空则为真,不空则为假
-n "string" //测试指定字符串是否不空,不空则为真,空则为假
1.5 文件测试
//存在性测试:
-e //测试文件是否存在
//存在性及类别测试:
-b //测试文件是否为块设备文件
-c //测试文件是否为字符设备文件
-f //测试文件是否为普通文件
-d //测试指定路径是否为目录
-h //测试文件是否为符号链接文件
-L //测试文件是否为符号链接文件
-p //测试文件是否为命名管道文件
-S //测试文件是否为套接字文件
//文件权限测试:
-r //测试当前用户对指定文件是否有读权限
-w //测试当前用户对指定文件是否有写权限
-x //测试当前用户对指定文件是否有执行权限
//文件特殊权限测试:
-g //测试文件是否有sgid权限
-u //测试文件是否有suid权限
-k //测试文件是否有sticky权限
//文件大小测试:
-s //测试文件是否非空
//文件是否打开测试:
-t fd //fd表示的文件描述符是否已经打开且与某终端相关
//双目测试:
file1 -ef file2 //测试file1与file2是否指向同一个设备上的相同inode,说白点就是两者是不是同一个文件
file1 -nt file2 //测试file1是否比file2新
file1 -ot file2 //测试file1是否比file2旧
//无分类:
-N //测试文件自从上一次被读取之后是否被修改过
-O //测试文件是否存在并且被当前用户拥有
-G //测试文件是否存在并且默认组是否为当前用户组
1.6 组合测试条件
-a //与关系
-o //或关系
! //非关系
[ $# -gt 1 -a $# -le 3 ]
[ $# -gt 1 ] && [ $# -le 3 ]
1.7 条件判断,控制结构
1.7.1 单分支if语句
if 判断条件; then
statement1
statement2
......
fi
1.7.2 双分支if语句
if 判断条件; then
statement1
statement2
......
else
statement3
statement4
......
fi
1.7.3 多分支if语句
if 判断条件1; then
statement1
statement2
......
elif 判断条件2; then
statement3
statement4
......
else
statement5
statement6
......
fi
2. 分支选择
case $变量名 in
value1)
statement
...
;;
value2)
statement
...
;;
*)
statement
...
;;
esac
eg:
#!/bin/bash
case $1(变量) in
start)
echo "starting..."
apachectl start
;;
stop)
echo "stopping..."
apachectl stop
;;
restart)
echo "restarting..."
apachectl stop ,apachectl start
;;
status)
ps -ef | grep httpd | grep -v "grep\|$0" &> /dev/null //表示过滤的结果不需要将他扔到null里面 grep -v取反
if [ $?(表示上一条命令) -eq 0 ];then
echo "httpd is started."
else
echo "httpd is stopped."
fi
;;
*) //表示如果输入的不是上述的东西 表示输入的有问题 则提示
echo "Usage: service httpd start | stop | restart | status"
;;
esac
//case支持glob风格的通配符:
* //任意长度任意字符
? //任意单个字符
[] //指字范围内的任意单个字符
abc|bcd //abc或bcd
3. 循环语句
循环语句通常需要有一个进入条件和一个退出条件。
3.1 for循环
for循环当列表不为空时进入循环,否则退出循环
for 变量 in 列表; do
循环体
done
for ((expr1;expr2;expr3(要做的事)))
{
循环体
}
for (( expr1 ; expr2 ; expr3 ));do
循环体
done
expr1 //用于指定初始条件,给控制变量一个初始值
expr2 //判定什么时候退出循环
expr3 //修正expr1指定的变量的值
//如何生成列表:
{1..100}
seq [起始数] [步进长度] 结束数
eg:
[root@localhost ~]# cat ten.sh
#!/bin/bash
for ((i=1;i<=10;i++))
{
echo $i
}
[root@localhost ~]# seq 1 3 10
1
4
7
10
3.2 while循环
while循环适用于循环次数未知的场景,注意要有退出条件。
条件满足时进入循环,条件不满足了退出循环。
3.2.1 while循环正常用法
while 条件; do
statement
...
done
3.2.2 while循环特殊用法
//while循环特殊用法一:死循环
while :;do
statement
...
done
//这里的冒号可以改成任何非空值
while循环特殊用法二:逐行读取某文件,将值存入line变量中
while read line;do
statement
...
done < /path/to/somefile
3.3 until循环
条件不满足时进入循环,条件满足了退出循环。
until 条件; do
statement
...
done
3.4 循环语句特殊情况
在循环语句中,有几种特别情况:
break [num]:提前退出循环。当循环语句中出现break时,将提前退出循环,不再执行循环后面的语句
continue [num]:提前结束本轮循环而进入下一轮循环。当循环语句执行到continue时,continue后面的语句将不再执行,提前进入下一轮循环
4. 定义脚本退出状态码
//exit命令用于定义执行状态结果
exit # //此处的#号是一个数字,其范围可以是0-255
如果脚本没有明确定义退出状态码,那么,最后执行的一条命令的退出码即为脚本的退出状态码
注意:脚本中一旦遇到exit命令,脚本会立即终止