精华内容
下载资源
问答
  • Linux shell 脚本编写

    千次阅读 2018-01-30 12:24:10
    1、Unix&Linux,GUN,Ubuntu,Red Hat,Fedora。 2、Linux用户管理。 —Root用户,普通用户,用户组。 —useradd,passwd,usermod,finger,sudo(su),groupadd,groups,whoami,who。 3、文件和目录操作。 ...

    知识点回顾:
    1、Unix&Linux,GUN,Ubuntu,Red Hat,Fedora。
    2、Linux用户管理。
    —Root用户,普通用户,用户组。
    —useradd,passwd,usermod,finger,sudo(su),groupadd,groups,whoami,who。
    3、文件和目录操作。
    —文件名和文件拓展名
    —层次的文件结构
    —In linux,Everything is file,if something is not file,it is ?(process)
    —文件类型:普通文件,符号链接文件,目录文件,设备文件等。
    —Touch,vim,cat,ls,pwd,cd,cp,rm,mkdir,rmdir,file。
    —Chmod,umask。
    —改变文件属主:chown。
    —改变文件用户组:chgrp。
    —其他的一些命令:more,less,tail,head,find。
    4、一个编辑器vi(vim)的使用
    —两种模式:编辑模式,命令模式。
    —Vi基本编辑功能:x, dd, i, c.
    —推出vi:q, q!, wq.

    参考资料
    1、鸟哥的linux私房菜:
    http://linux.vbird.org/linux_basic/0320bash.php#bash
    2、IBM shell编程系列:
    http://www.ibm.com/developerworks/cn/linux/shell/
    3、Linux Shell Scripting(详细英文文档) :
    http://bash.cyberciti.biz/guide/Main_Page

    Shell简介
    1、Shell是什么?
    Shell是系统的用户界面,提供了用户和内核进行互操作的一种接口。它接受用户的输入,并将命令传送到内核中去执行。此外,shell也能被系统中其他有效的linux实用程序和应用程序调用。
    这里写图片描述

    2、学习shell有何用途??
    —自动化工具:自动化软件测试等
    —文本处理:sed,awk
    —批处理
    —Unix界有一句名言:“一行shell脚本胜过万行C程序”
    —求职面试的需求:有兴趣去看看阿里,百度,腾讯等公司的招聘要求。只要是面向系统的几乎全部需要熟悉linux操作系统,熟悉shell编程。

    博主这边主要是在Android系统编译打包时要用到这个shell脚本文件,基本上都是用的这个shell脚本,去操作系统文件导入,压缩,copy,move,makedir,权限修改等,所以我们很有必要去了解这个shell程序的编写

    这里写图片描述
    build.makeimage代码片段:

    if [[ ! $SUDING_BT_VERSION -ne 1 ]];then
        echo "suding bt"
        #bin
        cp -vf $AUTOCHIPS_DIR/packages/externalsysapk/SUDINGBT/bin/*  $OUTPUT_SYS/bin
        #app
        cp -vf $AUTOCHIPS_DIR/packages/externalsysapk/SUDINGBT/apk/*  $OUTPUT_SYS/app
    
        #bt tools
        cp -vrf $AUTOCHIPS_DIR/packages/externalsysapk/SUDINGBT/tools/*  $OUTPUT_SYS
    
        #for bt app save the bt power state file
        if [ ! -f $OUTPUT_DIR/data/power_status ];then
            touch $OUTPUT_DIR/data/power_status
            chmod 666 $OUTPUT_DIR/data/power_status
        fi
    
        #rm mtk apk
        rm -rf $OUTPUT_SYS/app/AutoBT.apk
        rm -rf $OUTPUT_SYS/app/AutoBTService.apk
    else
        echo " mtk bt"
        rm -rf $OUTPUT_SYS/bin/blueletd
        rm -rf $OUTPUT_SYS/bin/bt_test
        rm -rf $OUTPUT_SYS/lib/libbluelet.so
        rm -rf $OUTPUT_SYS/lib/libbt_platform.so
        rm -rf $OUTPUT_SYS/bin/serial_rate_to_file
        rm -rf $OUTPUT_SYS/lib/libserialport_bt.so
        rm -rf $OUTPUT_SYS/app/AutoBtService.apk
        rm -rf $OUTPUT_SYS/app/AutoBtClient.apk
        rm -rf $OUTPUT_SYS/app/AutoBtMusic.apk
    fi

    Shell分类:各个shell中内置命令不相同

    Bourne shell(/bin/sh) 
    C shell(/bin/csh)
    Korn shell(/bin/ksh)
    Bourne again shell(/bin/bash)
    Tenex C shell(tcsh)

    Shell中的变量和变量的设定及使用

    1、shell本地变量:本地变量只在本shell中起作用。
    —变量无需声明
    —变量调用:在变量前加,echoHOME
    —unset删除变脸赋值
    —有条件命令替换:

    ${variable: -value}
    ${variable:=value}
    ${variable: +value}
    ${variable:?message}

    2、环境变量
    —查看环境变量:env
    —常见环境变量作用(实验作业)
    —export将一个局部变量提供给shell的其他命令使用
    —修改环境变量
    3、特定变量参数

    $#:传递给脚本的参数的个数
    $*:显示所有向脚本传递的参数
    $$:脚本运行的id号
    $!:后台运行的第一个进程的id号
    $?:最后一个命令执行情况,0表示没有错误
    $@:所有参数,每次参数使用””括起来

    Shell输入输出重定向
    重定向是什么?将shell命令的标准输入,输出,错误重定向到指定的文件中。

    这里写图片描述
    stdin(0表示):<, <<
    stdout(1表示):>, >>
    stderr(2表示):2>, 2>>
    /dev/null:黑洞

    Pipe
    Pipe是什么?将一个进程的标准输出连接到另外进程的标准输入。
    这里写图片描述
    Pipe简单应用
    —cut:从文件中的每一行剪切一定量的字符,送到stdout。
    —grep
    —sort,wc,uniq
    —tee –a [file],将管道中的数据写入[file]中,同时将数据写入stdin。
    这里写图片描述

    Shell 编写
    1、打造自己的shell编程环境
    —Shell功能
    —Shell中的变量和变量设定,使用
    —个人环境变量配置
    —Shell输入输出重定向
    —Shell中pipe
    2、第一个shell程序Hello Shell
    —Shell程序结构
    —执行shell程序
    3.Shell的输入输出
    4.Shell控制结构
    if – else
    do while
    for
    5.Shell中的函数
    6.Shell脚本调试

    下面编写shell脚本,了解程序结构
    这里写图片描述
    改变文件属性:sudo chmod +x helloshell.sh
    执行该文件: ./helloshell.sh或者是sh ./helloshell.sh

    这里写图片描述

    标准输出:echo,注意转移字符,\t, \n, \”等。
    这里写图片描述
    标准输入: read,cat
    这里写图片描述

    shell控制结构

    这里写图片描述

    这里写图片描述

    这里写图片描述

    这里写图片描述

    shell中的函数

    这里写图片描述

    这里写图片描述

    其实这个shell 编程语法表现的很随意,shell程序80%的时间基本上都是用于调试的。

    It bombs with a "syntax error" message, or
    It runs, but does not work as expected (logic error)
    It runs, works as expected, but has nasty side effects (logic bomb)
    

    那么该如何调试?
    1、在任何可能出错的地方使用echo打印变量的值。
    这里写图片描述
    2、使用tee命令在关键点检查数据流
    3、设置shell运行时参数
    sh -n your_script:返回所有的语法错误
    sh -x your_script:显示所有变量的值
    4、使用图形化的调试工具
    http://bashdb.sourceforge.net/
    这里写图片描述
    5、使用assert实现

    #!/bin/bash
    # filename: assert.sh
    
    assert ()                 #  If condition false,
    {                         #+ exit from script with error message.
      E_PARAM_ERR=98
      E_ASSERT_FAILED=99
    
      if [ -z "$2" ]          # Not enough parameters passed.
      then
        return $E_PARAM_ERR   # No damage done.
      fi
    
      lineno=$2
    
      if [ ! $1 ]
      then
        echo "Assertion failed:  \"$1\""
        echo "File \"$0\", line $lineno"
        exit $E_ASSERT_FAILED
      # else
      #   return
      #   and continue executing script.
    fi
    }
    
    
    a=5
    b=4
    condition="$a -lt $b"     # Error message and exit from script.
                              #  Try setting "condition" to something else,
                              #+ and see what happens.
    # assert failure
    assert "$condition" $LINENO
    

    demo点击下载

    另附相关参考资料及教程说明:
    http://www.linuxidc.com/Linux/2013-02/79468.htm
    使用env命令查看系统中的换将变量,并解释变量对应的含义。
    http://linux.vbird.org/linux_basic/0320bash.php
    Shell下的gui(libnotify-bin)编程
    http://blog.mpathirage.com/2009/09/12/using-libnotify-in-ubuntu-9-04/

    展开全文
  • Linux shell脚本编写基础

    万次阅读 2009-05-14 15:53:00
    在进行linux测试时编写脚本是必不可少的,Shell脚本的名称可以随便定义,也不要什么后缀名,例如可以写abc,smartzip这类名称,运行时只要键入./smartzip就能运行脚本了。。每行命令开头处不用就空格也行。。 第1...

    在进行linux测试时编写脚本是必不可少的,Shell脚本的名称可以随便定义,也不要什么后缀名,例如可以写abcsmartzip这类名称,运行时只要键入

    ./smartzip就能运行脚本了。。

    每行命令开头处不用就空格也行。。

     

     

    第1部分. Linux 脚本编写基础

    1.1 语法基本介绍
    1.1.1
    开头
    程序必须以下面的行开始(必须方在文件的第一行):
    #!/bin/sh
      符号#!用来告诉系统它后面的参数是用来执行该文件的程序。在这个例子中我们使用/bin/sh来执行程序。
      当编辑好脚本时,如果要执行该脚本,还必须使其可执行。
      要使脚本可执行:
    编译 chmod +x filename 这样才能用./filename 来运行
    1.1.2
    注释
      在进行shell编程时,以#开头的句子表示注释,直到这一行的结束。我们真诚地建议您在程序中使用注释。
      如果您使用了注释,那么即使相当长的时间内没有使用该脚本,您也能在很短的时间内明白该脚本的作用及工作原理。
    1.1.3
    变量
      在其他编程语言中您必须使用变量。在shell编程中,所有的变量都由字符串组成,并且您不需要对变量进行声明。要赋值给一个变量,您可以这样写:
    #!/bin/sh
    #
    对变量赋值:
    a="hello world"
    #
    现在打印变量a的内容:
    echo "A is:"
    echo $a
    有时候变量名很容易与其他文字混淆,比如:
    num=2
    echo "this is the $numnd"
    这并不会打印出"this is the 2nd",而仅仅打印"this is the ",因为shell会去搜索变量numnd的值,但是这个变量时没有值的。可以使用花括号来告诉shell我们要打印的是num变量:
    num=2
    echo "this is the ${num}nd"
      这将打印: this is the 2nd
    1.1.4
    环境变量

    export关键字处理过的变量叫做环境变量。我们不对环境变量进行讨论,因为通常情况下仅仅在登录脚本中使用环境变量。
    1.1.5 Shell
    命令和流程控制
    shell脚本中可以使用三类命令:


    1)Unix
    命令:
      虽然在shell脚本中可以使用任意的unix命令,但是还是由一些相对更常用的命令。这些命令通常是用来进行文件和文字操作的。

    常用命令语法及功能
      echo "some text": 将文字内容打印在屏幕上
      ls: 文件列表
      wc –l filewc -w filewc -c file: 计算文件行数计算文件中的单词数计算文件中的字符数
      cp sourcefile destfile: 文件拷贝
      mv oldname newname : 重命名文件或移动文件
      rm file: 删除文件
      grep 'pattern' file: 在文件内搜索字符串比如:grep 'searchstring' file.txt
      cut -b colnum file: 指定欲显示的文件内容范围,并将它们输出到标准输出设备比如:输出每行第5个到第9个字符cut -b5-9 file.txt千万不要和cat命令混淆,

    这是两个完全不同的命令
      cat file.txt: 输出文件内容到标准输出设备(屏幕)上
      file somefile: 得到文件类型
      read var: 提示用户输入,并将输入赋值给变量
      sort file.txt: file.txt文件中的行进行排序
      uniq: 删除文本文件中出现的行列比如: sort file.txt | uniq
      expr: 进行数学运算
    Example: add 2 and 3expr 2 "+" 3
      find: 搜索文件比如:根据文件名搜索
    find . -name filename -print
      tee: 将数据输出到标准输出设备(屏幕) 和文件比如:
    somecommand | tee outfile
      basename file: 返回不包含路径的文件名比如: basename /bin/tux将返回
    tux
      dirname file: 返回文件所在路径比如:dirname /bin/tux将返回
    /bin
      head file: 打印文本文件开头几行

      tail file : 打印文本文件末尾几行
      sed: Sed是一个基本的查找替换程序。可以从标准输入(比如命令管道)读入文本,并将
    结果输出到标准输出(屏幕)。该命令采用正则表达式(见参考)进行搜索。不要和shell中的通配符相混淆。比如:将linuxfocus 替换为LinuxFocus cat text.file | sed 's/linuxfocus/LinuxFocus/' > newtext.file  awk: awk 用来从文本文件中提取字段。缺省地,字段分割符是空格,可以使用-F指定其他分割符。
    cat file.txt | awk -F, '{print $1 "," $3 }'
    这里我们使用,作为字段分割符,同时打印第一个和第三个字段。如果该文件内容如下: Adam Bor, 34, IndiaKerry Miller, 22, USA命令输出结果为:Adam Bor, IndiaKerry Miller, USA


    2)

    backtick
      这些不是系统命令,但是他们真的很重要。

      管道 (|) 将一个命令的输出作为另外一个命令的输入。
    grep "hello" file.txt | wc -l
      在file.txt中搜索包含有”hello”的行并计算其行数。
      在这里grep命令的输出作为wc命令的输入。当然您可以使用多个命令。
      重定向:将命令的结果输出到文件,而不是标准输出(屏幕)。
      > 写入文件并覆盖旧文件
      >> 加到文件的尾部,保留旧文件内容。
    反短斜线
     使用反短斜线可以将一个命令的输出作为另外一个命令的一个命令行参数。
    命令:
    find . -mtime -1 -type f -print
      用来查找过去24小时(-mtime –2则表示过去48小时)内修改过的文件。如果您想将所有查找到的文件打一个包,则可以使用以下脚本:
    #!/bin/sh
    # The ticks are backticks (`) not normal quotes ('):
    tar -zcvf lastmod.tar.gz `find . -mtime -1 -type f -print`

    3)流程控制

    概念: 管道, 重定向和

    1.if


      "if" 表达式 如果条件为真则执行then后面的部分:
    if ....; then
      ....
    elif ....; then
     
    ....
    else
     
    ....
    fi
    大多数情况下,可以使用测试命令来对条件进行测试。比如可以比较字符串、判断文件是否存在及是否可读等等

      通常用" [ ] "来表示条件测试。注意这里的空格很重要。要确保方括号的空格。

    [ -f "somefile" ]
    :判断是否是一个文件
    [ -x "/bin/ls" ]
    :判断/bin/ls是否存在并有可执行权限
    [ -n "$var" ]
    :判断$var变量是否有值
    [ "$a" = "$b" ]
    :判断$a$b是否相等
      执行man test可以查看所有测试表达式可以比较和判断的类型。
      直接执行以下脚本:
    #!/bin/sh
    if [ "$SHELL" = "/bin/bash" ]; then
     echo "your login shell is the bash (bourne again shell)"
    else
     
    echo "your login shell is not bash but $SHELL"
    fi
      变量$SHELL包含了登录shell的名称,我们和/bin/bash进行了比较。

    快捷操作符
    熟悉C语言的朋友可能会很喜欢下面的表达式:
    [ -f "/etc/shadow" ] && echo "This computer uses shadow passwors"
      这里 && 就是一个快捷操作符,如果左边的表达式为真则执行右边的语句。
    您也可以认为是逻辑运算中的与操作。上例中表示如果/etc/shadow文件存在则打印” This computer uses shadow passwors”。同样或操作(||)shell编程中也是可用的。这里有个例子:
    #!/bin/sh
    mailfolder=/var/spool/mail/james
    [ -r "$mailfolder" ]' '{ echo "Can not read $mailfolder" ; exit 1; }
    echo "$mailfolder has mail from:"
    grep "^From " $mailfolder
    该脚本首先判断mailfolder是否可读。如果可读则打印该文件中的"From" 一行。如果不可读则或操作生效,打印错误信息后脚本退出。这里有个问题,那就是我们必须有两个命令:
      -打印错误信息
      -退出程序
      我们使用花括号以匿名函数的形式将两个命令放到一起作为一个命令使用。一般函数将在下文提及。
      不用与和或操作符,我们也可以用if表达式作任何事情,但是使用与或操作符会更便利很多。

     

     

     

     

    2.case

    case :表达式可以用来匹配一个给定的字符串,而不是数字。
    case ... in
    ...) do something here ;;
    esac
      让我们看一个例子。 file命令可以辨别出一个给定文件的文件类型,比如:
    file lf.gz
      这将返回:
    lf.gz: gzip compressed data, deflated, original filename,
    last modified: Mon Aug 27 23:09:18 2001, os: Unix
     我们利用这一点写了一个叫做smartzip的脚本,该脚本可以自动解压bzip2, gzip zip 类型的压缩文件:
    #!/bin/sh
    ftype=`file "$1"`
    case "$ftype" in
    "$1: Zip archive"*)
      unzip "$1" ;;
    "$1: gzip compressed"*)
      
    gunzip "$1" ;;
    "$1: bzip2 compressed"*)
      
    bunzip2 "$1" ;;
    *) echo "File $1 can not be uncompressed with smartzip";;
    esac
      您可能注意到我们在这里使用了一个特殊的变量$1。该变量包含了传递给该程序的第一个参数值。

    也就是说,当我们运行:
    smartzip articles.zip
    $1
    就是字符串 articles.zip

     

    3. selsect

    select 表达式是一种bash的扩展应用,尤其擅长于交互式使用。用户可以从一组不同的值中进行选择。
    select var in ... ; do
     break
    done
    .... now $var can be used ....
    下面是一个例子:

    #!/bin/sh
    echo "What is your favourite OS?"
    select var in "Linux" "Gnu Hurd" "Free BSD" "Other"; do
        break
    done
    echo "You have selected $var"
      下面是该脚本运行的结果:

    What is your favourite OS?
    1) Linux
    2) Gnu Hurd
    3) Free BSD
    4) Other
    #? 1
    You have selected Linux

     

    4.loop

    loop表达式:
    while ...; do
    ....
    done
      while-loop 将运行直到表达式测试为真。will run while the expression that we test for is true.
    关键字"break" 用来跳出循环。而关键字”continue”用来不执行余下的部分而直接跳到下一个循环。

      
    for-loop
    表达式查看一个字符串列表 (字符串用空格分隔) 然后将其赋给一个变量:
    for var in ....; do
      ....
    done
    在下面的例子中,将分别打印ABC到屏幕上:

    #!/bin/sh
    for var in A B C ; do
      echo "var is $var"
    done
    下面是一个更为有用的脚本showrpm,其功能是打印一些RPM包的统计信息:

    #!/bin/sh
    # list a content summary of a number of RPM packages
    # USAGE: showrpm rpmfile1 rpmfile2 ...
    # EXAMPLE: showrpm /cdrom/RedHat/RPMS/*.rpm
    for rpmpackage in $*; do
     if [ -r "$rpmpackage" ];then
      
    echo "=============== $rpmpackage =============="
      
    rpm -qi -p $rpmpackage
     
    else
      
    echo "ERROR: cannot read file $rpmpackage"
     
    fi
    done
      这里出现了第二个特殊的变量$*,该变量包含了所有输入的命令行参数值。

    如果您运行showrpm openssh.rpm w3m.rpm webgrep.rpm
    此时 $* 包含了 3 个字符串,即openssh.rpm, w3m.rpm and webgrep.rpm.

     

    5. 引号

    在向程序传递任何参数之前,程序会扩展通配符和变量。这里所谓扩展的意思是程序会把通配符(比如*)替换成合适的文件名,它变量替换成变量值。为了防止程序作这种替换,您可以使用引号:让我们来看一个例子,假设在当前目录下有一些文件,两个jpg文件, mail.jpg tux.jpg
    1.2
    编译SHELL脚本
    #ch#!/bin/sh mod +x filename
     cho *.jpg ∪缓螅梢酝ü淙耄?./filename 来执行您的脚本。
      这将打印出"mail.jpg tux.jpg"的结果。
        引号 (单引号和双引号) 将防止这种通配符扩展:
    #!/bin/sh
    echo "*.jpg"
    echo '*.jpg'
      这将打印"*.jpg" 两次。
      单引号更严格一些。它可以防止任何变量扩展。双引号可以防止通配符扩展但允许变量扩展。
    #!/bin/sh
    echo $SHELL
    echo "$SHELL"
    echo '$SHELL'
      运行结果为:
    /bin/bash
    /bin/bash
    $SHELL
      最后,还有一种防止这种扩展的方法,那就是使用转义字符——反斜杆:
    echo /*.jpg
    echo /$SHELL
      这将输出:
    *.jpg
    $SHELL

     

    6. Here documents

    当要将几行文字传递给一个命令时,here documents(译者注:目前还没有见到过对该词适合的翻译)一种不错的方法。对每个脚本写一段帮助性的文字是很有用的,此时如果我们四有那个 here documents就不必用echo函数一行行输出。 一个 "Here document" << 开头,后面接上一个字符串,这个字符串还必须出现在here document的末尾。在这里我们的字符串是“HELP”.

     

    here document 就是一段特殊目的的代码块. 他使用I/O 重定向的形式来将一个命令序列传递到一个交互程序或者命令中, 比如ftp, cat, 或者ex文本编辑器.

       1 COMMAND <<InputComesFromHERE
       2 ...
       3 InputComesFromHERE

    limit string 用来划定命令序列的范围(译者注: 两个相同的limit string之间就是命令序列). 特殊符号 << 用来表识limit string. 这个符号具有重定向文件的输出到程序或命令的输入的作用. 与 interactive-program < command-file 很相象, command-file包含:

       1 command #1
       2 command #2
       3 ...

    here document 的形式看上去是如下的样子:

       1 #!/bin/bash
       2 interactive-program <<LimitString
       3 command #1
       4 command #2
       5 ...
       6 LimitString

    选择一个名字非常诡异的limit string将会避免命令列表和limit string重名的问题.

    下面是一个例子,在该例子中,我们对多个文件进行重命名,并且使用here documents打印帮助:
    #!/bin/sh
    # we have less than 3 arguments. Print the help text:
    if [ $# -lt 3 ] ; then
    cat <<HELP
    ren -- renames a number of files using sed regular expressions
    USAGE: ren 'regexp' 'replacement' files...
    EXAMPLE: rename all *.HTM files in *.html:
     ren 'HTM$' 'html' *.HTM
    HELP
     
    exit 0
    fi
    OLD="$1"
    NEW="$2"
    # The shift command removes one argument from the list of
    # command line arguments.
    shift
    shift
    # $* contains now all the files:
    for file in $*; do
      
    if [ -f "$file" ] ; then
       
    newfile=`echo "$file" | sed "s/${OLD}/${NEW}/g"`
       
    if [ -f "$newfile" ]; then
        
    echo "ERROR: $newfile exists already"
       
    else
        
    echo "renaming $file to $newfile ..."
        
    mv "$file" "$newfile"
       
    fi
      
    fi
    done
     这是一个复杂一些的例子。让我们详细讨论一下。第一个if表达式判断输入命令行参数是否小于3 (特殊变量$# 表示包含参数的个数) 。如果输入参数小于3个,则将帮助文字传递给cat命令,然后由cat命令将其打印在屏幕上。打印帮助文字后程序退出。如果输入参数等于或大于3个,我们就将第一个参数赋值给变量OLD,第二个参数赋值给变量NEW。下一步,我们使用shift命令将第一个和第二个参数从参数列表中删除,这样原来的第三个参数就成为参数列表$*的第一个参数。然后我们开始循环,命令行参数列表被一个接一个地被赋值给变量$file。接着我们判断该文件是否存在,如果存在则通过sed命令搜索和替换来产生新的文件名。然后将反短斜线内命令结果赋值给newfile。这样我们就达到了我们的目的:得到了旧文件名和新文件名。然后使用mv命令进行重命名。

     

    4)函数
    如果您写了一些稍微复杂一些的程序,您就会发现在程序中可能在几个地方使用了相同的代码,并且您也会发现,如果我们使用了函数,会方便很多。一个函数是这个样子的:
    functionname()
    {
    # inside the body $1 is the first argument given to the function
    # $2 the second ...
    body
    }
    您需要在每个程序的开始对函数进行声明。
      下面是一个叫做xtitlebar的脚本,使用这个脚本您可以改变终端窗口的名称。
    这里使用了一个叫做help的函数。正如您可以看到的那样,这个定义的函数被使用了两次。
    #!/bin/sh
    # vim: set sw=4 ts=4 et:
    help()
    {
      cat <<HELP
    xtitlebar -- change the name of an xterm, gnome-terminal or kde konsole
    USAGE: xtitlebar [-h] "string_for_titelbar"
    OPTIONS: -h help text
    EXAMPLE: xtitlebar "cvs"
    HELP
      
    exit 0
    }
    # in case of error or if -h is given we call the function help:
    [ -z "$1" ] && help
    [ "$1" = "-h" ] && help
    # send the escape sequence to change the xterm titelbar:
    echo -e "33]0;$107"
    #
    在脚本中提供帮助是一种很好的编程习惯,这样方便其他用户(和您)使用和理解脚本。

    命令行参数
      我们已经见过$* $1, $2 ... $9 等特殊变量,这些特殊变量包含了用户从命令行输入的参数。迄今为止,我们仅仅了解了一些简单的命令行语法(比如一些强制性的参数和查看帮助的-h选项)。但是在编写更复杂的程序时,您可能会发现您需要更多的自定义的选项。通常的惯例是在所有可选的参数之前加一个减号,后面再加上参数值 (比如文件名)
    有好多方法可以实现对输入参数的分析,但是下面的使用case表达式的例子无遗是一个不错的方法。
    #!/bin/sh
    help()
    {
     cat <<HELP
    This is a generic command line parser demo.
    USAGE EXAMPLE: cmdparser -l hello -f -- -somefile1 somefile2
    HELP
     
    exit 0
    }
    while [ -n "$1" ]; do
    case $1 in
      
    -h) help;shift 1;; # function help is called
      
    -f) opt_f=1;shift 1;; # variable opt_f is set
      
    -l) opt_l=$2;shift 2;; # -l takes an argument -> shift by 2
      
    --) shift;break;; # end of options
      
    -*) echo "error: no such option $1. -h for help";exit 1;;
      
    *) break;;
    esac
    done
    echo "opt_f is $opt_f"
    echo "opt_l is $opt_l"
    echo "first arg is $1"
    echo "2nd arg is $2"
      您可以这样运行该脚本:

    cmdparser -l hello -f -- -somefile1 somefile2
      返回的结果是:
    opt_f is 1
    opt_l is hello
    first arg is -somefile1
    2nd arg is somefile2
      这个脚本是如何工作的呢?脚本首先在所有输入命令行参数中进行循环,将输入参数与case表达式进行比较,如果匹配则设置一个变量并且移除该参数。根据unix系统的惯例,首先输入的应该是包含减号的参数.

     

    2部分 实例


    现在我们来讨论编写一个脚本的一般步骤。任何优秀的脚本都应该具有帮助和输入参数。并且写一个伪脚本(framework.sh),该脚本包含了大多数脚本都需要的框架结构,是一个非常不错的主意。这时候,在写一个新的脚本时我们只需要执行一下copy命令:
    cp framework.sh myscript
     然后再插入自己的函数。
      让我们再看两个例子:
     (1) 二进制到十进制的转换
      脚本 b2d 将二进制数 (比如 1101) 转换为相应的十进制数。这也是一个用expr命令进行数学运算的例子:
    #!/bin/sh
    # vim: set sw=4 ts=4 et:
    help()
    {
     cat <<HELP
    b2h -- convert binary to decimal
    USAGE: b2h [-h] binarynum
    OPTIONS: -h help text
    EXAMPLE: b2h 111010
    will return 58
    HELP
     
    exit 0
    }
    error()
    {
      
    # print an error and exit
      
    echo "$1"
      
    exit 1
    }
    lastchar()
    {
      
    # return the last character of a string in $rval
      
    if [ -z "$1" ]; then
        
    # empty string
        
    rval=""
        
    return
      
    fi
      
    # wc puts some space behind the output this is why we need sed:
      
    numofchar=`echo -n "$1" | wc -c | sed 's/ //g' `
      
    # now cut out the last char
      
    rval=`echo -n "$1" | cut -b $numofchar`
    }
    chop()
    {
      
    # remove the last character in string and return it in $rval
      
    if [ -z "$1" ]; then
        
    # empty string
        
    rval=""
        
    return
      
    fi
      
    # wc puts some space behind the output this is why we need sed:
      
    numofchar=`echo -n "$1" | wc -c | sed 's/ //g' `
      
    if [ "$numofchar" = "1" ]; then
        
    # only one char in string
        
    rval=""
        
    return
      
    fi
      
    numofcharminus1=`expr $numofchar "-" 1`
      # now cut all but the last char:
      
    rval=`echo -n "$1" | cut -b 0-${numofcharminus1}`
    }
    while [ -n "$1" ]; do
    case $1 in
      -h) help;shift 1;; # function help is called
      
    --) shift;break;; # end of options
      
    -*) error "error: no such option $1. -h for help";;
      
    *) break;;
    esac
    done
    # The main program
    sum=0
    weight=1
    # one arg must be given:
    [ -z "$1" ] && help
    binnum="$1"
    binnumorig="$1"
    while [ -n "$binnum" ]; do
      
    lastchar "$binnum"
      
    if [ "$rval" = "1" ]; then
        
    sum=`expr "$weight" "+" "$sum"`
      
    fi
      
    # remove the last position in $binnum
      
    chop "$binnum"
      
    binnum="$rval"
      
    weight=`expr "$weight" "*" 2`
    done
    echo "binary $binnumorig is decimal $sum"
     该脚本使用的算法是利用十进制和二进制数权值 (1,2,4,8,16,..),比如二进制"10"可以这样转换成十进制:

    0 * 1 + 1 * 2 = 2
      为了得到单个的二进制数我们是用了lastchar 函数。该函数使用wc –c计算字符个数,然后使用cut命令取出末尾一个字符。Chop函数的功能则是移除最后一个字符。
    (2)文件循环程序
      或许您是想将所有发出的邮件保存到一个文件中的人们中的一员,但是在过了几个月以后,这个文件可能会变得很大以至于使对该文件的访问速度变慢。下面的脚本rotatefile可以解决这个问题。这个脚本可以重命名邮件保存文件(假设为outmail)为outmail.1,而对于outmail.1就变成了outmail.2 等等等等...
    #!/bin/sh
    # vim: set sw=4 ts=4 et:
    ver="0.1"
    help()
    {
      
    cat <<HELP
    rotatefile -- rotate the file name
    USAGE: rotatefile [-h] filename
    OPTIONS: -h help text
    EXAMPLE: rotatefile out
    This will e.g rename out.2 to out.3, out.1 to out.2, out to out.1
    and create an empty out-file
    The max number is 10
    version $ver
    HELP
      
    exit 0
    }
    error()
    {
      
    echo "$1"
      
    exit 1
    }
    while [ -n "$1" ]; do
    case $1 in
      
    -h) help;shift 1;;
      
    --) break;;
      
    -*) echo "error: no such option $1. -h for help";exit 1;;
      
    *) break;;
    esac
    done
    # input check:
    if [ -z "$1" ] ; then
    error "ERROR: you must specify a file, use -h for help"
    fi
    filen="$1"
    # rename any .1 , .2 etc file:
    for n in 9 8 7 6 5 4 3 2 1; do
      
    if [ -f "$filen.$n" ]; then
        
    p=`expr $n + 1`
        
    echo "mv $filen.$n $filen.$p"
        
    mv $filen.$n $filen.$p
      
    fi
    done
    # rename the original file:
    if [ -f "$filen" ]; then
      
    echo "mv $filen $filen.1"
      
    mv $filen $filen.1
    fi
    echo touch $filen
    touch $filen
      这个脚本是如何工作的呢?在检测用户提供了一个文件名以后,我们进行一个91的循环。文件9被命名为10,文件8重命名为9等等。循环完成之后,我们将原始文件命名为文件1同时建立一个与原始文件同名的空文件。

     

     

     

    第3部分:调试
      最简单的调试命令当然是使用echo命令。您可以使用echo在任何怀疑出错的地方打印任何变量值。这也是绝大多数的shell程序员要花费80%的时间来调试程序的原因。Shell程序的好处在于不需要重新编译,插入一个echo命令也不需要多少时间。
      shell也有一个真实的调试模式。如果在脚本"strangescript" 中有错误,您可以这样来进行调试:
    sh -x strangescript
      这将执行该脚本并显示所有变量的值。
      shell还有一个不需要执行脚本只是检查语法的模式。可以这样使用:
    sh -n your_script
      这将返回所有语法错误

     调试shell程序过程

      用户刚编写完Shell程序中,不可避免的会有错误,这时我们可以利用Bsh中提供的跟踪选项,该选项会显示刚刚执行的命令及参数。用户可以通过set命令打开-x选项或在启动Shell使用-x选项将Shell设置成跟踪模式。例如有下面代码ice_tx:

      if [ $# -eq 0 ]
      then
        echo "usage:sumints integer list"
        exit 1
      fi
      sum=0
      until [ $# -eq 0 ]
      do
        sum='expr $sum + $1'
        shift
      done
      echo $sum

      我们用跟踪模式运行:

      $sh -x ice_tx 2 3 4
      结果显示:
      +[ 3 -eq 0 ]
      +sum=0
      +[ 3 -eq 0 ]
      +expr 0+2
      +sum=2
      +shift
      +[ 2 -eq 0 ]
      +expr 2+3
      +sum=5
      +shift
      +[ 1 -eq 0 ]
      +expr 5+4
      +sum=9
      +[ 0 -eq 0 ]
      +echo 9
      9

      从上面可以看出,跟踪模式下Shell显示执行的每一条命令以及该命令使用的变量替换后的参数值。一些控制字如if、then、until等没显示。
    展开全文
  • linux shell脚本编写[: missing `]'错误

    千次阅读 2018-11-10 14:24:20
    使用 []时,在这种的内容需要和前括号和后括号都保持一个空格 比如: 正确的写法: if[ $1="abc" ] 在这里, $1="... 是和前后的括号都保持一个空格 ...没有保持空格,就会有[: missing `]'的错误...

    使用 []时,在这种的内容需要和前括号和后括号都保持一个空格

    比如:

    正确的写法:

    if[ $1="abc" ]

    在这里, $1="abc" 是和前后的括号都保持一个空格

     

    错误的写法:

    if[$1="abc"]

    在这里,$1="abc"没有保持空格,就会有[: missing `]'的错误

    展开全文
  • 注释:脚本中需扩大的文件为vmlinux.64.noinitrd,  执行之前先将源文件copy到目录 /root下。 ============================================================  #! /bin/sh # 使用的shell为sh if [ -e /...

    昨天验证bug时,需要在原来文件的基础上生成一个固定大小的新文件,具体要求如下:

      1. 源文件 src_file, 大小为4840896 byte;

      2. 目标文件obj_file(在源文件基础上扩大),大小为5263104 byte;

     

    需要的准备工作:

      1. 获得文件大小的组合指令: ls -l src_file | awk '{print $5}',其中 ls -l src_file 用来获得src_file

          的详细信息,文件大小在第5列的位置;awk '{print $5}' 以 ls -l src_file的输出作为该指令的输入,

          将其第5列内容打印出来,即文件的大小。

      2. 扩大源文件的指令: echo /0 >> src_file, 在文件filename 最后添加null字符。

      3. 截取文件的指令: dd if=src_file out=obj_file bs=256   count=20559 注释:每次写256byte, 

          重复20559个cycle, 即 256 * 20559=5263104 byte。

     

    具体的脚本实现:

    step1:生成大于等于 5263104 bytes 的目标文件

    注释:脚本中需扩大的文件为vmlinux.64.noinitrd,

             执行之前先将源文件copy到目录 /root下。

    ============================================================

     #! /bin/sh   # 使用的shell为sh
    if [ -e /root/vmlinux.64.noinitrd ]   # 判断文件vmlinux.64.noinitrd是否存在,存在则为真
    then
            size=`ls -l /root/vmlinux.64.noinitrd | awk '{print $5}'` # 获得vmlinux.64.noinitrd大小,
                                                                                                   # 并用变量size来保存 

           while [ $size -lt 5263104 ]     # 当size小于5263104 时,条件为真

           do
                    echo /0 >> /root/vmlinux.64.noinitrd       # 在vmlinux.64.noinitrd末尾写null字符,来扩大

                                                                                   # 文件的大小,实际内容不变

          done      # 对应于while语句                    

    fi                  # 对应于if语句

    exit 0     # 退出代码,成功则为0

    ============================================================

     

    step2: 执行脚本

      root@localhost:/root> chmod 555 create_file       #此处通过改变文件的权限来实现

     root@localhost:/root> ./create_file   #执行脚本

     

    step3:截取文件大小为5263104 bytes

    一般来说step2执行后得到的目标文件vmlinux.64.noinitrd的大小并不恰好就是5263104 byte,这就需要对目标文件进行截取操作,此处使用dd命令实现。

    root@localhost:/root> dd if=vmlinux.64.noinitrd of=vmlinux.64.noinitrd.test bs=256 count=20559 #源文件和目标文件均在root目录下;如果当前目录不是root目录,则if 和of需要改为:

     if=/root/vmlinux.64.noinitrd of=/root/vmlinux.64.noinitrd.test 。(源文件和目标文件也可属于不同目录)

     

    step4: 查看目标文件的大小是确实为5263104 byte

    root@localhost:/root> ls -l vmlinux.64.noinitrd.test

     

    体会:

    最初看到要求时,只有思路,每条指令的规范等都很陌生,写过之后就想把这些常用的指令和脚本记录下来,作为以后的参考,来减少组织规范的时间。      

     

    Karen

    展开全文
  • Linux编写Shell脚本

    万次阅读 多人点赞 2018-10-08 11:22:35
    Shell脚本编写规范 Shell 中的变量 变量的算术运算 双小括号 (()) 数值运算命令的用法 let 运算命令的用法 expr 命令的用法 br 命令的用法 $[]符号的运算示例 Shell脚本的条件测试 几种条件测试语句 文件...
  • linux shell脚本编写

    2013-01-15 13:12:41
  • linux服务器 shell脚本 编写定时器

    千次阅读 2017-05-11 12:10:48
    Shell脚本,每天自动清理catalina.out日志内容 时间 2016-08-20 15:49:40 麦穗技术 ...linux编写shell脚本,每天自动清理tomcat的catalina.out文件内容, 保证catalina.out都是当天的日志。
  • Shell脚本编写实战

    千人学习 2017-10-23 16:55:25
    根据实际的案例讲解怎么编写Shell脚本,在什么场景下编写为讲解导向。 课程内容如下: 1.编写Shell脚本注意事项与编写打印字体颜色函数 2.批量创建用户 3.监控主机存活状态 4.监控CPU、内存、硬盘和网卡流量利用率 5...
  • 《Linux shell脚本编程入门》 ...尤其还收录了现在门户网站、企业等使用的主流套件CentOS(CommunityENTerpriseOperatingSystem)为基础的各种Linux命令,并以此为基础编写Linuxshell脚本编程
  • linux shell java lib(linux shell脚本加载java环境变量)
  • Linux shell脚本习题

    2019-11-13 17:42:49
    Linux shell脚本习题新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个...
  • shell脚本编写笔记

    千次阅读 2019-07-26 14:32:28
    本文主要介绍如何编写简单的shell脚本,给shell脚本传参,shell脚本获取当前运行时间,通过shell执行hql语句。
  • 第一个Shell脚本​ 打开文本编辑器,新建一个文件,扩展名为sh(sh代表shell),扩展名并不影响脚本执行,见名知意就好。输入一些代码:#!/bin/bash echo "Hello World !"​ “#!” 是一个约定的标记,它...
  • shell脚本编写思路和实例讲解

    万次阅读 多人点赞 2017-06-11 13:18:34
    shell脚本编写思路和实例... 客观讲shell脚本的简洁程度确实有些堪忧,但是在Linux运维工作中shell脚本运用得非常广,在有些场合用shell会非常有效率,所以shell脚本编写是必须掌握的技能之一,我们还不能舍弃。 方法要
  • linux编写shell脚本

    2016-12-13 11:38:54
    linux编写shell脚本
  • 准备任务,在Linux服务器下编写一个shell脚本,脚本的可以存在任何你可以访问的目录,笔者存在根目录下,如果是刚入手Linux的话,具体的shell脚本语法可以查看下面这个链接,里面有非常详细的语法...
  • Linux shell脚本之函数 Function 详解

    千次阅读 2019-07-16 23:57:50
    Linux shell脚本函数详解 函数递归 函数示例
  • shell脚本编写进度条

    2017-08-06 20:15:58
    今天我们来看看用shell脚本该如何编写。 首先,同样的创建一个后缀为.sh的文件,然后vim+文件名,进入文件开始编写代码 直接上shell脚本的进度条代码 保存退出后,就要执行了 执行脚本的方法有好几种,在这
  • linux shell 脚本编程基本语法

    千次阅读 2017-06-06 17:32:03
    linux shell 脚本编程打印ip命令: ifconfig eth0 | grep ‘inet’| awk ‘{print $2}’ 第一行:#!/bin/sh:表示有bin/sh来执行 -a:表示and,类似于C语言中的& -o:表示or,类似C语言中的| linux有很多sheel ...
  • 前言翻译自Linux Shell Scripting with Bash作者:Ken O.Burtch出版社:DEVELOPER’S LIBRARY为了学习Linux外壳编程,特地翻译此书,希望可以坚持完成,并对Linux爱好者有用,本翻译仅作学习用途,未经本人同意不得...
  • Linux shell脚本的建立与执行

    万次阅读 2016-10-14 10:02:08
    最近经常使用Linux,感觉太频繁地敲击键盘有些累了,于是想到了Shell脚本。可以把太多的命令写成一个脚本,这样每次执行一遍 shell文件,就可以省去了敲击键盘的时间。于是在网上搜了一些有关Linux下脚本编程的内容...
  • Linux shell脚本判断网络畅通 介绍 在编写shell脚本时,有的功能需要确保服务器网络是可以上网才可以往下执行,那么此时就需要有个函数来判断服务器网络状态 我们可以通过curl来访问 www.baidu.com,从而判断服务器...
  • Linux shell脚本加密

    千次阅读 2015-05-28 19:08:28
    要保护自己编写shell脚本程序,方法有很多,最简单的方法有两种:1、加密 2、设定过期时间,下面以shc工具为例说明: 一、下载安装shc工具 shc是一个加密shell脚本的工具.它的作用是把shell脚本转换为一个可执行...
  • Linux编写shell脚本执行多个命令

    千次阅读 2020-06-04 21:22:27
    Linux编写shell脚本批量执行多个命令

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 93,926
精华内容 37,570
关键字:

linuxshell脚本编写

linux 订阅