一、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名

备注:

$@:输出所有参数,把输出的参数当做一个个独立的单词,便于遍历所有的参数

$*:输出所有参数,把所有输出的参数当做一个整体。

这两个变量在输出时,视觉上是一样的,但存储方式不一样