码迷,mamicode.com
首页 > 系统相关 > 详细

第七章,shell编程基础

时间:2018-04-13 19:06:30      阅读:224      评论:0      收藏:0      [点我收藏+]

标签:shell   脚本   shell编程   

更多笔记点击查看

Linux学习从入门到打死也不放弃,完全笔记整理(持续更新)

http://blog.51cto.com/13683480/2095439


笔记整理开始时间:2018年4月12日11:37:35

 

本章内容:

        编程基础

        脚本基本格式

        变量

        运算

        条件测试

        配置用户环境

        

编程基础:

        程序:指令+数据

        程序编程风格:

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

                      面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤

                      一步一步实现,使用的时候一个一个依次调用就可以了

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

                      面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为

                      了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为

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

                        是对一堆Linux命令的逻辑化处理

        

        程序的的执行方法:

               计算机:运行二进制指令

               编程语言:

                     低级:汇编

                     高级:

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

                                    在编译时将代码转换成2进制

                                    java,c#

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

                                    在程序执行时才转换成2进制

                                    shell,perl,python

        编程基本概念:

               编程逻辑处理方式

                     顺序执行,循环执行,选择执行

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

                     编程语言的基本结构:

                             各种系统命令的组合

                             数据存储:变量、数组

                            表达式:a + b

                            语句:if

        

shell脚本基础:

        shell脚本:

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

        格式要求:首行shebang机制

               #!/bin/bash                          shell

               #!/usr/bin/python        python

               #!/usr/bin/perl                    perl

        shell脚本的用途有:

               自动化常用命令

               执行系统管理和故障排除

               创建简单的应用程序

               处理文本或文件

 

创建shell脚本:

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

               第一行必须包括shell声明序列:#!

                     #!/bin/bash

               添加注释

                     注释以#开头

        第二步:运行脚本

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

                      /root/hello

               直接运行解释器(bash),如:

                     bash  /root/hello

                     cat ff115  |bash

        PS:source 执行程序  表示脚本会在当前shell运行不开启子进程

 

脚本规范:

        1.第一行一般为调用使用的语言

        2.程序名,避免更改文件名为无法,正确找到的文件

               (如不要取名bash,或者其他存在的程序名)

        3.版本号

        4.更改后的时间

        5.作者相关信息

        6.该程序的作用。以及注意事项

        7.最后是各版本的更新简要说明

 

脚本基本结构

        #!shebang

        configuration_variables        配置变量

        function_definitions              定义函数

        main code                                  主要代码

        

脚本调试:

        检测脚本中的语法错误

               bash -n hello.world

               如:

                     [root@sentos7 ~/bin]#bash -n ceshi

                     ceshi: line 2: unexpected  EOF while looking for matching `"'

                     ceshi: line 7: syntax  error: unexpected end of file

        调试执行:

               bash -x hello.world

        PS:

               bash -n 只检查语法错误

               如果是语法错误后续命令不执行

               如果是命令not found 后续会继续执行

               bash -x  +代表深度,直接执行+,被调用执行++

               脚本内不支持别名,也无法添加别名

               

变量:命名的内存空间

        数据存储方式:

               把程序中准备使用的数据赋给一个简短、易于记忆的名字

        类型:

               字符型

               数值:×××,浮点型

        作用:

               数据存储

               参与运算

               表示数据范围

        强类型:

               变量不经过强制转换,它永远是这个数据类型,不允许隐式的类型转化。一般

               定义变量时必须指定类型,参与运算必须符合类型要求;调用未声明变量会

               产生错误。

                     如jave c#

        弱类型:

               语言的运行时会隐式做数据类型转换。无须指定类型,默认均为字符型,参

               与运算会自动进行隐式类型转换,变量无须事先定义可直接调用

                     如:bash不支持浮点数, php

        变量命名法则:

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

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

               3.见名知义

               4.统一命名规则:驼峰命名法

 

bash中变量的种类:

        根据变量的生效范围等标准等标准划分下面变量类型:

               局部变量:

                     生效范围为当前shell进程;对当前shell之外的其他shell进程,

                     包括当前shell的子shell进程均无效

               环境(全局)变量:

                     生效范围为当前shell进程及其子进程

               本地变量:生效范围为当前shell进程中某代码片段,通常指函数

               位置变量:$1,$2,..${10}..来表示,用于让脚本在脚本代码中调用通过命令行传递

                     给它的参数

               特殊变量:

                     $?,$0,$*,$@,$#,$$

                     $?           前一个命令的退出状态,成功为0,不成功为非0

        

局部变量:     

        变量赋值:name='value'

               可以使用引用value:

                     1.可以是直接字串;     name=‘root’

                     2.变量引用:         name=$USER

                     3.命令引用:         name=`command`

                                                         name=$(cmd)

               ps:

                      变量一旦赋值,除非重新赋值,否则所占内存空间不变,值不变

                             name1=name2的情况

                                    就算赋值之后name2的值改变了,name1的值保持不变

                    

                     i=100      赋值为字符,不问数字类型

        

        变量引用:

                     ${name}  $name

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

                            [root@sentos7  ~/bin]#echo "$PS1"

                            \[\e[1;35m\][\u@\h \w]\$\[\e[0m\]

                      '':强引用,其中的变量引用不会被替换为变量值,而保持原字符串

                            [root@sentos7  ~/bin]#echo '$PS1'

                             $PS1

               

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

        删除变量:     unset name

        PS:

               pstree -p        进程tree

               echo $$  当前进程的进程编号

               echo $PPID 父进程的进程编号

        

练习1

?    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             相当于name=Value;export  name

               declare -x name2=Value

                     let  c=name+name2;export c

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

        显示所有环境变量:

               env

               printenv

               export

               declare -x

        删除变量:

               unset name

        bash内建的环境变量:

               PATH:    

               SHELL:

               USER:

               UID:

               HOME:

               PWD:

               SHLVL:          当前shell层数

               LANG:            语言键盘、字符编码

               MAIL:           当前用户mail目录

               HOSTNAME:

               HISTSIZE:

               _:                    前一个命令的最后一个参数

               

只读和位置变量:

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

               声明只读变量:

                     readonly  name

                     declare -r  name

               查看只读变量:

                     readonly  -p

        

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

               $1,$2,..${10}..:   对应相应第1,2..10..个参数

                     脚本中命令:shift[n] 可以传递参数位置,如:

                            shift              可以将原本$2,变成$1

                            shift 3            将原$4变成$1

               $0    命令本身,名字

                     默认带路径,可以用 `basename $0`取出来

               $0  如果是软链接的话 $0会显示各自软链接的名字

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

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

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

                     $@ $*    在脚本调用脚本传递参数时,如果用"$*",会将所有参数当成一个

                                           字符串传递

                                   $* $@  "$@"   会将每个参数单独传递

        set --     清空所有位置变量

        

退出状态

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

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

                     0            成功

                     1-255     失败

        例如:     

               ping -c1 172.20.3.14 &>/dev/null

               echo $?

        

        退出状态码:

               bash 自定义退出状态码

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

               注意:

                     脚本中一旦遇到exit命令,脚本会立即终止;终止退出状态取决于

               exit命令后面的数字

                      如果没有给脚本指定退出状态码,整个脚本的退出状态码取决于脚本

               中执行的最后一条命令的状态码

        

算术运算:let

        

        bash中的算术运算:help let

        常用算术:

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

        实现算术运算的格式:

               1.     let var=算术表达式

                            let  z=x+y;let x++;let  y=x**2;

                            let  z=(3*x+4*y/3)-2*x

               2.     var=$[算术表达式]

                             z=$[(3*x+4*y/3)-2*x]

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

                             z=$(((3*x+4*y/3)-2*x))

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

                            如:z=$(expr $x + $y)         表示z=x+y

                     *需要写成\*

               5.     declare -i  var=数值(可以使是算式)

                            declare -i  x=x+y

                            declare -i  x=3*x+y*4/2

               6.     echo ’算术表达式‘ |bc

 

        bash有内建的随即数生成器:$RANDOM(0-32676)

               echo $[$RANDOM%50]:               0-49之间随机数

        

赋值:

        增强型赋值:

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

               let x+=3;x-=1;x*=5;x/=4           

                            +3 -1  *5     /4

                      shell不支持浮点计算,所以除法会有商整取余

        自增,自减

               let x+=1;let x++

               let x-=1;let x--

               

练习2      

        1、编写脚本/root/bin/sumid.sh,计算/etc/passwd文件中的第10个用户和第

        20用户的ID之和

?     2、编写脚本/root/bin/sumspace.sh,传递两个文件路径作为参数给脚本,计

        算这两个文件中所有空白行之和

?     3、编写脚本/root/bin/sumfile.sh,统计/etc, /var, /usr目录中共有多少个一级

        子目录和文件

 

 

逻辑运算

        与:        &

        或:        |              

        非:        !

               !1=0

               !0=1

        短路运算:

               cmd1 && cmd2

               如果cmd1为假,cmd2不需要执行,反之cmd1为真,需要cmd2执行

 

               cmd1 || cmd2

               如果cmd1为真,cmd2不需要执行,反之cmd1为假,需要cmd2执行

 

               cmd1 && cmd2 || cmd3    要求cmd2必真

                     cmd1为真,执行cmd2

                            为假,执行cmd3

        异或:^ XOR

               二进制运算,同为0 异为1

               a=5;b=6;echo $a  $b;a=$[a^b];b=$[a^b];a=$[a^b];echo $a $b       

                     将a  b的值互换

ture 和false

        只返回真或者假,不做任何操作

        true && echo hello

     false   && echo hello||echo nihao

        

条件测试:test

        

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

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

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

               若真        则返回0

               若假        则返回1

        测试命令:

               test expression              如:test a = b ;echo  $?

               [ $a = b ] && echo ture || echo  false

              [[ $a =~ pattern ]]

        表达式epression 前后必须有空白字符

        

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

               && 代表条件性的and then

               ||      代表条件性的 or else

        例如:

               grep -q no_such_user /etc/passwd || echo 'NO such  user'

               id usera &>/dev/null && echo "usera is exist" || useradd  usera

               

        长格式的例子:

               test "$A" == "$B" && echo "Strings are  equal"

                     [ "$A" == "$B" ]

               test "$A" -eq "$B" && echo "Integers are  equal"

                     [ "$A" -eq "$B" ]

        

bash的数值测试:

        -v var

               变量是否设置 test -v var && echo hello||echo  nihao

               [ -v var ] && set || not  set

        PS:

               此处使用变量var前不可加"$",否则判断异常

                             

               

        数值测试:

               -gt 是否大于              [ $A -gt $B  ]

               -ge        是否大于等于

               -eq         是否等于

               -ne        是否不等于

               -lt           是否小于

               -le          是否小于等于

               

bash的字符串测试:

        

               ==          是否等于                                    等于为真,0

               >            ascii码是否大于ascii码     

               <                           是否小于

               !=            是否不等于                                 不等于为真,0

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

               注意:此表达式一般用于[[ ]]中,支持扩展的正则表达式

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

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

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

                     [[ ]]使用pattern时 表达式 不能加引号 ,也不能识别\< \>  \b

                    判断是否为空也可以:

                            [ x = x"$a" ] && echo ture || echo false

        

练习3:

        1、编写脚本/root/bin/argsnum.sh,接受一个文件路径作为参数;如果参数

        个数小于1,则提示用户“至少应该给一个参数”,并立即退出;如果参数个数

        不小于1,则显示第一个参数所指向的文件中的空白行数

? 2、编写脚本/root/bin/hostping.sh,接受一个主机的IPv4地址做为参数,测

        试是否可连通。如果能ping通,则提示用户“该IP地址可访问”;如果不可

        ping通,则提示用户“该IP地址不可访问”

? 3、编写脚本/root/bin/checkdisk.sh,检查磁盘分区空间和inode使用率,如

        果超过80%,就发广播警告空间将满

        

Bash的文件测试:

        存在性测试:

               -a file            同  -e

               -e file             文件存在性测试,存在为真,否则为假

        存在性及类别测试

               -b file             是否存在且为块设备文件

               -c file              是否存在且为字符设备文件

               -d file             是否存在且为目录文件

               -f file              是否存在且为普通文件

               -h file     或 -L file        是否存在且为符号链接文件

               -p file    是否存在且为命名管道文件

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

               

Bash的文件权限测试:

        文件权限测试:

               -r file              是否存在且可读

               -w file             是否存在且可写

               -x file     是否存在且可执行

        文件特殊权限测试:

               -u file             是否存在且拥有suid权限

               -g file             是否存在且拥有sgid权限

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

        

Bash的文件属性测试:

        文件大小测试:

               -s file              是否存在且为空

        文件是否打开

               -t fd:fd 文件描述符是否在某终端已经打开

               -N file             文件自从上一次被读取之后是否被修改过

               -O file             当前用户是否为文件属主

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

        双目测试:

               file1 -ef file2          file1是否是file2的硬链接

               file1 -nt file2 file1是否新于file2  (mtime)

               file1 -ot file2         file1是否旧与file2

        

Bash的组合测试条件:

        第一种方式:

               cmd1 && cmd2    且

               cmd1 ||   cmd2      或

               !cmd                  非

               如:       [[  -r FILE ]] && [[ -w FILE  ]]

        第二种方式:

               [ expression1 -a expression2 ]            并且

               [ expression1 -o expression2 ]            或者

               [ !expression ]                                非

        例:

               [ -z "$HOSTNAME" -o "$HOSTNAME" == "localhost.localdomain" ] &&

                     hostname www.magedu.com  

               [ -f /bin/cat -a -x /bin/cat ] && cat  /etc/fstab

        

        PS:

               &&(-a)     ||(-o)可连续使用

               

               [ -r "$1" -a -w "$1" -a -x "$1" ]  && echo ture ||  false

                     [ -a "$1"  ] && [ -r "$1" ] && [ -w "$1" ] && [ -x "$1" ]  && echo ture || false

                     只要有一个为假,就返回假

               [ -r "$1" -o -w "$1” -o "$1" ] && echo  ture || false

                     [ -r "$1"  ] || [ -w "$1" ] || [ -x "$1"] && echo ture ||  false

                     只要一个为真,则返回为真

练习:?

        1、编写脚本/bin/per.sh,判断当前用户对指定参数文件,是否不可读并且不可写

?    2、编写脚本/root/bin/excute.sh ,判断参数文件是否为sh后缀的普通文件,如

        果是,添加所有人可执行权限,否则提示用户非脚本文件

?    3、编写脚本/root/bin/nologin.sh和login.sh,实现禁止和充许普通用户登录系统              

        

read:

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

               -p                  指定要显示的提示,如:

                                   read -p  "Please input your name: " name

               -s                  静默输入,一般用于密码,如:

                                   read -s -p  "Please input your password: " passw

               -n N               指定输入的字符长度N

                                    指定长度之后,如达到长度,后续指令不会换行,直接在输入的内容之后显示了

                                    想要达到换行的目的,需要下一行加上

                                          echo  ""   但是如果手动回车则会显示一行空行

               -d '字符' 输入结束符     到此字符直接结束输入

                                   read -t 20 -n  20 -p "Please input you ID, end with'#' : "  ID

                                   与-n类似,也是不会换行

               -t N        TIMEOUT为N秒

                                    timeout并不会退出脚本,而是会执行后续指令

        

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

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

               不支持管道接受标准输入     | read name

 

bash如何展开命令行

               把命令行分成单个命令词

               展开别名

               展开大括号的声明({})

               展开波浪符声明(~)

               命令替换$()和(``)

               再次吧命令行分成命令词

               展开文件通配(*、?、[abc]等等)

               准备I/O重导向(<,>)

               运行命令

 

防止扩展:

        反斜线 \ 会使随后的字符按原意解释

               $     echo your cost:\$5.00

               your cost:$5.00

        加引号来防止扩展

               单引号''   防止所有扩展

               双引号"" 也防止所有扩展,但是以下情况例外

                     $                   --变量扩展

                     `` $()        --命令替换

                     \                    --禁止单个字符扩展

                     !                   --历史命令替换

 

bash的配置文件:

        按生效范围划分、存在两类

        全局配置:

               /etc/profile

               /etc/profile.d/*.sh

               /etc/bashrc

        个人配置:

               ~/.bash_profile

               ~/.bashrc

 

shell登录两种方式

        交互式登录:

               1)直接通过终端输入账号密码登录

               2)使用 su - username 切换的用户

               执行顺序:

                     /etc/profile -->  /etc/profile.d/*.sh --> ~/.bash_profile -->

               ~/.bashrc -->  /etc/bashrc

        非交互式登录:

               1)su username

               2)图形界面下打开的终端

               3)执行脚本

               4)任何其他的bash实例

               执行顺序:~/.bashrc -->  /etc/bashrc --> /etc/profile.d/*.sh

               

按功能划分:

        profile类:

               为交互式登录的shell提供配置

               全局:/etc/profile,  /etc/profile.d/*.sh

               个人:~/.bash_profile

               功能:

                     用于定义环境变量

                     运行命令或脚本

        

        bashrc类:

               为交互式和非交互式登录的shell提供配置

               全局:/etc/bashrc

               个人:~/.bashrc

               功能:

                     定义命令别名和函数

                     定义本地变量

        

配置文件修改生效:

        修改profile和bashrc文件后需生效

               两种方法:

                     重新启动shell进程(重新登录)

                     . 或  source

                     例如:  . ~/.bashrc

 

Bash退出任务:

        保存在~/.bash_logout文件中

        在退出登录shell时运行

        用于:

               创建自动备份

               清楚临时文件

               

变量:$-

        h:hashall,打开这个选项后,shell

        会将命令所在的路径hash下来,避免每次都要查询。通过set+h将h选项关闭

        

        i:interactive-comments,包含这个选项说明当前的shell是一个交互式的shell

        所谓的交互式shell,在脚本中,i选项都是关闭的

        

        m:monitor,打开监控模式,就可以通过job  control来控制进程的停止、继续、

        后台或者前台执行等。

        

        B:braceexpand,大括号扩展

        

        H:history,H选项打开,可以展开历史列表中的命令,可以通过!来完成,

               例如!!,返回最近的一个历史命令,!n  返回第n个历史命令

               

练习:

        1、让所有用户的PATH环境变量的值多出一个路径,例如:

        /usr/local/apache/bin

?    2、用户root登录时,将命令指示符变成红色,并自动启用如下别名:

        rm=‘rm –i’

        cdnet=‘cd  /etc/sysconfig/network-scripts/’

        editnet=‘vim  /etc/sysconfig/network-scripts/ifcfg-eth0’

        editnet=‘vim /etc/sysconfig/network-scripts/ifcfg-eno16777736  或 ifcfg-ens33 ’ (如果系

        统是CentOS7)

?    3、任意用户登录系统时,显示红色字体的警示提醒信息“Hi,dangerous!”

?    4、编写生成脚本基本格式的脚本,包括作者,联系方式,版本,时间,描述等

?    5、编写用户的环境初始化脚本reset.sh,包括别名,登录提示符,vim的设置,

环境变量等

        

        

笔记整理完成时间:2018年4月13日16:58:39     

        

        

 


第七章,shell编程基础

标签:shell   脚本   shell编程   

原文地址:http://blog.51cto.com/13683480/2103123

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!