• 学习shell script


    摘要:概述、script的编写、test命令、[]判断符号、默认变量($1...)、if...then条件判断式、

    一、概述

    【什么是shell script】

    针对shell所写的脚本,将多个命令汇整起来一起执行

    可以进行类似程序的编写,并且不需要经过编译就能够执行

    利用shell的功能所写的一个“程序”,这个程序是使用纯文本文件,将一些shell的语法与命令写在里面,搭配正则表达式、管道命令与数据流重定向等功能,以达到我们所想要的处理目的。

    【用途】

    简化我们日常的工作管理

    一些服务的启动都是通过shell script进行的

    二、编写第一个Hello world程序

    【预处理】

    新建一个script文件:vi helloworld.sh

    【代码】

    1 #!bin/bash
    2 # Program:
    3 #       This is my first script.
    4 # History:
    5 # 2017-9-30 liuyu First release
    6 
    7 echo "Hello World!"
    8 exit 0
    View Code

    说明:

    #!bin/bash:声明这个script使用的shell名称

    声明这个文件内是使用bash的语法,即这个程序被执行时,它就能够加载bash的相关环境配置文件(一般来说就是non-login shell的~/.bashrc),并且执行bash使我们下面的命名能够执行。

    exit 0:告知执行结果

    我们可以利用exit这个命令来让程序中断,并且回传一个数值给系统。如“exit 0”代表离开script并且回传一个0给系统,即我们执行完这个script后,若接着执行echo $?则可得到0的值。

    【执行script程序】

    bash 文件名

    三、简单的shell script练习

    1. 交互式脚本:变量内容由用户决定

    题目:请你以read命令的用途,编写一个script,它可以让用户输入firstname与lastname,最后并且在屏幕上显示“Your full name is: ”的内容。

     1 #!bin/bash
     2 # Program:
     3 #       an easy interactive program
     4 # History:
     5 # 2017-9-30 liuyu First release
     6 
     7 
     8 read -p "Please input your firstname: " firstname
     9 read -p "please input your lastname: " lastname
    10 echo "Your full name is $firstname $lastname!"
    View Code

    2. 把日期作文件名:利用日期进行文件的创建

    题目:我希望将每天的数据备份在不同的文件里,所以就需要以每天的日期作为文件名。关键是日期怎么来!假设我要创建3个空的文件,文件名最开头由用户决定(我们假设是filename),那今天的日期是2017/9/30,我想以前天、昨天、今天的日期来创建这些文件,即filename20170928, filename20170929, dilename20170930,该如何是好?

     1 #!bin/bash
     2 # Program:
     3 #       filename is created by user's input.
     4 # History:
     5 # 2017-9-30 liuyu First release
     6 
     7 echo "I will use 'touch' to create three files."
     8 read -p "Please input your filename: " fileuser
     9 
    10 #开始判断有否配置文件名,防止用户随意按[Enter],我们默认开头为filename
    11 filename=${fileuser:-"filename"}
    12 
    13 date1=$(date --date='2 days ago' +%Y%m%d) #前两天的日期
    14 date2=$(date --date='1 days ago' +%Y%m%d)
    15 date3=$(date +%Y%m%d)                   #今天的日期
    16 file1=${filename}${date1}       #追加的方式配置文件名
    17 file2=${filename}${date2}
    18 file3=${filename}${date3}
    19 
    20 touch "$file1"  #防止有空格
    21 touch "$file2"
    22 touch "$file3"
    View Code

    说明:此程序运用了许多bash中的变量知识,所以学好shell才能轻松地编写script!

    3. 数值运算:简单的加减乘除

    题目:让用户输入两个整数,然后计算出这两个数相乘的结果。

     1 #!bin/bash
     2 # Program:
     3 #       multiply two integer.
     4 # History:
     5 # liuyu 2017-9-30 First release
     6 
     7 echo "You should input 2 integers,i will cross them!"
     8 read -p "first number: " firnum
     9 read -p "second number: " secnum
    10 total=$(($firnum*$secnum))
    11 echo "The result of $firnum*$secnum is $total."
    View Code

    四、test命令的测试功能

    1. 功能

    检测系统上面某些文件、测试文件的相关属性。

    2. 常用命令

    命令 意义
    test -e filename 该文件名是否存在
    test -f filename 该文件名是否存在且为文件
    test -e filename 该文件名是否存在且为目录
    test -S filename 该文件名是否存在且为一个Socket文件
    test -L filename 该文件名是否存在且为一个连接文件
    test -r filename 该文件名是否存在且具有“可读”的权限
    test -w filename 该文件名是否存在且具有“可写”的权限
    test -x filename 该文件名是否存在且具有“可执行”的权限
    test file1 -nt file2  判断file1是否比file2新
    test file1 -ef file2 判断file1与file2是否为同一个文件,主要用于hard link
    test n1 -eq n2 两数值相等
    test n1 -gt n2 n1大于n2
    test n1 -lt n2 n1小于n2
    test n1 -ge n2 n1大于等于n2
    test n1 -le n2 n1小于等于n2
    test -z string 判断是否为空字符串,若是,返回true
    test str1=str2  判断str1是否等于str2
    -a 两个条件同时成立,如test -r file -a -x file,则file同时具有r与x权限时,才回传true
    -o 任何一个条件成立,如test -r file -o -x file,则file具有r或x权限时,就可回传true
    ! 反向状态,如test ! -x file,当file不具有x时,才回传true

    3. 示例

    题目:写一个script,让用户输入一个文件名,要求进行下面的判断:

    这个文件是否存在,若不存在则给予一个“Filename does not exist”的信息,并中断程序;

    若这个文件存在,则判断它是个目录或文件,结果输出“Filename is regular file”或“Filename is directory”;

    判断一下,执行者的身份对这个文件或目录所拥有的权限,并输出权限数据。

     1 #!bin/bash
     2 # Program:
     3 #       A script which covers the using of test.
     4 # History:
     5 # 2017-9-30 liuyu First release
     6 
     7 echo "Please input a filename, I will check the filename's type and permission."
     8 read -p "Input a filename: " filename
     9 test -z $filename && echo "You must input a filename." && exit 0
    10 
    11 test ! -e $filename && echo "The filename '$filename' DO NOT exist" && exit 0
    12 
    13 test -f $filename && filetype="regular file"
    14 test -d $filename && filetype="directory"
    15 test -r $filename && perm="readable"
    16 test -w $filename && perm="writable"
    17 test -x $filename && perm="executable"
    18 
    19 echo "The filename: $filename is a $filetype"
    20 echo "And the permissions are : $perm"
    View Code

    五、判断符号[]的使用

    1. 功能

    数据的判断、字符串判别

    2. 用法

    命令 意义
    [ -z "$HOME" ] 判断HOME变量是否为空
    [ "$HOME" == "$var" ] 判断两个变量是否相等
    [ "$HOME" == "string" ] 判断变量的内容是否为string

    3. 示例

    题目:写一个script,要求如下:

    当执行一个程序的时候,这个程序会让用户选择Y或N;

    如果用户输入Y或y时,就显示“OK, continue”;

    如果用户输入N或n时,就显示“Oh, interrupt!”;

    如果不是Y/y/N/n之内的其他字符,就显示“I don't know what your choice is”。

     1 #!/bin/bash
     2 # Program:
     3 #       A practice with [].
     4 # History:
     5 # 2017-9-30 liuyu First release
     6 
     7 read -p "Please input (Y/N): " yn
     8 [ "$yn" == "Y" -o "$yn" == "y" ] && echo "OK, continue" && exit 0
     9 [ "$yn" == "N" -o "$yn" == "n" ] && echo "Oh, interrupt!" && exit 0
    10 echo "I don't know what your choice is." && exit 0
    View Code

    六、默认变量($0,$1...)

    1. 概述

    我们知道命令可以带有参数,而我们还需要知道的是shell script也可以在脚本文件名后面带有参数。(注意!一定是script文件喔!)

    2. 示例

    题目:重新启动系统注册表文件

    命令:/etc/init.d/syslog restart

    评讲:此命令可以重新启动/etc/init.d/syslog这个程序

    题目:承上,关闭该服务

    命令:/etc/init.d/syslog stop

    3. 用法

    文件名 opt1 opt2 opt3 opt4

        $0      $1    $2     $3    $4

    解释:执行的脚本文件名为$0这个变量,第一个接的参数就是$1。

    补充:只要我们在script里面善用$1的话,就可以很简单地立即执行某些命令功能了!

    补充:除了这些数字的变量之外,我们还有一些较为特殊的变量可以在script内使用来调用这些参数。

    $#:代表后接的参数“个数”

    $@:代表"$1"、"$2"、"$3"、"$4"之意,每个变量是独立的(用双引号括起来)

    $*:代表“"$1c$2c$3c$4"”,其中c为分隔字符,默认为空格键,所以本例中代表“"$1 $2 $3 $4"”之意

    4. 练习

    题目:假设你要执行一个可以带参数的script,执行该脚本后屏幕会显示如下的数据。

    程序的文件名

    共有几个参数

    若参数的个数小于2则告知用户参数数量太少

    全部的参数内容

    第一个参数

    第二个参数

     1 #!/bin/bash
     2 # Program:
     3 #       Default variable of shell script.
     4 # History:
     5 # 2017-10-1 liuyu First release
     6 
     7 echo "The script name is  ==> $0"
     8 echo "Total parameter number is  ==> $#"
     9 [ "$#" -lt 2 ] && echo "The number of parameter is less than 2. Stop here." && exit 0
    10 echo "Your whole parameter is  ==> '$@'"
    11 echo "The 1st parameter    ==> $1"
    12 echo "The 2nd parameter    ==> $2"
    sh07.sh

    注意:参数个数就是你执行该文件时在该文件后加的参数个数,即,若你执行“bash sh07.sh”,则参数个数为0。

    5. shift:造成参数变量号码偏移

    我们要知道的是——脚本后面所接的变量能够进行偏移。

    我们通过一个例子来说明偏移是什么。

    题目:我们将上个文件中的内容稍作变化,用来显示每次偏移后参数的变化情况。

     1 #!/bin/bash
     2 # Program:
     3 #       Default variable of shell script.
     4 # History:
     5 # 2017-10-1 liuyu First release
     6 
     7 echo "Total parameter number is  ==> $#"
     8 echo "Your whole parameter is    ==> '$@'"
     9 shift           #进行第一次“一个变量的shift”
    10 echo "Total parameter number is  ==> $#"
    11 echo "Your whole parameter is    ==> '$@'"
    12 shift 3         #进行第二次“三个变量的shift”
    13 echo "Total parameter number is  ==> $#"
    14 echo "Your whole parameter is    ==> '$@'"
    sh08.sh

    如果我们执行“bash sh08.sh one two three four five six”,我们会看到如下显示:

    分析:通过这个结果,我们知道shift会移动变量,而且shift后面可以接数字,代表拿掉最前面的几个参数的意思。

    注:“七/八/九”都属于条件判断式下的子内容。

    七、条件判断式——if...then

    1. 单层判断

    【命令】

    if [ 条件判断式 ]; then

      当条件判断式成立时,可以进行的命令工作内容;

    fi

    【条件判断式】

    当有多个条件要判别时,除了可以将多个条件写入一个中括号内的情况之外,还可以使用多个中括号,而此时每个中括号内只写入一个判断式。

    即[ "$yn" == "Y" -o "$yn" == "y" ] 可以被替换为 [ "$yn" == "Y" ] || [ "$yn" == "y" ]

    【示例】

    题目:将sh06.sh这个脚本修改成为if...then的样式

     1 #!/bin/bash
     2 # Program:
     3 #       A practice with [].
     4 # History:
     5 # 2017-9-30 liuyu First release
     6 
     7 read -p "Please input (Y/N): " yn
     8 if [ "$yn" == "Y" ] || [ "$yn" == "y" ]; then
     9         echo "OK, continue"
    10         exit 0
    11 fi
    12 if [ "$yn" == "N" ] || [ "$yn" == "n" ]; then
    13         echo "oh, interrupt!"
    14         exit 0
    15 fi
    16 echo "I don't know what your choice is." && exit 0
    sh06-2.sh

    2. 多层判断

    【命令1】

    if [ 条件判断式 ]; then

      当条件判断式成立时,可以进行的命令工作内容;

    else

      当条件判断式不成立时,可以进行的命令工作内容;

    fi

    【命令2】

    if [ 条件判断式一 ]; then

      当条件判断式一成立时,可以进行的命令工作内容;

    elif [ 条件判断式二 ]; then

      当条件判断式二成立时,可以进行的命令工作内容;

    else

      当条件判断式一与二均不成立时,可以进行的命令工作内容;

    fi

    【示例】

    题目:将sh06-2.sh这个脚本修改成为if...elif...else的样式

     1 #!/bin/bash
     2 # Program:
     3 #       A practice with [].
     4 # History:
     5 # 2017-9-30 liuyu First release
     6 
     7 read -p "Please input (Y/N): " yn
     8 if [ "$yn" == "Y" ] || [ "$yn" == "y" ]; then
     9         echo "OK, continue"
    10 elif [ "$yn" == "N" ] || [ "$yn" == "n" ]; then
    11         echo "oh, interrupt!"
    12 else
    13         echo "I don't know what your choice is."
    14 fi
    View Code

    【练习】

    题目:一般来说,如果你不希望用户由键盘输入额外的数据时,可以使用上一节提到的参数功能($1)!让用户在执行命令时就将参数代进去。现在我们想让用户输入“hello”这个关键字时,利用参数的方法可以这样依序设计:①判断$1是否为hello,如果是的话,就显示“Hello,how are you?”;②如果没有加任何参数,就提示用户必须要使用的参数;③而如果加入的参数不是hello,就提醒用户仅能使用hello为参数。

     1 #!/bin/bash
     2 # Program:
     3 #       Check $1 is equal to "hello"
     4 # History:
     5 # 2017-10-1 liuyu FIrst release
     6 
     7 if [ "$1" == "hello" ]; then
     8         echo "Hello,how are you?"
     9 elif [ "$1" == "" ]; then
    10         echo "You must input parameters,ex> {$0 someword}"
    11 else
    12         echo "The only parameter is 'hello',ex> {$0 hello}"
    13 fi
    View Code

    评讲:我们在$1的位置分别输入hello、没有输入、随意输入,就可以看到不同的输出。

    八、利用case...esac判断

    九、利用函数功能

    十、循环(loop)

    1. 条件循环

    【while do done】

    while [ condition ]    //中括号内的状态就是判断式

    do        //循环的开始

      程序段落

    done       //循环的结束

    解释:当 condition 条件成立时,就进行循环,直到 condition 的条件不成立才停止。

    【until do done】

    until [ condition ]

    do

      程序段落

    done

    解释:当 condition 条件成立时,就终止循环,否则就持续进行循环的程序段。

    【练习】

    题目1:假设我要让用户输入yes或者是YES才结束程序的执行,否则就一直进行告知用户输入字符串。

     1 #!/bin/bash
     2 # Program:
     3 #       while:Repeat question until user input correct answer.
     4 # History:
     5 # 2017-10-1 liuyu First release
     6 
     7 while [ "$yn" != "yes" -a "$yn" != "YES" ]
     8 do
     9         read -p "Please input yes/YES to stop this program: " yn
    10 done
    11 echo "OK! you input the correct answer."
    sh13.sh(while)
     1 #!/bin/bash
     2 # Program:
     3 #       until:Repeat question until user input correct answer.
     4 # History:
     5 # 2017-10-1 liuyu First release
     6 
     7 until [ "$yn" == "yes" -o "$yn" == "YES" ]
     8 do
     9         read -p "Please input yes/YES to stop this program: " yn
    10 done
    11 echo "OK! you input the correct answer."
    sh13-2.sh(until)

    题目2:计算1+2+3+...+100这个数据。

     1 #!/bin/bash
     2 # Program:
     3 #       Use loop to calculate "1+2+3+...+100" result.
     4 # History:
     5 # 2017-10-1 liuyu First release
     6 
     7 ans=0           # 这是累加的数值变量
     8 i=0             # 这是累计的数值,亦即是1,2,3...
     9 while [ "$i" != "100" ]
    10 do
    11         i=$(($i+1))
    12         ans=$(($ans+$i))
    13 done
    14 echo "The result of '1+2+3+...+100' is ==> $ans"
    sh14.sh

    题目3:让用户自行输入一个数字,让程序由1+2+...直到用户输入的数字为止。

     1 #!/bin/bash
     2 # Program:
     3 #       practice of until of page 394.
     4 # History:
     5 # 2017-10-1 liuyu First release
     6 
     7 ans=0
     8 i=0
     9 read -p "Please input a integer: " n
    10 if [ "$n" -le "0" ]; then
    11         echo "Sorry, you input a integer which isn't bigger than one!"
    12         exit 0;
    13 else
    14         until [ "$i" -eq "$n" ]
    15         do
    16                 i=$(($i+1))
    17                 ans=$(($ans+$i))
    18         done
    19         echo "The result of '1+2+3+...+$n' is ==> $ans"
    20 fi
    View Code

    2. 固定循环

    【for do done】

    for var in con1 con2 con3 ...

    do

      程序段

    done

    解释:变量var的内容在第 i 次循环时为coni

    【练习】

    题目1:假设我有三种动物,分别是 dog, cat, elephant 三种,我想每一行都输出这样:“There are dogs...”之类的字样。

     1 #!/bin/bash
     2 # Program:
     3 #       Using for...loop to print 3 animals
     4 # History:
     5 # 2017-10-1 liuyu First release
     6 
     7 for animal in dog cat elephant
     8 do
     9         echo "There are ${animal}s..."
    10 done
    View Code

    题目2:系统上的账号都是写在/etc/passwd内的第一个字段,你能不能通过管道命令 cut 找出单纯的账号名称后,以 id 及 finger 分别检查用户的标识符与特殊参数呢?

     1 #!/bin/bash
     2 # Program:
     3 #       Use id,finger command to check system account's information.
     4 # History:
     5 # 2017-10-1 liuyu First release
     6 
     7 users=$(cut -d ':' -f1 /etc/passwd)
     8 for username in $users
     9 do
    10         id $username
    11         finger $username
    12 done
    View Code

    评讲:执行此脚本后,我们的系统账号就会被获取出来检查。

    补充:这个操作还可以用在每个账号的删除/更改上面呢!

    题目3:我现在需要一连串的数字来进行循环。如我想要利用 ping 这个可以判断网络状态的命令。来进行网络状态的实际检测时,我想要检测的域是本机所在的192.168.1.1~192.168.1.100,由于有100台主机,故我不想在 for 后面输入1到100。

     1 #!/bin/bash
     2 # Program:
     3 #       Use ping command to check the network's PC state.
     4 # History:
     5 # 2017-10-1 liuyu First release
     6 
     7 network="192.168.1"   #先定义一个域的前面部分
     8 for sitenu in $(seq 1 100)   #seq为sequence(连续)的缩写之意
     9 do
    10         #下面的语句取得ping的回传值是正确的还是失败的
    11         ping -c l -w l ${network}.${sitenu} &> /dev/null && result=0 || result=1
    12         #开始回显结果是正确的启动(UP)还是错误的没有连通(DOWN)
    13         if [ "$result" == 0 ]; then
    14                 echo "Sever ${network}.${sitenu} is UP."
    15         else
    16                 echo "Sever ${network}.${sitenu} is DOWN."
    17         fi
    18 done
    View Code

    评讲:上面这一串命令执行之后就可以显示出192.168.1.1~192.168.1.100共100部主机目前是否能与你的机器连通!如果你的域与我们所在的位置不同,则直接修改上面那个network的变量内容即可!

    题目4:让用户输入某个目录文件名,然后找出某目录内的文件名的权限。

     1 #!/bin/bash
     2 # Program:
     3 #       User input dir name, I find the permission of files.
     4 # History:
     5 # 2017-10-1 liuyu First release
     6 
     7 # 1.先看看这个目录是否存在
     8 read -p "Please input a directory: " dir
     9 if [ "$dir" == "" -o ! -d "$dir" ]; then
    10         echo "The $dir is NOT exist in your system."
    11         exit 1;
    12 fi
    13 
    14 # 2. 开始测试文件
    15 filelist=$(ls $dir)     # 列出所有在该目录下的文件名
    16 for filename in $filelist
    17 do
    18         perm=""
    19         test -r "$dir/$filename" && perm="$perm readable"
    20         test -w "$dir/$filename" && perm="$perm writable"
    21         test -x "$dir/$filename" && perm="$perm executable"
    22         echo "The file $dir/$filenam's permission is $perm."
    23 done
    View Code

    评讲:此题涉及判断式与循环的综合。

    【另一种使用方式——适合于数值运算中】

    for ( ( 初始值; 限制值; 执行步长 ) )

    do

      程序段

    done

    解释:初始值为某个变量在循环当中的初始值(直接以类似i=1设置好);限制值为当变量的值在这个限制值的范围内,就继续进行循环,例如i<=100;执行步长为每做一次循环时变量的变化量,如i=i+1。

    题目:进行1累加到用户输入的循环

     1 #!/bin/bash
     2 # Program:
     3 #       Use for to calculate "1+2+...+${your_input}".
     4 # History:
     5 # 2017-10-1 liuyu release
     6 
     7 read -p "Please input a number, I will count for 1+2+...+your_input: " n
     8 
     9 ans=0
    10 for ((i=1; i<=$n; i=i+1))
    11 do
    12         ans=$(($ans+$i))
    13 done
    14 echo "The result of '1+2+3+...+$n' is ==> $ans."
    sh19.sh

    十一、shell script的追踪与调试

    1. 概述

    script在执行之前,最怕出现语法错误的问题了!那么我们如何调试呢?

    我们有没有办法不需要通过直接执行该 script 就可以来判断是否有问题呢?

    有的,而且很简单,只要在执行该script的命令中加上相关参数即可。

    2. 用法

    bash [-nx] 文件名  //-n为不执行script,仅查询语法的问题;-x为将使用到的script内容显示到屏幕上(执行过程显示出来,很重要)

  • 相关阅读:
    java final计算
    浅析Java中的final关键字
    easyui
    Java:类与继承
    java中&和&&
    XML
    JSON
    SQL
    selenium
    Metasploit
  • 原文地址:https://www.cnblogs.com/xzxl/p/7614607.html
Copyright © 2020-2023  润新知