shell脚本编程:

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

    编译运行:源代码--》编译器(编译)--》程序文件

    解释运行:源代码--》运行时启动解释器,又解释器边解释边运行

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

    shell脚本编程:
      利用系统上的命令及编程组件进行编程;
    完整编程:
      利用库或编程组件进行编程;

  编程模型:过程式编程语言,面向对象的编程语言
    程序=指令+数据
      过程式:以指令为中心来组织代码,数据是服务于代码;
        顺序执行
        选择执行
        循环执行
        代表:C,bash
      对象式:以数据为中心来组织代码,围绕数据来组织指令;
        类(class):实例化对象,method;
        代表:Java, C++, Python

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

    如何写shell脚本:
      脚本文件的第一行,顶格:给出shebang,解释器路径,用于指明解释执行当前脚本的解释器程序文件
        常见的解释器:
          #!/bin/bash
          #!/usr/bin/python
          #!/usr/bin/perl

    文本编程器:nano
      行编辑器:sed
      全屏幕编程器:nano, vi, vim

    shell脚本是什么?
      命令的堆积;
      但很多命令不具有幂等性,需要用程序逻辑来判断运行条件是否满足,以避免其运行中发生错误;

    运行脚本:
      (1) 赋予执行权限,并直接运行此程序文件;
        chmod +x /PATH/TO/SCRIPT_FILE
        /PATH/TO/SCRIPT_FILE
      (2) 直接运行解释器,将脚本以命令行参数传递给解释器程序;
        bash /PATH/TO/SCRIPT_FILE

    注意:脚本中的空白行会被解释器忽略;
       脚本中,除了shebang,余下所有以#开头的行,都会被视作注释行而被忽略;此即为注释行;
       shell脚本的运行是通过运行一个子shell进程实现的;

练习1:写一个脚本,实现如下功能;
(1) 显示/etc目录下所有以大写p或小写p开头的文件或目录本身;
(2) 显示/var目录下的所有文件或目录本身,并将显示结果中的小写字母转换为大写后显示;
(3) 创建临时文件/tmp/myfile.XXXX;

  bash的配置文件:
    两类:
      profile类:为交互式登录的shell进程提供配置

        全局:对所有用户都生效;
          /etc/profile 
          /etc/profile.d/*.sh

        用户个人:仅对当前用户有效;
          ~/.bash_profile

        功用:
          1、用于定义环境变量;
          2、运行命令或脚本;
      bashrc类:为非交互式登录的shell进程提供配置

        全局:
          /etc/bashrc 
        用户个人:
          ~/.bashrc

        功用:
          1、定义本地变量;
          2、定义命令别名;

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

    登录类型:
      交互式登录shell进程:
        直接通过某终端输入账号和密码后登录打开的shell进程;
        使用su命令:su - USERNAME, 或者使用 su -l USERNAME执行的登录切换;
        /etc/profile --> /etc/profile.d/* --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc

      非交互式登录shell进程:
        su USERNAME执行的登录切换;
        图形界面下打开的终端;

        ~/.bashrc --> /etc/bashrc --> /etc/profile.d/*
        运行脚本


      命令行中定义的特性,例如变量和别名作用域为当前shell进程的生命周期;
      配置文件定义的特性,只对随后新启动的shell进程有效;

      让通过配置文件定义的特性立即生效:
        (1) 通过命令行重复定义一次;
        (2) 让shell进程重读配置文件;
          ~]# source /PATH/FROM/CONF_FILE
          ~]# . /PATH/FROM/CONF_FILE

bash脚本编程
 
    脚本文件格式:
        第一行,顶格:#!/bin/bash
        注释信息:#
        代码注释:
        缩进,适度添加空白行;
         
    语言:编程语法格式,库,算法和数据结构
    编程思想:
        问题空间 --> 解空间
         
    变量:
        局部变量
        本地变量
        环境变量
         
        位置参数变量
        特殊变量
         
    数据类型:字符型、数值型
        弱类型:字符型
         
    算术运算:
        +, -, *, /, %, **
         
        let  VAR=expression
        VAR=$[expression]
        VAR=$((expression))
        VAR=$(expr argu1 argu2 argu3)
         
        注意:有些时候乘法符号需要转义;
         
        增强型赋值:
            变量做某种算术运算后回存至此变量中;
                let i=$i+#
                let i+=#
                 
            +=,-=,*=, /=, %=
             
            自增:
                VAR=$[$VAR+1]
                let  VAR+=1
                let  VAR++
                 
            自减:
                VAR=$[$VAR-1]
                let  VAR-=1
                let  VAR--
                 
    练习:
        1、写一个脚本
            计算/etc/passwd文件中的第10个用户和第20个用户的id号之和;
                id1=$(head -10  /etc/passwd | tail -1  | cut  -d:  -f3)
                id2=$(head -20   /etc/passwd | tail -1  | cut  -d:  -f3)
                 
             
        2、写一个脚本
            计算/etc/rc.d/init.d/functions和/etc/inittab文件的空白行数之和;
             
                grep "^[[:space:]]*$"   /etc/rc.d/init.d/functions | wc -l
                 
    条件测试:
        判断某需求是否满足,需要由测试机制来实现;
         
        如何编写测试表达式以实现所需的测试:
            (1) 执行命令,并利用命令状态返回值来判断;
                0:成功
                1-255:失败
            (2) 测试表达式
                test  EXPRESSION
                [ EXPRESSION ]
                [[ EXPRESSION ]]
                 
                注意:EXPRESSION两端必须有空白字符,否则为语法错误;
                 
        bash的测试类型:
            数值测试
            字符串测试
            文件测试
             
            数值测试:数值比较
                -eq:是否等于; [ $num1 -eq $num2 ]
                -ne:是否不等于;
                -gt:是否大于;
                -ge:是否大于等于;
                -lt:是否小于;
                -le:是否小于等于;
                 
            字符串测试:
                ==:是否等于;
                >:是否大于;
                <:是否小于;
                !=:是否不等于;
                =~:左侧字符串是否能够被右侧的PATTERN所匹配;
                 
                -z "STRING":判断指定的字串是否为空;空则为真,不空则假;
                -n "STRING":判断指定的字符串是否不空;不空则真,空则为假;
                 
                注意:
                    (1) 字符串要加引用;
                    (2) 要使用[[ ]];
                     
            文件测试:
                存在性测试
                    -a  FILE
                    -e  FILE
                        文件的存在性测试,存在则为真,否则则为假;
                存在性及类型测试
                    -b  FILE:是否存在并且为 块设备 文件;
                    -c  FILE:是否存在并且为 字符设备 文件;
                    -d  FILE:是否存在并且为 目录文件;
                    -f  FILE:是否存在并且为 普通文件;
                    -h  FILE或 -L  FILE:是否存在并且为 符号链接文件;
                    -p FILE:是否存在且为 命名管道文件;
                    -S  FILE:是否存在且为 套接字文件;
                文件权限测试:
                    -r  FILE:是否存在并且 对当前用户可读;
                    -w  FILE:是否存在并且 对当前用户可写;
                    -x  FILE:是否存在并且 对当前用户可执行;
                特殊权限测试:
                    -u  FILE:是否存在并且 拥有suid权限;
                    -g  FILE:是否存在并且 拥有sgid权限;
                    -k  FILE:是否存在并且 拥有sticky权限;
                文件是否有内容:
                    -s  FILE:是否有内容;
                时间戳:
                    -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
                         
                        [ -O FILE ] && [ -r FILE ]
                         
                    第二种方式:
                        EXPRESSION1  -a  EXPRESSION2
                        EXPRESSION1  -o  EXPRESSION2
                        ! EXPRESSION
                         
                        [ -O FILE -a -x FILE ]
                         
                练习:将当前主机名称保存至hostName变量中;
                    主机名如果为空,或者为localhost.localdomain,则将其设置为www.magedu.com;
                     
                    hostName=$(hostname)
                     
                    [ -z "$hostName" -o "$hostName" == "localhost.localdomain" -o "$hostName" == "localhost" ] && hostname www.magedu.com                  
                     
        脚本的状态返回值:
            默认是脚本中执行的最后一条件命令的状态返回值;
            自定义状态退出状态码:
                exit  [n]:n为自己指定的状态码;
                    注意:shell进程遇到exit时,即会终止,因此,整个脚本执行即为结束;
                     
    向脚本传递参数:
        位置参数变量
         
        myscript.sh  argu1 argu2
            引用方式:
                $1,  $2, ..., ${10}, ${11}, ...
                 
            轮替:
                shift  [n]:位置参数轮替;
                 
        练习:写一脚本,通过命令传递两个文本文件路径给脚本,计算其空白行数之和;
             
            #!/bin/bash
            #
            file1_lines=$(grep "^$" $1 | wc -l)
            file2_lines=$(grep "^$" $2 | wc -l)
 
            echo "Total blank lines: $[$file1_lines+$file2_lines]" 
             
    特殊变量:
        $0:脚本文件路径本身;
        $#:脚本参数的个数;
        $*:所有参数
        $@:所有参数
 
    过程式编程语言的代码执行顺序:
        顺序执行:逐条运行;
        选择执行:
            代码有一个分支:条件满足时才会执行;
            两个或以上的分支:只会执行其中一个满足条件的分支;
        循环执行:
            代码片断(循环体)要执行0、1或多个来回;
             
        选择执行:
            单分支的if语句:
                if  测试条件
                then
                    代码分支
                fi
             
            双分支的if语句:
                if  测试条件; then
                    条件为真时执行的分支
                else
                    条件为假时执行的分支
                fi
                 
        示例:通过参数传递一个用户名给脚本,此用户不存时,则添加之;
            #!/bin/bash
            #
            if ! grep "^$1\>" /etc/passwd &> /dev/null; then
                useradd $1
                echo $1 | passwd --stdin $1 &> /dev/null
                echo "Add user $1 finished."
            fi 
             
            #!/bin/bash
            #
            if [ $# -lt 1 ]; then
                echo "At least one username."
                exit 2
            fi
 
            if ! grep "^$1\>" /etc/passwd &> /dev/null; then
                useradd $1
                echo $1 | passwd --stdin $1 &> /dev/null
                echo "Add user $1 finished."
            fi     
                 
            #!/bin/bash
            #
            if [ $# -lt 1 ]; then
                echo "At least one username."
                exit 2
            fi
 
            if grep "^$1\>" /etc/passwd &> /dev/null; then
                echo "User $1 exists."
            else
                useradd $1
                echo $1 | passwd --stdin $1 &> /dev/null
                echo "Add user $1 finished."
            fi         
             
        练习1:通过命令行参数给定两个数字,输出其中较大的数值;
            #!/bin/bash
            #
            if [ $# -lt 2 ]; then
                echo "Two integers."
                exit 2
            fi
 
            if [ $1 -ge $2 ]; then
                echo "Max number: $1."
            else
                echo "Max number: $2."
            fi
 
             
            #!/bin/bash
            #
 
            if [ $# -lt 2 ]; then
                echo "Two integers."
                exit 2
            fi
 
            declare -i max=$1
 
            if [ $1 -lt $2 ]; then
                max=$2
            fi
 
            echo "Max number: $max."
                     
        练习2:通过命令行参数给定一个用户名,判断其ID号是偶数还是奇数;
        练习3:通过命令行参数给定两个文本文件名,如果某文件不存在,则结束脚本执行;
            都存在时返回每个文件的行数,并说明其中行数较多的文件;
         
         
    练习:
        1、创建一个20G的文件系统,块大小为2048,文件系统ext4,卷标为TEST,要求此分区开机后自动挂载至/testing目录,且默认有acl挂载选项;
            (1) 创建20G分区;
            (2) 格式化:
                mke2fs -t ext4 -b 2048 -L 'TEST' /dev/DEVICE
            (3) 编辑/etc/fstab文件
            LABEL='TEST'    /testing    ext4    defaults,acl    0 0
 
        2、创建一个5G的文件系统,卷标HUGE,要求此分区开机自动挂载至/mogdata目录,文件系统类型为ext3;
 
        3、写一个脚本,完成如下功能:
            (1) 列出当前系统识别到的所有磁盘设备;
            (2) 如磁盘数量为1,则显示其空间使用信息;
                否则,则显示最后一个磁盘上的空间使用信息;
                if [ $disks -eq 1 ]; then
                    fdisk -l /dev/[hs]da
                else
                    fdisk -l $(fdisk -l /dev/[sh]d[a-z] | grep -o "^Disk /dev/[sh]d[a-]" | tail -1 | cut -d' ' -f2)
                fi
 
 
bash脚本编程之用户交互:
    read [option]... [name ...]
        -p 'PROMPT'
        -t TIMEOUT
 
    bash -n /path/to/some_script
        检测脚本中的语法错误
 
    bash -x /path/to/some_script
        调试执行
 
    示例:
        #!/bin/bash
        # Version: 0.0.1
        # Author: MageEdu
        # Description: read testing
 
        read -p "Enter a disk special file: " diskfile
        [ -z "$diskfile" ] && echo "Fool" && exit 1
 
        if fdisk -l | grep "^Disk $diskfile" &> /dev/null; then
            fdisk -l $diskfile
        else
            echo "Wrong disk special file."
            exit 2
        fi

【Linux】【Shell】【Basic】Programming的更多相关文章

  1. 【Linux下自定义Shell终端提示符】

    目录 基本转义符 字体颜色 背景颜色 移动光标 @ Linux系统终端提示符的特征由系统环境变量 PS1(Prompt String One)定义. 我们可以通过命令echo $PS1来查看当前设置, ...

  2. 【linux之挂载,Raid,LVM】

    一.挂载,卸载 挂载:将新的文件系统关联至当前根文件系统卸载:将某文件系统与当前根文件系统的关联关系移除 cat /etc/mtab 存储着已经挂载的文件系统 (跟 mount 一样) mount:显 ...

  3. 【Linux&amp;Unix--open/close/write/read系统调用】

    个人学习整理.如有不足之处,请不吝不吝赐教. 转载请注明:@CSU-Max 系列博文:      Linux&Unix学习第一弹 -- 文件描写叙述符与权限  Linux&Unix学习 ...

  4. 【linux之设备,分区,文件系统】

    一.设备 IDE磁盘的设备文件采用/dev/hdx来命名,分区则采用/dev/hdxy来命名,其中x表示磁盘(a是第一块磁盘,b是第二块磁盘,以此类推), y代表分区的号码(由1开始,..3以此类推) ...

  5. 【linux之进程管理,系统监控】

    一.进程管理 前台进程:一般是指占据着标准输入和/或标准输出的进程后台进程:不占据默认开启的进程都是前台进程ctrl+C 中断ctrl+z 从前台转入后台bg 后台进程编号 让其在后台运行ls -R ...

  6. 【python中调用shell命令使用PIPE】使用PIPE作为stdout出现假卡死的情况——将stdout重定向为输出到临时文件

    在Python中,调用:subprocess.Popen(cmd, stdout = PIPE, stderr = PIPE, shell= true)的时候,如果调用的shell命令本身在执行之后会 ...

  7. 【Linux运维-集群技术进阶】Nginx+Keepalived+Tomcat搭建高可用/负载均衡/动静分离的Webserver集群

    额.博客名字有点长.. . 前言 最终到这篇文章了,心情是有点激动的. 由于这篇文章会集中曾经博客讲到的全部Nginx功能点.包含主要的负载均衡,还有动静分离技术再加上这篇文章的重点.通过Keepal ...

  8. 【Linux磁盘优化管理--RAID和LVM】

    在现阶段的企业环境中,为了数据的安全性及完整性必须要有一个合理的存储方案.面对着每秒可能产生超过几TB的数据,考虑到磁盘能不能实现 热冗余,及扩容,缩容.Linux给出了RAID(磁盘阵列)以及LVM ...

  9. 【Linux 内核网络协议栈源码剖析】网络栈主要结构介绍(socket、sock、sk_buff,etc)

    原文:http://blog.csdn.net/wenqian1991/article/details/46700177 通过前面的分析,可以发现,网络协议栈中的数据处理,都是基于各类结构体,所有有关 ...

  10. 【linux之链接,函数,随机数】

    一.链接 硬链接(hard link):同一个文件使用了多个别名.新建文件是已经存在的一个别名,,当原文件删除时,新建的文件仍然可以使用.硬链接和原来的文件没有什么区别,而且共享一个inode号.通过 ...

随机推荐

  1. IP基础 & 子网划分 & 路由寻址

    IP地址详解 IP地址概念 就像用身份证号码来区别毎个人一样,为了区别 网上的每台计算机,我们给因特网上的每一台计算机一个唯一的编号 ,我们把它称为IP地址 IP地址就是一个唯一标识 ,是一段网络编码 ...

  2. Python基础入门(1)- Python环境搭建与基础语法

    Python编程环境搭建 Python环境搭建 官网下载:https://www.python.org/ python --version PyCharm下载安装 安装 官网下载:https://ww ...

  3. leetcode 剪绳子系列

    ### 剪绳子一 利用动态规划 状态转移方程 为啥是这个样子?首先  代表 长度为i的绳子被剪去j,且继续剪(子问题)  表示长度为i的绳子被剪去j,不剪了的乘积 注意初始化: n<2 f=0 ...

  4. PTA7-1 迷宫寻路 (20分)

    7-1 迷宫寻路 (20分) 给定一个M行N列的迷宫图,其中 "0"表示可通路,"1"表示障碍物,无法通行.在迷宫中只允许在水平或上下四个方向的通路上行走,走过 ...

  5. 解决一个C#中定时任务被阻塞问题

    解决一个C#中定时任务被阻塞问题 目录 解决一个C#中定时任务被阻塞问题 1.摘要 2.C#中定时任务的最简方法 3.定时任务阻塞现象 4.阻塞现象原因分析 5.问题解决 1.摘要 本文会介绍一个C# ...

  6. GO语言数据结构之链表

    链表是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的.链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成.每个结点包括两个部分: ...

  7. WPF仿Tabcontrol加载切换多个不同View

    在同一块区域显示不同的视图内容,直接使用Tabcontrol,可能要重写TabItem的控件模板,最直接的方法通过按钮的切换,控制一个ContentControl的Content值,实现切换不同的视图 ...

  8. [bzoj5343]混合果汁

    二分枚举答案,问题转化为计算至少取到一定体积,价格最少是多少,显然是贪心取最小,用线段树维护,然后因为要判断答案,所以可持久化一下即可. 1 #include<bits/stdc++.h> ...

  9. [atARC064F]Rotated Palindromes

    (长度为$n$的序列$a_{i}$,下标范围为$[0,n)$,且用字符串的方式即$a_{[l,r]}$来表示子区间) 定义一个长为$n$的序列$a_{i}$的周期为的$l$满足$l|n$且$\fora ...

  10. [loj3278]收获

    人的移动之间会相互影响,因此不妨看成果树逆时针移动,显然果树之间独立 考虑建图:1.每一棵果树向其逆时针旋转后第一个人连边:2.每一个人向其逆时针旋转不小于$C$的第一个人连边(即下一个摘的人),边权 ...