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?$?