Shell脚本 --Shell脚本有点像早期的批处理文件,将一些命令汇总起来一次执行,但Shell有更强大的功能,可以类似于程序的编写,不需要编译就能执行,使用起来很方便,可以简化我们日常的管理工作。
目录什么是Shell
脚本的运行方法
#!(读shabang)的作用详解
结合案例分析变量类型
特殊变量及其$@ $*的区别
退出状态
算数运算
test和[ expression ]判断
一、什么是Shell
我们知道管理整个计算机硬件的其实是核心(kernel),用户都是以Shell来与核心沟通,只要有操作系统,就离不开Shell。
如图显示了Shell,用户和硬件的关系,形象的说Shell就是用户控制硬件的一种语言工具。
二、脚本的运行方法
①chmod u+x 脚本名
然后直接输入脚本路径执行
(要求shell脚本中第一行加入#!解释器)
(因为这是文件执行,需要有执行权限)
②/bin/bash 脚本名
(如果shell脚本中第一行加入#!解释器,则自动忽略,仍然以bash作为shell)
(这是运用解释器处理文件,所以不需要给文件加执行权限)
总之,上述的两种方法中真正执行永远的都是shell(默认为bash)
当然#!还可以跟/usr/bin/python,/usr/bin/perl
脚本调试
bash -n 脚本路径语法检测
bash -x 脚本路径调试执行,把执行成功的结果显示,不成功的报错
三、#!(读shabang)的作用详解
先看这个Shell脚本#!/bin/bash
echo "Hello World"
当没有#!的时候,默认/bin/bash
举个例子加深#!的作用:vim test.rm
#!/bin/rm -f
echo hello world
保存退出
ls 发现多了一个text.rm的文件/bin/bash test.rm
结果显示 hello worldchmod u+x test.rm
./test.rm
没有显示任何信息
ls 发现test.rm文件没有了
总结:当运行脚本是bin/bash或/usr/bin/python或/usr/bin/perl + 脚本时,则忽略第一行#!后边的内容,使用手动输入的shell,结果执行例子中的echo;当运行脚本是直接脚本路径时,test.sh调用#!后边的命令,删除该文件,不执行echo.
#--->后边的内容为注释
四、结合案例分析变量类型
局部变量
生效为仅为当前shell(即使子shell也不能)
A=123 B=$USER C=$(hostname)
echo $A echo $B echo $C
echo "$A"456
echo ${A}456
set命令查看所有局部变量
unset + 变量名取消指定局部变量和环境变量
案例:
1、编写脚本/root/bin/systeminfo.sh,显示当前主机系统信息,包括主机名,IPv4地址,操作系统版本,内核版本,CPU型号,内存大小,硬 盘大小#!/bin/bash
echo ipv4地址:$(ifconfig eth0 |tr "\n" " " |tr -s " " $ |cut -d$ -f7 |cut -d: -f2)
echo 系统版本:$(cat /etc/redhat-release)
echo 内核版本:$(uname -r)
echo 内存大小:$(cat /proc/meminfo |tr "\n" $ |cut -d$ -f1 |grep -o "[0-9]*") KB
echo 硬盘大小:$(fdisk -l |grep "sda\>" |cut -d: -f2 |cut -d, -f1)
echo CPU型号:$(cat /proc/cpuinfo |grep "name" |sort -u |cut -d: -f2)
2、编写脚本/root/bin/backup.sh,可实现将/etc/目录备份到/root/etcYYYY-mm-dd中(date +%F 以年-月-日显示日期)
#!/bin/bash
cp -r /etc/ /root/etc$(date +%F)
环境变量
当前shell和子shell
如:A=mage
echo $A #显示mage
bash #开启当前shell的子shell
echo $A #没有显示内容
说明A只是一个局部变量
环境变量的声明
export + 变量名
declare -x 变量名
查看所有环境变量
export , declare -x , env ,printenv
只读变量
readonly 变量名声明只读变量
readonly -p查看所有只读变量
本地变量:通常指函数
位置变量:传递参数
$1,$2,...对应的1等,2等参数
set --清空所有位置变量
五、特殊变量及其$@ $*的区别
特殊变量
$?上个命令的退出状态
$0当前脚本的文件名
$*传递给脚本或函数的所有参数(当做一个整体的字符)
$@传递给脚本或函数的所有参数(每个参数作为一个独立的字符)
$#传递给脚本或函数的参数个数
$$当前Shell进程ID
如:
vim test.sh
echo $1
echo $2
echo $3
echo $#
/bin/bash ./test.sh 4 5 6 7
结果显示:4 5 6 4(7多余;共输入了4个参数)
$@ $*的区别
都表示传递给函数或脚本的所有参数,但是当它们被双引号(" ")包含时,"$*" 会将所有的参数作为一个整体;"$@" 会将各个参数分开
写两个脚本实验$*,$@的区别:
vim b.sh
#!/bin/bash
echo '$@是' $1
保存退出
vim a.sh
#!/bin/bash
echo '$*是' $*
/app/b.sh $@
保存退出
chmod +x a.sh b.sh
./a.sh {a..z}
结果显示:$*是 a b c d e f g h i j k l m n o p q r s t u v w x y z
$@是 a
六、退出状态
所谓退出状态,就是上一个命令执行后的返回结果。
0代表成功1-255代表失败(不同类型)
$?保存最近的命令的退出状态,命令执行成功就为0,失败就为1-255
小tip:我们可以把变量$?用在判断语句中
exit [n]自定义退出状态码
脚本一旦运行到exit [n],当前shell就会退出,并把n赋值给$?
六、算数运算
+ - * / %(取余) **(乘方)
实现算数运算方法:
(1)letvar=算术表达式
(2) var=$[算术表达式]
(3) var=$((算术表达式))
(4)declare –ivar= 算数表达式
(5)echo '算术表达式' | bc
随机数生成器:$RANDOM(0-32767)----相当于一个算数表达式
echo $[$RANDOM%50]:0-49之间随机数
七、test和[ expression ]判断
test + expression
=或者==判断两个字符是否相等,并不能判断数字是否相等
!=判断两个字符不相等
>判断两个字符大于
=~判断两个字符是否匹配 (常用于[[ ]]中,支持扩展正则表达式,两个字符最好用""括起来)
-eq判断两个数值是否相等(equal)
-ne判断两个数值不等(not equal)
-gt判断两个数值大于(greater than)
-ge判断两个数值大于等于(greater equal)
-lt判断两个数值小于(less than)
-le判断两个数值小于等于(less equal)
[ expression ]
注意:[ 后边的空格和 ] 前面的空格,必须要有,其实 [ 是一个命令,位于/usr/bin/目录下
-f判断是否是普通文件
-d判断是否是目录
-x判断是否有执行权限
-z判断字符是否为空
-n判断字符是否为不空
test和 [ ] 通用