Linux运维学习历程-第九天-bash脚本初步了解

概述:

  本章重点在于讲解bash脚本的基础知识,为今后学习使用bash脚本打下基础

一、bash基础特性

        程序:指令+数据

            指令:由程序文件提供

            数据:IO设备、文件、管道、变量

        程序:算法+数据结构

        变量:变量名+指向的内存空间

        变量赋值:name=value

        变量类型:存储格式(变量存储数据的数据类型)、表示数据范围、参与的运算

            编程语言:

                 强类型变量:变量类型不可变,是什么类型就是什么类型;例如C语言

                 弱类型变量:

                       bash把所有变量统统视作字符型

                       bash正常情况下不支持浮点型数据,除非借助其他工具

                       bash中的变量无需事先声明:相当于把声明和赋值过程同时实现

                          声明:说明数据类型,定义变量名

        变量替换(引用):把变量名出现的位置替换为其所指向的内存空间中数据

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

        变量名:变量名只能包含数字、字母和下划线,而且不能以数字开头

            变量名:见名知义,命名机制遵循某种法则:不能够使用程序的保留字,例如if,else,then,while等等

        bash变量类型:根据作用范围划分的

            本地变量:作用域范围仅为当前shell进程

            环境变量:作用域为当前shell进程及其子进程

            局部变量:作用域仅为某代码片段(函数上下文)

            位置参数变量:向执行脚本的shell进程传递的参数

            特殊变量:shell内置的有特殊功用的变量;例如$?保存上一个命令执行的状态结果

                                                       0:成功

                                                       1-255:失败

        本地变量:只对当前shell进程有效

            变量赋值:name=value

                  name=$user

                  name=`Command`

                  name=$(Command)

                 这里需要注意的是“ 和 $()的意义是不同的。

           推荐使用$()

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

                ""弱引用:变量名会替换为其值

                ''强引用:变量名不会替换为其值

            查看变量:set

            撤销变量:unset name

                注意:此处非变量引用,不加$

        环境变量:对当前进程及其子进程有效,对父进程无效(除非写进配置文件,并且重新读取配置文件)

            变量赋值:

                 (1)export name=value

                 (2)name=value

                    export name

                 (3)declare -x name=value

                 (4)name=value

                    declare -x name

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

            注意:bash内嵌了许多环境变量(通常为全大写字符),用于定义bash的工作环境

                 PATH,HISTFILE,HISTSIZE,HISTFILESIZE,HISTCONTROL,SHELL,HOME,UID,PWD,OLDPWD

            查看环境变量:export,declare -x,printenv,env

            撤销环境变量:unset name

        只读变量:不能修改和撤销

             (1)declare -r name

             (2)readonly name

             只读变量无法重新赋值,并且不支持撤销;存活时间为当前shell进程的生命周期,随shell进程终止而终止

            位置变量:见下文第二部分整理

            局部变量:对当前shell进程中的某代码片段有效(通常指函数上下文)

PATH变量定义位置:.bash_profile  –>  $PATH:$HOME/binPATH=$PATH:$HOME/.local/bin:$HOME/bin     –.local/bin  centos7普通用户有的隐藏的目录,可以放写隐藏的脚本
写脚本的时候可以先mkdir /home/bin 在bin目录下写脚本,可省去相对路径。
source bash.sh 也可以执行脚本:其执行过程相当于直接在当前shell进程中进行,而不是开一个子进程进行,所有脚本执行完,echo 变量,还可以查看到变量的值。(正常父进程是不能查看子进程的变量的)shadow 默认权限000  但是root用户属于超级用户 可读可写,但是如果文件没有x权限,root也不能执行

算数运算符bash中的算数运算符:+、-、*、/、%、**(平方) 注意:在使用expr的时候“*” 要转义“\*”实现算数运算:                let var=算数表达式                var=$[算数表达式]                var=$((算数表达式))                var=$(expr arg1 arg2 arg3)   注意:每个参数之间要用空格隔开

declare -i var =数字

echo ‘算数表达式’| bc

随机数生成器:echo $[RANDOM%50]:0-49之间的随机数                           echo $[RANDOM%50+1]:1-50之间的随机数                           $RANDOM :1-32767 聚合命令 #!/bin/bash
echo xxx;(echo zzz;exit)     ############():代表开个子shell,exit退出子shell非当前shell
echo yyy

退出状态

0 代表成功, 1-255代表失败$? 变量保存最近的命令退出状态

我们也可以指定程序退出的状态码,根据状态码的数值,来判断工作状态,脚本中一旦遇到exit命令,脚本会立即终止,终止,终止退出状态取决于exit命令后面的数字,如果没有执行exit,则取脚本最后一条命令的执行状态结果。


条件测试

测试命令:test [expression]
                   [ $a = $b ]           判断 一对[]或两对[[]] 都可以
                   [[ $a == $b ]]      两个等号也可以  
                  [ -f /bin/cat -a -x /bin/cat ]    此时必须使用 一对[]  否则会报错 数值测试:                        -gt:大于                        -ge:大于等于                        -lt:小于                        -le:小于等于                        -eq:等于                        -ne:不等于字符串测试:                          ==:是否相等                          >:大于(比较ascll码)                          <:小于                          !=:是否不等于                          =~:左侧字符串是否能够被右侧的PATTERN所匹配,注意: 此表达式一般用于[[ ]]中;                          -z “string”:判断字符串是否为空,如果为空则为真                           -n “string”:判断字符串是否为空,如果不为空则为真 注意:用于字符串比较的时候,操作数应该使用引号存在性测试:               -a file:文件存在为真,否则为假               -e file:同-a              存在性及类别测试:         -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 ] && [ -r FILE ]
第二种方式:
         EXPRESSION1 -a EXPRESSION2 并且
         EXPRESSION1 -o EXPRESSION2 或者
         ! EXPRESSION

  bash特性之多命令执行:

      ~]#COMMAND1;COMMAND2;COMMAND3;…

      逻辑运算:

          运算数:真(true,yes,on,1)

                  假(false,no,off,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,不同则为1

        短路法则:可以提前判断出结果

        ~]#COMMAND1 && COMMAND2

           COMMAND1为“假”,则COMMAND2不会再执行

           否则,COMMAND1为“真”,则COMMAND2必须执行

        ~]#COMMAND1 || COMMAND2

          COMMAND1为“真”,则COMMAND2不会再执行

           否则,COMMAND1为“假”,则COMMAND2必须执行

           示例:~]#id $username || useradd $username

       示例: ~】#id $username ||useradd $username

        shell脚本编程:

            编程语言的分类:根据运行方式

                编译运行:源代码–>编译器(编译)–>程序文件

                解释运行:源代码–>运行时启动解释器,由解释器边解释边运行

        根据其编程过程中功能的实现是调用库还是外部的程序文件

            shell脚本编程:利用系统上的命令及编程组件进行编程

            完整程序:利用库或编程组件进行编程

        编程模型:过程式编程语言,面向对象的编程语言

           程序=指令+数据

               过程式:以命令为中心来组织代码,数据是服务于代码

                       顺序执行

                       选择执行

                       循环执行

                       代表:C,bash

               对象式:以数据为中心来组织代码,围绕数据来组织指令

                       类(class):实例化对象(数据结构),method;

                       代表:java,C++,Python

        shell脚本编程:过程式编程、解释运行、依赖于外部程序文件运行;

             如何写shell脚本:

               常见的解释器:shellbang

                #!/bin/bash

                #!/user/bin/python

                #!/user/bin/perl

        文本编辑器:nano

            行编辑器:sed

            全屏幕编辑器:nano、vi、vim

        shell脚本是什么?

             命令的堆积:

               但很多命令不具有幂等性,需要用程序逻辑来判断运行条件是否满足,,以避免其运行中发生错误

        运行脚本:

           (1)赋予执行权限。并直接运行此程序文件;

                 chmod +x /PATH/SCRIPT_FILE

                 /PATH/TO/SCRIPT_FILE

           (2)直接运行解释器,将脚本以命令行参数传递给解释器程序

                bash/PATH/TO/SCRIPT_FILE

          注意:脚本中的空白行会被解释器忽略

                脚本中,除了shebang,余下所有以#开头的行,都会被视作注释行而被忽略;此即为注释行;

                shell脚本的运行是通过运行一个子shell进程实现的

    bash的配置文件:

      两类:

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

      bashrc类:为非交互式登录的shell进程提供配置

      登录类型:

          交互式登录shell进程:

              直接通过某终端输入账号和密码后登陆打开的shell进程

              使用su命令:su – USERNAME,或者使用su -l USERNAME执行的登录切换

          非交互式登录shell进程:

             su USERNAME执行的登录切换

             图像界面下打开的终端

             运行脚本(bash子进程)

    profile类:

         全局:对所有用户都生效;

            /etc/profile

            /etc/profile.d/*.sh

         用户个人:仅对当前用户有效

             ~/.bash_profile

         功用:

             1、用于定义环境变量

             2、运行命令或脚本

    bashrc类:

          全局:/etc/bashrc

          用户个人:~/.bashrc

          功用:

              1、定义本地变量

              2、定义命令别名

    注意:仅管理员可修改全局配置文件

  

    交互式登录shell进程:

          /etc/profile–>/etc/profile.d/*–>~/.bash_profile–>~/.bashrc–>/etc/bashrc

    非交互式登录shell进程:

         ~/.bashrc–>/etc/bashrc–>/etc/profile.d/* 

    命令行中定义的特性,例如变量和别名作用域为当前shell进程的生命周期

    配置文件定义的特性,只对随后新启动的shell进程有效

    让通过配置文件定义的特性立即生效:

       (1)通过命令行重复定义一次

       (2)让shell进程重读配置文件

            ~]#source /PAHT/FROM/CONF_FILE

            ~]#./PATH/FROM/CONF_FILE

    问题1:定义对所有用户都生效的命令别名,例如lftps='lftp 172.16.0.1/pub'?

    问题2:让centos用户登录时。提供其已经登录,并显示当前系统时间?

     bash的特性:hash变量

           命令hash:hash命令

           变量:

                本地变量、环境变量、局部变量、位置参数变量、特殊变量

                变量赋值:name=value,export name=value,declare -x name=value

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

                        注意:有些时候{}不能省略,例如

                myvalue=

                撤销:unset name

     bash脚本编程,运行脚本

          #!/bin/bash      shebang

          #                注释

          空白行           忽略不显示行

     bash的配置文件

         porfile类:登录式shell

         bashrc类:非登录式shell

         登录式shell:/etc/profile–>/etc/profile.d/*.sh–>~/.bash_profile–>~/.bashrc–>/etc/bashrc

         非登录式shell:~/.bashrc–>/etc/bashrc–>/etc/profile.d/*.sh

二、总结位置变量:

$1,$2.. ${10},${11}..:对应调用的第1、第2个等参数;用于让脚本在脚本代码中通过调用命令行中的传递的参数,1和2 等分别代表第一个参数和第二个参数…,shift可以替换参数

特殊变量:$?:判断执行结果0-255

     $0:表示命令本身脚本名称

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

     $*:传递给脚本的所有参数(所有参数整体一次性传递给脚本)

     $@:引用传递给脚本的所有参数(每个参数单独为一个整体一次性传递给脚本)

     $*与$@的区别:

    相同点:都是引用所有参数

    不同点:只有在双引号中体现出来
      假设你的脚本运行时你写了三个参数 分别存储在$1 $2 $3中 
      则"$*" 等价于 “$1 $2 $3" —>传递了一个参数
      而“$@" 等价于 "$1" "$2" "$3" —>传递了三个参数

例证:

wKioL1ezAdrzxVGDAACxW1TOM0o970.jpg

三、作业:

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

解决思路:

     分步拆解,将所要的信息用合理的方法先单独获取到,再整合到shell script中

主机名:有两种简单的获取方式

hostname       #hostname命令(推荐)
echo $HOSTNAME    #利用hostname命令所调用的环境变量
uname -n        #利用uname命令直接获取(基本上包括很多系统信息)

IPv4地址:利用ifconfig命令、扩展正则表达式、head命令获取

ifconfig |egrep -o "((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[1-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[1-9])"|head -1

此种方法看上去虽然很乱和繁琐,但是此公式的实用性很广,在Centos6与7中,ifconfig中获取的ip信息格式有些许不同,这就会造成我们从一个版本到另一个版本时,要调整表达式,而用上述表达式则可以尽量避免此种情况

操作系统版本:

cat /etc/redhat-release   #适用于6、7版本(推荐适用性广、直接获取到我们需要的,没有其它)
lsb_release               #适用于6
cat /etc/issue            #适用于6

内核版本:

uname -r

CPU型号:

lscpu |head -n 13|tail -n +13|cut -d: -f2|tr -s " "

内存大小:

free -h |head -2|tail -1|tr -s " "|cut -d" " -f2

硬盘大小:

lsblk -d|egrep "^sd.*"|tr -s " "|cut -d" " -f1,4

注意:在不同版本中和不同的语言环境下,命令行不一定通用,例如CPU型号,我的centos7安装了中文环境,在不调整语言环境和命令行的情况下是与centos6英文版,不通用,所以大家要多多注意

根据上面的信息逐一获取方法我们可以编写以下内容作为/root/bin/systeminfo.sh脚本

vim /root/bin/systeminfo.sh

wKiom1ex3BvD9xbmAAGPT2mMy_Y768.jpg

wKioL1ex3Dihdq9LAAA8Z-vYwn8431.jpg

wKiom1ex3DnyyjGfAACQwcXaOeE323.jpg

注意:在运行之前需要给脚本添加执行权限哦

chmod +x /root/bin/systeminfo.sh

这样就可以直接运行脚本文件了

直接运行

绝对路径:/root/bin/systeminfo.sh

相对路径:./systeminfo.sh

不赋予执行权限就只能再打开一个bash子进程解析运行此脚本了,但是注意结果能得到,但是在我们以后用配置脚本的话,则不见用用此方法,因为子进程运行的变量是不能影响父进程的

间接运行:

bash /root/bin/systeminfo.sh

以下每题都是默认赋予执行权限我就不说了

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

wKioL1eyrifC_a2tAAE0ZJlzUF0021.jpg

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

wKioL1eyrkKBRc0zAAFXu3ivfsE757.jpg

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

wKioL1eyrmSzqTKOAAFVCh0q8EU853.jpg

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

wKioL1eyrn6TPeufAAF4dq-Feto236.jpg

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

wKiom1eyrpuCxZIgAAFwz7VjVaw872.jpg

7、写一个脚本/root/bin/sumfile.sh,统计/etc, /var, /usr目录中共有多少个一级子目录和文件

wKioL1eyswuSHYYMAAFIcsJrdak625.jpg

wKioL1eyswuRLFlWAAAfyz6B45w600.jpg

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

wKiom1eyt4uh_TGiAAFbcx2svCU569.jpg

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

wKiom1eyy83g_rRGAAGvkWzhR-U983.jpg

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

wKiom1ey1IrDiegHAACE62dmHrI480.jpg

wKioL1ey1IyCdQTBAAFWvJnwiYI529.jpg

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

wKiom1ey3XOTCuC9AAEqVZtat2Q978.jpg

wKiom1ey3XSx8i_VAAEmhBTPdyA659.jpg

12、计算1+2+3+…+100的值

echo {1..10}|tr " " "+"|bc
echo $((`echo {1..10}|tr " " "+"`))

13、计算从脚本第一参数A开始,到第二个参数B的所有数字的总和,判断B是否大于A,否提示错误并退出,是则计算之

wKiom1ey_GPzFBkUAAGlYdAt9zg207.jpg

原创文章,作者:NameLess,如若转载,请注明出处:http://www.178linux.com/36670

(0)
NameLessNameLess
上一篇 2016-08-18
下一篇 2016-08-18

相关推荐

  • 描述器

    Edit 描述器 |[Descriptors] 描述器的表现 用到3个魔术方法:__get__()、__set__()、__delete__() 方法用法: object.__get__(self,instance,owner) object.__set__(self,instance,value) object.__delete__(self,instan…

    Linux干货 2017-11-29
  • 关于大型网站技术演进的思考(十一)–网站静态化处理—动静分离策略(3)

    原文出处: 夏天的森林   前文里我讲到了网站静态化的关键点是动静分离,动静分离是让动态网站里的动态网页根据一定规则把不变的资源和经常变的资源区分开来,动静资源做好了拆分以后,我们就可以根据静态资源的特点将其做缓存操作,这就是网站静态化处理的核心思路。由此可见,网站静态化处理的核心就是动静分离和缓存两大方面,上篇我简单讲述了动静…

    Linux干货 2015-03-11
  • 计算机的组成、Linux主流三大版本的区别、Linux的哲学思想、Linux的使用格式及命令的使用简略说明,以及如何查看命令帮助、FHS目录机构

    计算机的组成极其功能? 按功能来说计算机是由运算器、控制器、I/O系统(输入、输出系统)、存储器五部分组成。 运算器:即中央处理器(CPU)作为五大部分中心的主脑,对数据进行逻辑运算或算数运算。 控制器:主要是指内存设备,将读取到的数据临时保存在内存中这个过程被成为寻址。在cpu中也有属于自己的控制器称之为CPU的寄存器来进行多指令的行。 I/O系统:输入系…

    2017-12-03
  • 如何编译源码安装

    #include <stdio.h> main() {printf(“Hello World!\n”); } gcc -o hello hello.c 在编写hello.c的时候出现问题一直找不到,后来发现是因为我安装的gcc有问题 我在安装的时候是用rpm -ivh gcc –nodeps忽略依赖关系直接安装…

    2017-08-19
  • 创建私有CA和申请证书流程

    创建私有CA和申请证书流程 由于很多时候做实验需要用到证书,就需要自己搭建一个私有CA来给自己颁发证书。同时通过整理创建CA和申请证书、吊销证书的过程加深自己的理解. PKI:Publilc Key Infrastructure 公钥基础设施:     签证机构:CA     注册机构:RA &nb…

    Linux干货 2016-12-01
  • 2016 10 19 第5天作业

    20161019第5天作业 软链接和硬链接的区别 硬链接 ①硬链接文件不能跨分区创建 ②一个硬链接文件的删除不影响其他链接的访问 ③链接文件指向的源文件被删除后,链接文件还能正常访问源文件的数据 ④硬链接的文件类型是 –  普通文件 ⑤硬链接和源文件的属性(大小,权限,时间戳,Inode号)相同 ⑥硬链接不能对目录创建 ⑦创建硬链接会增…

    Linux干货 2016-10-20

评论列表(1条)

  • 马哥教育
    马哥教育 2016-08-19 11:12

    总结的很详细,希望以后的作业能按时完成