【Linux---08】Shell脚本

关于执行结果,以及检测存在性,返回值为0表示正常,返回值为非0表示不正常。这个与正常逻辑相反,需要注意。

1. 前置说明

shell脚本是linux系统中的一个可执行文件,它可以用来批量执行linux命令,比手动输入大量命令要高。

1.1 创建shell脚本

创建shell脚本有几个必须点:

  1. 文件必须以.sh结尾

  2. 文件的开头必须加上#! /biin/bash,指明脚本解释器

    cd ~
    vim myshell.sh
    

    在这里插入图片描述

1.2 执行shell脚本

shell脚本的执行:

  1. 方式一:使用 shbash命令

    sh myshell.sh
    # 等价于
    bash myshell.sh
    

    bash 是 sh 的超集

  2. 方式二:授予文件可执行权限,这样可以直接输入文件名运行文件

    # chmod a+x myshell.sh
    chmod +x myshell.sh   # 为当前用户增加对该文件权限
    myshell.sh
    

    在这里插入图片描述

  3. 方式三:使用source.命令

    source myshell.sh
    # 等价于
    . myshell.sh
    

    sh vs source

    1. 相同:都会执行脚本
    2. 区别:使用source执行的脚本会修改父环境的变量,主要表现为调用的脚本出现了与父环境中相同的变量,会将其值替换。而sh脚本不能修改其父Shell的环境。

1.3 调试shell脚本

  1. 方式一:在执行脚本时加上-x

    1. sh -x myshell.sh (未授权)
    2. -x myshell.sh (已授权)
      在这里插入图片描述
  2. 方式二:在shell脚本中的开头设置set -x,再直接执行脚本

    注意:使用set -e可以告诉shell,如果一个命令的退出状态是非零值,则退出shell。这通常用来在脚本中处理错误。如果一个命令失败了(即返回非零退出状态),脚本将立即停止执行。

    例如,你有以下的shell脚本:

    #!/bin/bash
    
    set -ex
    
    echo "This is a test"
    non_existent_command
    echo "This will not be printed"
    

    在这个脚本中,non_existent_command 是一个不存在的命令,所以它会返回一个非零的退出状态。因为我们使用了 -e 选项,所以脚本在这条命令失败后将停止执行,echo "This will not be printed" 这一行将不会被执行。

    因为我们使用了 -x 选项,所以脚本在执行每一条命令前都会先将命令本身打印出来。所以,如果你运行这个脚本,你将看到类似以下的输出:

    + echo 'This is a test'
    This is a test
    + non_existent_command
    ./script.sh: line 7: non_existent_command: command not found
    

1.4 字符冲突

通过下面可以知道$字符可以用来获取变量值,但是当我们要打印$符号怎么办?
使用\转义。其他字符冲突也是这样处理。

#! /bin/bash
money=100
echo "我有\$${money}元"  # 输出:我有$100元

2. 变量

2.1 创建&使用变量

  1. 创建变量:和Java一样,=左边是变量名,右边是变量值。

    注意事项:

    1. 变量名首字符必须为字母,名字只能用字母、数字、下滑线,不要用bash关键字。非法的名字:8var、var-8
    2. 变量名=值,等号两边不能有空格。
    3. 值只有字符串类型,值可以用单引号、可以用双引号,也可以都不用。但是值中有空格或特殊字符必须需要用双引号或单引号引起来。
    #! /bin/bash
    name="zhansgan"
    age=18
    echo $name  # 输出:zhangsan
    echo "${name}目前${age}岁!"  # 输出:zhangsan目前18岁!
    
  2. 使用变量:$变量名${变量名} 形式获取变量值。一般首先使用$变量名,当存在歧义没有达到理想效果时使用${变量名}方式,获取数组值必须用后者。

    注意:变量取值不能嵌套,比如:year=${$3:0:4} # 这样会报错,因为不允许${}里面嵌套$

  3. 判断变量的值的是否为空。linux变量值都是字符串,没有其他类型。所以其本质上判断变量值是否为空字符串。
    -z是检查变量是否为空。如果变量为空,那么-z条件为真。
    -n是检查变量是否非空。如果变量非空,那么-n条件为真。

    if [[ -z "${var}" ]]; then
        echo "var is empty"
    fi
    
    if [[ -n "${var}" ]]; then
        echo "var is not empty"
    fi
    

2.2 位置变量

  1. 如果要想向shell脚本里传入参数,可以在运行shell脚本时携带参数。在shell脚本内可以通过一些符号获取传递的值:

    1. $0${BASH_SOURCE[0]}:脚本的名称

    2. $1:脚本的第一个参数,$2是第二个参数,以此类推

      注意:使用shift N命令可以将参数整体左移。这个命令将每个位置参数向左移动N个位置。例如,$3的值移动到$2$2的值移动到$1。同时,$1的值将被丢弃,原来$N+1的值将被移动到$N,以此类推。

      #!/bin/bash
      echo "Parameter 1 before shift: $1"
      echo "Parameter 2 before shift: $2"
      shift 1
      echo "Parameter 1 after shift: $1"
      echo "Parameter 2 after shift: $2"
      
    3. $#:传入脚本的参数个数

    4. $*:传入的所有参数拼接为一个字符串后返回

      #! /bin/bash
      # 判断当前目录下的所有文件,哪些是文件,哪些不是文件 
      arr=(`ls ./`)
      for file in ${arr[*]}
      do
      	if [ -f file ];then
      		echo "$file is a file"
      	else
      		echo "$file is not a file"
      	if
      dome
      
    5. $@:传入的每个参数是一个字符串

    6. $?:上一条命令执行是否成功,0表示执行成功,非0表示执行失败

      $(命令)可以获取命令的执行结果
      在这里插入图片描述

    7. $$:当前进程的id

    比如:有 a.sh 脚本,内容如下

    #! /bin/bash
    
    echo $0
    echo $1
    echo $2
    echo $#
    echo $*
    echo $@
    echo $?
    

    在这里插入图片描述

  2. 判断对应的位置变量是否有值,可借助 -z-n命令。
    -z是检查变量是否为空。
    -n是检查变量是否非空。

    if [ -z "$1" ]; then
      echo "variable is empty"
    fi
    

2.3 引号与变量

  1. 单引号:里面的所有字符都是普通字符,不能够获取变量值。单引号内的${变量名}会无效。
  2. 双引号:会保留变量特性。可以使用${变量名}获取变量值。
    #! /bin/bash
    name="zhansan"
    echo '$name'   # 输出:$name
    echo "$name"   # 输出:zhangsan
    
  3. 倒引号$():引起来的命令将会被执行,执行后的结果作为这个表达式的值
    在这里插入图片描述
    [root@host ~]$ str=`echo "hello"`
    [root@host ~]$ echo $str
    hello
    [root@host ~]$ str2=$(echo 'hello')
    [root@host ~]$ echo $str2
    hello
    [root@host ~]$ 
    

2.4 变量生命周期

  1. 普通变量只会在当前文件生效,该变量不会被传递给子shell。假设有text.sh文件:

    #!/bin/bash
    # HOME变量只会在当前文件生效,不会在csv.sh文件中生效
    HOME=/usr/zhangsan 
    sh csv.sh
    
  2. 能够传递给子文件的变量。前面加上export关键字:

    #!/bin/bash
    # HOME变量不仅在当前文件生效,在csv.sh文件中也生效
    export HOME=/usr/zhangsan 
    sh csv.sh
    
  3. 用户级别的环境变量

    1. 能够在 当前会话 中的每一个shell脚本中都生效的变量。打开用户目录下的.bashrc文件进行编辑,在此脚本里使用export定义的变量即可在每个shell脚本中生效。因为当你启动一个新的bash shell(即打开一个新的终端窗口)时,它会被自动执行。
      vim ~/.bashrc
      
    2. 能够在 每个会话 中都生效的变量。打开用户目录下的.bash_profile文件进行编辑,里面export定义的变量即可在每个会话中都生效。
      vim ~/.bash_profile
      
      .bash_profile文件会调用.bashrc,保证每次会话都拥有相同的系统变量。一般来说,只需要修改.bashrc文件即可。
      在这里插入图片描述
  4. 全局的环境变量:在Unix和Linux系统中,/etc/profile文件是一个全局配置脚本,里面使用export定义的变量会为每个用户都生效,常用来定义JAVA_HOME这类软件变量。当用户登录时,该脚本就会运行。需要注意的是,对/etc/profile的修改需要管理员权限。

2.5 系统变量

(1) PATH

PATH 是一个环境变量,用于指定系统在哪些目录下搜索可执行文件。通常在~/.bashrc~/.bash_profile文件中使用,用来修改环境变量。

比如:~/.bashrc文件中

export HADOOP_HOME=/home/work/software/hadoop-client/hadoop
export SCALA_HOME=/home/work/software/scala-2.12.7
export SPARK_HOME=/home/work/software/spark-2.4.3.9/

# 记得加上$PATH
export PATH=$PATH:$HADOOP_HOME/bin:$SPARK_HOME/bin:$SCALA_HOME/bin:$YARN_HOME/bin:${JAVA_HOME}/bin:${MAVEN_HOME}/bin:${PMCLIENT_HOME}/bin

(2) EXIT

在shell脚本中,如果需要在某个条件满足后让脚本异常结束,可以使用 exit 命令。

exit 命令用于结束当前脚本的执行,它后面可以接一个退出状态码(0-255)。其中,0表示成功,其他值表示出错。如果 exit 命令后面没有指定退出状态码,那么默认使用前一个命令的退出状态码。

例如:

#!/bin/bash

# 运行脚本的用户不是root,那么脚本会打印一条错误消息并退出,退出状态码是1if [ $(whoami) != 'root' ]; then
    echo "You must be root to run this script."
    exit 1
fi

2.6 正则匹配

=~ 是一个正则表达式匹配操作符,用于检查一个变量的值是否匹配一个正则表达式。

# 检查第三个参数是否为整数
if ! [[ $3 =~ ^[0-9]+$ ]]; then
  echo "Error: $3 is not a number"
  exit 1
fi

3. 字符串

3.1 字符串切片

  1. 字符串切片
    1. 正向切片
      # 下标为正
      str='abcdef'
      sub_str=${str:2:1}  # 2是下标(下标从0开始);1是截取长度
      echo $sub_str  # 输出:c
      
      # 下标也可以为负
      str="Hello"
      lastChar=${str: -1}
      allButLast=${str:0:-1}
      echo "Last character is: $lastChar"   # 输出:Last character is: o
      echo "All but last character is: $allButLast"  # 输出:All but last character is: Hell
      
    2. 反向切片:中间的下标用空格代替
      str="Hello"
      echo ${str: -2}  # 输出:lo
      

      注意:${str: -1}中的空格是必要的,否则Bash会将:-1解析为默认值的语法,从而报错

    3. 注意:如果是直接对传入的参数进行切片,则可以省略$符号,加上会报错,因为${}语法不能嵌套。
      #!/bin/bash
      year=${3:0:4}   # 取传入的第三个参数的前4位
      month=${3:4:2}  # 取传入的第三个参数的5,6位
      day=${3:6:2}    # 取传入的第三个参数的7,8位
      
      year=${$3:0:4}  # 这样会报错,因为不允许${}里面嵌套$
      

4. 运算符

4.1 比较&数值运算

4.1.1 方式一:[ ] 📍 数值比较&字符串比较

  1. 语法:[ 比较&运算表达式 ] 注意:整体前后空格,运算符前后空格
  2. 支持的运算有
    1. 比较运算(数值比较)
      在这里插入图片描述
    2. 比较运算(字符串比较)
      在这里插入图片描述

      注意:这里的==,也可以只用单等号=

  3. 例子:
    1. 比较运算(数值比较)的例子:
      [root@localhost shell]# [ 1 -eq 1 ] && echo 'ok'
      ok
      [root@localhost shell]# [ 1 -lt 0 ] && echo 'ok'   
      [root@localhost shell]# [ 1 -lt 2 ] && echo 'ok' 
      ok
      # 没有空格隔开,报错
      [root@localhost shell]# [ 1 -lt 2] && echo 'ok' 
      -bash: [: 缺少 ]
      # 变量替换也可以
      [root@localhost shell]# a=1
      [root@localhost shell]# [ $a -lt 2 ] && echo 'ok' 
      ok
      [root@localhost shell]# 
      
    2. 比较运算(字符串比较)的例子:
      [root@localhost shell]# [ "aaa" == "aaa" ] && echo 'ok'
      ok
      [root@localhost shell]# 
      [root@localhost shell]# [ "aaa" != "bbb" ] && echo 'ok'    
      ok
      # 字符串判空
      [root@localhost shell]# s=aaa
      # 字符串非空
      [root@localhost shell]# [ "${s}x" == "x" ] && echo 'ok'         
      [root@localhost shell]# 
      # 字符串为空
      [root@localhost shell]# s=""
      [root@localhost shell]# [ "${s}x" == "x" ] && echo 'ok'
      ok
      

4.1.3 方式二:(()) 📌 只可用于数值比较

  1. 语法:((数字比较 或 运算表达式)) 注意:整体前后不需要空格,运算符前后空格

  2. 支持的运算有:

    1. 比较:==!=<<=
    2. 数值运算:加减乘除取模自加【a++或++a】、+=

    注意:无论是比较还是数值运算,只支持数字,不支持字符串,因为字符串会自动转为true,两个字符串比较的结果永远为true

    flag='h'  
    if $(($flag == 'd' )); then
        echo "Flag is d" else
        echo "Flag is not d" fi
    
    # 输出:Flag is d ```
    
  3. 加上$可取运算后的值$((数值运算))

  4. 例子:

    #! /bin/bash
    a=10
    b=20
    echo "$((a+b))"  # 输出:30
    
    a=10
    echo "$((a%2))"  # 删除:0
    
    a=10
    echo "$((a++))"  # 输出:10,此时a=11
    
    a=10
    echo "$((++a))"  # 输出:11,此时a=11
    
    a=10
    echo "$((a!=2))"  # 输出:11,此时a=11
    
    a=10
    echo "$((a==2))"  # 输出:11,此时a=11
    
    a=10
    echo "$((a<=2))"  # 输出:0
    
    a=10
    echo "$((a<2))"  # 输出:0
    
    a=10
    echo "$((a+=2))"  # 输出:12
    

4.2 逻辑运算

  1. 语法:

    1. 采用[ ]进行运算
      在这里插入图片描述

    2. 采用(())进行运算

      运算符说明示例
      !非运算((! 2 < 1)) && echo ‘ok’
      |或运算((1 == 1 | 1 == 2)) && echo ‘ok’
      &与运算((1 == 1 & 1 == 2)) && echo ‘ok’
      &&短路与((1 == 1 && 1 == 2)) && echo ‘ok’
      ||短路或((1 == 1|| 1 == 2)) && echo ‘ok’
  2. 细节:

    1. &&||有一个非常有用的作用—将多行命令变成一行,这对于平台化的shell脚本执行非常有帮助。通过平台执行shell脚本时,往往限制只能执行一行命令。比如:cd bin && sh run.sh $@
      在这里插入图片描述
      1. &&:前面的命令若执行成功(返回0),则执行后面的代码;前面的命令若执行失败(返回非0),则不执行后面的代码。
      2. ||:前面的命令若执行成功(返回0),则不执行后面的代码;前面的命令若执行失败(返回非0),则执行后面的代码。
    2. 通过使用&&||类似于三元运算符功能
      [[ -e ${BASH_LOG_FILE} ]] && echo 'file is exist' || echo 'file is not exist.'
      

4.3 文件运算

语法:[ 运算符 文件相对路径|绝对路径 ] 注意:整体前后空格,运算符前后空格
在这里插入图片描述

判断目录是否为空目录:

dir="/path/to/dir"
if [ "$(ls -A $dir)" ]; then
    echo "$dir is not empty"
else
   echo "$dir is empty"
fi
[root@localhost shell]# [ -e hello.sh ] && echo 'ok'        
ok
[root@localhost shell]# [ -f hello.sh ] && echo 'ok'
ok
[root@localhost shell]# [ -d hello.sh ] && echo 'ok'      
[root@localhost shell]# 

5. 控制语句

5.1 分支语句

5.1.1 if分支

# 方式一:表达式后面写分号,再写then
if  条件表达式一 ; then   
    表达式一true时执行这里
elif  条件判断式二 ; then    
    表达式二true时执行这里
elif  条件判断式三 ; then    
    表达式三true时执行这里
else    
    都不成立时,执行这里
fi

# 方式二:表达式后面写不写分号,则必须换行后写thenthen
if  条件表达式一 
	then 表达式一true时执行这里
elif  条件判断式二 
	then 表达式二true时执行这里
elif  条件判断式三
	then 表达式三true时执行这里
else    
    都不成立时,执行这里
fi

注意 :

  1. 最后要以 if反过来的fi结尾
  2. 关键字与关键字之间的表达式前后必须空格,所以:关键字ifelif 后面必须接空格,then的前面必须接空格否则报错。

例子:

[root@localhost shell]# vim test.sh
#! /bin/bash
cmd=$1
if [ $cmd == "start" ]
	then echo "start"
elif [ $cmd == "stop" ]
	then echo "stop"
elif [ $cmd == "restart" ]
	then echo "restart"
else
	echo "other"
fi
[root@localhost shell]# sh test.sh 123   # 输出:other

5.1.2 模式匹配

case $var in
     模式1)  
             代码块1
             ;; 
     模式2)    
             代码块2    
             ;;    
     模式3)    
             代码块3   
             ;;    
        *)    
             代码块4    
             ;;
esac

注意 :最后要以 case反过来的esac结尾

例子:

[root@localhost shell]# vim s6.sh 
#! /bin/bash
cmd=$1
case $cmd in
        "start") echo "start operation"
                ;;
        "stop") echo "stop operation"
                ;;
        "restart") echo "restart operation"
                ;;
        *) echo "other operation"
                ;;
esac

5.2 循环语句

5.2.1 for循环

  1. 语法:
    # 方式一:for-each循环
    for 循环变量 in 数据列表; do
        循环体代码段
    done
    
    或者
    
    for 循环变量 in 数据列表
    do
        循环体代码段
    done
    
    # 方式二:下标循环
    for ((控制变量的初始化;循环的条件;循环控制变量的更新))
    do
         循环体代码段
    done
    
    或者
    
    for ((控制变量的初始化;循环的条件;循环控制变量的更新)); do
         循环体代码段
    done
    
    1. 数据列表{1..100}:表示1到100
      #! /bin/bash
      for i in {1..10}
      do
        echo $i
      done
      # 打印1到10
      
    2. 结尾必须写上done
    3. 关键字for 后面可以不接空格,但是推荐空格。
  2. 例子:
    ① for-each循环
    #! /bin/bash
    # 判断当前目录下哪些文件是普通文件
    arr=(`ls ./`)
    # 遍历数组的每个元素(文档)
    for f in ${arr[*]}
    do
        # 判断是否是文件
        if [ -f $f ]; then
                echo "$f is file"
        fi
    done
    
    ② 下标循环
    #! /bin/bash
    # 计算1-10内的偶数之和
    sum=0
    for((i=1;i<=10;i++))
    do
      if [ $((i%2)) -eq 0 ];then
        sum=$((sum+i))
      fi
    done
    echo "sum=${sum}"
    
    
    for ((time=start_time; time>end_time; time--)); do
      date -d "@$time" '+%Y%m%d %H:%M:%S'
    done
    

5.2.2 while循环

  1. 语法:

    while ((循环的条件))
    do
        循环体代码段
    done
    
    1. done结束
    2. 关键字for 后面可以不接空格,但是推荐空格。
  2. 例子

    #! /bin/bash
    i=1
    while((i<10))
    do
      ((i++))
    done
    echo "i=$i"  # 输出:i=10
    

6. 函数定义

6.1 没有返回值的函数

#!/bin/bash

fun(){
    echo "hello student!"
}

fun   # 输入方法名时,调用函数

6.2 有返回值的函数

#!/bin/bash

num1=$1
num2=$2
funandReturn(){
    return $(($num1+$num2))
}

funandReturn  # 输入函数名,会调用函数
echo "输入的两个数字之和为 $? !" # 通过 $? 获取函数返回值

6.3 定义函数内变量

在Linux中,local是一个bash shell内建命令,用于在函数中创建局部变量。这些变量只在定义它们的函数及其子进程中可见,而在函数外部则不可见。

function myfunc() {
    local myvar="Hello, World!"
    echo $myvar
}

myfunc  # Prints "Hello, World!"
echo $myvar  # Prints nothing because myvar is not defined in this scope

3. 数据结构

3.1 数组

3.1.1 创建数组

  1. 方式一:直接定义并初始化。

    #! /bin/bash
    arr=("aaa" "bbb" "ccc")
    arr=("aaa"
    	 "bbb"
    	 "ccc"
    )
    

    注意:元素间使用空格或回车,而不是逗号分隔;并且后续可以继续添加元素,并不是静态的。

  2. 方式二:使用declare -a

    #! /bin/bash
    # 1. 定义并初始化
    declare -a arr=("aaa" "bbb" "ccc")
    
    # 2. 先定义,再赋值
    declare -a arr
    arr[0]="aaa"
    arr[1]="bbb"
    arr[2]="ccc"
    
  3. 搭配for循环,能够将字符串使用默认的\t\n分割做为一个数组。比如:
    在这里插入图片描述

    #! /bin/bash
    arr=$(ls -l ./)
    for x in ${arr[@]}; do
      echo $x
    done
    

    输出:

    [fenrun@njjs-passport-bigdata00.njjs.baidu.com utils]$
    总用量
    20
    -rw-rw-r--
    1
    fenrun
    fenrun
    8120
    1010
    17:45
    AfsToDataframe.scala
    -rw-rw-r--
    1
    fenrun
    fenrun
    3732
    99
    11:13
    HiRobot.scala
    -rw-rw-r--
    1
    fenrun
    fenrun
    66
    1023
    15:43
    my.sh
    -rw-rw-r--
    1
    fenrun
    fenrun
    3568
    1022
    10:36
    Mytest.scala
    

3.1.2 使用数组

  1. 获取数组长度:${#数组名[*]}${#数组名[@]}。 eg:${#arr[*]}${#arr[@]}

  2. 读取数组元素

    1. 读取一个元素:${数组名[下标]}
    2. 一次读取所有元素:${数组名[*]}${数组名[@]}
  3. 给数组元素赋值:数组名[下标]=值

  4. 删除数组元素:unset 数组名[下标]

    [root@localhost shell]# arr1=("a1" "b1" "c1")
    [root@localhost shell]# echo ${arr1[*]}
    a1 b1 c1
    [root@localhost shell]# declare -a arr2=("a2" "b2" "c2")
    [root@localhost shell]# echo ${arr2[*]}
    a2 b2 c2
    [root@localhost shell]# declare -a arr3
    [root@localhost shell]# arr3[0]="a3"
    [root@localhost shell]# arr3[1]="b3"
    [root@localhost shell]# arr3[2]="c3"
    [root@localhost shell]# echo ${arr3[*]}
    a3 b3 c3
    [root@localhost shell]# 
    # 查看数组长度
    [root@localhost shell]# echo ${#arr3[*]}
    3
    # 获取数组第一个元素
    [root@localhost shell]# echo ${arr3[0]}
    a3
    # 删除数组第一个元素,数组长度-1
    [root@localhost shell]# unset arr3[0]
    [root@localhost shell]# echo ${#arr3[*]}
    2
    [root@localhost shell]# echo ${arr3[*]}
    b3 c3
    

4. Map

4.1 创建Map

和数组的创建有点类似,但是必须加上declare -a

declare -A arr=([a]="aaa" [b]="bbb" [c]="ccc")
echo "${arr[b]}"   # 输出:bbb


declare -A arr=(
	[a]="aaa"
	[b]="bbb"
	[c]="ccc"
)
echo "${arr[b]}"   # 输出:bbb

元素间依旧是以 空格回车 分隔。

7. 连接数据库

7.1 连接MySQL数据库

# 1. 设置主机信息、账号密码、数据库名
MYSQL_CLIENT=$HOME/.jumbo/bin/mysql  # mysql的安装路径/bin/mysql,如果此时机器MySQL已经配置了环境变量,则可以写 MYSQL_CLIENT=mysql
MYSQL_HOST="xxxx"
MYSQL_PORT="xxxx"
MYSQL_USER="xxxx"
MYSQL_PASSWORD="xxxx"
MYSQL_DATABASE="xxxx"

# 2. 登入MySQL  
#   --skip-column-names 或 -N:输出结果中不显示列名
#   -e:表示后续会接一个 SQL 查询语句,这个 SQL 查询语句会被 MySQL 客户端执行
LOGIN_MYSQL="${MYSQL_CLIENT} -h${PALO_HOST} -P${PALO_PORT} -u${PALO_USER} -p${PALO_PASSWORD} -D${PALO_DATABASE} --skip-column-names -e"
LOGIN_MYSQL="${MYSQL_CLIENT} -h${PALO_HOST} -P${PALO_PORT} -u${PALO_USER} -p${PALO_PASSWORD} -D${PALO_DATABASE} -N -e"

# 3. 执行sql
result=${LOGIN_MYSQL} "select * from table"

拉取数据时,如果需要保证数据已经加载完毕,可以采用拉取两次,进行对比的方式,以保证数据拉取完成:

event_day=`date -d "$BASETIME" +'%Y%m%d'`

SQL="select count(1) from xxx where count_date=${event_day};"

i=0
while (( i <= 50 ))
do
  ((i++))
  # 拉取第一次
  count_1=$($MYSQL_LOGIN "${SQL}")
  echo "get _1 data done, count_1 = ${count_1}"
  sleep 5m

  # 拉取第二次
  count_2=$($MYSQL_LOGIN "${SQL}")
  echo "get _2 data done, count_2 = ${count_2}"
  sleep 5m

  # 两者对比
  if ((count_1 > 0 && count_2 > 0 && count_1==count_2));then
    echo "month_dump_db_check.sh [query_data_count] date=${event_day} success"
    exit ${EXE_SUCCESS}
  fi
done

echo "month_dump_db_check.sh [query_data_count] date=${event_day} failed"
exit ${EXE_FAIL}

8. 注意点

8.1 $() 与 ${}的作用

  1. ${}

    1. 用来取变量的值。注意可以设置默认值和错误信息
      # 1. 设置默认值:${变量名:-默认值},如果变量未设置或为空,返回默认值。
      echo "Hello, ${name:-user}"  # 如果 name 为空或未设置,输出 "Hello, user"
      
      # 2. 设置默认值并赋值给变量:${变量名:=默认值}
      echo "Hello, ${name:=user}"  # 如果 name 为空或未设置,输出 "Hello, user",并将 "user" 赋给 name
      
      # 3. 变量未设置,打印错误信息并退出程序:${变量名:?错误信息}
      echo "Hello, ${name:?name is not set}"  # 如果 name 为空或未设置,打印 "name is not set" 并退出
      
    2. 还可以用于字符串的截取:${变量名:偏移量}${变量名:偏移量:长度}
      name="hello world"
      echo ${name:6:5}  # 输出 "world"
      
    3. 还可以用于字符串替换:${变量名/查找/替换}
      name="hello world"
      echo ${name/world/WORLD}  # 输出 "hello WORLD"
      
    4. 获取字符串长度:${#变量名}
      name="hello world"
      echo ${#name}  # 输出 "11"
      
  2. $():用来执行命令,并将执行结果作为变量的值。

8.2 exit与return

  1. 位置不同:exit可以在脚本的任何地方;而return在shell脚本的函数内或者最后一行。
  2. 作用不用:exit用于结束当前进程;return在函数内时用于结束函数,在shell脚本的最后一行时用于返回脚本中最后一个命令的 exit status
  3. 细节:当return位于shell脚本的最后一行时,用sh执行会报错,得用source执行。
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ElegantCodingWH

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值