bash语言笔记

测试开发的shell水平

  • linux

    • 文件操作
    • 网络操作 netstat
    • 系统数据分析 ps、top
    • 数据分析能力(linux 三剑客)
  • shell语法、脚本、管道、环境变量

  • 编写各种自动化脚本

    • 环境部署自动化
    • 测试用例调度自动化
    • jenkins持续集成中辅助脚本

bash语言总览

  • 变量

  • 逻辑控制

  • shell环境

  • 脚本应用

  • 自动化

变量

变量的定义

a=1
b=daybreak
c="hello world"
d='你玩过"吃鸡"游戏吗'
e=`pwd`
  • =左右两边不要有空格
  • 双引号支持转义
  • $ 开头的变量会被自动替换

变量的使用

echo $a
echo ${b}
echo "${a}"
  • 使用$var${var}来访问变量。后者更严谨。$var_x${var_x}是不同的
  • 变量未定义也可以使用。引用未定义的变量 ,默认为空值

预定义变量

echo $PWD
echo $USER
echo $HOME
echo $PATH

数组变量

  • 定义数组变量
array=(1,2,3)
array=(`ls`)
  • 使用数组变量
echo ${array[index]}
echo ${array[*]}  //获取数组中的所有元素
echo ${#array[*]} //获取数组的长度

变量类型

  • 字符串 a="hello"
  • 数字 b=1
  • 布尔 c=true

数字型变量操作

  • 计算
i=1;
echo $i
echo $(i+1)
  • 更新
i=i+1;
echo $i
  • 注意
    • 只能进行整数运算
    • 浮点数计算请使用awk 'BEGIN{print 1/3}'
    • 格式化显示可以换用 awk'BEGIN{print("%.2f\n,1/3")}'

字符串操作

  • 取值
    ${string:start:lenght} 从变量中提取字串

    a="hello"
    echo ${a:0:3}   #结果为hel
    

    ${#string} 获取字符串长度

  • 掐头去尾与内容替换
    ${string#pattern} ${string##pattern} #表示掐头
    ${string%pattern} ${string%%pattern} %表示去尾
    ${string/pattern/替换的string} ${string//pattern/替换的string} /表示替换
    使用#或##、%或%%、/或//的区别:最短匹配或最长匹配模式

布尔变量

  • true
  • false
  • 命令执行返回值$?
命令
echo $?

#任何命令执行都有一个返回值,0表示正确,非0表示错误

判断类型

  • 算术判断
    -eq 等于 [2 -eq 2]
    -ne 不等于
    -gt 大于
    -ge 大于等于
    -lt 小于
    -le 小于等于

  • 字符串判断
    [string1=string2] 两字符串相同,则结果为真
    [string1!=string2] 两字符串不相同,则结果为真
    [-n "$var" ] 如字符串不是空,则结果为真
    [-z "$var" ] 如字符串是空,则结果为真
    [["xxxx"==x*] ] 在表达式中表示0或者多个字符
    [[xxx==x??]] 在表达式中表示单个字符

    • 在引用变量的时候要记得加双引号[-z "$var" ]否则当a未定义时会语法报错
  • 逻辑判断
    [2 -ge 1 -a 3 -ge 4];echo $? -a and 与
    [2 -ge 1 -o 3 -ge 4];echo $? -o or 或
    [2 -ge 1 && 3 -ge 4];echo $?
    [2 -ge 1 || 3 -ge 4];echo $?
    [!2 -ge 1 ];echo $?

  • shell内置判断
    -e file 如果文件存在,则结果为真
    -d file 如果文件是一个子目录,则结果为真
    -f file 如果文件是一个普通文件,则结果为真
    -r file 如果文件可读,则结果为真
    -s file 如果文件的长度不为0,则结果为真
    -w file 如果文件可写,则结果为真
    -x file 如果文件可执行,则结果为真

    • [[]][]的拓展语法,在老的sh里并不支持。推荐用[]

逻辑控制

If结构

  • if [condition];then...;fi

  • if [condition];then...;else...;fi

  • if [condition];then...;elif...;fi

  • 简单的逻辑可以使用&& ||去替代

  • 条件可以用命令返回值代替

for 循环

  • 语法
for((i=0;i<10;i++));do echo $i;done
  • for遍历循环
    用于递归数组和递归以空格隔开的字符串,或者某个命令的返回值
    for f in $array[*];
    do
    ...;
    done
    
    ss="aa bb cc dd";for x in $ss;do echo $x;done
    for x in `ls`;do echo $x;done
    ss=(aa bb cc "sss dd");for x in "${ss[@]}";do echo $x;done
    

while循环

  • 语法
i=0;
while [$i -lt 3];
do echo $i;
((i=i+1));
done
  • 一行行读取文件
while read line;
do echo $line;
done<tmp/tmp

退出控制

  • return 函数返回
  • exit 脚本进程退出
  • break 退出当前循环
  • continue 跳过当前的循环,进入下一个循环

shell环境

shell环境概念

  • bash下还可以再重新启动一个shell,这个shell是sub shell,原shell会复制自身给他。在sub shell中定义的变量,会随着sub shell的消亡而消亡。
  • () 子shell中运行
  • $(ls) 表示执行ls后的结果,与``作用一致,不过可以嵌套
  • {} 当前shell中执行
  • $$ 当前脚本执行的pid
  • & 后台执行
  • $! 运行在后台的最后一个作业的pid(进程id)

shell环境变量

  • shell首先是一个工作环境,有很多变量可以提供我们使用
  • set可以获得当前的所有变量
  • env可以获得可以传递给子进程的变量
  • export aa=bbb 把私有变量导出

shell输入输出

  • read用来读取输入,并赋值给变量
  • echo print可以输出简单变量
  • >file 将输出重定向到另一个文件
  • >>表示追加 等价于tee -a
  • | 表示管道,也就是前一个命令的输出传入下一个命令的输入

文件描述符

  • 输入文件-标准输入0
  • 输出文件-标准输出1
  • 错误输出文件-标准错误2
  • curl
  • 使用2>&1>/tmp/tmp</tmp/tmp

脚本编写

  • 注释
    #以后的语句,shell不会解析
    多行注释可以采用:<<

  • 传入参数

    • $0 表示执行的程序,是相对于执行目录的路径
    • $1,$2,$3分别表示第几个参数,默认shell只支持9个参数,使用shift可以传递更多的参数
    • $@,$*表示所有参数,不含$0
    • ${#*}${#@}表示位置参数的个数
    • 通过${*:1:3},${*:$#}来表示多个参数
  • 函数

    • 语法
    [function] name()
    {
    ..
    }
    
    • function 可以省略。除了可以在脚本文件中使用函数外,还可以shell中定义。这些定义在本次shell结束后消失
    • 如果没有return,返回值是最后一句指令的返回值
  • 执行

方式一:
chmod u+x xxx.sh;
./xxx.sh
方式二:
bash xxx.sh #这种方式会开启一个sub shell
方式三:
source xxx.sh  #在当前shell中执行

 - eval 可以执行shell原义语句
 - exec 尽量不要使用,这会破坏当前的shell
  • 调试
    • bash -x 读取每一句并执行,可以方便的看到执行的语句
    • set -x 在当前shell中调试,set+x还原
    • trap 相关的信号,包括ERR DEBUG等
    • trap cmd ERR

三剑客

  • grep 数据查找定位(检索)

  • awk 数据切片

  • sed 数据修改

bash自动化

自动化交互

  • 批处理并不等于自动化
  • 让交互程序实现非交互执行
  • 借用第三方工具expect

自动输入方法

  • << 文档字符串。可以实现对序列化输入的操作自动化
  • 管道方式 echo 'password' |passwd
  • 去掉sudo密码提示,也可以通过修改sudoer文件
  • 去掉ssh密码,也可以通过添加认证
  • except

linux命令

测试开发应该达到的水平:

  • 文件操作
  • 网络操作 netstat
  • 系统数据分析 ps、top
  • 数据分析能力(linux 三剑客)

一键搭建web网站

python -m CGIHTTPServer 8080
python3 -m http.server

gnuplot 绘图

  • 通过管道读取数据并绘图

更多工具

  • 文件系统

    • find、ls、chmod、chown
  • 系统性能统计命令

    • ps netstat top vmstat free
    • netstat -tlnp
    • netstat -tnp
    • /proc 目录保存了所有进程的性能数据

Andriod常用命令

  • adb

    • adb devices
    • adb kill-server
    • adb tcpip
    • adb connect
    • adb logcat
    • adb bugreport
  • 模拟器的命令

    • 进入emulator所在目录
    • emulator -list-avds
    • emulator@avd
  • adb shell
    adb shell本身就是一个linux shell,可以调用所有的Android内置命令
    adb shell

    • adb shell dumpsys
    • adb shell pm
    • adb shell am
    • adb shell ps
    • adb shell monkey

iOS命令

(以后讲)

快速搜索历史输入

ctrl+r
bck-i-search:
ctrl+a 行首
ctrl+e 行尾

实战

提取对外连接的ip数量

  • 题目解析

    • 目标对象是对外连接的ip,从ngnix上提取
    • netstat命令用于显示与IP、TCP、UDP和ICMP协议相关的统计数据,一般用于检验本机各端口的网络连接情况。
  • bash

#使用命令netstat 参数-ntp
netstat -ntp
#删掉多余的数据行第一行、第二行, 使用sed 1,2d
netstat -ntp | sed 1,2d
#提取内容第五部分,使用awk '{print $5}'
netstat -ntp | sed 1,2d | awk '{print $5}'
#去掉端口号,使用awk -F ':' '{print $1}'
netstat -ntp | sed 1,2d | awk '{print $5}' | awk -F ':' '{print $1}'
#使用sort进行排序,使数据看上去规整一些
netstat -ntp | sed 1,2d | awk '{print $5}' | awk -F ':' '{print $1}' | sort
#去除重复的ip,使用uniq 命令删除重复的行,参数-c显示每个ip出现的次数
netstat -ntp | sed 1,2d | awk '{print $5}' | awk -F ':' '{print $1}' | sort | uniq -c
#使用wc获取ip的数量,参数-l统计行数
netstat -ntp | sed 1,2d | awk '{print $5}' | awk -F ':' '{print $1}' | sort | uniq -c | wc -l

提取testhome首页精华帖的点赞数

  • 题目解析

    • 目标对象是testhome首页所有精华帖的点赞数量
    • 使用curl命令可以模拟http请求
  • bash

#使用curl命令模拟http请求
curl https://testerhome.com
#讲请求返回的错误信息仍进黑洞/dev/null
curl https://testerhome.com 2>/dev/null
#通过开发者工具-检查元素可以查看到精华帖后面的一个钻石icon属于class="fa fa-diamond"
curl https://testerhome.com 2>/dev/null | grep "fa fa-diamond"
#精华帖的list在钻石icon的上一行,使用参数-b1,代表before1行
curl https://testerhome.com 2>/dev/null | grep -b1 "fa fa-diamond"
#实际需要的是精华帖列表那一行,通过该行的关键字筛选
curl https://testerhome.com 2>/dev/null | grep -b1 "fa fa-diamond" | grep "href"
#每个精华帖的href不一样,同时也是每个精华帖的路径,使用awk进行切割
curl https://testerhome.com 2>/dev/null | grep -b1 "fa fa-diamond" | grep "href" | awk -F '\"' '{print $4}'
#因为article是文章集,所以只要topic开头的
curl https://testerhome.com 2>/dev/null | grep -b1 "fa fa-diamond" | grep "href" | awk -F '\"' '{print $4}' | grep "topics"
#进入精华帖详情页去获取点赞数,精华帖详情页的路径https://testerhome.com+上面获取的路径列表
#一行行读取列表,使用while read line;do echo $line;done
curl https://testerhome.com 2>/dev/null | grep -b1 "fa fa-diamond" |grep "href"|awk -F '\"' '{print $4}'| grep "topics"| while read line;do curl https://testerhome.com$line 2>/dev/null;done 
#进入了精华帖详情页,根据开发者工具-检查元素可以发现记录点赞数的class是 "fa fa-heart"
curl https://testerhome.com 2>/dev/null | grep -b1 "fa fa-diamond" |grep "href"|awk -F '\"' '{print $4}'| grep "topics"| while read line;do curl https://testerhome.com$line 2>/dev/null;done |grep "fa fa-heart" 
#除了话题点赞数之外,还有回复的点赞数,使用 grep "data-type=\"Topic\""去掉回复的点赞数的行
curl https://testerhome.com 2>/dev/null | grep -b1 "fa fa-diamond" |grep "href"|awk -F '\"' '{print $4}'| grep "topics"| while read line;do curl https://testerhome.com$line 2>/dev/null;done |grep "fa fa-heart" |grep "data-type=\"Topic\""
#通过awk分割后展示topic、topicid 、点赞数
curl https://testerhome.com 2>/dev/null | grep -b1 "fa fa-diamond" |grep "href"|awk -F '\"' '{print $4}'| grep "topics"| while read line;do curl https://testerhome.com$line 2>/dev/null;done |grep "fa fa-heart" |grep "data-type=\"Topic\""|awk -F '\"' '{print $8,$10,$4}'
#另一种显示:在curl详情页时把点赞数记为一个变量
curl https://testerhome.com 2>/dev/null | grep -b1 "fa fa-diamond" |grep "href"|awk -F '\"' '{print $4}'| grep "topics"| while read line;do count=$(curl https://testerhome.com$line 2>/dev/null |grep "fa fa-heart" |grep "data-type=\"Topic\""|head -1|awk -F '\"' '{print $4}');echo "$line 点赞数是: $count";done

从nginx log中提取数据并可视化

  • nginx log在/tmp目录下
  • ls -l *.log搜索日志
  • bash
#确定目标日志是1206_2.log
cat 1206_2.log
#使用sed提取某个时间段的日志
#-n选项:只显示匹配处理的行(否则会输出所有)
cat 1206_2.log | sed -n '/07:48:00/,/07:52:00/p'
#使用gnuplot插件进行数据展示(gnuplot不会,随便看看吧)
cat 1206_2.log | sed -n '/07:48:00/,/07:52:00/p' | gnuplot -e "set terminal dumb;set datafile |separator ' ';set timefmt '[%d/%b/%Y:%H%:%M:%S]';set ydata time;set format y '%H%M'%S;|plot '<cat' using 8:4 with lines"
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354