一、Shell 脚本概述
1.Shell 的作用
Linux 系统中的 Shell 是一个特殊的应用程序,它介于操作系统内核与用户之间,充当 了一个“命令解释器”的角色,负责接收用户输入的操作指令(命令)并进行解释,将需要执行的操作传递给内核执行,并输出执行结果。
通过/etc/shells 文件可以了解当前系统所支持的 Shell 脚本种类。
[root@localhost ~]# cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
……
//省略部分内容
2.编写第一个 Shell 脚本
Bash(/bin/bash)是目前大多数 Linux 版本采用的默认 Shell。
[root@localhost ~]# vim first.sh //新建 first.sh 文件
cd /boot/
pwd
ls -lh vml*
[root@localhost ~]# chmod +x first.sh //添加可执行权限
[root@localhost ~]# ./first.sh
[root@localhost ~]# sh first.sh
[root@localhost ~]#bash first.sh
[root@localhost ~]# . first.sh
[root@localhost ~]#source first.sh
备注:“./”、sh、bash是相同的执行方式,“.”和source是相同的
- source和“.”执行脚本时,将脚本中语句在本shell中执行,
- sh、bash和./(需要该文件拥有执行权 +x)是在执行脚本时先启动一个新的shell,然后让脚本中的语句在新的shell中执行,执行完后就退出。
对于代码较多,结构复杂的脚本,应添加必要的注释文字。
[root@localhost ~]# vim first.sh
#!/bin/bash
# This is my first Shell-Script.
cd /boot
echo "当前的目录位于:"
pwd
echo "其中以 vml 开头的文件包括:"
ls -lh vml*
备注:第一行“#!/bin/bash”是一行特殊的脚本声明,表示此行以后的 语句通过/bin/bash 程序来解释执行;其他以“#”开头的语句表示注释信息;echo 命令用于输 出字符串,以使脚本的输出信息更容易读懂。
二、重定向与管道操作
1.重定向
用户通过操作系统处理信息的过程中,包括以下几类交互设备文件:
- 标准输入(STDIN):默认的设备是键盘,文件编号为 0,命令将从标准输入文件 中读取在执行过程中需要的输入数据。
- 标准输出(STDOUT):默认的设备是显示器,文件编号为 1,命令将执行后的输 出结果发送到标准输出文件。
- 标准错误(STDERR):默认的设备是显示器,文件编号为 2,命令将执行期间的 各种错误信息发送到标准错误文件。
(1)重定向输出
[root@localhost ~]# uname -p > kernel.txt
[root@localhost ~]# cat kernel.txt
[root@localhost ~]# uname -r >> kernel.txt \\追加并保存,不覆盖原有的数据
[root@localhost ~]# cat kernel.txt
扩展:
[root@localhost ~]# sed -i '1a\aaa' 123.txt#在第一行的下一行添加文字
[root@localhost ~]# sed -i '1i\aaa' 123.txt#在第一行的上一行添加文字
(2)重定向输入
[root@localhost ~]# echo "123456">pass.txt
[root@localhost ~]# useradd aaa
[root@localhost ~]# passwd --stdin aaa <pass.txt \\selinux要设置为disabled
或
[root@localhost ~]# echo aptech | passwd --stdin aaa \\不用关闭selinux
(3)重定向错误
[root@localhost ~]# tar jcf /nonedir/etc.tgz /etc/ 2>error.log
[root@localhost ~]# cat error.log
2.管道操作
[root@localhost ~]#grep "/bin/bash$" /etc/passwd \\以bash结尾的行
[root@localhost ~]#grep "/bin/bash$" /etc/passwd | awk -F: '{print $1,$7}'
[root@localhost ~]# df -hT
[root@localhost ~]# df -hT | grep "/$" | awk '{print $6}'#根目录下磁盘利用率
三、使用shell变量
- 变量名不能用数字开头
- 变量名中不能有小数点
- 变量名不能用纯数字
- 变量名可以是字母开头再加数字,或下划线开头加字母或数字
- 变量名中不能有斜杠“/”、“$”、“#”、“@”等特殊符号
- 等号前后不能加空格
1.自定义变量
(1)定义新的变量
[root@localhost ~]# name=benet
[root@localhost ~]# version=5.0
(2)查看和引用变量的值
[root@localhost ~]# echo $name
benet
[root@localhost ~]# echo $name$version
benet 5.0
[root@localhost ~]# echo $name4.5\\错误的引用
.5
[root@localhost ~]# echo ${name}4.5
benet4.5
备注:引用变量时如果变量名后有其他的字符,要将变量名应大括号引起来,用以定界
(3)变量赋值的特殊操作
1)双引号
双引号可用于字符串的声明,双引号中的$符号或当做变量进行输出。连续的字符可以省略双引号,字符串中有空格的话就不能省略,另外,声明的变量值中如果要引用另一个变量,也需要双引号。
[root@localhost ~]# name=benet 5.0\\错误的赋值
bash: 5.0: command not found
[root@localhost ~]# name="benet 5.0"
[root@localhost ~]# echo $name
benet 5.0
[root@localhost ~]# accp="accp $version"
[root@localhost ~]# echo $accp
accp 5.0
2)单引号
单引号用于原样输出的变量声明,意思是变量的值中需要保留显示$符号
[root@localhost ~]# accp='accp $version'
[root@localhost ~]# echo $accp
accp $version
3)反撇号
反撇号用于命令的引用,相当于$(),区别在于反引号不能嵌套,而$()可以嵌套
[root@localhost ~]# ls -lh `which useradd`
-rwxr-x---. 1 root root 101K 8 月 2 2011 /usr/sbin/useradd
[root@localhost ~]# aaa=`grep -v "^#" /etc/profile`
[root@localhost ~]# echo $aaa
.......
[root@localhost ~]# rpm -qc $(rpm -qf $(which useradd))
/etc/default/useradd
/etc/login.defs
备注:
- -qf:查找该文件属于哪一个已安装的软件包
- -qc:列出该软件包生成的所有文件
4)read命令
除了上述赋值操作以外,还可以使用 Bash 的内置命令 read 来给变量赋值。read 命令 用来提示用户输入信息,从而实现简单的交互过程。执行时将从标准输入设备(键盘)读入 一行内容,并以空格为分隔符,将读入的各字段依次赋值给指定的变量(多余的内容赋值给 最后一个变量)。若指定的变量只有一个,则将整行内容赋值给此变量。
[root@localhost ~]# read todir1
/opt/backup/ \\用户输进去的
[root@localhost ~]# echo $todir1
/opt/backup/
[root@localhost ~]# read -p "请制定备份存放的目录:" todir2
请制定备份存放的目录:/opt/backup
[root@localhost ~]# echo $todir2
/opt/backup
(4)设置变量的作用范围
默认情况下,新定义的变量只在当前的 Shell 环境中有效,因此称为局部变量。当进入第 13 页 共 19 页 子程序或新的子 Shell 环境时,局部变量将无法再使用。
[root@localhost ~]# echo "$name $version" //查看当前定义的变量值
benet 5.0
[root@localhost ~]# bash //进入子 Shell 环境
[root@localhost ~]# echo "$name $version" //无法调用父 Shell 环境中的变量
[root@localhost ~]# exit //返回原有的 Shell 环境
为了使用户定义的变量在所有的子 Shell 环境中能够继续使用,减少重复设置工作,可 以通过内部命令 export 将指定的变量导出为全局变量。用户可以同时指定多个变量名称作 为参数(无须使用“$”符号),变量名之间以空格分隔。
[root@localhost ~]# echo "$name $version" //查看当前定义的变量值
benet 5.0
[root@localhost ~]# export name version //将 Product、Version 设为全局变量
[root@localhost ~]# bash //进入子 Shell 环境
[root@localhost ~]# echo "$name $version"
benet 5.0 //可以调用父 Shell 的全局变量
[root@localhost ~]# exit //返回原有的 Shell 环境
使用 export 导出全局变量的同时,也可以为变量进行赋值,这样在新定义全局变量时 就不需要提前进行赋值了。
[root@localhost ~]# export FQDN="www.jb-aptech.com.cn"
[root@localhost ~]# echo $FQDN
www.jb-aptech.com.cn
(5)数值变量的运算
[root@localhost ~]# x=35
[root@localhost ~]# y=16
[root@localhost ~]# expr $x+$y
35+16
[root@localhost ~]# expr $x + $y
51
[root@localhost ~]# expr $x - $y
19
[root@localhost ~]# expr $x \* $y
560
[root@localhost ~]# expr $x / $y
2
[root@localhost ~]# expr $x % $y
3
[root@localhost ~]# Ycube=`expr $y \* $y \* $y`
[root@localhost ~]# echo $Ycube
4096
[root@localhost ~]# a=2
[root@localhost ~]# echo $((a*3))
6
[root@localhost ~]# echo $((a**3))#3次方
8
备注:运算符与变量之间必须有至少一个空格。
- +:加法运算。
- -:减法运算。
- \*:乘法运算,注意不能仅使用“*”符号,否则将被当成文件通配符。
- /:除法运算。
- %:求模运算,又称为取余运算,用来计算数值相除后的余数。
2.环境变量
- set命令也可以显示环境变量,它显示的是系统中所有的环境变量,包括全局变量和局部变量
- env只显示全局变量
PATH 变量用于设置可执行程序的默认搜索路径,当仅指定文件名称来执行命令程序 时,Linux 系统将在 PATH 变量指定的目录范围查找对应的可执行文件,如果找不到则会提示“command not found”。例如,first.sh 脚本位于/root 目录下,若希望能直接通过文件名称来运行脚本,可以修改 PATH 变量以添加搜索路径,或者将 first.sh 脚本复制到现有搜索路 径中的某个文件夹下。
[root@localhost ~]# env
.......省略部分内容
[root@localhost ~]# ls -lh /root/first.sh
[root@localhost ~]# echo $PATH
[root@localhost ~]# first.sh
bash: first.sh: command not found
[root@localhost ~]# PATH="$PATH:/root"
[root@localhost ~]# echo $PATH
[root@localhost ~]# first.sh
.......省略部分内容
在 Linux 系统中,环境变量的全局配置文件为/etc/profile,在此文件中定义的变量作用 于所有用户。例如,执行以下操作可以将记录的历 史命令条数改为 200 条(默认为 1000 条),只针对 root 用户。
[root@localhost ~]# vi /etc/profile
修改
export HISTORYSIZE=20
[root@localhost ~]# history | wc -l
89
[root@localhost ~]# source /etc/profile
[root@localhost ~]# history | wc -l
20
3.位置变量
当执行命令行操作时,第一个字段表示命令名或脚本程序名,其余的字符 串参数按照从左到右的顺序依次赋值给位置变量。 位置变量也称为位置参数,使用$1、$2、$3、…、$9 表示。
[root@localhost ~]# vi adder2num.sh
#!/bin/bash
SUM=`expr $1 + $2`
echo "$1 + $2 = $SUM"
[root@localhost ~]# chmod +x adder2num.sh
[root@localhost ~]# ./adder2num.sh 12 14
12 + 14 = 26
4.预定义变量
- $# 传送给命令Shell的参数个数
- $- 在Shell启动或使用set命令时提供选项
- $? 上一条命令执行后返回的值
- $$ 当前shell的进程号
- $! 上一个子进程的进程号
- $@ 所有的参数,每个都用双括号括起
- $* 所有参数,用双括号括起
- $n 位置参数值,n表示位置
- $0 当前shell名
备注:
$@:输出所有参数,把输出的参数当做一个个独立的单词,便于遍历所有的参数
$*:输出所有参数,把所有输出的参数当做一个整体。
这两个变量在输出时,视觉上是一样的,但存储方式不一样