Linux shell脚本编程

Linux shell脚本编程:
  守护进程,服务进程:启动?开机时自动启动:
  交互式进程:shell应用程序

      广义:GUI,CLI
        GUI:
        CLI:
          词法分析:命令,选项,参数
              内建命令:
              外部命令:PATH
              fork()创建为一个进程:

          把要运行的一系列命令,写在文件中:
        脚本或程序源文件:文本文件
              两种方式:
                  编译执行:预处理---->编译---->汇编---->链接:事先完成,结果:二进制程序文件
                      C,C++
                  解释执行:由解释器全程参与运行过程,每次读取一行,运行一行;
                    Python:程序库
                        程序控制结构:调用编程库完成编程编写;
                        库文件:功能模块,在编程中可调用;通过其API:应用编程接口;
                    Bash:程序
                        程序控制结构,调用机器上命令程序文件进行编程编写;
                        外部命令:各应用程序提供;
        程序:指令+数据
            算法+数据结构

            过程式编程:以指令为中心,设计算法,数据服务于算法;
            对象式编程:以数据为中心,设计数据结构(类),程序服务于数据结构;

            bash过程式编程:
                顺序执行:逐个执行
                选择执行:只执行其中一个分支
                循坏执行:一段代码要执行0,1或多遍

                编程元素:变量、流程、函数

            变量:可变化的量,命名内存空间

                bash环境:
                  本地变量:当前shell进程;
                  环境变量:当前shell进程及其子进程;
                  局部变量:某个函数执行过程;
                  位置参数变量:在脚本中引用传递给脚本的参数;在函数中引用传递给函数的参数;
                  特殊变量:$?,$*,$@,$#,$$

                变量类型:
                    数值,字符:

                        数值:
                            整数
                            浮点数
                        字符:
                            ASCII
                        120:
                            字符:1, 2 , 0
                            数值:120 --->

                变量类型的作用:
                      存储空间
                      运算格式

                语言对变量类型的支持力度:
                    强类型:
                    弱类型:变量类型不严格区分;
                        默认存储机制:bash为字符

                bash的变量使用特点:弱类型、无需事先说明;

            本地变量:
                name=value
                    name:变量名
                    =:赋值符号
                    value:值

                    变量名:只能包含数字、字母和下划线:且不能以数字开头;
                      引用变量:${name},name
                      例:
                          [root@localhost ~]# animal="panao"
                          [root@localhost ~]# echo ${animal}
                          panao
                引用:
                    弱引用:"",其内部的变量引用会替换为变量值;
                    强引用:'',其内部的变量引用会保持原有字符;
                    命令引用:`COMMAND`,$(COMMAND),引用命令的执行结果;

                声明为整型:
                    declare -i name[=value]
                    let name=value

                生命周期:
                    创建
                    销毁:
                        自动销毁:shell进程终止;
                        手动销毁:unset name
                            例:
                                [root@localhost ~]# unset animal

                环境变量:
                    被"导出"的本地变量
                        export name[=value]
                        declare -x name[=value]

                    查看所有环境变量:env,printenv,export

                    销毁:
                      unset name

            脚本:文本文件
                  运行脚本:事实上是运行一个bash进程,此进程负责从脚本文件中读取一个执行逻辑,而后有bash进程负责解析并运行此逻辑;
                  启动脚本:
                        (1) #bash /PATH/TO/SCRIPT_FILE
                        (2)一个执行权限,
                        # ./PATH/TO/SCRIPT_FILE

                        shebang:
                          #!/bin/bash

                  第一行:顶格给出shebang
                  注释行:#

                  bash的常用选项:
                    -n:检查脚本中的语法错误;
                    -x:调试执行脚本;

            命令的状态结果:
                bash进程用于追踪执行的命令成功与否的状态;
                    0:成功
                    1-222:失败

                  特殊变量:
                    $?:上一条命令的执行状态结果;
                        例:
                          [root@localhost bin]# echo $?
                          0 // 0表示成功


                  布尔型:
                      "真":成功
                      "假":失败

                  自定义脚本的状态结果:
                    exit[n]

                    注意:脚本中任何位置执行了exit命令即会终止当前shell进程;

                  条件测试:
                    界定程序执行环境:

                    (1)根据运行的命令的状态结果;
                    (2)测试表达式
                        test EXPRESSION
                        [ EXPRESSION ]  //括号两边必须有空格
                        [[ EXPRESSION ]] //括号两边必须有空格

                  整数测试:隐含着做数值大小比较,所以不要给变量引用加引用;
                      $A -gt $B:是否大于:是则为"真",否则为"假";
                      $A -ge $B:是否大于等于;
                      $A -lt $B:是否小于;
                      $A -le $B:是否小于等于;
                      $A -eq $B:是否等于;
                      $A -ne $B:是否不等于;
                  字符串测试:ASCII数值越大,字符比较时其值越大
                      "$A" > "$B":是否大于;
                      "$A" < "$B":是否小于;
                      "$A" == "$B":是否等于;
                      "$A" != "$B":是否不等于;
                      -z "$A":是否为空;空则为"真",否则为"假"
                      -n "$A":是否不空;不空则为"真",空则为"假"

                      注意:应该使用[[ EXPRESSION ]]

                  文件测试:测试文件的存在性以及属性;
                      -e $file:是否存在,存在则为"真",否则为"假"
                      -a $file:同上
                      -f $file:文件是否存在且为普通文件;
                      -d $file:文件是否存在且为目录;
                      -h $file:是否存在且为符号链接文件;
                      -L $file:同上;
                      -b $file:是否存在且为块设备文件;
                      -c $file:是否存在且为字符设备文件;
                      -S $file:是否存在且为套接字文件;
                      -p $file:是否存在且为管道文件;

                      -r $file:当前用户对文件是否拥有读权限;
                      -w $file:当前用户对文件是否拥有写权限;
                      -x $file:当前用户对文件是否拥有执行权限;

                      -u $file:文件是否拥有SUID权限;
                      -g $file:文件是否拥有SGID权限;
                      -k $file:文件是否拥有sticky权限;

                      -O $file:当前用户是否为指定文件的属主;
                      -G $file:当前用户是否为指定文件的属组;

                  双目操作符:
                  $file1 -nt $file2:file1是否新于file2,file1的最近一次的修改时间是否晚于file2的;
                  $file1 -ot $file2:file1是否旧于file2,file1的最近一次的修改时间是否早于file2的;
                  $file1 -ef $file2:file1与file2是否指向了同一个inode:测试二者是否为同一个文件的硬链接;

 

              特殊设备:
                  /dev/null:空,bit buckets,吞下所有数据,并直接丢弃;
                  /dev/zero:突出一堆0:

              bash之条件判断(选择执行):
                  if/then,case

                  if CONDITTION;then
                      if-true-分支
                  fi
                 
                  if CONDITTION;then
                      if-true-分支
                  else
                      if-false-分支

                  !CONDITTION:取反

    练习:写一个脚本
        如果其路径不存在,则将其创建为目录,否则显示其存在,并显示内容类型;
                   
              #!/bin/bash
              #
              filename="/tmp/x/y/z/testdir"
              if [ -e $filename ];then
                  echo "$filename exists."
                  file $filename
              else
                  mkdir -p $filename
              fi
              ~                                                                                                             
              ~       
      脚本参数(位置参数变量):
          ./script.sh /etc/fstab /etc/grub2.cfg
              $0            $1          $2

          位置参数变量:$1,$2,....
              ${10}

          特殊变量:
              $?:命令的状态结果;
              $#:传递给脚本或函数的参数个数;
              $*和$@:引用传递给脚本或函数的参数列表;

          shift:[n]:轮替

      与用户交互:
        read命令:
              read [option] VAR...
                  -p "PROMPT"
                  -t  timeout
            示例:

                #!/bin/bash
                #

                read -p "Plz enter a username: " -t 5 username

                if [ -z "$username" ]; then
                    username="myuser"
                fi

                if id $username &> /dev/null; then
                    echo "$username exists."
                else
                    useradd $username
                fi
       


      命令引用:
          `COMMAND`,$(COMMAND)

          引用命令的执行结果:
          (1)ls `which cat`
          (2)lines=$(wc -l /etc/fstab | cut -d '' -f1)
         
          #!/bin/bash
          #
          if [ -f $1 ]; then
              lines=$(wc -l $1 | cut -d' ' -f1)
              echo "$1 has $lines lines."
          else
              echo "$1 not exists or not a file."
          fi
     
      练习:写一个脚本,完成如下功能:
          判断给定的两个数值,孰大孰小;
            给定数值的方法:脚本参数,命令交互;
代码如下:

  1 #!/bin/bash
  2 #
  3 read -p "Plz enter two integer: " -t 10 num1 num2
  4
  5 if [ -z "$num1" ];then
  6    echo "Plz give two integers."
  7    exit 1
  8 fi
  9
 10 if [ -z "$num2" ];then
 11    echo "Plz give two integers."
 12    exit 1
 13 fi
 14
 15 if [$num1 -ge $num2 ];then
 16    echo "Max: $num1,Min;$num2."
 17 else
 18    echo "Max:$num2,Min:$num1."
 19 fi
      循环语句:
          for,while,until

            循环:将循坏体代码执行0、1或多次;
              进入条件:进入循环的条件;
              退出条件:循环终止的条件;

            for VARIABLE in LIST;do
                循环体
            done

            LIST:是由一个或多个空格分隔开的字符串组成;
                把列表的每个字符串逐个赋值给VARIABLE表示的变量;

                for username in user1 user2 user3;do
                    循环体
                done

                进入条件:列表非空
                退出条件:列表遍历结束;

添加5个用户:
#!/bin/bash
#
for username in user1 user2 user3 user4 user5; do
    if id $username &> /dev/null; then
      echo "$username exists."
    else
      useradd $username
      echo "Add user $username finished."
    fi
done
    LIST的生成方法:
      (1)整数列表
        (a){start..end}
        (b)$(seq start [[step]end])
      (2)直接给出
      (3)glob
      (4)根据命令生成


示例:数值列表
#!/bin/bash
#
for i in {1..10}; do
    if id user$i &> /dev/null; then
      echo "user$i exists."
    else
      useradd user$i
      echo "Add user user$i finished."
    fi
done

示例:glob
#!/bin/bash
#
for filename in /var/log/*; do
    file $filename
done

示例:命令生成列表
#!/bin/bash
#
for username in $(cut -d: -f1 /etc/passwd); do
  echo "$username primary group: $(id -n -g $username)."
done

算术运算:
  +,-,*,%,**

  sum=$a+$b
  (1)$[$A+$B]
  (2)$(($A+$B))
  (3)let VARIABLE=$A+$B
  (4)VARIABLE$(expr $A + $B)

  示例:

[root@localhost bin]# a=6
[root@localhost bin]# b=7
[root@localhost bin]# sum=$a+$b
[root@localhost bin]# echo $a+$b
6+7
[root@localhost bin]# echo $[$a+$b]
13
[root@localhost bin]# let $a+$b
[root@localhost bin]# let sum=$a+$b
[root@localhost bin]# echo $sum
13
[root@localhost bin]# expr $a + $b
13

示例:求100以内正整数之和;
#!/bin/bash
#
declare -i sum=0

for i in {1..100}; do
  sum=$[$sum+$i]
done

echo $sum

练习:求100以内所有偶数之和;
使用至少三种方法实现;

相关推荐