固件加头部信息
在OTA升级中,常常需要对固件进行合法性校验,比如完整性、硬件版本、软件版本等,
这里是一个简单的格式,可用于普通的场景,正式环境中还应该考虑加密等安全措施。
参考格式
固件的头部信息,可以是多种格式,一般可能更多的是二进制数据格式,考虑到后期方便扩展,这里选择使用json格式。
1 | ABCD{ |
JSON参数说明
ABCD – json数据的长度,2字节,16进制字串格式,如 3456表示0x3456;
magic – 魔数,表示固件的类型,以设备类型_XX
表示,其中XX
用于区别同一类型设备的不同版本;
appVer – 固件版本号,设备根据版本号决定是否升级;
hardVer – 支持的硬件(最低)版本,设备根据硬件版本信息,判断此固件是否适用,从而决定是否可以升级;
format – 固件格式,主要有如下格式:
格式 | 说明 |
---|---|
elf | linux可执行文件格式,主要用于网关 |
ipk | openwrt固件安装包格式,用于网关 |
bin | 二进制格式, 主要用于子设备 |
hex | hex文件格式,主要用于子设备 |
size – 固件大小(不包含固件头json信息),int型,占4字节,单位byte;
md5 – 固件的MD5校验值, 32位字符串。
相关知识
jq – JSON命令行处理工具
jq简介
jq 是一款命令行下处理 JSON 数据的工具。其可以接受标准输入,命令管道或者文件中的 JSON 数据,经过一系列的过滤器(filters)和表达式的转后形成我们需要的数据结构并将结果输出到标准输出中。jq 的这种特性使我们可以很容易地在 Shell 脚本中调用它。
需要说明的是 jq 只能接受 well form 的 JSON 字符串作为输入内容。也就是说输入内容必须严格遵循 JSON 格式的标准。所有的属性名必须是以双引号包括的字符串。对象的最后一个属性的末尾或者数组的最后一个元素的末尾不能有逗号。否则 jq 会抛出无法解析 JSON 的错误。
jq基本操作
帮助
1
jq -h
格式化json
1
2
3
4
5
6
7
8-c 删除漂亮的格式输出
echo '{"url": "mozillazg.com"}' |jq -c .
{"url":"mozillazg.com"}
echo '{"url": "mozillazg.com"}' |jq .
{
"url": "mozillazg.com"
}获取某个key值
.key
,.foo.bar
,["key"]
1
2
3
4
5
6
7
8
9
10
11
12如果key对应的值存在,则输出值
echo '{"url": "mozillazg.com"}' |jq .url
"mozillazg.com"
echo '{"url": "mozillazg.com"}' | jq '.["url"]'
"mozillazg.com"
如果key对应的值不存在,则输出null
echo '{"notfoo": true, "alsonotfoo": false}' | jq '.foo'
null
echo '{"notfoo": true, "alsonotfoo": false}' | jq .foo
null数组操作
.[]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25取出所有元素
echo '[{"name": "tom"}, {"name": "mozillazg"}]' |jq .[]
{
"name": "tom"
}
{
"name": "mozillazg"
}
取出第1个元素,下标从0开始
echo '[{"name": "tom"}, {"name": "mozillazg"}]' |jq .[0]
{
"name": "tom"
}
取出下标为 0 到 2(不包括2)之间的元素
echo '[{"name": "tom"}, {"name": "mozillazg"}, {"name": "jim"}]' |jq .[0:2]
[
{
"name": "tom"
},
{
"name": "mozillazg"
}
]取出数组元素中的key的值
1
2
3
4
5
6
7
8
9
10echo '[{"name": "foo"},{"name": "bar"},{"name": "foobar"}]' |jq .[].name
"foo"
"bar"
"foobar"
使用管道
echo '[{"name": "foo"},{"name": "bar"},{"name": "foobar"}]' |jq '.[]|.name'
"foo"
"bar"
"foobar"将结果重新组成数组
1
2
3
4
5
6
7
8
9
10
11
12
13
14echo '[{"name": "foo"},{"name": "bar"},{"name": "foobar"}]' |jq [.[].name]
[
"foo",
"bar",
"foobar"
]
使用map实现
echo '[{"name": "foo"},{"name": "bar"},{"name": "foobar"}]' |jq 'map(.name)'
[
"foo",
"bar",
"foobar"
]处理文件
使用
jq [选项] <jq表达式> [files]
形式;
使用cat [files] | jq [选项] <jq表达式>
jq高级操作
管道
- 支持管道线|,它如同linux命令中的管道线——把前面命令的输出当作是后面命令的输入。
1
2echo '{"url": "mozillazg.com", "name": "mozillazg"}' | jq '.|.url'
"mozillazg.com"- 获取内容的长度(字符串,数组的长度)
1
2
3
4
5echo '{"url": "mozillazg.com", "name": "mozillazg"}' |jq '.url|length'
13
echo '["mozillazg.com", "mozillazg"]' |jq '.|length'
2map
map(foo)
可以实现对数组的每一项进行操作,然后合并结果的功能:1
2
3
4
5echo '["mozillazg.com", "mozillazg"]' | jq 'map(length)'
[
13,
9
]filter(select)
select(foo)
可以实现对输入项进行判断,只返回符合条件的项:1
2
3
4echo '["mozillazg.com", "mozillazg"]' | jq 'map(select(.|length > 9))'
[
"mozillazg.com"
]字符串插值,拼接
可以使用\(foo)
实现字符串插值功能:1
2echo '{"url": "mozillazg.com", "name": "mozillazg"}' |jq '"hi \(.name)"'
"hi mozillazg"注意要用双引号包围起来,表示是一个字符串。
if/elif/else
可以使用if .. then .. elif .. then .. else .. end
实现条件判断:1
2
3
4
5
6
7echo '[0, 1, 2, 3]' | jq 'map(if . == 0 then "zero" elif . == 1 then "one" elif . == 2 then "two" else "many" end)'
[
"zero",
"one",
"two",
"many"
]构造object或数组
可以通过{}
和[]
构造新的 object 或 数组:1
2
3
4
5
6
7
8
9
10
11
12object
echo '["mozillazg.com", "mozillazg"]' |jq '{name: .[1]}'
{
"name": "mozillazg"
}
array
echo '{"url": "mozillazg.com", "name": "mozillazg"}' |jq '[.name, .url]'
[
"mozillazg",
"mozillazg.com"
]
jq内置运算支持
jq 内部支持的数据类型有:数字,字符串,数组和对象(object)。并且在这些数据类型的基础上, jq 提供了一些基本的操作符来实现一些基本的运算和数据操作。列举如下:
- 数学运算。对于数字类型,jq 实现了基本的加减乘除(/)和求余(%)运算。对于除法运算,jq 最多支持 16 位小数。
- 字符串操作。jq 提供字符串的连接操作(运算符为’+’,例如:”tom “+”jerry”结果为”tom jerry”),字符串的复制操作(例如:’a’*3 结果为’aaa’),以及字符串分割操作(将字符串按照指定的分割符分成数组,例如”sas”/“s”的结果为[“”,”a”,””],而”sas”/“a”的结果为[“s”,”s”]。
- 数组操作。jq 提供两种数组运算:并集(‘+’)运算,结果数组中包含参与运算的数组的所有元素。差集运算(‘-‘),例如:有数组 a,b, a-b 的结果为所有在 a 中且不包含在 b 中的元素组成的数组。
- 对象操作。jq 实现了两个 JSON 对象的合并操作(merge)。当两个参与运算的对象包含相同的属性时则保留运算符右侧对象的属性值。有两种合并运算符:’+’和’‘。所不同的是,运算符’+’只做顶层属性的合并,运算符’‘则是递归合并。例如:有对象 a={“a”:{“b”:1}}, b={“a”:{“c”:2}},a+b 的结果为{“a”:{“c”:2}},而 a*b 的结果为{“a”:{“b”:1,”c”:2}}
- 比较操作:jq 内部支持的比较操作符有==, !=,>,>=,<=和<。其中,’==’的规则和 javascript 中的恒等(‘===’)类似,只有两个操作数的类型和值均相同时其结果才是 true。
- 逻辑运算符: and/or/not。在 jq 逻辑运算中,除了 false 和 null 外,其余的任何值都等同于 true。
- 默认操作符(‘//‘), 表达式’a//b’表示当表达式 a 的值不是 false 或 null 时,a//b 等于 a,否则等于 b。
jq修改json数据
原json内容:
例如需要修改size的值为123,方式如下:
1 | 重定向到新的文件,注意不能是原文件 |

参考引用
https://www.ibm.com/developerworks/cn/linux/1612_chengg_jq/index.html
https://mozillazg.com/2018/01/jq-use-examples-cookbook.html#hidid4
shell获取文件的大小
1 | ls -l filename | awk '{print $5}' |
shell计算文件的MD5
md5sum:
显示或检查 MD5(32-bit) 校验和,若没有文件选项,或者文件处为”-“,则从标准输入读取。
echo -n : 不打印换行符。
cut: cut用来从标准输入或文本文件中剪切列或域。剪切文本可以将之粘贴到一个文本文件。
-d 指定与空格和tab键不同的域分隔符。-f1 表示第一个域。
1 | md5sum iot_gateway |
shell删除某个字符
例如使用 tr -d '[ \t]
删除换行字符
1 | echo " 123 567 " | tr -d '[ \t]' #输出12345 |
使用shell添加头部信息
1 | !/bin/bash |