shell脚本
一、shell概述
shell 的两层含义:既是一种应用程序,又是一种程序设计语言 作为应用程序:交互式地解释、执行用户输入的命令,将用户的操作翻译成机器可以识别的语言,完成相应功能,因而又可称为shell命令解析器。shell 是用户和 Linux 内核之间的接口程序
1、用户在提示符下输入的命令都由 shell 先解释然后传给 Linux 核心;
2、它调用了系统核心的大部分功能来执行程序、并以并行的方式协调各个程序的运行;
3、Linux 系统中提供了好几种不同的 shell 命令解释器,如 sh、ash、bash 等。一般默认使用 bash 作为默认的解释器;
4、shell 是用户跟内核通信几种方式的一种。
作为程序设计语言:它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支完成类似于 windows 下批处理操作,简化我们对系统的管理与应用程序的部署称之为shell 脚本。
shell脚本是shell命令的有序集合c/c++等语言,属于编译性语言(编写完成后需要使用编译器完成编译、汇编、链接等过程变为二进制代码方可执行);shell 脚本是一种脚本语言,我们只需使用任意文本编辑器,按照语法编写相应程序,增加可执行权限,即可在安装 shell 命令解释器的环境下执行
shell 脚本主要用于:帮助开发人员或系统管理员将复杂而又反复的操作放在一个文件中,通过简单的一步执行操作完成相应任务, 从而解放他们的负担。
二、shell语法
2.1 shell 脚本的定义与执行
shell脚本的代码编写流程
第一步:指定shell脚本文件,一般以.sh作为后缀名,也可以不加,例如:test.sh
第二步:编写代码#!/bin/bash # #!用于指定当前脚本文件的shell解释器的类型,如不写,则用默认的shell #shell脚本是shell命令的有序集合,代码的构成就是命令 ls pwd echo hello world第三步:修改文件权限
chmod +x test.sh第四步:执行脚本文件 三种执行方式
./test.sh 增加可执行权限后执行 bash test.sh 直接指定使用 bash 解释 test.sh . test.sh(或source test.sh) 使用当前 shell 读取解释 test.sh
三种执行脚本的方式不同点:
./和 bash 执行过程基本一致,后者明确指定 bash 解释器去执行脚本,脚本中#!指定的解释器不起作用前者首先检测#!,使用#!指定的 shell,如果没有使用默认的 shell
用./和 bash 去执行会在后台启动一个新的 shell 去执行脚本
用.去执行脚本不会启动新的 shell,直接由当前的 shell 去解释执行脚本。
2.2 变量
2.2.1 自定义变量
#!/bin/bash #定义变量 #shell脚本中没有数据类型可言,所以定义变量时不需要加数据类型 #shell脚本中,赋值操作时不能在等号两边加空格 #NUM = 100 #错误 NUM=100 #引用变量 # $变量名 取一个变量的值 i=$NUM #显示变量 echo $NUM echo $i #清除变量 unset NUM echo ************* echo $NUM #使用read从终端读取数据保存在变量中 read str echo str = $str #使用readonly创建一个只读的变量 readonly n=999 echo n = $n #指定变量初始化后不能再次修改变量的值,只能使用 #n=666 #echo n = $n
2.2.2 环境变量
shell在开始执行时就已经定义了一些和系统的工作环境有关的变量,我们在shell中可以直接使用$name引用 一般在~/.bashrc或/etc/profile文件中(系统自动调用的脚本)使用export设置,允许用户后来更改 设置环境变量: 方法1:临时设置 在终端执行命令MYVAL=999 export MYVAL方法2:永久设置 需要在配置文件(~/.bashrc或/etc/profile)中进行设置即可,设置完毕后需要通过source命令配置文件立即生效 使用环境变量,一般环境变量类似c语言中的全局变量,可以再shell脚本文件中任意使用
#!/bin/bash echo You are welcome to use bash echo Current work dirctory is $PWD echo the host name is $HOSTNAME echo your home dir $HOME echo Your shell is $SHELL echo user env val is $MYVAL1
2.2.3 预设变量
$#:传给shell脚本参数的数量 $*:传给shell脚本参数的内容 $1、$2、$3、...、$9:运行脚本时传递给其的参数,用空格隔开 $?:命令执行后返回的状态 $?用于检查上一个命令执行是否正确(在Linux中,命令退出状态为0表示该命令正确执 行,任何非0值表示命令出错)。 $0:当前执行的进程名 $$:当前进程的进程号 $$变量最常见的用途是用作临时文件的名字以保证临时文件不会重复#! /bin/bash #位置变量$0 ‐ $9 保存从终端输入的每一个参数 echo \$0 = $0 echo \$1 = $1 echo \$2 = $2 echo \$5 = $5 echo \$6 = $6 echo \$7 = $7 echo \$8 = $8 echo \$9 = $9 #如果超过9,需要加大括号 echo \$10 = ${10} #$#:保存命令行传入的参数的个数,不包括$0 echo \$# = $# #$@或者$*:保存所有的命令行传入的参数,但是不包括$0 echo \$@ = $@ echo \$* = $* #$$:获取当前进程的进程号 echo \$$ = $$ #read NUM # $? 返回上一个命令执行的结果,如果执行成功,则$?的值为0,执行失败,则为非0 ls echo \$? = $? ls asdfasdf echo \$? = $?
2.2.4 脚本变量的特殊用法
(双引号):包含的变量会被解释 ''(单引号):包含的变量会当做字符串解释 ``(数字键1左面的反引号):反引号中的内容作为系统命令,并执行其内容,可以替换输出为一个变量 $ echo today is `date` today is 2012年07月29日星期日 12:55:21 CST \ 转义字符:同c语言 \n \t \r \a等 echo命令需加-e转义 (命令序列):由子shell来完成,不影响当前shell中的变量 { 命令序列 }:在当前shell中执行,会影响当前变量#!/bin/bash name=zhangsan #双引号里面的特殊字符,会使用其特殊含义 string1=good moring $name #单引号里面的特殊字符,都会失去特殊含义 string2='good moring $name' echo $string1 echo $string2
#反引号:获取一个shell命令的输出结果,一般对有输出结果的命令经常去使用,也可以使用$()与反引号等价 echo today is date echo today is `date` echo 'today is `date`' echo My dir is $(ls)
#转义字符:使用时,需要在echo后面加上‐e选项 echo ************** echo this \n is\ta\ntest echo ‐e this \n is\ta\ntest echo **************
num=100 #由子shell来完成,不影响当前shell中的变量 ( num=999;echo 1 $num ) echo 1:$num #在当前shell中执行,会影响当前变量 { num=666; echo 2 $num; } echo 2:$num
2.3 条件测试语句
在写shell脚本时,经常遇到的问题就是判断字符串是否相等,可能还要检查文件状态或进行数字测试,只有这些测试完成才能做下一步动作 test命令:用于测试字符串、文件状态和数字 test命令有两种格式: test condition 或 [ condition ] 使用方括号时,要注意在条件两边加上空格 shell脚本中的条件测试如下: 文件测试、字符串测试、数字测试、复合测试 测试语句一般与后面讲的条件语句联合使用2.3.1 文件测试
1)按照文件类型 -e 文件名 文件是否存在 -s 文件名 是否为非空 -b 文件名 块设备文件 -c 文件名 字符设备文件 -d 文件名 目录文件 -f 文件名 普通文件 -L 文件名 软链接文件 -S 文件名 套接字文件 -p 文件名 管道文件 2)按照文件权限 -r 文件名 可读 -w 文件名 可写 -x 文件名 可执行 3)两个文件之间的比较 文件1 -nt 文件2 文件1的修改时间是否比文件2新 文件1 -ot 文件2 文件1的修改时间是否比文件2旧 文件1 -ef 文件2 两个文件的inode节点号是否一样,用于判断是否是硬链接#! /bin/bash echo please input a filename read FILE test ‐e $FILE echo 存在?$? test ‐s $FILE echo 非空?$? [ ‐r $FILE ] echo 可读?$? [ ‐w $FILE ] echo 可写?$? [ ‐x $FILE ] echo 可执行?$? test ‐b $FILE echo 块设备文件?$? test ‐c $FILE echo 字符设备文件?$? test ‐d $FILE echo 目录文件?$? test ‐f $FILE echo 普通文件?$? test ‐L $FILE echo 软链接文件?$? test ‐S $FILE echo 套接字文件?$? test ‐p $FILE echo 管道文件?$?2.3.2 字符串测试 s1 = s2 测试两个字符串的内容是否完全一样 s1 != s2 测试两个字符串的内容是否有差异 -z s1 测试s1 字符串的长度是否为0 -n s1 测试s1 字符串的长度是否不为0
#! /bin/bash test hello = hello echo 相等?$? test hello = hella echo 相等?$? test hello != hello echo 不相等?$? test hello != hella echo 不相等?$? test ‐z hello echo 长度是否为0?$? test ‐n hello echo 长度是否不为0?$?