前言
概述
Shell是什么
Shell是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用Shell来启动,挂起,停止,编写一些程序
Linux运维中需要编写Shell程序来进行服务器的管理;编写Shell脚本可以用于程序或者服务器的维护,如定时备份数据库的脚本
编写Shell脚本
新建并保存一个.sh文件(Shell脚本通常都以sh作为后缀名,但不是必须的)
脚本文件必须以#!/bin/bash
开头
脚本文件中每一个语句结尾不需要加分号
'#'用于单行注释;用":<<!“以及”!"包含内容进行多行注释,且这两个符号都要自己单独占一行:
:<<!
注释内容
!
hello world 示例:
#!/bin/bash
echo "hello world"
执行Shell脚本
- 输入脚本的绝对路径或相对路径。首先要赋予脚本文件可执行权限
sh 脚本文件路径
或bash 脚本文件路径
,不用赋予脚本可执行权限可以直接执行。这种方式不推荐
变量
Shell中的变量分为 系统变量 和 用户自定义变量
系统变量如 $HOME,$PWD,$SHELL,$USER,$PATH等等,如echo "PATH=$PATH"
。其中,$RANDOM 变量可以用于获取 0~32767 之间的整数随机数
使用set
命令可以查看当前Shell中所有变量
定义变量:变量=值
撤销变量:unset 变量
A=100
echo "A=$A" #输出 A=100。用'$'来引用变量,或者加上大括号:${变量名}
unset A
echo "A=$A" #输出 A=
声明静态变量:readonly 变量
(静态变量不能unset,脚本中有unset静态变量的操作的话执行脚本时会报错)
变量定义时的规则
1.变量名可以由字母,数字,下划线组成,但不能以数字开头(会报错)
2.等号两侧不能有空格
3.变量名称一般习惯为大写
将命令的返回值赋给变量
1.A=`ls - la`,反引号,运行里面的命令,并把结果返回给变量A
2.A=$(ls - la),等价于反引号;MYDATE=$(date),获取日期然后赋值
环境变量
在配置文件(如/etc/profile文件)中设置环境变量,可在其它地方引用
export 变量名=变量值
,将shell变量输出为环境变量
source 配置文件
,让修改后的配置信息立即生效而不用重启系统
$变量名
,取环境变量的值
位置参数变量
当执行一个shell脚本时,如果希望获取到命令行的参数信息,就可以使用到位置参数变量。比如执行./myshell.sh 10 20
命令时,想在myshell.sh脚本文件中获取10或20这些命令行中的参数
具体使用方法是在shell脚本中使用下面这些符号:
$n
,n为数字,$0表示命令本身,$1-$9代表第一到第九个参数,十以上的参数需要用大括号括起来,如${13}
$*
,表示命令行中的所有参数,把所有的参数看成一个整体
$@
,也表示命令行中的所有参数,不过它把每个参数区分对待
$#
,表示命令行中所有参数的个数
预定义变量
预定义变量就是shell设计者事先已经定义好的变量,可以直接在shell脚本中使用
$$
,当前进程的进程号(PID)
$!
,后台运行的最后一个进程的进程号(PID)
$?
,最后一次执行的命令的返回状态。如果它的值为0,说明上一个命令正确执行;如果为非0(具体是哪个数有命令自身决定),则说明上一个命令执行不正确
运算符
语法形式:
$((运算式))
或$[运算式]
(推荐)
`expr m + n`,expr中运算符之间要有空格;用反引号括起来,且反引号与前面的等号间不能有空格
`expr m - n`
`expr \*` 乘法,`expr /` 除法,`expr %` 取余
乘法运算’*'前的反斜杠用于转义,expr中如果有左右括号的话也需要转义
条件判断
[ condition ]
,注意condition前后要有空格
非空返回true,可使用$?验证,0为true,>1为false;[]返回false
条件判断符号
以下符号左右都要有空格
两个整数的比较
-lt
小于;-le
小于等于;-eq
等于;-gt
大于;-ge
大于等于;-ne
不等于
=
字符串的比较。比较结果可以用 ! 取反
按照文件权限进行判断
-r
有读的权限;-w
有写的权限;-x
有执行的权限
将要判断的文件放在符号右边
按照文件类型进行判断
-f
文件存在且是一个常规的文件
-e
文件存在
-d
文件存在且是一个目录
将要判断的文件放在符号右边
流程控制
if语句
if [ 条件判断式 ];then
其它语句
fi
或者
if [ 条件判断式 ]
then
其它语句
elif [ 条件判断式 ]
then
其它语句
fi
条件判断中中括号跟条件判断式之间必须有空格;推荐第二种方式
case语句
case $变量名 in
"值1")
#如果变量值为值1,执行这里的语句
;;
"值2")
#如果变量值为值2,执行这里的语句
;;
......
*)
#如果变量的值不是上面列举的值,执行这里的语句
;;
esac
for语句
for 变量 in 值1 值2 值3...
do
其它语句
done
或者
for((初始值;循环控制条件;变量变化))
do
其它语句
done
示例1: 打印命令行中的参数
脚本文件test.sh:
#!/bin/bash
for i in "$*"
do
echo "num is $i"
done
执行./test.sh 10 20 30
命令后,控制台会打印输出num is 10 20 30。因为$*将命令行参数当作一个整体。用$@代替$*的话,就会输出:
num is 10
num is 20
num is 30
这就是$*和$@的区别
示例2:从1累加到100输出结果
SUM=0
for((i=1;i<=100;i++))
do
SUM=$[$SUM+$i]
done
echo "SUM=$SUM"
while语句
while [ 条件判断式 ]
do
其它语句
done
示例:从命令行输入一个数n,统计从1加到n的值
#!/bin/bash
SUM=0
i=0
while [ $i -le $1 ] #可以根据颜色变化判断是否需要空格,如果这里while后面的空格去掉的话while会变颜色,说明是需要空格的
do
SUM=$[$SUM+$i]
i=$[$i+1]
done
echo "sum= $SUM"
read读取控制台输入
read [选项] [参数]
选项:-p,指定读取值时的提示符;-t,指定读取值时等待的时间(秒),如果没有在指定的时间内输入,就不再等待了
参数:指定读取值的变量名
函数
shell中的函数有系统函数,也可以有自定义函数
系统函数举例
basename
该函数用于返回完整路径最后/的部分,常用于获取文件名
basename [path] [suffix]
basename [string] [suffix]
选项suffix为后缀,如果suffix被指定了,basename会将path或string中的suffix去掉,如 basename /home/test/test.txt .txt 会得到test
dirname
该函数返回完整路径最后/的前面的部分,常用于返回路径部分
dirname 文件绝对路径
如 dirname /home/test/test.txt 会得到/home/test
自定义函数
[ function ] funName[()]
{
Action;
[return int;]
}
调用时直接写函数名funName。这里的中括号function以及return语句是可以不写的意思
示例:计算两个输入参数的和
#!/bin/bash
function getSum(){
SUM=$[$n1+$n2]
echo "和为$SUM"
}
read -p "请输入第一个数" n1
read -p "请输入第二个数" n2
getSum $n1 $n2
可以看到并没有形参