首页 文章 精选 留言 我的

精选列表

搜索[腾讯极客挑战赛],共10000篇文章
优秀的个人博客,低调大师

第七章 Shell文本处理三剑客之sed

本章大纲: 7.2sed 流编辑器,过滤和替换文本。 工作原理:sed命令将当前处理的行读入模式空间进行处理,处理完把结果输出,并清空模式空间。然后再将下一行读入模式空间进行处理输出,以此类推,直到最后一行。还有一个空间叫保持空间,又称暂存空间,可以暂时存放一些处理的数据,但不能直接输出,只能放到模式空间输出。 这两个空间其实就是在内存中初始化的一个内存区域,存放正在处理的数据和临时存放的数据。 Usage: sed [OPTION]... {script-only-if-no-other-script} [input-file]... sed [选项] '地址 命令' file 选项 描述 -n 不打印模式空间 -e 执行脚本、表达式来处理 -f 脚本文件的内容添加到命令被执行 -i 修改原文件 -r 使用扩展正则表达式 命令 描述 s/regexp/replacement/ 替换字符串 p 打印当前模式空间 P 打印模式空间的第一行 d 删除模式空间,开始下一个循环 D 删除模式空间的第一行,开始下一个循环 = 打印当前行号 a \text 当前行追加文本 i \text 当前行上面插入文本 c \text 所选行替换新文本 q 立即退出sed脚本 r 追加文本来自文件 : label label为b和t命令 b label 分支到脚本中带有标签的位置,如果分支不存在则分支到脚本的末尾 t label 如果s///是一个成功的替换,才跳转到标签 h H 复制/追加模式空间到保持空间 g G 复制/追加保持空间到模式空间 x 交换模式空间和保持空间内容 l 打印模式空间的行,并显示控制字符$ n N 读取/追加下一行输入到模式空间 w filename 写入当前模式空间到文件 ! 取反、否定 & 引用已匹配字符串 地址 描述 first~step 步长,每step行,从第first开始 $ 匹配最后一行 /regexp/ 正则表达式匹配行 number 只匹配指定行 addr1,addr2 开始匹配addr1行开始,直接addr2行结束 addr1,+N 从addr1行开始,向后的N行 addr1,~N 从addr1行开始,到N行结束 博客地址:http://lizhenliang.blog.51cto.com QQ群:323779636(Shell/Python运维开发群) 借助以下文本内容作为示例讲解: #tail/etc/services nimgtw48003/udp#NimbusGateway 3gpp-cbsp48049/tcp#3GPPCellBroadcastServiceProtocol isnetserv48128/tcp#ImageSystemsNetworkServices isnetserv48128/udp#ImageSystemsNetworkServices blp548129/tcp#Bloomberglocator blp548129/udp#Bloomberglocator com-bardac-dw48556/tcp#com-bardac-dw com-bardac-dw48556/udp#com-bardac-dw iqobject48619/tcp#iqobject iqobject48619/udp#iqobject 7.2.1 匹配打印(p) 1)打印匹配blp5开头的行 #tail/etc/services|sed-n'/^blp5/p' blp548129/tcp#Bloomberglocator blp548129/udp#Bloomberglocator 2)打印第一行 #tail/etc/services|sed-n'1p' nimgtw48003/udp#NimbusGateway 3)打印第一行至第三行 #tail/etc/services|sed-n'1,3p' nimgtw48003/udp#NimbusGateway 3gpp-cbsp48049/tcp#3GPPCellBroadcastServiceProtocol isnetserv48128/tcp#ImageSystemsNetworkServices 4)打印奇数行 #seq10|sed-n'1~2p' 1 3 5 7 9 5)打印匹配行及后一行 #tail/etc/services|sed-n'/blp5/,+1p' blp548129/tcp#Bloomberglocator blp548129/udp#Bloomberglocator 6)打印最后一行 #tail/etc/services|sed-n'$p' iqobject48619/udp#iqobject 7)不打印最后一行 #tail/etc/services|sed-n'$!p' 3gpp-cbsp48049/tcp#3GPPCellBroadcastServiceProtocol isnetserv48128/tcp#ImageSystemsNetworkServices isnetserv48128/udp#ImageSystemsNetworkServices blp548129/tcp#Bloomberglocator blp548129/udp#Bloomberglocator com-bardac-dw48556/tcp#com-bardac-dw com-bardac-dw48556/udp#com-bardac-dw iqobject48619/tcp#iqobject iqobject48619/udp#iqobject 感叹号也就是对后面的命令取反。 8)匹配范围 #tail/etc/services|sed-n'/^blp5/,/^com/p' blp548129/tcp#Bloomberglocator blp548129/udp#Bloomberglocator com-bardac-dw48556/tcp#com-bardac-dw 匹配开头行到最后一行: #tail/etc/services|sed-n'/blp5/,$p' blp548129/tcp#Bloomberglocator blp548129/udp#Bloomberglocator com-bardac-dw48556/tcp#com-bardac-dw com-bardac-dw48556/udp#com-bardac-dw iqobject48619/tcp#iqobject iqobject48619/udp#iqobject 以逗号分开两个样式选择某个范围。 9)引用系统变量,用引号 #a=1 #tail/etc/services|sed-n''$a',3p' 或 #tail/etc/services|sed-n"$a,3p" sed命令用单引号时,里面变量用单引号引起来,或者sed命令用双引号,因为双引号解释特殊符号原有意义。 7.2.2 匹配删除(d) #tail/etc/services|sed'/blp5/d' nimgtw48003/udp#NimbusGateway 3gpp-cbsp48049/tcp#3GPPCellBroadcastServiceProtocol isnetserv48128/tcp#ImageSystemsNetworkServices isnetserv48128/udp#ImageSystemsNetworkServices com-bardac-dw48556/tcp#com-bardac-dw com-bardac-dw48556/udp#com-bardac-dw iqobject48619/tcp#iqobject iqobject48619/udp#iqobject #tail/etc/services|sed'1d' 3gpp-cbsp48049/tcp#3GPPCellBroadcastServiceProtocol isnetserv48128/tcp#ImageSystemsNetworkServices isnetserv48128/udp#ImageSystemsNetworkServices blp548129/tcp#Bloomberglocator blp548129/udp#Bloomberglocator com-bardac-dw48556/tcp#com-bardac-dw com-bardac-dw48556/udp#com-bardac-dw iqobject48619/tcp#iqobject iqobject48619/udp#iqobject #tail/etc/services|sed'1~2d' 3gpp-cbsp48049/tcp#3GPPCellBroadcastServiceProtocol isnetserv48128/udp#ImageSystemsNetworkServices blp548129/udp#Bloomberglocator com-bardac-dw48556/udp#com-bardac-dw iqobject48619/udp#iqobject #tail/etc/services|sed'1,3d' isnetserv48128/udp#ImageSystemsNetworkServices blp548129/tcp#Bloomberglocator blp548129/udp#Bloomberglocator com-bardac-dw48556/tcp#com-bardac-dw com-bardac-dw48556/udp#com-bardac-dw iqobject48619/tcp#iqobject iqobject48619/udp#iqobject 去除空格http.conf文件空行或开头#号的行: #sed'/^#/d;/^$/d'/etc/httpd/conf/httpd.conf 删除与打印使用方法类似,可以理解是打印的取反。不用-n选项。 7.2.3 替换(s///) 1)替换blp5字符串为test #tail/etc/services|sed's/blp5/test/' 3gpp-cbsp48049/tcp#3GPPCellBroadcastServiceProtocol isnetserv48128/tcp#ImageSystemsNetworkServices isnetserv48128/udp#ImageSystemsNetworkServices test48129/tcp#Bloomberglocator test48129/udp#Bloomberglocator com-bardac-dw48556/tcp#com-bardac-dw com-bardac-dw48556/udp#com-bardac-dw iqobject48619/tcp#iqobject iqobject48619/udp#iqobject matahari49000/tcp#MatahariBroker 全局替换加g: #tail/etc/services|sed's/blp5/test/g' 2)替换开头是blp5的字符串并打印 #tail/etc/services|sed-n's/^blp5/test/p' test48129/tcp#Bloomberglocator test48129/udp#Bloomberglocator 3)使用&命令引用匹配内容并替换 #tail/etc/services|sed's/48049/&.0/' 3gpp-cbsp48049.0/tcp#3GPPCellBroadcastServiceProtocol isnetserv48128/tcp#ImageSystemsNetworkServices isnetserv48128/udp#ImageSystemsNetworkServices blp548129/tcp#Bloomberglocator blp548129/udp#Bloomberglocator com-bardac-dw48556/tcp#com-bardac-dw com-bardac-dw48556/udp#com-bardac-dw iqobject48619/tcp#iqobject iqobject48619/udp#iqobject matahari49000/tcp#MatahariBroker IP加单引号: #echo'10.10.10.110.10.10.210.10.10.3'|sed-r's/[^]+/"&"/g' "10.10.10.1""10.10.10.2""10.10.10.3" 4)对1-4行的blp5进行替换 #tail/etc/services|sed'1,4s/blp5/test/' 3gpp-cbsp48049/tcp#3GPPCellBroadcastServiceProtocol isnetserv48128/tcp#ImageSystemsNetworkServices isnetserv48128/udp#ImageSystemsNetworkServices test48129/tcp#Bloomberglocator blp548129/udp#Bloomberglocator com-bardac-dw48556/tcp#com-bardac-dw com-bardac-dw48556/udp#com-bardac-dw iqobject48619/tcp#iqobject iqobject48619/udp#iqobject matahari49000/tcp#MatahariBroker 5)对匹配行进行替换 #tail/etc/services|sed'/48129\/tcp/s/blp5/test/' 3gpp-cbsp48049/tcp#3GPPCellBroadcastServiceProtocol isnetserv48128/tcp#ImageSystemsNetworkServices isnetserv48128/udp#ImageSystemsNetworkServices test48129/tcp#Bloomberglocator blp548129/udp#Bloomberglocator com-bardac-dw48556/tcp#com-bardac-dw com-bardac-dw48556/udp#com-bardac-dw iqobject48619/tcp#iqobject iqobject48619/udp#iqobject matahari49000/tcp#MatahariBroker 6)二次匹配替换 #tail/etc/services|sed's/blp5/test/;s/3g/4g/' 4gpp-cbsp48049/tcp#3GPPCellBroadcastServiceProtocol isnetserv48128/tcp#ImageSystemsNetworkServices isnetserv48128/udp#ImageSystemsNetworkServices test48129/tcp#Bloomberglocator test48129/udp#Bloomberglocator com-bardac-dw48556/tcp#com-bardac-dw com-bardac-dw48556/udp#com-bardac-dw iqobject48619/tcp#iqobject iqobject48619/udp#iqobject matahari49000/tcp#MatahariBroker 7)分组使用,在每个字符串后面添加123 #tail/etc/services|sed-r's/(.*)(.*)(#.*)/\1\2test\3/' 3gpp-cbsp48049/tcptest#3GPPCellBroadcastServiceProtocol isnetserv48128/tcptest#ImageSystemsNetworkServices isnetserv48128/udptest#ImageSystemsNetworkServices blp548129/tcptest#Bloomberglocator blp548129/udptest#Bloomberglocator com-bardac-dw48556/tcptest#com-bardac-dw com-bardac-dw48556/udptest#com-bardac-dw iqobject48619/tcptest#iqobject iqobject48619/udptest#iqobject matahari49000/tcptest#MatahariBroker 将不变的字符串匹配分组,剩余就是要替换的,再反向引用。 8)将协议与端口号位置调换 #tail/etc/services|sed-r's/(.*)(\<[0-9]+\>)\/(tcp|udp)(.*)/\1\3\/\2\4/' 3gpp-cbsptcp/48049#3GPPCellBroadcastServiceProtocol isnetservtcp/48128#ImageSystemsNetworkServices isnetservudp/48128#ImageSystemsNetworkServices blp5tcp/48129#Bloomberglocator blp5udp/48129#Bloomberglocator com-bardac-dwtcp/48556#com-bardac-dw com-bardac-dwudp/48556#com-bardac-dw iqobjecttcp/48619#iqobject iqobjectudp/48619#iqobject mataharitcp/49000#MatahariBroker 9)位置调换 #echo"abc:cde;123:456"|sed-r's/([^:]+)(;.*:)([^:]+$)/\3\2\1/' abc:456;123:cde 10)注释匹配行后的多少行 #seq10|sed'/5/,+3s/^/#/' 1 2 3 4 #5 #6 #7 #8 9 10 11)去除开头和结尾空格或制表符 #echo"123"|sed's/^[\t]*//;s/[\t]*$//' 123 7.2.4 多重编辑(-e) #tail/etc/services|sed-e'1,2d'-e's/blp5/test/' isnetserv48128/udp#ImageSystemsNetworkServices test48129/tcp#Bloomberglocator test48129/udp#Bloomberglocator com-bardac-dw48556/tcp#com-bardac-dw com-bardac-dw48556/udp#com-bardac-dw iqobject48619/tcp#iqobject iqobject48619/udp#iqobject matahari49000/tcp#MatahariBroker 也可以使用分号分隔: #tail/etc/services|sed'1,2d;s/blp5/test/' 7.2.5 添加新内容(a、i和c) 1)在blp5上一行添加test #tail/etc/services|sed'/blp5/i\test' 3gpp-cbsp48049/tcp#3GPPCellBroadcastServiceProtocol isnetserv48128/tcp#ImageSystemsNetworkServices isnetserv48128/udp#ImageSystemsNetworkServices test blp548129/tcp#Bloomberglocator test blp548129/udp#Bloomberglocator com-bardac-dw48556/tcp#com-bardac-dw com-bardac-dw48556/udp#com-bardac-dw iqobject48619/tcp#iqobject iqobject48619/udp#iqobject matahari49000/tcp#MatahariBroker 2)在blp5下一行添加test #tail/etc/services|sed'/blp5/a\test' 3gpp-cbsp48049/tcp#3GPPCellBroadcastServiceProtocol isnetserv48128/tcp#ImageSystemsNetworkServices isnetserv48128/udp#ImageSystemsNetworkServices blp548129/tcp#Bloomberglocator test blp548129/udp#Bloomberglocator test com-bardac-dw48556/tcp#com-bardac-dw com-bardac-dw48556/udp#com-bardac-dw iqobject48619/tcp#iqobject iqobject48619/udp#iqobject matahari49000/tcp#MatahariBroker 3)将blp5替换新行 #tail/etc/services|sed'/blp5/c\test' 3gpp-cbsp48049/tcp#3GPPCellBroadcastServiceProtocol isnetserv48128/tcp#ImageSystemsNetworkServices isnetserv48128/udp#ImageSystemsNetworkServices test test com-bardac-dw48556/tcp#com-bardac-dw com-bardac-dw48556/udp#com-bardac-dw iqobject48619/tcp#iqobject iqobject48619/udp#iqobject matahari49000/tcp#MatahariBroker 4)在指定行下一行添加一行 #tail/etc/services|sed'2a\test' 3gpp-cbsp48049/tcp#3GPPCellBroadcastServiceProtocol isnetserv48128/tcp#ImageSystemsNetworkServices test isnetserv48128/udp#ImageSystemsNetworkServices blp548129/tcp#Bloomberglocator blp548129/udp#Bloomberglocator com-bardac-dw48556/tcp#com-bardac-dw com-bardac-dw48556/udp#com-bardac-dw iqobject48619/tcp#iqobject iqobject48619/udp#iqobject matahari49000/tcp#MatahariBroker 5)在指定行前面和后面添加一行 #seq5|sed'3s/.*/txt\n&/' 1 2 txt 3 4 5 #seq5|sed'3s/.*/&\ntxt/' 1 2 3 txt 4 5 7.2.6 读取文件并追加到匹配行后(r) #cata.txt 123 456 #tail/etc/services|sed'/blp5/ra.txt' 3gpp-cbsp48049/tcp#3GPPCellBroadcastServiceProtocol isnetserv48128/tcp#ImageSystemsNetworkServices isnetserv48128/udp#ImageSystemsNetworkServices blp548129/tcp#Bloomberglocator 123 456 blp548129/udp#Bloomberglocator 123 456 com-bardac-dw48556/tcp#com-bardac-dw com-bardac-dw48556/udp#com-bardac-dw iqobject48619/tcp#iqobject iqobject48619/udp#iqobject matahari49000/tcp#MatahariBroker 7.2.7 将匹配行写到文件(w) #tail/etc/services|sed'/blp5/wb.txt' 3gpp-cbsp48049/tcp#3GPPCellBroadcastServiceProtocol isnetserv48128/tcp#ImageSystemsNetworkServices isnetserv48128/udp#ImageSystemsNetworkServices blp548129/tcp#Bloomberglocator blp548129/udp#Bloomberglocator com-bardac-dw48556/tcp#com-bardac-dw com-bardac-dw48556/udp#com-bardac-dw iqobject48619/tcp#iqobject iqobject48619/udp#iqobject matahari49000/tcp#MatahariBroker #catb.txt blp548129/tcp#Bloomberglocator blp548129/udp#Bloomberglocator 博客地址:http://lizhenliang.blog.51cto.com QQ群:323779636(Shell/Python运维开发群) 7.2.8 读取下一行(n和N) n命令的作用是读取下一行到模式空间。 N命令的作用是追加下一行内容到模式空间,并以换行符\n分隔。 1)打印匹配的下一行 #seq5|sed-n'/3/{n;p}' 4 2)打印偶数 #seq6|sed-n'n;p' 2 4 6 sed先读取第一行1,执行n命令,获取下一行2,此时模式空间是2,执行p命令,打印模式空间。 现在模式空间是2,sed再读取3,执行n命令,获取下一行4,此时模式空间为4,执行p命令,以此类推。 3)打印奇数 #seq6|sed'n;d' 1 3 5 sed先读取第一行1,此时模式空间是1,并打印模式空间1,执行n命令,获取下一行2,执行d命令,删除模式空间的2,sed再读取3,此时模式空间是3,并打印模式空间,再执行n命令,获取下一行4,执行d命令,删除模式空间的3,以此类推。 4)每三行执行一次p命令 #seq6|sed'n;n;p' 1 2 3 3 4 5 6 6 sed先读取第一行1,并打印模式空间1,执行n命令,获取下一行2,并打印模式空间2,再执行n命令,获取下一行3,执行p命令,打印模式空间3。sed读取下一行3,并打印模式空间3,以此类推。 5)每三行替换一次 方法1: #seq6|sed'n;n;s/^/=/;s/$/=/' 1 2 =3= 4 5 =6= 我们只是把p命令改成了替换命令。 方法2: 这次用到了地址匹配,来实现上面的效果: #seq6|sed'3~3{s/^/=/;s/$/=/}' 1 2 =3= 4 5 =6= 当执行多个sed命令时,有时相互会产生影响,我们可以用大括号{}把他们括起来。 6)再看下N命令的功能 #seq6|sed'N;q' 1 2 将两行合并一行: #seq6|sed'N;s/\n//' 12 34 56 第一个命令:sed读取第一行1,N命令读取下一行2,并以\n2追加,此时模式空间是1\n2,再执行q退出。 为了进一步说明N的功能,看第二个命令:执行N命令后,此时模式空间是1\n2,再执行把\n替换为空,此时模式空间是12,并打印。 #seq5|sed-n'N;p' 1 2 3 4 #seq6|sed-n'N;p' 1 2 3 4 5 6 为什么第一个不打印5呢? 因为N命令是读取下一行追加到sed读取的当前行,当N读取下一行没有内容时,则退出,也不会执行p命令打印当前行。 当行数为偶数时,N始终就能读到下一行,所以也会执行p命令。 7)打印奇数行数时的最后一行 #seq5|sed-n'$!N;p' 1 2 3 4 5 加一个满足条件,当sed执行到最后一行时,用感叹号不去执行N命令,随后执行p命令。 7.2.9 打印和删除模式空间第一行(P和D) P命令作用是打印模式空间的第一行。 D命令作用是删除模式空间的第一行。 1)打印奇数 #seq6|sed-n'N;P' 1 3 5 2)保留最后一行 #seq6|sed'N;D' 6 读取第一行1,执行N命令读取下一行并追加到模式空间,此时模式空间是1\n2,执行D命令删除模式空间第一行1,剩余2。 读取第二行,执行N命令,此时模式空间是3\n4,执行D命令删除模式空间第一行3,剩余4。 以此类推,读取最后一行打印时,而N获取不到下一行则退出,不再执行D,因此模式空间只剩余6就打印。 7.2.10 保持空间操作(h与H、g与G和x) h命令作用是复制模式空间内容到保持空间(覆盖)。 H命令作用是复制模式空间内容追加到保持空间。 g命令作用是复制保持空间内容到模式空间(覆盖)。 G命令作用是复制保持空间内容追加到模式空间。 x命令作用是模式空间与保持空间内容互换 1)将匹配的内容覆盖到另一个匹配 #seq6|sed-e'/3/{h;d}'-e'/5/g' 1 2 4 3 6 h命令把匹配的3复制到保持空间,d命令删除模式空间的3。后面命令再对模式空间匹配5,并用g命令把保持空间3覆盖模式空间5。 2)将匹配的内容放到最后 #seq6|sed-e'/3/{h;d}'-e'$G' 1 2 4 5 6 3 3)交换模式空间和保持空间 #seq6|sed-e'/3/{h;d}'-e'/5/x'-e'$G' 1 2 4 3 6 5 看后面命令,在模式空间匹配5并将保持空间的3与5交换,5就变成了3,。最后把保持空间的5追加到模式空间的。 4)倒叙输出 #seq5|sed'1!G;h;$!d' 5 4 3 2 1 分析下: 1!G 第一行不执行把保持空间内容追加到模式空间,因为现在保持空间还没有数据。 h 将模式空间放到保持空间暂存。 $!d 最后一行不执行删除模式空间的内容。 读取第一行1时,跳过G命令,执行h将模式空间1复制到保持空间,执行d命令删除模式空间的1。 读取第二行2时,模式空间是2,执行G命令,将保持空间1追加到模式空间,此时模式空间是2\n1,执行h将2\n1覆盖到保持空间,d删除模式空间。 读取第三行3时,模式空间是3,执行G命令,将保持空间2\n1追加到模式空间,此时模式空间是3\n2\n1,执行h将模式空间内容复制到保持空间,d删除模式空间。 以此类推,读到第5行时,模式空间是5,执行G命令,将保持空间的4\n3\n2\n1追加模式空间,然后复制到模式空间,5\n4\n3\n2\n1,不执行d,模式空间保留,输出。 由此可见,每次读取的行先放到模式空间,再复制到保持空间,d命令删除模式空间内容,防止输出,再追加到模式空间,因为追加到模式空间,会追加到新读取的一行的后面,循环这样操作, 就把所有行一行行追加到新读取行的后面,就形成了倒叙。 5)每行后面添加新空行 #seq10|sedG 1 2 3 4 5 7.2.11 标签 标签可以控制流,实现分支判断。 : lable name 定义标签 b lable 跳转到指定标签,如果没有标签则到脚本末尾 t lable 跳转到指定标签,前提是s///命令执行成功 1)将换行符替换成逗号 方法1: #seq6|sed'N;s/\n/,/' 1,2 3,4 5,6 这种方式并不能满足我们的需求,每次sed读取到模式空间再打印是新行,替换\n也只能对N命令追加后的1\n2这样替换。 这时就可以用到标签了: #seq6|sed':a;N;s/\n/,/;ba' 1,2,3,4,5,6 看看这里的标签使用,:a 是定义的标签名,b a是跳转到a位置。 sed读取第一行1,N命令读取下一行2,此时模式空间是1\n2$,执行替换,此时模式空间是1,2$,执行b命令再跳转到标签a位置继续执行N命令,读取下一行3追加到模式空间,此时模式空间是1,2\n3$,再替换,以此类推,不断追加替换,直到最后一行N读不到下一行内容退出。 方法2: #seq6|sed':a;N;$!ba;s/\n/,/g' 1,2,3,4,5,6 先将每行读入到模式空间,最后再执行全局替换。$!是如果是最后一行,则不执行b a跳转,最后执行全局替换。 #seq6|sed':a;N;ba;s/\n/,/g' 1 2 3 4 5 6 可以看到,不加$!是没有替换,因为循环到N命令没有读到行就退出了,后面的替换也就没执行。 2)每三个数字加个一个逗号 #echo"123456789"|sed-r's/([0-9]+)([0-9]+{3})/\1,\2/' 123456,789 #echo"123456789"|sed-r':a;s/([0-9]+)([0-9]+{3})/\1,\2/;ta' 123,456,789 #echo"123456789"|sed-r':a;s/([0-9]+)([0-9]+{2})/\1,\2/;ta' 1,23,45,67,89 执行第一次时,替换最后一个,跳转后,再对123456匹配替换,直到匹配替换不成功,不执行t命令。 7.2.12 忽略大小写匹配 #echo-e"a\nA\nb\nc"|sed's/a/1/Ig' 1 1 b c 7.2.13 获取总行数 #seq10|sed-n'$=' 如有问题欢迎加技术×××流!Python运维开发群(249171211)

优秀的个人博客,低调大师

集群对讲机通信系统工程实战:野外极寒场景组网落地与优化案例

案例摘要:在野外林区、边境值守、寒地工矿等复杂作业场景下,传统单机对讲组网模式存在覆盖范围碎片化、无分级调度机制、运行数据无法溯源、极端环境适配性不足等问题,难以支撑规模化班组协同、标准化应急处置、常态化安全生产管控工作。本文依托北方寒地野外真实工程项目,严格参照《森林防火通信系统建设技术规范》《应急指挥通信网络建设规范》等行业标准,完整复盘数字集群对讲机系统的架构设计、设备合规选型、组网部署流程、现场问题迭代优化方案。针对寒地常见的信号衰减、低温适配、调度无序、运维无台账等共性问题,提供标准化工程解决思路。本文属于纯技术落地复盘,其中野外弱网环境下的应急调度闭环管控,依托lonptt调度平台完成场景适配与功能落地,可为同类野外集群通信改造项目提供可复用的工程参考。

优秀的个人博客,低调大师

“豆包手机”工程机被炒至近万元,行业评价两极分化

据报道,「豆包手机助手」首批工程机在官方渠道售罄后迅速在二级市场被炒高,闲鱼等平台上部分未拆封机型报价已达 7999 – 9999 元,相较官方 3499 元定价溢价超过一倍。 与此同时,昨日社交媒体出现对于“豆包手机”的分化评价。 魅族科技公开表示期待有机会深入合作,认为豆包手机拓展了 AI 手机的想象空间,并强调 Flyme AIOS 2 同样以系统级自动化为目标。 荣耀首席影像工程师罗巍则直言软件公司做手机难度极大,若坚持可能三世而亡,否则一代死。但荣耀产品线高管方飞则认为豆包助手的通用场景自动执行路径与荣耀的方向一致,期待生态共建。 而据此前报道,部分用户在使用助手执行微信相关操作时出现被动下线或登录异常,微信方面回复称暂勿在工程机上通过助手操作敏感环节,相关问题正在核实;字节跳动方面则强调,权限清单与白皮书已公开,执行过程需用户授权且可中断。 对此,罗永浩在微博发文称,技术革命是谁都拦不住的,AI 助手一定会遍地开花。

优秀的个人博客,低调大师

海柔仿真系统存储实践:混合云架构下实现高可用与极简运维

海柔创新是一家专注于箱式仓储机器人系统的研发和设计的科技公司,其仿真平台通过数字模拟技术,再现实际仓库环境和设备,利用导入的地图、订单、库存及策略配置等数据来验证和优化仓储解决方案,确保设计方案的效率和合理性。 最初,海柔的仿真平台在单机环境中运行,但随着数据量的增长,运维逐渐面临挑战。因此,平台被迁移到私有云的 Kubernetes 环境中,团队随后开始寻找适合在 k8s 环境中运用的分布式文件系统。 仿真平台的数据特征包括:大量小文件、并发写入、跨云架构等。经过对比 Longhorn、Ceph 等多种系统后,海柔科技选择了 JuiceFS。目前,平台的总文件数量为 1100 万、日均写入文件数量 6000 多,以小文件为主,平均文件大小是 3.6KB;同时,Mount Point 数量超过 50个。 01 仿真平台存储挑战:从商用软件到自建 仿真平台(simulator)是基于离散事件引擎的工具平台。它通过底层的数字模拟,对接上层业务系统,在没有实体设备的情况下,达到与实体设备等效的能力。 简单的说 其实仿真平台就是建立了一个虚拟仓库,所有的模拟都是基于这个虚拟仓库来完成的。 传统公司通常使用商业软件,但这些软件无法进行大规模调度或减少计算资源消耗。为此,我们自研了一个仿真平台,涵盖 IaaS、PaaS 等服务。我们的仿真主要是基于离散事件进行,与使用 GPU 的商业软件不同,通过简化计算步骤,优化事件的抽象,显著减少了计算量,甚至可以只使用 CPU 完成倍速仿真的计算任务。 我们的仿真系统主要涵盖几个关键部分:首先是仿真本体,如机器人模拟,包括其运动、旋转和移动速度的逻辑模拟。仿真设备与我们自研的调度系统和 WMS (Warehose Management System)系统直接对接。这也是商业软件所不直接提供的功能。 仿真过程中还包括机械模拟、拣选作业模拟和上游系统环境的业务集成。仿真完成后,会生成大量事件数据,这些数据被记录在小文件中。我们通过这些小文件在另一节点进行存算分离,从而提取和分析这些数据。通过这种方法,我们能够有效地从仿真数据中洞察操作效率和潜在问题,进一步优化系统性能。 我们的仿真平台一开始是一个纯单机版系统。单机版主要包括一个启动器(starter),核心引擎(core engine,可以类比为一个游戏引擎),它将通过真实的通信协议与真实业务系统 RCS (Robot Control System)连接,从而高度还原现场。 然而,单机版系统存在一些缺点,如原 Core Enging 使用 Python 编写,不能满足单机高并发 IO 的需要,另外当系统扩展至 50 台虚拟机时,运维变得尤为困难。考虑到我们团队的人员数量,这种规模的运维对我们来说是一个巨大的挑战。 02 仿真平台上云:从私有云到混合云架构 单机系统大约持续了 2 年时间,随着数据量的增长,单机系统面临的运维问题日益复杂,于是我们迁移到了 Kubernetes 架构,采用了服务化 (SAAS) 的方式,将所有组件都部署在 K8s 环境中。由此面临,如何在 Kuberenetes 环境中进行存储选型。 K8s 环境存储选型:JuiceFS vs CephFS vs Longhorn 在我们选择分布式文件系统时,性能并不是首要考虑因素,更关键的是如何有效实现跨云网络结构。我们简单评估了 JuiceFS、CephFS 和 Longhorn。 Longhorn 仅支持单集群内文件共享,需要先打通 Kubernetes 的多云集群网络通信,这对我们来说运维成本繁琐。而 CephFS 对于我们这种小规模团队来说,存在过高的维护难度。 因此,我们选择了 JuiceFS,主要因为它的运维特别简单,非常适合小团队使用。JuiceFS 的即插即用特性意味着即使是初学者也能轻松上手,几乎不会遇到大问题,这降低了运营风险。此外,自从部署以来,JuiceFS 未出现过任何故障,这一点非常值得赞扬。 目前 JuiceFS 使用规模方面,过去六个月我们处理了大约 1,100 万个文件。我们每半年会进行一次数据清洗,删除不再需要的数据,因此总数据量不会继续增加。日均写入大约是 6.4k 个文件,平均每日总文件数量为 6 万个,文件大小介于 5kB 到 100kB 之间。日均数据写入量约为 5GB,最高可达 8GB。我们计划将并发写入量逐步扩展至 50 个。 在私有云 K8s 环境中搭建仿真平台 2023 年中,我们开始在 K8s 环境中搭建仿真平台。当系统扩展到 1000 台机器人时,我们发现 Python的 IO 处理能力不足以支撑。因此,我们采用了 Go 语言,这一改变显著提升了系统的 IO 性能,使得单机可以轻松支持超过 1 万台机器人的并发操作。 整个系统的文件处理特征为小文件的高并发写入,当前的并发级别为 50,能够满足了我们的需求。 最近,我们将系统从单体架构转变为微服务架构。这一转变解决了原有团队代码混杂和耦合的问题,确保各个服务间代码的独立性,从而提升了系统的可维护性和扩展性。 我们还实施了存算分离的策略,在仿真节点通过使用 JuiceFS 写入仿真过程数据小文件,并在写入结束时重命名为 *.fin 文件;当另一个分析计算节点实时发现 *.fin 文件并开始计算,从而实现隔离仿真与分析的存算分离,避免 CPU 抢占造成仿真过程失真。 混合云 SaaS 仿真服务 在私有云 K8s 环境中,我们的团队需要管理众多组件,如 MySQL、OSS 等,为了解决资源和精力分散的问题,我们在 2024 年 1 月开始转向混合云 SaaS 解决方案,并选择将存储服务迁移到阿里云。对于小团队来说,如果条件允许,我建议尽量利用公有云服务,特别是在存储方面,因为数据安全是基本需求,不能有失误。 我们采用了阿里云的 OSS 和 MySQL 服务,在两个集群间实现数据共享。这种配置不仅提升了数据处理的效率,还带来了成本效益和灵活性的优势。例如,当本地数据中心的机器资源不足时,利用 JuiceFS 天然的跨云存储能力,在这个架构下,我们可以轻松地从任意云厂商租用机器弹性伸缩集群以满足需求,从而实现成本节约。 03 使用 JuiceFS 踩过的坑 在迁移到云端之前,我们本地使用 Redis 和 Minio 运行得很好,因为我们拥有充足的内存和存储空间,这样就不会出现性能问题。然而,迁移到云端后,遇到了一些问题。 默认的缓存过大,导致 Pod 驱逐 默认的缓存大小设为 100GB,而标准阿里云服务器通常配备的磁盘只有 20GB。这种配置不匹配会导致 Pod 被驱逐,因为缓存过大超出了实际可用磁盘空间。 混合云场景下 storageClasses 的 bucket 设置问题 在实现跨云功能时,尽管官方文档可能推荐使用内网,实际操作表明应当使用外网地址,特别是在使用容器存储接口(CSI)时。默认情况下,第一个执行的操作是格式化 Pod(format pod),它会将当前的配置参数写入数据库。如果其他节点未指定 bucket 设置并依赖于数据库中的这一设置,使用内网地址可能导致外网访问失败。 对象存储占用空间比实际多 尽管阿里云账户下我们有 6TB 的存储空间,实际使用中发现只存储了大约 1.27TB 数据,对象存储占用的空间明显膨胀,远超实际数据量。这可能是由于缺乏自动垃圾回收(GC)处理。因此,我们必须定期手动执行 GC 操作,以减少存储占用。 04 未来展望 我们计划在云端实现弹性伸缩,采用混合平台策略,并推出高速版服务。目前,我们在机器学习领域的高效仿真已经取得显著进展,成功实现了仿真倍速提升至 100 倍。 为了进一步提升效率,我们计划完善整个系统的闭环管理。由于我们的仿真系统已经能够生成大量数据,这些数据理应被充分利用,通过机器学习训练来完善闭环系统,实现数据的最大化利用。这将极大地增强我们系统的智能化和自动化水平。 询问AI

优秀的个人博客,低调大师

腾讯云代理商:腾讯云直播流量包和按量计费有什么区别?

⭕️本文由 ➡️国内云代理商『聚搜云 JuSouYunClouD -服务器服务商•撰写』如需转载请注明!聚搜云(深圳)信息有限公司本期关注企业直播采购中的费用选择:已经可以按实际用量付费,是否还需要提前购买直播流量包?两者的主要区别在于付款时间、抵扣条件和用量风险。直播流量包是预先购买的抵扣额度,按量计费则根据实际产生的用量结算,两者可以在符合条件的情况下配合使用。

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册