zoukankan      html  css  js  c++  java
  • shell脚本编程基础

    一编程基础

       1程序编程风格


    程序:指令+数据

    程序编程风格:


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

    程序员把主要的精力集中在程序指令上,一步步怎么做的。比如C、C++符合人类处理事情的逻辑关系的,不过这适合简单的事情。

    对于大型的应用程序的开发这种方法是非常难的,会产生混乱。


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

    通过指令处理数据,得到我们关心的结果,程序最重要的功能是在处理数据上。

    对于大型的事是采用这种方法。比如盖大楼要雇用一些团队,把大的工作分解成小的工作。设计图纸有专门的设计院来完成,搬砖要有专门的工人。

    对于大的项目来说不太关注每个流程了。更多的考虑把任务分包给具体的人,每个团队做自己的事,做完就好,不关心做事的方式。

    就像有句话叫做只要白猫黑猫能抓住老鼠的就是好猫。

    大项目使用的是面向对象,而小项目是面向过程。我们现在编脚本还是面向过程式的。

       2程序的执行方式


    (1)计算机:运行二进制指令

    计算机只能识别二进制。计算机真的要运行一个程序,要把人类能够理解的东西转化成二进制。


    (2)编程语言:

    1低级:汇编

    汇编语言也是字符串,和机器语言是一一对应的,要把汇编语言转化成机器码进行分析。

    2高级:

    <1>编译

    <1>编译:高级语言-->编译器-->目标代码   比如java,C#

    编译型的语言要转化成二进制的内容才会执行,需要有编译器生成二进制的东西。

    比如ls命令是一个二进制的东西,是编译完了的最终结果。

    我们看里面的东西是乱码的。

    [root@centos73 ~]# cat  /bin/ls


     

    <2>解释


    <2>解释:高级语言-->解释器-->机器代码   比如shell, perl, python

    对于解释型语言,在运行的时候,系统后台有一个解释器,自动把文字的东西解释成机器代码。

    虽然也是转换成二进制的,但是是放在内存中的,不需要生成文件。

    所以感觉好像就是一个文本在运行。

    而shell里面的解释器有很多,比如bash shell。

    shell程序就是把我们所学的命令按照逻辑关系写到文本中。提供了编程能力,翻译成机器码解释执行。

    编译是要人工去做,而解释是系统自动完成的,所以在代码出现问题需要修改编译更麻烦。

    Java,C语言事先要进行编译一下,变成了看不懂的二进制的文档,而不是解释执行。

       3编程基本概念——编程逻辑处理方式

    1顺序执行。就是指令按照顺序执行。

    2循环执行。重复的执行某个指令,比如创建100个账号。

    3选择执行。当满足某个条件执行一个指令,而当满足另外一个条件的时候执行另外的指令。

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


    编程语言的基本结构:各种系统命令的组合,数据存储:变量、数组,表达式: a + b,语句:if。




    二shell脚本基础

       1shell脚本介绍

    规范的shell脚本的语法要求,包含一些命令或声明,并符合一定格式的文本文件格式要求。


    格式要求:首行shebang机制

    #在英文里面叫做sharp,!叫做bang.#!就是shebang

    第一行要告诉shell,使用的是那种shell,对于其他语言写上自己语言的类型即可。


    #!/bin/bash


    #!/usr/bin/python


    #!/usr/bin/perl 

       2shell脚本的用途

    1. 自动化常用命令,做事要3次以上建议写脚本。
    2. 执行系统管理和故障排除
    3. 创建简单的应用程序
    4. 处理文本或文件

     

     

     

     

       3shell脚本的执行原理

     

     

    当执行一个命令的时候,先判断是不是别名,内部命令。如果不是就看是否是外部命令,外部命令是对应PATH变量的路径来找的。

    在Linux里面,执行命令是不会寻找当前目录的

     

     

    而当shell脚本运行时,它会先查找系统环境变量ENV里面的PATH路径。

    该变量指定了环境文件(加载顺序一般默认是/etc/profile、.bash profile.、~/.bashrc, /etc/bashrc等),在加载了上述环境变量文件后, shell就开始执行shell脚本中的内容。


    shell脚本是从上至下、从左至右依次执行每一行的命令及语句的,即执行完了一个命令后再执行下一个。

    如果在shell脚本中遇到子脚本(即脚本嵌套)时,就会先执行子脚本的内容,完成后再返回父脚本继续执行父脚本内后续的命令及语句。


    通常情况下,在执行shell脚本时,会向系统内核请求启动一个新的进程,以便在该进程中执行脚本的命令及子shell脚本。

    基本流程如图所示:

     

     

     

     

     

     

     PATH=/root/shell_scripts:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

    注意第1个路径是我后来加的,为了执行方便

    [root@centos733 ~]# env
    XDG_SESSION_ID=1
    HOSTNAME=centos733.huawei.com
    SELINUX_ROLE_REQUESTED=
    TERM=xterm
    SHELL=/bin/bash
    HISTSIZE=1000
    SSH_CLIENT=192.168.137.34 58583 22
    SELINUX_USE_CURRENT_RANGE=
    SSH_TTY=/dev/pts/0
    USER=root
    LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:
    MAIL=/var/spool/mail/root
    PATH=/root/shell_scripts:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
    PWD=/root
    LANG=en_US.UTF-8
    SELINUX_LEVEL_REQUESTED=
    HISTCONTROL=ignoredups
    SHLVL=1
    HOME=/root
    LOGNAME=root
    SSH_CONNECTION=192.168.137.34 58583 192.168.137.73 22
    LESSOPEN=||/usr/bin/lesspipe.sh %s
    XDG_RUNTIME_DIR=/run/user/0
    _=/usr/bin/env

       4创建shell脚本的步骤

    第一步:使用文本编辑器,比如常见的vim来创建文本文件。

    第一行必须包括shell声明序列#!/bin/bash

    添加注释,注释以#开头

    第二步:运行脚本,给予执行权限,在命令行上指定脚本的绝对或相对路径。直接运行解释器,将脚本作为解释器程序的参数运行。

    由于系统默认的是使用bash,所以可以省略不写,但是把脚本拷到其他的机器上,不一定使用的是这个bash。为了避免产生BUG建议都要写。

    为了让程序更易于维护,要加注释,包括作者,版本号,功能等等。

    注意shell本身是开源的,没法加密的。

       5shell脚本规范

    脚本代码开头约定

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

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

    3、版本号

    4、更改后时间

    5、作者相关信息

    6、该程序的作用,及注意事项

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

       6shell脚本的基本结构

    第一行  #!SHEBANG

    变量 CONFIGURATION VARIABLES

    函数 FUNCTION DEFINITIONS

    主要代码 MAIN CODE

       7shell脚本执行的方式

    Shell脚本的执行通常可以采用以下几种方式


    1 bash   script-name或sh script-name

    这是当脚本文件本身没有可执行权限(即文件权限属性x位为-号)时常使用的方法,或者脚本文件开头没有指定解释器时需要使用的方法。

    推荐使用这种方法


    2 path/script-name或/script-name 

    在当前路径下执行脚本(脚本需要有执行权限),需要将脚本文件的权限先改为可执行(即文件权限属性加x位),

    具体方法为chmod +x script-name,然后通过脚本绝对路径或相对路径就可以直接执行脚本了。


    在企业生产环境中,不少运维人员在写完Shell脚本之后,由于忘记为该脚本设置执行权限,然后就直接应用了,结果导致脚本没有按照自己的意愿手动或定时执行,

    对于这一点,避免出现该问题的方法就是用第1种方法替代第2种。


    3 source script-name或. script-name

    这种方法通常是使用source或"." (点号)读入或加载指定的Shell脚本文件(如san.sh),然后,依次执行指定的Shell脚本文件san.sh中的所有语句。

    这些语句将在当前父Shell脚本father.sh进程中运行(其他几种模式都会启动新的进程执行子脚本)。

    因此,使用source或“."可以将san.sh自身脚本中的变量值或函数等的返回值传递到当前父Shell脚本father.sh中使用。

    这是它和其他几种方法最大的区别。


    source或“."命令的功能是:在当前Shell中执行source或“."加载并执行的相关脚本文件中的命令及语句,而不是产生一个子Shell来执行文件中的命令。

    注意"."和后面的脚本名之间要有空格。


    source或"."相当于PHP开发的include的功能。HTTP服务软件Apache,Nginx等配置文件里都支持这样的用法。


    4 sh<script-name或cat scripts-namelsh

    同样适用于bash,不过不常见

    不用循环语句来实现精简开机自启动服务就是通过将所有字符串拼接为命令的形式,然后经由管道交给bash操作

    注意不写路径直接执行脚本,那么就把脚本放到PATH变量里面的路径去,即使是在其他的路径也可以执行。

    [root@centos733 shell_scripts]# pwd
    /root/shell_scripts
    [root@centos733 shell_scripts]# echo  $PATH 
    /root/shell_scripts:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

    运行第1个脚本

    注意最后找一个集中的目录来存放自己写的脚本,便于查看和备份

    #!/bin/bash
    
    # Filename: hel1o.sh
    
    # Revision: 1.1
    
    # Date: 2018/06/01
    
    #Author: wangm
    
    # Description: This is the first script
    
    echo "hello world"
     

    1 bash   script-name或sh script-name

    脚本是在 shell_scripts目录下写的,但是是在root目录下执行

    [root@centos733 ~]# ll    shell_scripts/ -d
    drwxr-xr-x. 3 root root 4096 Mar 14 21:50 shell_scripts/
    [root@centos733 ~]# ll  shell_scripts/hello.sh 
    -rw-r--r--. 1 root root 161 Mar 14 21:50 shell_scripts/hello.sh
    [root@centos733 ~]# bash   hello.sh
    hello world
    [root@centos733 ~]# cat  shell_scripts/hello.sh 
    #!/bin/bash
    #Author=wang
    
    # Filename: hel1o.sh
    
    # Revision: 1.1
    
    # Date: 2018/06/01
    
    #Author: wangm
    
    # Description: This is the first script
    
    echo "hello world"

    2 path/script-name或/script-name 

    [root@centos733 ~]# ./shell_scripts/hello.sh
    -bash: ./shell_scripts/hello.sh: Permission denied
    [root@centos733 ~]# cd  shell_scripts/
    [root@centos733 shell_scripts]# pwd
    /root/shell_scripts
    
    [root@centos733 shell_scripts]# ./hello.sh
    -bash: ./hello.sh: Permission denied
    
    [root@centos733 shell_scripts]# ll  hello.sh 
    -rw-r--r--. 1 root root 161 Mar 14 21:50 hello.sh
    [root@centos733 shell_scripts]# chmod   +x  hello.sh 
    [root@centos733 shell_scripts]# ./hello.sh
    hello world
    [root@centos733 shell_scripts]# cd  
    [root@centos733 ~]# ./shell_scripts/hello.sh
    hello world
    [root@centos733 ~]# ./shell_scripts/hello.sh
    hello world
    
    [root@centos733 ~]# ll  shell_scripts/hello.sh 
    -rwxr-xr-x. 1 root root 161 Mar 14 21:50 shell_scripts/hello.sh

     3 source script-name或. script-name

    和法1一样不需要加执行权限也可以执行

    [root@centos733 ~]# .  shell_scripts/hello.sh 
    hello world
    [root@centos733 ~]# source   shell_scripts/hello.sh 
    hello world
    [root@centos733 ~]# chmod   -x  shell_scripts/hello.sh 
    [root@centos733 ~]# ll  shell_scripts/hello.sh 
    -rw-r--r--. 1 root root 161 Mar 14 21:50 shell_scripts/hello.sh
    [root@centos733 ~]# .  shell_scripts/hello.sh 
    hello world
    [root@centos733 ~]# source   shell_scripts/hello.sh 
    hello world

       8脚本语法检测和调试

    1脚本语法检测

    bash -n    /path/to/some_script   

    检测脚本中的语法错误。注意bash -n对于语法错误是可以查出来的,但是对于命令写错是不能查出来的。

    2 调试执行

    bash   -x     /path/to/some_script

    编写关于显示操作系统各种信息的脚本

    [root@centos733 shell_scripts]# cat  OS.sh 
    #!/bin/bash
    #Description: show system info
    echo   "The  host is `hostname`"
    echo   "The  kernel version is `uname -r`"
    echo   "The  CPU  is   `lscpu | grep "Model name:" | tr -s ' ' |   cut -d :  -f2`"
    cat  /proc/meminfo | head -n1 
    echo "The IP is `ifconfig   ens33 | grep netmask  | tr -s ' '  | cut -d " "  -f3`"
    

     1脚本语法检测

    [root@centos733 shell_scripts]# pwd
    /root/shell_scripts
    [root@centos733 shell_scripts]# bash  -n  OS.sh 

    2 调试执行

    跟踪每一步的执行结果。可以看出命令是分解执行的,同一行也是这样。

    命令嵌套,所以看到是先执行里面的hostname,然后执行外面的echo

    [root@centos733 shell_scripts]# bash  -x   OS.sh 
    ++ hostname
    + echo 'The  host is centos733.huawei.com'
    The  host is centos733.huawei.com
    ++ uname -r
    + echo 'The  kernel version is 3.10.0-862.el7.x86_64'
    The  kernel version is 3.10.0-862.el7.x86_64
    ++ lscpu
    ++ grep 'Model name:'
    ++ tr -s ' '
    ++ cut -d : -f2
    + echo 'The  CPU  is    Intel(R) Core(TM) i7-7500U CPU @ 2.70GHz'
    The  CPU  is    Intel(R) Core(TM) i7-7500U CPU @ 2.70GHz
    + cat /proc/meminfo
    + head -n1
    MemTotal:         997980 kB
    ++ grep netmask
    ++ cut -d ' ' -f3
    ++ tr -s ' '
    ++ ifconfig ens33
    + echo 'The IP is 192.168.137.73'
    The IP is 192.168.137.73

    因为hostname是一个命令,我们用echo调用他是要加上反引号,为了看起来更清晰,使用单引号引起来。

    显示内核版本的命令是uname   -r

    显示一下CPU的型号

    [root@centos73 ~]# lscpu
    
    Architecture:          x86_64
    
    CPU op-mode(s):        32-bit, 64-bit
    
    Byte Order:            Little Endian
    
    CPU(s):                1
    
    On-line CPU(s) list:   0
    
    Thread(s) per core:    1
    
    Core(s) per socket:    1
    
    Socket(s):             1
    
    NUMA node(s):          1
    
    Vendor ID:             GenuineIntel
    
    CPU family:            6
    
    Model:                 142
    
    Model name:            Intel(R) Core(TM) i7-7500U CPU @ 2.70GHz

    查看内存,使用命令free

    显示当前系统的地址,调用命令是要在命令的左右两边加上反单引号。

    [root@centos73 ~]# free  -h     -h, --human         show human-readable output
    
                  total        used        free      shared  buff/cache   available
    
    Mem:           992M        169M         82M         13M        739M        623M
    
    Swap:          3.0G        520K        3.0G
    [root@centos73 ~]# cat /proc/meminfo
    
    MemTotal:        1015828 kB
    
    MemFree:           84564 kB
    
    MemAvailable:     638036 kB
    
    Buffers:              36 kB
    
    Cached:           656816 kB
    
    SwapCached:          216 kB
    
    Active:           333592 kB


    作者:wang618
    出处:https://www.cnblogs.com/wang618/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。

  • 相关阅读:
    fixed与sticky的区别
    自我介绍以及web课程目标
    DOM&BOM
    web中常用单位的使用
    Oracle 使用 DBLINK详解(转载) 挪威
    Sql server 无法删除用户的处理办法(转载) 挪威
    ICMP类型
    makefile笔记
    [笔记]Makefile wildcard
    在Visual Studio 2005下配置WinPcap开发环境
  • 原文地址:https://www.cnblogs.com/wang618/p/10534404.html
Copyright © 2011-2022 走看看