首页 > 代码库 > shell脚本基础

shell脚本基础

Shell脚本简介:

Shell脚本是一种特殊的程序,它是用户与linux系统内核之间的一个接口,shell是一个工具程序,在用户登录后系统启动。它解释并运行由命令行或脚本文件输入的命令,从而实现用户与内核间的交互。

Shell脚本:也就是用各类命令预先放入到一个文件中,方便一次性执行的一个程序文件,主要是方便管理员进行设置或者管理用的,是利用shell的功能所写的一个程序,这个程序是使用纯文本文件,将一些shell的语法与指令写在里面,然后用正规表示法,管道命令以及数据流重导向等功能,以达到我们所想要的处理目的

 

程序:指令+ 数据

程序编程风格:

过程式:以指令为中心,数据服务于指令

对象式:以数据为中心,指令服务于数据

shell 程序:提供了编程能力,解释执行

程序的执行方式:

 计算机:运行二进制指令;

编程语言:

低级:汇编

高级:

编译:高级语言-->编译器--> 目标代码

java,C#

解释:高级语言-->解释器--> 机器代码

shell, perl, python

编程逻辑处理方式:

顺序执行

循环执行

选择执行

shell 编程:过程式、解释执行

编程语言的基本结构:

数据存储:变量、数组

表达式: a + b

语句:if

shell 脚本是包含一些命令或声明,并符合一定格式的文

本文件

格式要求:首行shebang 机制

#!/bin/bash

#!/usr/bin/python

#!/usr/bin/perl

shell 脚本的用途有:

        自动化常用命令

        执行系统管理和故障排除

        创建简单的应用程序

        处理文本或文件

创建shell脚本

    第一步:使用文本编辑器来创建文本文件

第一行必须包括shell 声明序列:#!(要顶格写)

#!/bin/bash

添加注释

注释以# 开头

第二步:运行脚本

给予执行权限,在命令行上指定脚本的绝对或相对路径

直接运行解释器,将脚本作为解释器程序的参数运行

脚本的调试:

        bash -n/path/to/some_script

检测脚本中的语法错误

bash -x /path/to/some_script

调试执行

 

变量:

     变量:命名的内存空间

数据存储方式:

字符:

数值:整型,浮点型

变量:变量类型

作用:

1 、数据存储格式

2 、参与的运算

3 、表示的数据范围

类型:

字符

数值:整型、浮点型

 

编程程序语言分类:

  强类型:定义变量时必须指定类型、参与运算必须符合类型

要求;调用未声明变量会产生错误

java,python

弱类型:无须指定类型,默认均为字符型;参与运算会自动

进行隐式类型转换;变量无须事先定义可直接调用

bash  不支持浮点数

变量命名法则:

1 、不能使程序中的保留字:例如if, for;

2 、只能使用数字、字母及下划线,且不能以数字开头

3 、见名知义

4 、统一命名Shell脚本包括一些命令或声明,并符合一个格式的文件

Bash中变量的种类

     根据变量的生效范围等标准:

本地变量:生效范围为当前shell进程;对当前shell 之外的其它shell 进程,包括当前shell 的子shell 进程均无效

环境变量:生效范围为当前shell进程及其子进程

局部变量:生效范围为当前shell进程中某代码片断( 通常指函数)

位置变量:$1, $2,... 来表示,用于让脚本在脚本代码中调用通过命令行传递给它的参数

特殊变量:$?, $0,$*, $@, $#

 

 

本地变量:

变量赋值:name=value’,

可以使用引用value:

(1)  可以是直接字串;name=root"

(2)  变量引用:name="$USER"

(3)  命令引用:name=`COMMAND `, name =$(COMMAND)

变量引用:${name},$name

"" :弱引用,其中的变量引用会被替换为变量值

‘‘ :强引用,其中的变量引用不会被替换为变量值,而保

持原字符串

显示已定义的所有变量:set

删除变量:unsetname

举例演示:

 1编写脚本/root/bin/systeminfo.sh.显示当前主机系统信息,包括主机名,IPv4地址,操作系统版本,内核版本,CPU型号,内存大小,硬盘大小。

 

脚本:

 技术分享                         

 

  2、编写脚本/root/bin/backup.sh,可实现每日将/etc/ 目录备份到/root/etcYYYY-mm-dd

 

脚本:

技术分享

3、编写脚本/root/bin/disk.sh,显示当前硬盘分区中空间利用率最大的值

 技术分享


 

4、编写脚本/root/bin/links.sh,显示正连接本主机的每个远程主机的IPv4 地址和连接数,并按连接数从大到小排序

 技术分享

脚本:


 

环境变量:

                变量声明、赋值:

export name=VALUE

declare -x name=VALUE

变量引用:$name,${name}

显示所有环境变量命令:

export

env

printenv

删除:unset name

bash 有许多内建的环境变量:PATH, SHELL, USRE,UID,

HISTSIZE, HOME, PWD, OLDPWD, HISTFILE, PS1

    

只读

     只读变量:只能声明,但不能修改和删除

readonly name   

declare -r name      

位置变量

         位置变量:在脚本代码中调用通过命令行传递给脚本的参数

$1, $2, ... :对应第1 、第2 等参数,shift [n] 换位置

$0:  命令本身

$*:  传递给脚本的所有参数,全部参数合为一个字符串

$@:  传递给脚本的所有参数,每个参数为独立字符串

$#:  传递给脚本的参数的个数

$@ $*  只在被双引号包起来的时候才会有差异

示例:判断给出的文件的行数

linecount="$(wc -l $1| cut -d‘ ‘ -f1)"

echo "$1 has $linecount lines."   

算术运算

        bash 中的算术运算:help let

+, -, *, /, % 取模(取余), ** (乘方)

实现算术运算:

(1) let var= 算术表达式

(2) var=$[ 算术表达式]

(3) var=$(( 算术表达式))

(4) var=$(expr arg1 arg2 arg3 ...)

(5) declare i var =  数值

(6) echo 算术表达式’ | bc

乘法符号有些场景中需要转义 ,如 *

bash 有内建的随机数生成器:$RANDOM 1-32767

echo $[$RANDOM%50]  0-49

赋值

      增强型赋值:

+=, -=, *=, /=, %=

let varOPERvalue

例如:letcount+=3

自加3 后自赋值

自增,自减:

let var+=1

let var++

let var-=1

let var—

 

举例演示:

1 :写一个脚本/root/bin/sumid.sh,计算/etc/passwd文件中的第10 个用户和第20 用户的ID 之和

 

脚本:

技术分享

2 :写一个脚本/root/bin/sumspace.sh,传递两个文件路径作为参数给脚本,计算这两个文件中所有空白行之和

 

脚本:

技术分享

3 :写一个脚本/root/bin/sumfile.sh,统计/etc,  /var,  /usr目录共有多少个一极子目录和文件

脚本:

技术分享

逻辑运算

      true, false

1, 0

与:

1 1 = 1

1 0 = 0

0 1 = 0

0 0 = 0

:

1 1 = 1

1 0 = 1

0 1 = 1

0 0 = 0

      非:!

! 1 = 0

! 0 = 1

短路运算:

短路与:

第一个为0 ,结果必定为0

第一个为1 ,第二个必须要参与运算;

短路或

第一个为1 ,结果必定为1

第一个为0 ,第二个必须要参与运算;

异或:^

异或的两个值,相同为假,不同为真

 

       聚集命令

               有两种聚集命令的方法:

                 复合式:date; who | wc -l

命令会一个接一个地运行

                       shell (date; who |wc -l ) >>/tmp/trace

所有的输出都被发送给单个STDOUTSTDERR

退出状态

        进程使用退出状态来报告成功或失败

 0 代表成功,1 255 代表失败

 $?  变量保存最近的命令退出状态

        例如:

$ ping -c1 -W1 hostdown &> /dev/null

$ echo $?

退出状态码

          bash 自定义退出状态码

exit [n] :自定义退出状态码;

注意:脚本中一旦遇到exit 命令,脚本会立即终止;终止退出

状态取决于exit 命令后面的数字

注意:如果未给脚本指定退出状态码,整个脚本的退出状态码

取决于脚本中执行的最后一条命令的状态码

条件测试

           判断某需求是否满足,需要由测试机制来实现;

专用的测试表达式需要由测试命令辅助完成测试过程;

评估布尔声明,以便用在条件性执行中

若真,则返回0

若假,则返回1

测试命令:

test EXPRESSIO

[ EXPRESSION ]

[[ EXPRESSION ]]

注意EXPRESSION前后必须有空白字符

条件性的执行操作符

        根据退出状态而定,命令可以有条件地运行

&&  代表条件性的AND THEN

|| 代表条件性的OR ELSE

Bash的测试类型

         数值测试:

-gt:  是否大于;

-ge:  是否大于等于;

-eq:  是否等于;

-ne:  是否不等于;

 

-lt:  是否小于;

-le:  是否小于等于

         字符串测试:

== :是否等于;

>: ascii 码是否大于ascii

<:  是否小于

!=:  是否不等于

=~:  左侧字符串是否能够被右侧的PATTERN 匹配

注意此表达式一般用于[[ ]] 中;

-z "STRING" :字符串是否为空,空为真,不空为假

-n "STRING" :字符串是否不空,不空为真,空为假

注意:用于字符串比较时的用到的操作数都应该使用引号

 

举例演示:

1 、写一个脚本/root/bin/argsnum.sh ,接受一个文件路径作为参数;如果参数个数小于1 ,则提示用户“至少应该给一个参数”,并立即退出;如果参数个数不小于1 ,则显示第一参数所指向的文件中的空白行数

 

脚本:

技术分享

 

2 、写一个脚本/root/bin/hostping.sh ,接受一个主机的IPv4 地址做为参数,测试是否可连通。如果能ping 通,则提示用户“该IP 地址可访问” ;如果不可ping 通,则提示用户“该IP 地址不可访问”

 

脚本:

技术分享

          文件测试

                 存在性测试

-a FILE :同-e

-e FILE:  文件存在性测试,存在为真,否则为假;

存在性及类别测试

-b FILE :是否存在且为块设备文件;

-c FILE :是否存在且为字符设备文件;

-d FILE :是否存在且为目录文件;

-f FILE :是否存在且为普通文件;

-h FILE -L FILE :存在且为符号链接文件;

-p FILE :是否存在且为命名管道文件;

-S FILE :是否存在且为套接字文件

                  文件权限测试:

-r FILE :是否存在且可读

-w FILE:  是否存在且可写

-x FILE:  是否存在且可执行

文件特殊权限测试:

-g FILE :是否存在且拥有sgid 权限;

-u FILE :是否存在且拥有suid 权限;

-k FILE :是否存在且拥有sticky 权限

                  文件大小测试:

-s FILE:  是否存 且非空;

文件是否打开:

-t fd: fd 表示文件描述符是否已经打开且与某终端相关

-N FILE :文件自动上一次被读取之后是否被修改过

-O FILE :当前有效用户是否为文件属主

-G FILE :当前有效用户是否为文件属组

                  双目测试:

FILE1 -ef FILE2: FILE1 FILE2 是否指向同一个设备上的相同inode

FILE1 -nt FILE2: FILE1 是否新于FILE2

FILE1 -ot FILE2: FILE1 是否旧于FILE2

组合测试条件

          第一种方式:

COMMAND1 &&COMMAND2  并且

COMMAND1 || COMMAND2  或者

! COMMAND

如:[ -e FILE ] && [ -rFILE ]

第二种方式:

EXPRESSION1 -aEXPRESSION2  并且

EXPRESSION1 -oEXPRESSION2  或者

! EXPRESSION

必须使用测试命令进行

举例演示:

1 chmod -rw /tmp/file1,编写脚本/root/bin/per.sh,判断当前用户对/tmp/fiile1文件  是否不可读且不可写

 

脚本:

技术分享

 

2 、编写脚本/root/bin/nologin.shlogin.sh, 实现禁止和允许普通用户登录系统

脚本:

 禁止登录:

技术分享

 

允许登录:

技术分享

 

使用read 来把输入值分配给一个或多个shell 变量:

-p 指定要显示的提示

-t TIMEOUT

read 从标准输入中读取值,给每个单词分配一个变量

所有剩余单词都被分配给最后一个变量

read -p “Enter a filename: “ FILE

流程控制

       过程式编程语言:

顺序执行

选择执行

循环执行

条件选择if语句

        选择执行:

注意 if 语句可 嵌套

单分支

if  判断条件:then

条件为真的分支代码

fi

双分支

if  判断条件; then

条件为真的分支代码

else

条件为假的分支代码

fi

          多分支

if  CONDITION1 ; then

if-true

elif CONDITION2 ; then

if-ture

elif CONDITION3 ; then

if-ture

...

else

all-false

fi

逐条 件进行判断,第一次遇为“真”条件时,执行其分支,而后 结束整个if 语句

条件判断:case语句

         case 变量引用 in

PAT1)

分支1

;;

PAT2)

分支2

;;

...

*)

默认分支

;;

esac

    case 支持glob 风格的通配符:

*:  任意长度任意字符

?:  任意单个字符

[] :指定范围内的任意单个字符

a|b: ab

举例演示:

1 、写一个脚本/root/bin/createuser.sh,实现如下功能:使用一个用户名做为参数,如果指定参数的用户存在,就显示其存在,否则添加之;显示添加的用户的id 号等信息

 

脚本:

技术分享

2 、写一个脚本/root/bin/yesorno.sh,提示用户输入yesno, 并判断用户输入的是yes 还是no, 或是其它信息

脚本:

技术分享

3 、写一个脚本/root/bin/filetype.sh,判断用户输入文件路径,显示其文件类型(普通,目录,链接,其它文件类型)

脚本:

技术分享

4 、写一个脚本/root/bin/checkint.sh,判断用户输入的参数是否为正整数

脚本:

技术分享

5、判断硬盘的每个分区空间和inode的利用率是否大于80,如果是,发邮件通知root磁盘

 

脚本:

技术分享

 

6、指定文件做为参数,判断文件是否为.sh后缀,如果是,添加x权限

技术分享

 

7、计算1+2+3+...+100

脚本:

技术分享 


shell脚本基础