五.shell脚本的跟踪与调试

最近在看《鸟哥的LINUX私房菜 基础学习篇》,目前看到了shell脚本这一章,打算在这里简单记录一下这一整章的学习过程和相关的知识点。

参考资料:《鸟哥的LINUX私房菜 基础学习篇》第四版 第十二章
实验环境: Ubuntu18.04

这一小节是shell脚本系列的最后一节内容。在前面的四个小节里,我们学习了编写shell脚本的基本语法,利用之前的知识可以编写复杂的脚本。在实践中,我们常常需要对脚本进行调试,寻找出错的位置和原因。在这一节里,我们学习如何跟踪和调试shell脚本。
在执行脚本前,我们可以直接使用bash的相关参数判断脚本是否有问题。

bash [ -nvx ] scripts.sh
#参数说明:
-n: 不执行脚本,只检查语法错误(没有错误时不显示任何信息)
-v: 在执行前,将脚本的内容显示到屏幕上
-x:将使用到的脚本内容显示在屏幕上
  • 简单的示例
# + 符号后面的内容为脚本内容,通过显示使用到的脚本内容可以方便的知道当前执行到哪一个指令
(base) laifeng@laifeng-X6:~/bin$ bash -x show_animal.sh 
+ for animal in dog cat elephant
+ echo 'There are dogs...'
There are dogs...
+ for animal in dog cat elephant
+ echo 'There are cats...'
There are cats...
+ for animal in dog cat elephant
+ echo 'There are elephants...'
There are elephants...

到这里,我们已经了解了关于shell脚本的全部内容。下面通过一个实际的脚本,来了解之前的内容都是怎样在实际中被运用的。
下面的脚本来自于github中tf-fater-rcnn-master中的脚本文件,如果是做计算机视觉领域相关领域的同学肯定听说过目标检测网络faster rcnn。为了方便,一些指令的功能已经进行了注释。

  • 示例:test_faster_rcnn.sh
#!/bin/bash

#设置bash的输入和输出的环境
set -x  #-x 在命令执行前,会显示命令内容(前面有++符号)
set -e #-e 告诉bash如果任何语句的执行结果不是true则应该退出,防止错误像滚雪球般变大导致一个致命的错误

export PYTHONUNBUFFERED="True"

GPU_ID=$1
DATASET=$2
NET=$3

array=( $@ )#定义数组,数组的元素为执行脚本时输入的参数
len=${#array[@]} #固定用法,获取数组元素的个数
EXTRA_ARGS=${array[@]:3:$len} #取下标为3开始的所有元素
EXTRA_ARGS_SLUG=${EXTRA_ARGS// /_} #变量替换 ${value//pattern/string}将value中与pattern匹配的部分替换成string,这里将 替换成_

#case分支判断
case ${DATASET} in
  pascal_voc)
    TRAIN_IMDB="voc_2007_trainval"
    TEST_IMDB="voc_2007_test"
    ITERS=70000
    ANCHORS="[8,16,32]"
    RATIOS="[0.5,1,2]"
    ;;
  pascal_voc_0712)
    TRAIN_IMDB="voc_2007_trainval+voc_2012_trainval"
    TEST_IMDB="voc_2007_test"
    ITERS=110000
    ANCHORS="[8,16,32]"
    RATIOS="[0.5,1,2]"
    ;;
  coco)
    TRAIN_IMDB="coco_2014_train+coco_2014_valminusminival"
    TEST_IMDB="coco_2014_minival"
    ITERS=490000
    ANCHORS="[4,8,16,32]"
    RATIOS="[0.5,1,2]"
    ;;
  *)
    echo "No dataset given"
    exit
    ;;
esac

LOG="experiments/logs/test_${NET}_${TRAIN_IMDB}_${EXTRA_ARGS_SLUG}.txt.`date +'%Y-%m-%d_%H-%M-%S'`" #'命令' 执行命令相当于$(命令)
exec &> >(tee -a "$LOG")
echo Logging output to "$LOG"

set +x #关闭,与set -x对应
if [[ ! -z  ${EXTRA_ARGS_SLUG}  ]]; then #-z 判断字符串是否为空,为空时返回true;
  NET_FINAL=output/${NET}/${TRAIN_IMDB}/${EXTRA_ARGS_SLUG}/${NET}_faster_rcnn_iter_${ITERS}.ckpt
else
  NET_FINAL=output/${NET}/${TRAIN_IMDB}/default/${NET}_faster_rcnn_iter_${ITERS}.ckpt
fi
set -x

if [[ ! -z  ${EXTRA_ARGS_SLUG}  ]]; then
  CUDA_VISIBLE_DEVICES=${GPU_ID} time python ./tools/test_net.py \
    --imdb ${TEST_IMDB} \
    --model ${NET_FINAL} \
    --cfg experiments/cfgs/${NET}.yml \
    --tag ${EXTRA_ARGS_SLUG} \
    --net ${NET} \
    --set ANCHOR_SCALES ${ANCHORS} ANCHOR_RATIOS ${RATIOS} \
          ${EXTRA_ARGS}
else
  CUDA_VISIBLE_DEVICES=${GPU_ID} time python ./tools/test_net.py \
    --imdb ${TEST_IMDB} \
    --model ${NET_FINAL} \
    --cfg experiments/cfgs/${NET}.yml \
    --net ${NET} \
    --set ANCHOR_SCALES ${ANCHORS} ANCHOR_RATIOS ${RATIOS} \
          ${EXTRA_ARGS}
fi                                                                                                                                                                            

在这个脚本中可能使用到了一些我们不知道的指令,但是通过查阅相关指令的功能,可以发现整个脚本还是很简单的。我们慢慢的来分析。
首先,#!/bin/bash是第一节内容,脚本的开头指定使用的shell程序。接下的是一些对bash的设置,可以先不管。
然后是GPU_ID=$1 DATASET=$2 NET=$3 这是第二节中关于脚本的默认参数的内容,12...是执行脚本时传入的参数。
接下来又是一堆看不懂的指令,没关系,不影响继续阅读。
我们看接下来的一大段,不就是case...esac条件判断,也是很简单的内容。

case ${DATASET} in
  pascal_voc)
    TRAIN_IMDB="voc_2007_trainval"
    ...
    ;;
  pascal_voc_0712)
    TRAIN_IMDB="voc_2007_trainval+voc_2012_trainval"
    ...
    ;;
  coco)
    TRAIN_IMDB="coco_2014_train+coco_2014_valminusminival"
    ...
    ;;
  *)
    echo "No dataset given"
    exit
    ;;
esac

最后的两大段,就是简单的if...else..fi条件判断。

if [[ ! -z  ${EXTRA_ARGS_SLUG}  ]]; then #-z 判断字符串是否为空,为空时返回true;
  NET_FINAL=output/${NET}/${TRAIN_IMDB}/${EXTRA_ARGS_SLUG}/${NET}_faster_rcnn_iter_${ITERS}.ckpt
else
  NET_FINAL=output/${NET}/${TRAIN_IMDB}/default/${NET}_faster_rcnn_iter_${ITERS}.ckpt
fi
...

整个脚本看完,是不是感觉还是很简单的?当然,其中的一些没见过的指令还是需要一个个耐心的查阅相关资料,但是整体来说,shell脚本还是很简单而功能强大的。
想要了解更多关于shell脚本的内容?欢迎参考Linux shell脚本 :)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容