Linux 下Shell的学习

1.Shell学习

1.什么是Shell
    shell是一个命令解析器,在操作系统的最外层,负责和用户对话,将用户的输入解释给操作系统,并处理各种各样的操作系统的输出结果。
2.什么是shell脚本
    当命令捉着语句不在命令行执行,而是通过一个程序文件执行的时候,改程序就是shell程序。
3.需要注意的是ishell是包含命令,变量,流行和控制语句的脚本
4.Shell脚本擅长处理纯文本类型的数据,
    Rsync Nfs Crond Ssh key 基础命令 Apache Mysql Php Nginx Lvx+keepalive + Iptables +Cacti/流量监控
5.Shell脚本语言种类
    UNINX主要包括2大类:
        Bourne shell(sh,ksh,bash)  ->bash主流
        C shell(csh, tcsh)
    Linux的默认是Bash      -->标准的
    echo $SHELL            -->/bin/bash
        也可以通过cat /etc/passwd 查看一个用户对应的shell

6.Shell与PHP,Perl,Pph语言的差别:
    Shell的优势在于快速的处理操作系统底层业务(大量的命令作支撑)
         一键安装,报警脚本,常规的业务,shell更简单
    Python:开发运维工具,WEB的管理界面,自动化等有优势
7.常见的Linux脚本语言解析
    #!/bin/sh
    #!/bin/bash
    #!/bin/awk
    #!/bin/perl
    #!/usr/bin/env python

2. Shell脚本的建立

0.shell脚本规范
    1.#!/bin/sh 开头
    2.添加注释
    3.开头添加版本信息
    4.每次dos2unix格式化脚本  -->cat -v *.sh  可以查看
1.shell脚本(bash shell程序)中编写
    脚本开头,指定哪个解析器来执行脚本的内容
    默认是/bin/sh,且必须是第一行
    如果环境没有,则必须在使用的时候指定解析器  sh h.sh 或 python h.py
        #!/bin/bash            -->必须是第一行,默认bash,如果环境没有,则必须在是用的时候指定解析器
            ==> #!/bin/sh      -->必须是第一行
                ll /bin/sh     -->/bin/sh 是bash的链接文件,实为同一文件
2.脚本的执行
    1.原理:
        当shell脚本非交互式运行的时候,会开始寻找环境变量ENV,找到指定的(.bashrc)文件,然后从该环境变量中执行脚本内容
    2.shell脚本常用的方式
        1.bash *.sh     |  sh *.sh
        2./bin/sh *.sh  |  ./*.sh(当前路径下)
        3.source *.sh   |  . *.sh(用点读入或者加载指定的脚本)
            -->source的作用是传递变量值到当前shell
            -->我们写的*.sh本事就是一个shell,但是在脚本shell里面的结果,不会传递给当前shell,所以使用将脚本shell里面的变量定义传递给我们看到的shell去呈现
               所以使用点号可以将子脚本的结果作为输入传递到我们看到的shell里面
               实际例子: vim /etc/init.d/nfs  -->里面调用函数库的时候就是使用点调用的
                           在一个脚本里面加载/调用另一个脚本里面的变量的时候,必须用点或者source

3.Shell变量的基础及深入

1.全局变量
    环境变量(全局变量):定义shell的运行环境,可以再创建他们的shell以及派生出来的任意子进程shell中使用
        例如:用户名,命令路径等,全局使用,每次用户登录均会初始化
        修改全局变量:  用户家目录下 ~/.bash_profile
                        /etc/profile
                        /etc/profile.d/
                        /etc/bashrc
        全局变量生效:source /etc/bashrc  
                        ==>  . /etc/bashrc
        全局变量查看:set
                        set可以像命令行一样设置传参
                        set -- "I am"  a student  -->3个参数
                        env
        取消全局变量:unset USER

        自定义全局变量:
            1.在修改全局变量的文件内使用export命令:
                vi /etc/profile
                    export ftl ="Come on Ftl,Ha";      -->第一种方法
                    ftl = "Second Method " export ftl  -->第二种方法
                source vi /etc/profile
                echo $ftl

局部变量:只能在创建他们的shell脚本中使用,用户创建,专用shell变量
    $a = ${a}

2.导出变量名:
    export: 设置或显示环境变量
        在shell中执行程序时,shell会提供一组环境变量。
        export可新增,修改或删除环境变量,供后续执行的程序使用。
        export的效力仅及于该次登录操作。
        export 变量名=value
    其他:
        变量名=value; export 变量名
        declare -x 变量名=value

3.单引号,双引号,不加引号的区别:
    一般情况下:
        单引号:输入即输出
        双引号:解析变量名,不扩展正则
        不加引号:连续字符串,与双引号无差异,如果字符串含有空格,则不能完整输出
    特殊情况下:
        awk: 单引号会解析变量,双引号则不能
    建议:
        1.直接定义:       ftl = 22
        2.有空格,双引号: ftl = "Come on boy"
        3.输入即输出,单引号
        4.变量名大写字母
        5.引用时${FTL}或者“$(FTL)”
        6.脚本中的局部变量:以local声明,只在本函数内有效
          脚本中的全局变量:大写
        7.变量学习: /etc/init.d/functions
4.把命令定义为变量
    echo `date +%F`    -->反引号
    echo $(date +%F)  
    tar czvf hhh_${hhh}_ftl.tar.gz   -->容易引起误会的加大括号 :${变量名}
    推荐:平时就使用: 字符串变量用双引号括起来 “$A”或 ${A}
5.shell的特殊变量
    1.位置变量
        $0: 获取当前脚本的名称,包括路径(前台是加入了脚本绝对路径:sh /home/omd/hhh.sh)
        $n: 获取当前的脚本的第n个参数,n=1..9,大于9,则需要大括号${10}
        $*: 获取当前shell的所有参数,将所有的命令行参数视为单个字符串,相当于“$1$2$3”
        $#: 当前shell命令行中参数的总个数
        $@: 这个程序的所有参数,作为一个i整体传递、
        basename $0: 只输出脚本名称
        dirname  $0: 输出路径的名称

    2.进程状态变量:
        $$: 获取当前shell的进程号
        $?: 判断上一个命令是否成功
            0:   成功
            2:   权限拒绝
            127: 命令无效
            >128:强制结束
        $_: 在此之前执行的命令或脚本的最后一个参数
        $@: 这个程序的所有参数

           
    3.答疑$#和$@的区别:
        $*: 将所有的参数当做一个参数进行传递,"$1$2$3"
        $@: 将每个参数视为单独的字符串,等同于"$1", "$2", "$3"  3个参数

            set -- "I am"  a student          -->临时定义了3个参数,set可以像命令行一样设置传参
            echo $#                           -->输出3
            for i in $*; do echo $i; done;    -->"$*"由于未加引号,所以会解析"I am"为2个字符
            for i in $@; do echo $i; done;    -->"$@"由于未加引号,所以会解析"I am"为2个字符
            for i in ; do echo $i; done;      -->什么都不加,相当于引用了加引号的“$@”,输出 I am \n  a student
            for i in "$@"; do echo $i; done;  -->输出 I am \n  a student
            for i in "$*"; do echo $i; done;  -->输出一整行"I am a student"

    4.Bash内部命令和shift
        echo:  变量名输出到标准设备
        eval args:  读入args参数,并将他们组合成一个新的命令,然后执行
        exec 参数:  当shell执行到exec的时候,不会去创建新的子进程,而是去执行指定的命令;
                      指定的命令执行完后,该进程(最初的shell)终止。
                    所以shell程序的exec后面的语句不再被执行
        export 变量名=value,把他的变量带入子shell,从而让子进程继承父进程中的环境变量
        read:  标准读入,传递给指定变量
        wait:  等待
        sleep: 休眠
        exit:  0成功退出  1异常退出
        shift: 重新命名所有位置的参数变量,即$2变成$1,直到$#为0
        .(点): ?
        readonly: 只读变量,显示所有的只读变

    5.Shell变量的子串应用技术
        常用操作:初步测试,对原文件不生效
            hello="Hello World"
            ${#String}: 统计字符数量  echo ${#hello}" -->11 | echo ${hello} |wc -m
            ${String:position:length}:
                echo ${hello:2}   -->删除前2个字符,也即是从第三个输出到最后 -->llo world
                echo ${hello:2:2} -->删除前2个字符,取出后面的2个字符 -->ll
            ${String#substring}   -->从变量$String开头,开始删除最短匹配字符$substring子串
            ${String##substring}  -->从变量$String开头,开始删除最长匹配字符$substring子串
            ${String%substring}   -->从变量$String结尾,开始删除最短匹配字符$substring子串
            ${String%%substring}  -->从变量$String结尾,开始删除最长匹配字符$substring子串
            ${String/#substring/replace} -->如果$string前缀匹配了$substring,就用replace代替
            ${String/%substring/replace} -->如果$string后缀匹配了$substring,就用replace代替
        总结一下:
            # :从前匹配
            % :从后匹配
            ::删除字符

    6.其他变量替换;
        ${value:-word}: 如果value已定义,则显示原来的默认值         -->判断变量未定义,可以解决变量未定义问题
                        如果value未定义,则显示值为word
                            result=${test:-UNSET}      -->如果test有值,则赋值给result
                                                       -->如果test为空,则设置-UNSET给result
                           
        ${value:=word}: 如果value已定义,则显示原来的默认值
                        如果value未定义,则设置默认值为word
                            result=${test:=UNSET}     -->如果test有值,则赋值给result
                                                      -->如果test为空,则设置-UNSET给test和result

        ${value:? "not default"}:用于捕捉变量未定义而导致的错误,并退出程序
                            result=${test:?"sorry"}  -->如果test有值,则赋值给result
                                                      -->如果test为空,则显示-bash:test sorry,并退出

        ${value:+word}:测试变量是否存在,如果已经定义,则返回word
                            result=${test:+hello}     -->如果test有值,则返回hello
                                                      -->如果test为空,则返回null

        ${value-word}:去掉冒号  httpd=${HTTPD-/usr/local/httpd}    -->/etc/httpd
                      如果变量未存在,则用后面的替代

        说明:    每个运算符内的冒号都是可选的  -->用于判断测试变量是否存在
                    带帽号:存在且非null
                    去冒号:存在
                /etc/init.d/httpd
                /etc/init.d/crond
                对路径进行操作的时候,最好先进行路径判断是否为空,然后后进入目标路径删除
                    path=/home/omd
                    cd $path
                    find ${path:=/home/omd/} -name "*.txt"|xargs rm -f
                        #rm -rf ${path:=/tmp} 
                                    --->注意增加${path:=/home/omd}和omd加反斜线,防止omd目录被干掉

shell开发规范

1.指定脚本解析器
#!/bin/sh
2.开头添加版本版权等信息
#Date     2017-0905-21:00
#Author   Lvfengtao
#Mail     ws415659
#Function This script is for MysqlBakcup
#Version  V1.1.1
    可以配置Vim的品配置文件 ~/.vimrc添加2的内容
3.脚本尽量少用中文注释
4.脚本以*.sh结尾
5.代码书写优秀习惯
    1.成对的内容一起输出
        {} [] '' "" ``
    2.[]括号的2端必须有空格,书写时[  ],退格在书写[ fsfs ]
    3.if语句格式一次成型
        if 条件内容
            then
                内容
        fi
    4.for 循环一次成型
        for n in list
            do
                内容
            done;
6.通过缩写让代码易读


【更多参考】

Linux 下Shell的学习2

Linux 下Shell的学习3-demo

Linux 下shell中exec解析

posted @ 2018-07-14 17:34  小a玖拾柒  阅读(736)  评论(0编辑  收藏  举报