以下内容为本人的学习笔记,如需要转载,请声明原文链接微信公众号「englyf」https://www.cnblogs.com/englyf/p/16721350.html


从头一二去阅读语法和命令说明,对于脚本小白来说比较枯燥,难以坚持,所以这里选择对一份完整的shell脚本代码来逐行逐段解读,希望可以一渡小白,帮助我们快速进入脚本的大门_

司机要开车了:


#!/bin/sh

用注释的形式说明文件打开类型,此处意指本脚本需要用 /bin/sh 打开。

#V1.0 Added hardware type detection
#V1.1 xxxx-xx-xx 重构脚本
#V1.2 xxxx-xx-xx 将日志信息输出到U盘
#V1.3 xxxx-xx-xx 读取存储的检测结果值
#V1.4 xxxx-xx-xx 添加校验程序版本,U盘下有对应版本信息文件才校验

上面几行表示注释内容。单行注释,以#开始

UDiskMountDir=$(df | grep /mnt/sd | awk 'END{print $NF}')

声明变量 UDiskMountDir 并赋值。

$() 括号内填入命令并执行,最后返回输出到变量 UDiskMountDir。

df命令显示liinux系统上的文件系统磁盘使用情况统计。后边还可以带选项,执行更复杂的输出。命令后边加 '|' 表示将此命令的输出作为后边紧接着的命令的输入。

grep命令用于对文本按行搜索然后输出该行。英文全称 global search regular expression(RE) and print out the line。grep /mnt/sd 表示搜索输入信息里包含 /mnt/sd的一行,并输出该行。

awk命令用于对文本处理,END表示执行最后的运算或者打印最终的输出结果,这里用于打印输出,$NF 表示列数,print $NF 表示打印最后一个字段,各个字段默认以空格划分,可用选项 -F指定使用什么字符串来划分。

LogFile=${UDiskMountDir}/Debug.log

声明变量 LogFile 并以右边的内容赋值。将变量 UDiskMountDir 所代表的路径名与后边的字符串结合为新的文件名。一般命令中用到的文件名,要不是带相对路径的文件名,如 ./diretion/filename,就是带绝对路径的文件名,如 /root/diretion/filename

${UDiskMountDir} 表示引用变量 UDiskMountDir 的值。

AllCheckPassed=true

声明变量 AllCheckPassed 并赋值为true。

AddError()
{
    AllCheckPassed=false
    echo "-200" > /tmp/VerCheckRes
}

声明函数 AddError,输入参数无需声明。

变量 AllCheckPassed 赋值为true。

echo命令用于输出字符串。echo "-200" > /tmp/VerCheckRes 将 -200 输出到文件 /tmp/VerCheckRes 并覆盖原有内容。如果将符号 > 换成 >> 则是将内容追加到最后位置。

AddRecord()
{
    if [ ! -d "/userdata/recordsDir/" ];then
        mkdir -p /userdata/recordsDir/
    fi
    echo "$*" > /userdata/recordsDir/test
    sync
    AddDebugLog2UDisk $*
}

声明函数 AddRecord。

if 表示 if 语句的开始。if[]方括号内填判断条件,如为 true 则执行 then 后的语句,否则跳出 if 语句。fi表示 if 语句的结束。和 C 语言类似,if 语句也可以有 else 甚至 else if (shell 内应该写成 elif)。if/elifthen 如果不在同一行则可以省略符号 ;if [ ! -d "/userdata/recordsDir/" ] 判断目录 /userdata/recordsDir/ 是否存在,并对结果值取反(!)。

mkdir命令用于构建目录。带选项 -p表示构建路径下所有的目录。mkdir -p /userdata/recordsDir/创建目录 /userdata/recordsDir/, /userdata/ 如果不存在也会被构建。

echo "$*" > /userdata/recordsDir/test 将函数输入的所有参数都输出到文件 '/userdata/recordsDir/test' 并覆盖原有内容。'$*' 表示当前函数或者脚本的所有输入参数,由于在函数内引用,所以这里表示函数的所有输入参数。

sync命令用于数据同步。Linux 系统中写入硬盘的数据往往会被先存放于 buffer 中,这样是为了效率起见,但是如果系统突然断电,那么数据就会丢失,这时可以调用 sync 将 buffer 中的数据同步到硬盘。

AddDebugLog2UDisk $* 调用函数 AddDebugLog2UDisk 并传入当前函数(AddRecord)的所有参数。

AddDebugLog2UDisk()
{
    echo "$*" >>"$LogFile"
    sync
}

声明函数 AddDebugLog2UDisk。

echo "\$*" >>"$LogFile" 表示将函数的所有输入参数输出到变量 LogFile 表示的文件中,以追加的形式输入到文件末尾。

sync同步数据到硬盘。

#生成下/tmp/App/version.txt版本信息

注释内容

rm -f "$LogFile"

rm命令用于移除文件。选项 -f表示强制。rm -f "$LogFile"强制移除变量 LogFile 代表的文件,变量 LogFile 存储的是文件名,包括路径。

echo "0" > /tmp/VerCheckRes

输出字符串 '0' 到文件 /tmp/VerCheckRes

sh /data/bin/run_normal.sh

在当前的环境中使用另一个shell来执行脚本文件 /data/bin/run_normal.sh,当前环境中变量的值可以在新脚本(/data/bin/run_normal.sh)中被使用(非引用,如果使用 source则变为引用),新脚本文件属性可以无执行权限。sh后边可以带选项 -n-x等,-n 用于进行shell脚本的语法检查,-x用于实现shell脚本的逐句跟踪调试并打印该行命令和状态等。

sleep 2

阻塞当前进程,睡眠 2 秒,和 sleep 2s 同样效果。sleep 2h 表示睡眠 2 小时。

sh /tmp/App/kill.sh

执行脚本文件 /tmp/App/kill.sh

killall MachineCheckNode

杀掉进程 MachineCheckNode,MachineCheckNode 为进程名。

lastSNScanResult=$(cat /userdata/recordsDir/scan)

读取文件 /userdata/recordsDir/scan 内容并赋值给变量 lastSNScanResult。

cat命令用于连接文件并输出内容到标准输出。

AddDebugLog2UDisk "last sn scan result:$lastSNScanResult"

调用函数 AddDebugLog2UDisk,并传递字符串 last sn scan result:$lastSNScanResult$lastSNScanResult 获取变量 lastSNScanResult 的值然后和前面的字符串结合成新的字符串。

#检查SN和markData
if [ ! -f /data/bin/sysData/sn ]; then 
    AddRecord "sn missing"
    AddError
else
    snContent=$(cat /data/bin/sysData/sn)
    AddRecord "sn is:$snContent"
    snLen=$(cat /data/bin/sysData/sn | awk '{print length($0)}')
    if [ "$snLen" != "16" ] ; then
        AddRecord "sn length error $snLen"
        AddError
    fi
fi

if [ ! -f /data/bin/sysData/sn ] 判断文件 /data/bin/sysData/sn 是否是常规文件而且存在,'!' 表示对结果值取反。

如果文件 /data/bin/sysData/sn 找不到或者不是常规文件,则调用后边的语句块,直到 else 为止。调用函数 AddRecord(传入字符串 "sn missing") 和 AddError(无参数传入)。

否则,获取文件内容并赋值给变量 snContent,调用函数 AddRecord(输入 sn is:$snContent", 字符串其中会插入变量 snContent 的值);声明变量 snLen,赋值为命令 cat /data/bin/sysData/sn | awk '{print length($0)}'的执行结果;判断 snLen 是否不等于 16,是则调用函数 AddRecord 和 AddError。

$(cat /data/bin/sysData/sn | awk '{print length($0)}') 读取文件 /data/bin/sysData/sn 的内容,通过管道('|')输入到后一命令语句,awk 计算输入内容的第一字段的字符长度并输出。

if [ ! -f /data/bin/sysData/markData ]; then 
    AddRecord "markData missing"
    AddError
fi

判断文件 /data/bin/sysData/markData 是否不存在,不存在则调用后边的语句(以 fi 为止)。

#检验版本信息
while read -r line || [ -n "${line}" ]; do
    [ "$line" = "" ] && continue
    item_filename=$(echo "$line" | awk -F":" '{print $1}')
    item_filemd5=$(echo "$line" | awk -F":" '{print $2}')
    if [ ! -e "$item_filename" ]; then
        AddRecord "$item_filename missing"
        AddError
    fi
    acture_md5=$(md5sum "$item_filename" | awk '{print $1}')
    if [ "$item_filemd5" = "$acture_md5" ]; then
        continue
    else
        AddRecord "$item_filename" "md5 diff! file:" "$item_filemd5" "acture:" "$acture_md5"
        AddError
    fi
done </tmp/MachineDecDir/check_md5list

while read xxx; do

...

done </filename

循环读取文件名 filename 所指向的文件的内容,每读取一行存入 xxx 变量。read xxx为 while 语句的判断语句,判断语句和 do如果不在同一行,则 ;可省略,如:

while read xxx

do

...

done </filename

read 后边的 -r 表示读取内容过程中对特殊字符有效,如 / (输入未结束需要换行继续输入的特殊符号),'/n' 等等。

[ -n "${line}" ] 判断 line 的内容不为空。而前边的 '||' 表示前一语句 read -r line 返回 false 才执行这个语句。

[ "$line" = "" ] && continue 表示如果 line 的内容为空则执行 continue;continue 命令用于跳过当前循环内容回去执行 while 判断语句。

 item_filename=$(echo "$line" | awk -F":" '{print $1}') 声明变量 item_filename 并以后边语句执行结果赋值。awk -F":" '{print $1}') 将输入的内容按照 : 来划分字段并输出第1个字段。awk -F":" '{print $2}') 则是将输入的内容按照 ':' 来划分字段并输出第2个字段。

if [ ! -e "$item_filename" ] 用于判断变量 item_filename 代表的文件名所指的文件是否不存在。!表示取反。if 判断的内容为 true 则执行 then 后边的语句,直到 fi 为止,否则跳过。

md5sum "$item_filename" 表示计算变量 item_filename 代表的文件名所指的文件的MD5值。

 | awk '{print $1}' 将前一语句的输出通过管道连接到后边的这个语句的输入,默认按照空格划分内容并输出第1个字段内容。

if [ "$item_filemd5" = "$acture_md5" ]; then 判断 item_filemd5 和 acture_md5 所代表的内容作为字符串是否一样,是则执行 then 后的语句。continue 指示程序执行流程直接回到执行 while 判断语句。else 后的语句块当 if 的判断条件不为 true 时执行。

#找到 U 盘路径
UDiskMountDir=$(df | grep /mnt/sd | awk 'END{print $NF}')
#校验mcu程序版本,U盘下有mcuversion.txt才校验
UDiskMountDirfile="${UDiskMountDir}/SpecialDir/mcuversion.txt"
CurMcuVersionFile="/tmp/mcuversion.txt"
if [ -f "$UDiskMountDirfile" ]; then
    TargetMcuVersion=$(cat "$UDiskMountDirfile")
    if [ -f "$CurMcuVersionFile" ]; then
        CurMcuVersion="$(cat "$CurMcuVersionFile")"
        if [ "$TargetMcuVersion" != "$CurMcuVersion" ]; then
            AddRecord "mcuversion diff cur:$CurMcuVersion target:$TargetMcuVersion"
            AddError
        fi
    else
        AddRecord "$CurMcuVersionFile not found"
        AddError
    fi
fi

UDiskMountDirfile="${UDiskMountDir}/SpecialDir/mcuversion.txt" 声明变量 UDiskMountDirfile 并赋值为其后的内容,其后是将变量 UDiskMountDir 所代表的路径名与后边的字符串结合为新的文件名。

if 语句可以有多重嵌套,如上。

[ "$TargetMcuVersion" != "$CurMcuVersion" ] 判断 TargetMcuVersion 和 CurMcuVersion 所代表的内容是否不相等。

#写入检查结果
if [ $AllCheckPassed = "true" ]; then
    AddRecord "Pass"
else
    AddRecord "Fail"
fi

if [ $AllCheckPassed = "true" ]; then 判断 AllCheckPassed 的值是否等于字符串 "true",是则调用函数 AddRecord 并传入参数字符串 "Pass",否则调用函数 AddRecord 并传入参数字符串 "Fail"。

#启动checkall
/data/bin/Factory/MachineCheckNode MachineImcomingTest

调用绝对路径下的程序 MachineCheckNode,并传入字符串参数 MachineImcomingTest。此种调用方式,要求程序文件 MachineCheckNode 具有可执行的权限属性x。想要查看指定路径下所有文件或某个文件的属性可以使用命令 ls -l查看,r表示可读,w表示可写,x表示可执行。

username@DESKTOP-ABCDEF:/mnt/d/username/work/temp$ ls -l
total 0
drwxrwxrwx 1 username username 4096 May 21 16:10 Udisk_IQC

这篇讲解到此为止,下期再见!

尝试阅读理解一份linux shell脚本的更多相关文章

  1. 读《Linux Shell脚本攻略》(第2版) 总结

    前段时间读完了<Linux Shell脚本攻略>(第2版)这本书,给部分想读这本书的人分享下个人感受. 说下这本书的难度吧.纯新手或者只懂少部分编程知识的人,读起来还是有很大难度的.以我为 ...

  2. linux ——shell 脚本

                                                      linux—shell 脚本  精简基础                 2018/10/30 13 ...

  3. 读《Linux Shell脚本攻略》(第2版) 一遍、二遍体会

    前段时间读完了<Linux Shell脚本攻略>(第2版)这本书,给部分想读这本书的人分享下个人感受. 第一遍体会解读:就像黑夜中的灯塔,指明前进的道路. 推荐指数:强烈推荐. 书中讲解的 ...

  4. Linux Shell脚本入门--wget 命令用法详解

    Linux Shell脚本入门--wget 命令用法详解 wget是在Linux下开发的开放源代码的软件,作者是Hrvoje Niksic,后来被移植到包括Windows在内的各个平台上.它有以下功能 ...

  5. linux shell 脚本攻略学习20--awk命令入门详解

    awk生于1977年,创始人有三个,分别为 Alfred Aho,Peter Weinberger, 和 Brian Kernighan,名称源于三个创始人的姓的首字母. 作用:处理文本文件. awk ...

  6. LINUX SHELL脚本攻略笔记[速查]

    Linux Shell脚本攻略笔记[速查] 资源 shell script run shell script echo printf 环境变量和变量 pgrep shell数学运算 命令状态 文件描述 ...

  7. Linux shell脚本基础学习详细介绍(完整版)二

    详细介绍Linux shell脚本基础学习(五) Linux shell脚本基础前面我们在介绍Linux shell脚本的控制流程时,还有一部分内容没讲就是有关here document的内容这里继续 ...

  8. Linux shell脚本编程(三)

    Linux shell脚本编程 流程控制: 循环语句:for,while,until while循环: while CONDITION; do 循环体 done 进入条件:当CONDITION为“真” ...

  9. Linux shell脚本编程(二)

    Linux shell脚本编程(二) 练习:求100以内所有偶数之和; 使用至少三种方法实现; 示例1: #!/bin/bash # declare -i sum=0 #声明一个变量求和,初始值为0 ...

随机推荐

  1. 交替方向乘子法(Alternating Direction Multiplier Method,ADMM)

    交替方向乘子法(Alternating Direction Multiplier Method,ADMM)是一种求解具有可分结构的凸优化问题的重要方法,其最早由Gabay和Mercier于1967年提 ...

  2. SLSA 框架与软件供应链安全防护

    随着软件供应链攻击浪潮愈演愈烈,Google 发布了一系列指南来确保软件包的完整性,旨在防止影响软件供应链的未经授权的代码修改.新的 Google SLSA 框架(Supply-chain Level ...

  3. .NET Core 实现后台任务(定时任务)BackgroundService(二)

    原文连接:https://www.cnblogs.com/ysmc/p/16468560.html 在上一篇文档中说到使用 IHostedService 接口实现定时任务,其中,有小伙伴就问到,为什么 ...

  4. 【FAQ】应用内支付服务无法拉起支付页面常见原因分析和解决方法

    华为应用内支付服务(In-App Purchases)通过简便的接入流程为用户提供良好的应用内支付体验,然而在实际接入过程中,有一些开发者反馈测试时会无法正常拉起支付页面,下文将详细分析问题出现的5种 ...

  5. 【USACO 2012 Open】奶牛赛跑_题解

    奶牛赛跑 目录 奶牛赛跑 题目描述 输入格式 输出格式 样例 样例输入#1 样例输出#1 题解 代码 题目描述 约翰有头奶牛,他为这些奶牛准备了一个周长为的环形跑牛场.所有奶牛从起点同时起跑,奶牛在比 ...

  6. DelayQueue达到定时触发效果

    DelayQueue的特点就是插入Queue中的数据可以按照自定义的delay时间进行排序.只有delay时间小于0的元素才能够被取出. 这样子,只要开启一个线程循环从DelayQueue中取值执行, ...

  7. 重写Object的equals方法和Objects的equals方法

    Object类的equals方法默认比较的是两个对象的地址值,没有意义 所以我们需要重写equals方法,比较两个对象的属性值(name,age等等): 对象的属性值一样返回true否则返回false ...

  8. vue-resource && axios

    1 # axios 2 # 1.安装:npm i axios 3 # 2.使用: 4 import axios from 'axios' 5 axios.get(URL).then(response= ...

  9. beego下让swagger按照更新了controllers的接口信息自动更新commentsRouter_controllers.go

    beego下让swagger按照更新了controllers的接口信息自动更新commentsRouter_controllers.go (1)在beego环境中,当更新了controllers目录下 ...

  10. Git 06 分支

    参考源 https://www.bilibili.com/video/BV1FE411P7B3?spm_id_from=333.999.0.0 版本 本文章基于 Git 2.35.1.2 概述 分支用 ...