首页 文章 精选 留言 我的

精选列表

搜索[运维产品],共10007篇文章
优秀的个人博客,低调大师

Linux运维笔记-日常操作命令总结(3)

使用"whois"命令可以查询到域名的注册信息 1)比如查询www.kevin.com、www.qq.com域名注册信息(使用whois命令查询时,需要去掉域名前面的www) [root@bastion~]#whoiskevin.com [root@bastion~]#whoisqq.com 2)查询ip注册信息 [root@bastion~]#whois112.110.116.15 "syntax error: unexpected end of file"一般从windows下的shell脚本传到Linux上可能会出现这样的问题,是因为Windows和Linux下的行末结束符是不一样的。即windoes下的dos格式文件传输到unix系统时,会在每行的结尾多一个^M,也就是说dos文件中的换行符"\r\n"会被转换为unix文件中的换行符"\n",而此文件若是一个可执行文件的话,会导致此文件不能被执行。 ======================================================================================================================= 案例一: 比如:我有一个test.sh脚本需要上传到centos系统中执行,但是传输到centos系统中,无法正常执行(前提脚本是完全可以执行的,没有错误)。可能原因是在windos系统上使用了类似notepad++的工具修改了可执行文件内容,导致在centos系统下无法正常执行。 案例二: 在本机(win10)测试正常的程序到了线上linux环境下就是跑步起来,tomcat总是卡在loadingconfig.properties这里,换了一个tomcat也是这种情况,以前是没有问题的。最后怀疑是config.properties文件的问题,然后通过vim查看config.properties文件的fileformat格式,命令":setfileformat",结果显示的是dos,最后通过命令修改为":setfileformat=unix" ======================================================================================================================= 这样先弄清楚一下"回车"和"换行符"的区别: 1)回车"\r" 本义是光标重新回到本行开头,r的英文return,控制字符可以写成CR,即CarriageReturn 2)换行"\n" 本义是光标往下一行(不一定到下一行行首),n的英文newline,控制字符可以写成LF,即LineFeed 解决办法: 1)使用vim打开file.sh脚本文件,进入编辑模式,修改如下: :setff=unix(或者:setfileformat=unix) :wq 2)如果以上步骤要求在一个shell批处理文件中完成,那么该怎么办?可以这样: vi+':w++ff=unix'+':q'${file} 这样一条命令就可以搞定了,但是要严格注意上面空格的位置,不能多不能少。 ================================================================================ 总结:在windows下新建的sh文件,copy到linux下有的会报错,一般是格式问题。 解决办法:使用vim编辑器进行一下文件格式fileformat转换可使用fileformat或简写ff。 在vim编辑可执行文件: setff或setff?#显示当前文件格式 setfileformat=unix或setff=unix#设置成unix格式 setff=dos#设置成dos格式 dos格式文件传输到unix系统时,会在每行的结尾多一个^M(/r) 删除^M的方法: :%s//r//g %s/\r//g sed文本操作命令使用 sed是一个很好的文件处理工具,本身是一个管道命令,主要是以行为单位进行处理,可以将数据行进行替换、删除、新增、选取等特定工作。 sed命令行格式为: sed[-nefri]‘command’输入文本 常用选项: -n∶使用安静(silent)模式。在一般sed的用法中,所有来自STDIN的资料一般都会被列出到萤幕上。但如果加上-n参数后,则只有经过sed特殊处理的那一行(或者动作)才会被列出来。 -e∶直接在指令列模式上进行sed的动作编辑; -f∶直接将sed的动作写在一个档案内,-ffilename则可以执行filename内的sed动作; -r∶sed的动作支援的是延伸型正规表示法的语法。(预设是基础正规表示法语法) -i∶直接修改读取的档案内容,而不是由萤幕输出。kevin.txt 常用命令: a∶新增,a的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~ c∶取代,c的后面可以接字串,这些字串可以取代n1,n2之间的行! d∶删除,因为是删除啊,所以d后面通常不接任何咚咚; i∶插入,i的后面可以接字串,而这些字串会在新的一行出现(目前的上一行); p∶列印,亦即将某个选择的资料印出。通常p会与参数sed-n一起运作~ s∶取代,可以直接进行取代的工作哩!通常这个s的动作可以搭配正规表示法!例如1,20s/old/new/g就是啦! 替换一行中的某部分。s后面的替换符号可以使用/,#,_三种符号 格式:sed's/要替换的字符串/新的字符串/g'(要替换的字符串可以用正则表达式) [root@kevin~]#sed-n'/ruby/p'kevin.txt|sed's/ruby/bird/g'#替换ruby为bird [root@kevin~]#sed-n'/ruby/p'kevin.txt|sed's#ruby#bird#g'#替换ruby为bird [root@kevin~]#sed-n'/ruby/p'kevin.txt|sed's_ruby_bird_g'#替换ruby为bird 定址 定址用于决定对哪些行进行编辑。地址的形式可以是数字、正则表达式、或二者的结合。 如果没有指定地址,sed将处理输入文件的所有行。 地址是一个数字,则表示行号;是“$"符号,则表示最后一行。例如: [root@kevin~]#sed-n'3p'datafile 只打印第三行 只显示指定行范围的文件内容,例如只查看文件的第100行到第200行 [root@kevin~]#sed-n'100,200p'mysql_slow_query.log 地址是逗号分隔的,那么需要处理的地址是这两行之间的范围(包括这两行在内)。范围可以用数字、正则表达式、或二者的组合表示。 [root@kevin~]#sed'2,5d'datafile 删除第二到第五行 [root@kevin~]#sed'/My/,/You/d'datafile 删除包含"My"的行到包含"You"的行之间的行 [root@kevin~]#sed'/My/,10d'datafile 删除包含"My"的行到第十行的内容 示例说明 kevin.txt删除某行 [root@kevin~]#sed'1d'kevin.txtkevin.txt#删除第一行 [root@kevin~]#sed'$d'kevin.txtkevin.txt#删除最后一行 [root@kevin~]#sed'1,2d'kevin.txt#删除第一行到第二行 [root@kevin~]#sed'2,$d'kevin.txt#删除第二行到最后一行 显示某行 [root@kevin~]#sed-n'1p'kevin.txt#显示第一行 [root@kevin~]#sed-n'$p'kevin.txt#显示最后一行 [root@kevin~]#sed-n'1,2p'kevin.txt#显示第一行到第二行 [root@kevin~]#sed-n'2,$p'kevin.txt#显示第二行到最后一行 使用模式进行查询 [root@kevin~]#sed-n'/ruby/p'kevin.txt#查询包括关键字ruby所在所有行 [root@kevin~]#sed-n'/\$/p'kevin.txt#查询包括关键字$所在所有行,使用反斜线\屏蔽特殊含义 增加一行或多行字符串 [root@kevin~]#catkevin.txt kevin.txtHello! kevin.txtrubyisme,welcometomyblog. kevin.txtend [root@kevin~]#sed'1adrinktea'kevin.txt#第一行后增加字符串"drinktea" kevin.txtHello! kevin.txtdrinktea kevin.txtrubyisme,welcometomyblog. kevin.txtend [root@kevin~]#sed'1,3adrinktea'kevin.txt#第一行到第三行后增加字符串"drinktea" kevin.txtHello! kevin.txtdrinktea kevin.txtrubyisme,welcometomyblog. kevin.txtdrinktea kevin.txtend kevin.txtdrinktea [root@kevin~]#sed'1adrinktea\norcoffee'kevin.txt#第一行后增加多行,使用换行符\n kevin.txtHello! kevin.txtdrinktea kevin.txtorcoffee kevin.txtrubyisme,welcometomyblog. kevin.txtend 代替一行或多行 [root@kevin~]#sed'1cHi'kevin.txt#第一行代替为Hi kevin.txtHi kevin.txtrubyisme,welcometomyblog. kevin.txtend [root@kevin~]#sed'1,2cHi'kevin.txtkevin.txt#第一行到第二行代替为Hi kevin.txtHi kevin.txtend 替换一行中的某部分 格式:sed's/要替换的字符串/新的字符串/g'(要替换的字符串可以用正则表达式) [root@kevin~]#sed-n'/ruby/p'kevin.txt|sed's/ruby/bird/g'#替换ruby为bird [root@kevin~]#sed-n'/ruby/p'kevin.txt|sed's/ruby//g'#删除ruby kevin.txt插入 [root@kevin~]#sed-i'$abye'kevin.txt#在文件kevin.txt中最后一行直接输入"bye" [root@kevin~]#catkevin.txt kevin.txtHello! kevin.txtrubyisme,welcometomyblog. kevin.txtend kevin.txtbye 替换: -e是编辑命令,用于sed执行多个编辑任务的情况下。在下一行开始编辑前,所有的编辑动作将应用到模式缓冲区中的行上。 [root@kevin~]#sed-e'1,10d'-e's/My/Your/g'datafile 选项-e用于进行多重编辑。 第一重编辑删除第1-3行。 第二重编辑将出现的所有My替换为Your。 因为是逐行进行这两项编辑(即这两个命令都在模式空间的当前行上执行),所以编辑命令的顺序会影响结果。 替换两个或多个空格为一个空格 [root@kevin~]#sed's/[][]*//g'file_name 替换两个或多个空格为分隔符: [root@kevin~]#sed's/[][]*/:/g'file_name 如果空格与tkevin.txt共存时用下面的命令进行替换 替换成空格 [root@kevin~]#sed's/[[:space:]][[:space:]]*//g'filename 替换成分隔符: [root@kevin~]#sed's/[[:space:]][[:space:]]*/:/g'filename ======================================= sed命令的调用: 在命令行键入命令;将sed命令插入脚本文件,然后调用sed;将sed命令插入脚本文件,并使sed脚本可执行 sed[option]sed命令输入文件在命令行使用sed命令,实际命令要加单引号 sed[option]-fsed脚本文件输入文件使用sed脚本文件 sed脚本文件[option]输入文件第一行具有sed命令解释器的sed脚本文件 option如下: n不打印;sed不写编辑行到标准输出,缺省为打印所有行(编辑和未编辑),p命令可以用来打印编辑行 c下一命令是编辑命令,使用多项编辑时加入此选项 f如果正在调用sed脚本文件,使用此选项,此选项通知sed一个脚本文件支持所用的sed命令,如 #sed-fmyscript.sedinput_file这里myscript.sed即为支持sed命令的文件 使用重定向文件即可保存sed的输出 使用sed在文本中定位文本的方式: xx为一行号,比如1 x,y表示行号范围从x到y,如2,5表示从第2行到第5行 /pattern/查询包含模式的行,如/disk/或/[a-z]/ /pattern/pattern/查询包含两个模式的行,如/disk/disks/ /pattern/,x在给定行号上查询包含模式的行,如/disk/,3 x,/pattern/通过行号和模式查询匹配行,如3,/disk/ x,y!查询不包含指定行号x和y的行 基本sed编辑命令: p打印匹配行c/用新文本替换定位文本 =显示文件行号s使用替换模式替换相应模式 a/在定位行号后附加新文本信息r从另一个文本中读文本 i/在定位行号后插入新文本信息w写文本到一个文件 d删除定位行q第一个模式匹配完成后退出或立即退出 l显示与八进制ASCII代码等价的控制字符y传送字符 n从另一个文本中读文本下一行,并附加在下一行{}在定位行执行的命令组 g将模式2粘贴到/patternn/ 基本sed编程举例: 使用p(rint)显示行:sed-n'2p'temp.txt只显示第2行,使用选项n 打印范围:sed-n'1,3p'temp.txt打印第1行到第3行 打印模式:sed-n'/movie/'ptemp.txt打印含movie的行 使用模式和行号查询:sed-n'3,/movie/'ptemp.txt只在第3行查找movie并打印 显示整个文件:sed-n'1,$'ptemp.txt$为最后一行 任意字符:sed-n'/.*ing/'ptemp.txt注意是.*ing,而不是*ing 打印行号:sed-e'/music/='temp.txt 附加文本:(创建sed脚本文件)chmodu+xscript.sed,运行时./script.sedtemp.txt #!/bin/sed-f /name1/a/#a/表示此处换行添加文本 HEREADDNEWLINE.#添加的文本内容 插入文本:/name1/a/改成4i/4表示行号,i插入 修改文本:/name1/a/改成/name1/c/将修改整行,c修改 删除文本:sed'1d'temp.txt或者sed'1,4d'temp.txt 替换文本:sed's/source/OKSTR/'temp.txt将source替换成OKSTR sed's//$//g'temp.txt将文本中所有的$符号全部删除 sed's/source/OKSTR/wtemp2.txt'temp.txt将替换后的记录写入文件temp2.txt 替换修改字符串:sed's/source/"ADDBEFORE"&/p'temp.txt 结果将在source字符串前面加上"ADDBEFORE",这里的&表示找到的source字符并保存 sed结果写入到文件:sed'1,2wtemp2.txt'temp.txt sed'/name/wtemp2.txt'temp.txt 从文件中读文本:sed'/name/rtemp2.txt'temp.txt 在每列最后加文本:sed's/[0-9]*/&Pass/g'temp.txt 从shell向sed传值:echo$NAME|sed"s/go/$REP/g"注意需要使用双引号 快速一行命令: 's//.$//g'删除以句点结尾行 '-e/abcd/d'删除包含abcd的行 's/[][][]*/[]/g'删除一个以上空格,用一个空格代替 's/^[][]*//g'删除行首空格 's//.[][]*/[]/g'删除句号后跟两个或更多的空格,用一个空格代替 '/^$/d'删除空行 's/^.//g'删除第一个字符,区别's//.//g'删除所有的句点 's/COL/(.../)//g'删除紧跟COL的后三个字母 's/^////g'删除路径中第一个/ ================================================= 1)使用句点匹配单字符 句点“.”可以匹配任意单字符。“.”可以匹配字符串头,也可以是中间任意字符。假定正在过滤一个文本文件,对于一个有10个字符的脚本集,要求前4个字符之后为XC,匹配操作如下:....XC.... 2)在行首以^匹配字符串或字符序列 ^只允许在一行的开始匹配字符或单词。在行首第4个字符为1,匹配操作表示为:^...1 3)在行尾以$匹配字符串或字符 可以说$与^正相反,它在行尾匹配字符串或字符,$符号放在匹配单词后。如果在行尾匹配单词jet01,操作如下:jet01$如果只返回包含一个字符的行,操作如下:^.$ 4)使用*匹配字符串中的单字符或其重复序列 使用此特殊字符匹配任意字符或字符串的重复多次表达式。 5)使用/屏蔽一个特殊字符的含义有 时需要查找一些字符或字符串,而它们包含了系统指定为特殊字符的一个字符。如果要在正则表达式中匹配以*.pas结尾的所有文件,可做如下操作:/*/.pas 6)使用[]匹配一个范围或集合 使用[]匹配特定字符串或字符串集,可以用逗号将括弧内要匹配的不同字符串分开,但并不强制要求这样做(一些系统提倡在复杂的表达式中使用逗号), 这样做可以增加模式的可读性。使用“-”表示一个字符串范围,表明字符串范围从“-”左边字符开始,到“-”右边字符结束。假定要匹配任意一个数字, 可以使用:[0123456789]要匹配任意字母,则使用:[A-Za-z]表明从A-Z、a-z的字母范围。 7)使用/{/}匹配模式结果出现的次数 使用*可匹配所有匹配结果任意次,但如果只要指定次数,就应使用/{/},此模式有三种形式,即: pattern/{n/}匹配模式出现n次。 pattern/{n,/}匹配模式出现最少n次。 pattern/{n,m}匹配模式出现n到m次之间,n,m为0-255中任意整数。 匹配字母A出现两次,并以B结尾,操作如下:A/{2/}B匹配值为AAB匹配A至少4次,使用:A/{4,/}B ====================== 替换单引号为空,可以这样写: sed's/'"'"'//g' sed's/'\''//g' seds/\'//g ===================== 在文件的第一行前面插入一行abc sed-i'1i\abc'urfile awk命令使用 awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入, 以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。 awk有3个不同版本:awk、nawk和gawk,未作特别说明,一般指gawk,gawk是AWK的GNU版本。 awk其名称得自于它的创始人AlfredAho、PeterWeinberger和BrianKernighan姓氏的首个字母。实际上AWK的确拥有自己的语言: AWK程序设计语言,三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、 对输入执行计算以及生成报表,还有无数其他的功能。 使用方法 awk'{pattern+action}'{filenames} 尽管操作可能会很复杂,但语法总是这样,其中pattern表示AWK在数据中查找的内容,而action是在找到匹配内容时所执行的一系列命令。 花括号({})不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。pattern就是要表示的正则表达式,用斜杠括起来。 awk语言的最基本功能是在文件或者字符串中基于指定规则浏览和抽取信息,awk抽取信息后,才能进行其他文本操作。完整的awk脚本通常用来格式化文本 文件中的信息。 通常,awk是以文件的一行为处理单位的。awk每接收文件的一行,然后执行相应的命令,来处理文本。 调用awk 有三种方式调用awk 1)命令行方式 awk[-Ffield-separator]'commands'input-file(s) 其中,commands是真正awk命令,[-F域分隔符]是可选的。input-file(s)是待处理的文件。 在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格。 2)shell脚本方式 将所有的awk命令插入一个文件,并使awk程序可执行,然后awk命令解释器作为脚本的首行,一遍通过键入脚本名称来调用。 相当于shell脚本首行的:#!/bin/sh 可以换成:#!/bin/awk 3)将所有的awk命令插入一个单独文件,然后调用: awk-fawk-script-fileinput-file(s) 其中,-f选项加载awk-script-file中的awk脚本,input-file(s)跟上面的是一样的。 假设last-n5的输出如下: [root@kevin~]#last-n5<==仅取出前五行 rootpts/1192.168.1.100TueFeb1011:21stillloggedin rootpts/1192.168.1.100TueFeb1000:46-02:28(01:41) rootpts/1192.168.1.100MonFeb911:41-18:30(06:48) dmtsaipts/1192.168.1.100MonFeb911:41-11:41(00:00) roottty1FriSep514:09-14:10(00:01) 如果只是显示最近登录的5个帐号 [root@kevin~]#last-n5|awk'{print$1}' root root root dmtsai root awk工作流程是这样的: 读入有'\n'换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域。 默认域分隔符是"空白键"或"[tab]键",所以$1表示登录用户,$3表示登录用户ip,以此类推。 如果只是显示/etc/passwd的账户 [root@kevin~]#cat/etc/passwd|awk-F':''{print$1}' root daemon bin sys 这种是awk+action的示例,每行都会执行action{print$1}。 -F指定域分隔符为':'。 如果只是显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以tab键分割 [root@kevin~]#cat/etc/passwd|awk-F':''{print$1"\t"$7}' root/bin/bash daemon/bin/sh bin/bin/sh sys/bin/sh 如果只是显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以逗号分割,而且在所有行添加列名name,shell,在最后一行添加"blue,/bin/nosh"。 [root@kevin~]#cat/etc/passwd|awk-F':''BEGIN{print"name,shell"}{print$1","$7}END{print"blue,/bin/nosh"}' name,shell root,/bin/bash daemon,/bin/sh bin,/bin/sh sys,/bin/sh .... blue,/bin/nosh awk工作流程是这样的: 先执行BEGING,然后读取文件,读入有/n换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域, $n表示第n个域,随后开始执行模式所对应的动作action。接着开始读入第二条记录······直到所有的记录都读完,最后执行END操作。 搜索/etc/passwd有root关键字的所有行 [root@kevin~]#awk-F:'/root/'/etc/passwd root:x:0:0:root:/root:/bin/bash 这种是pattern的使用示例,匹配了pattern(这里是root)的行才会执行action(没有指定action,默认输出每行的内容)。 搜索支持正则,例如找root开头的:awk-F:'/^root/'/etc/passwd 搜索/etc/passwd有root关键字的所有行,并显示对应的shell [root@kevin~]#awk-F:'/root/{print$7}'/etc/passwd /bin/bash 这里指定了action{print$7} awk内置变量 awk有许多内置变量用来设置环境信息,这些变量可以被改变,下面给出了最常用的一些变量。 ARGC命令行参数个数 ARGV命令行参数排列 ENVIRON支持队列中系统环境变量的使用 FILENAMEawk浏览的文件名 FNR浏览文件的记录数 FS设置输入域分隔符,等价于命令行-F选项 NF浏览记录的域的个数 NR已读的记录数 OFS输出域分隔符 ORS输出记录分隔符 RS控制记录分隔符 此外,$0变量是指整条记录。$1表示当前行的第一个域,$2表示当前行的第二个域,......以此类推。 统计/etc/passwd:文件名,每行的行号,每行的列数,对应的完整行内容: [root@kevin~]#awk-F':''{print"filename:"FILENAME",linenumber:"NR",columns:"NF",linecontent:"$0}'/etc/passwd filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash filename:/etc/passwd,linenumber:2,columns:7,linecontent:daemon:x:1:1:daemon:/usr/sbin:/bin/sh filename:/etc/passwd,linenumber:3,columns:7,linecontent:bin:x:2:2:bin:/bin:/bin/sh filename:/etc/passwd,linenumber:4,columns:7,linecontent:sys:x:3:3:sys:/dev:/bin/sh 使用printf替代print,可以让代码更加简洁,易读 [root@kevin~]#awk-F':''{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$0)}'/etc/passwd print和printf awk中同时提供了print和printf两种打印输出的函数。 其中print函数的参数可以是变量、数值或者字符串。字符串必须用双引号引用,参数用逗号分隔。如果没有逗号,参数就串联在一起而无法区分。 这里,逗号的作用与输出文件的分隔符的作用是一样的,只是后者是空格而已。 printf函数,其用法和c语言中printf基本相似,可以格式化字符串,输出复杂时,printf更加好用,代码更易懂。 awk编程:变量和赋值 除了awk的内置变量,awk还可以自定义变量。 下面统计/etc/passwd的账户人数 [root@kevin~]#awk'{count++;print$0;}END{print"usercountis",count}'/etc/passwd root:x:0:0:root:/root:/bin/bash ...... usercountis40 count是自定义变量。之前的action{}里都是只有一个print,其实print只是一个语句,而action{}可以有多个语句,以;号隔开。 这里没有初始化count,虽然默认是0,但是妥当的做法还是初始化为0: [root@kevin~]#awk'BEGIN{count=0;print"[start]usercountis",count}{count=count+1;print$0;}END{print"[end]usercountis",count}'/etc/passwd [start]usercountis0 root:x:0:0:root:/root:/bin/bash ... [end]usercountis40 统计某个文件夹下的文件占用的字节数 [root@kevin~]#ls-l|awk'BEGIN{size=0;}{size=size+$5;}END{print"[end]sizeis",size}' [end]sizeis8657198 如果以M为单位显示: [root@kevin~]#ls-l|awk'BEGIN{size=0;}{size=size+$5;}END{print"[end]sizeis",size/1024/1024,"M"}' [end]sizeis8.25889M 注意,统计不包括文件夹的子目录。 条件语句 awk中的条件语句是从C语言中借鉴来的,见如下声明方式: if(expression){ statement; statement; ...... } if(expression){ statement; }else{ statement2; } if(expression){ statement1; }elseif(expression1){ statement2; }else{ statement3; } 统计某个文件夹下的文件占用的字节数,过滤4096大小的文件(一般都是文件夹): [root@kevin~]#ls-l|awk'BEGIN{size=0;print"[start]sizeis",size}{if($5!=4096){size=size+$5;}}END{print"[end]sizeis",size/1024/1024,"M"}' [start]sizeis0 [end]sizeis0.0610514M 循环语句 awk中的循环语句同样借鉴于C语言,支持while、do/while、for、break、continue,这些关键字的语义和C语言中的语义完全相同。 数组 因为awk中数组的下标可以是数字和字母,数组的下标通常被称为关键字(key)。值和关键字都存储在内部的一张针对key/value应用hash的表格里。 由于hash不是顺序存储,因此在显示数组内容时会发现,它们并不是按照你预料的顺序显示出来的。数组和变量一样,都是在使用时自动创建的,awk 也同样会自动判断其存储的是数字还是字符串。一般而言,awk中的数组用来从记录中收集信息,可以用于计算总和、统计单词以及跟踪模板被匹配的次数等。 显示/etc/passwd的账户 [root@kevin~]#awk-F':''BEGIN{count=0;}{name[count]=$1;count++;};END{for(i=0;i<NR;i++)printi,name[i]}'/etc/passwd 0root 1daemon 2bin 3sys 4sync 5games ...... 这里使用for循环遍历数组 grep命令:从文件中查找匹配模式的行 1.作用 Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。grep全称是GlobalRegularExpressionPrint,表示全局正则表达式版本,它的使用权限是所有用户。 2.格式 grep[options] 3.主要参数 [options]主要参数: -c:只输出匹配行的计数。 -I:不区分大小写(只适用于单字符)。 -h:查询多文件时不显示文件名。 -l:查询多文件时只输出包含匹配字符的文件名。 -n:显示匹配行及行号。 -s:不显示不存在或无匹配文本的错误信息。 -v:显示不包含匹配文本的所有行。 pattern正则表达式主要参数: \:忽略正则表达式中特殊字符的原有含义。 ^:匹配正则表达式的开始行。 $:匹配正则表达式的结束行。 \<:从匹配正则表达式的行开始。 \>:到匹配正则表达式的行结束。 []:单个字符,如[A]即A符合要求。 [-]:范围,如[A-Z],即A、B、C一直到Z都符合要求。 。:所有的单个字符。 *:有字符,长度可以为0。 grep-v过滤 grep-c打印关键字符所在的行数 grep-An打印关键字符所在的行的后n行内容 grep-Bn打印关键字符所在的行的前n行内容 grep-Cn打印关键字符所在的行的前后各n行内容 catfilename|grep"abc" fgrep-R"abc"./* 4.grep命令使用简单实例 [root@kevin~]#grep‘test’d* 显示所有以d开头的文件中包含test的行。 [root@kevin~]#grep‘test’aabbcc 显示在aa,bb,cc文件中匹配test的行。 [root@kevin~]#grep‘[a-z]\{5\}’aa 显示所有包含每个字符串至少有5个连续小写字符的字符串的行。 [root@kevin~]#grep‘w\(es\)t.*\1′aa 如果west被匹配,则es就被存储到内存中,并标记为1,然后搜索任意个字符(.*),这些字符后面紧跟着另外一个es(\1),找到就显示该行。 如果用egrep或grep-E,就不用”\”号进行转义,直接写成’w(es)t.*\1′就可以了。 5.grep命令使用复杂实例 假设您正在’/usr/src/Linux/Doc’目录下搜索带字符串’magic’的文件: [root@kevin~]#grepmagic/usr/src/Linux/Doc/* sysrq.txt:*HowdoIenablethemagicSysRQkey? sysrq.txt:*HowdoIusethemagicSysRQkey? 其中文件’sysrp.txt’包含该字符串,讨论的是SysRQ的功能。 默认情况下,’grep’只搜索当前目录。如果此目录下有许多子目录,’grep’会以如下形式列出: grep:sound:Isadirectory 这可能会使’grep’的输出难于阅读。这里有两种解决的办法: 明确要求搜索子目录:grep-r 或忽略子目录:grep-dskip 如果有很多输出时,您可以通过管道将其转到’less’上阅读: [root@kevin~]#grepmagic/usr/src/Linux/Documentation/*|less 这样,您就可以更方便地阅读。 有一点要注意, 您必需提供一个文件过滤方式(搜索全部文件的话用*)。如果您忘了,’grep’会一直等着,直到该程序被中断。 如果您遇到了这样的情况,按<CTRLc>,然后再试。 下面还有一些有意思的命令行参数: grep-ipatternfiles:不区分大小写地搜索。默认情况区分大小写, grep-lpatternfiles:只列出匹配的文件名, grep-Lpatternfiles:列出不匹配的文件名, grep-wpatternfiles:只匹配整个单词,而不是字符串的一部分(如匹配’magic’,而不是’magical’), grep-Cnumberpatternfiles:匹配的上下文分别显示[number]行, greppattern1|pattern2files:显示匹配pattern1或pattern2的行, greppattern1files|greppattern2:显示既匹配pattern1又匹配pattern2的行。 grep-npatternfiles即可显示行号信息 grep-cpatternfiles即可查找总行数 这里还有些用于搜索的特殊符号: \<和\>分别标注单词的开始与结尾。 例如: grepman*会匹配‘Batman’、’manic’、’man’等, grep‘\<man’*匹配’manic’和’man’,但不是’Batman’, grep‘\<man\>’只匹配’man’,而不是’Batman’或’manic’等其他的字符串。 ‘^’:指匹配的字符串在行首, ‘$’:指匹配的字符串在行尾, ==============grep、fgrep、egrep的区别================= 者都是搜索工具,但功能上有区别。 1)首先,grep支持的是标准正则表达式。 2)fgrep,不支持正则表达式,只用于匹配固定字符串。 grep把模式当做正则表达式看,fgrep把模式当做固定字符串看,所以后者要比前者速度快,当然同时后者的搜索功能要弱于前者。 3)egrep:为grep的扩充版本,改良了许多传统grep不能或不便的操作.比如: -grep之下不支持?与+这两种modifier,但egrep则可。 -grep不支持a|b或(abc|xyz)这类"或一"比对,但egrep则可。 -grep在处理{n,m}时,需用\{与\}处理,但egrep则不需。 =========================================== 示例说明 [root@kevin~]#ps-ef|grepin.telnetd root19955181013:43:53?0:00in.telnetd [root@kevin~]#moresize.txtsize文件的内容 b124230 b034325 a081016 m7187998 m7282064 a022021 a061048 m9324822 b103303 a013386 b044525 m8987131 B081016 M45678 B103303 BADc2345 [root@kevin~]#moresize.txt|grep'[a-b]'范围;如[A-Z]即A,B,C一直到Z都符合要求 b124230 b034325 a081016 a022021 a061048 b103303 a013386 b044525 [root@kevin~]#moresize.txt|grep'[a-b]'* b124230 b034325 a081016 m7187998 m7282064 a022021 a061048 m9324822 b103303 a013386 b044525 m8987131 B081016 M45678 B103303 BADc2345 [root@kevin~]#moresize.txt|grep'b'#单个字符;如[b]即b符合要求 b124230 b034325 b103303 b044525 [root@kevin~]#moresize.txt|grep'[bB]'#b或者B b124230 b034325 b103303 b044525 B081016 B103303 BADc2345 [root@kevin~]#grep'root'/etc/group root::0:root bin::2:root,bin,daemon sys::3:root,bin,sys,adm adm::4:root,adm,daemon uucp::5:root,uucp mail::6:root tty::7:root,tty,adm lp::8:root,lp,adm nuucp::9:root,nuucp daemon::12:root,daemon [root@kevin~]#grep'^root'/etc/group#匹配正则表达式的开始行 root::0:root [root@kevin~]#grep'uucp'/etc/group uucp::5:root,uucp nuucp::9:root,nuucp [root@kevin~]#grep'\<uucp'/etc/group uucp::5:root,uucp [root@kevin~]#grep'root[root@kevin~]#'/etc/group#匹配正则表达式的结束行 root::0:root mail::6:root [root@kevin~]#moresize.txt|grep-i'b1..*3'#忽略大小写 b124230 b103303 B103303 [root@kevin~]#moresize.txt|grep-iv'b1..*3'#查找不包含匹配项的行 b034325 a081016 m7187998 m7282064 a022021 a061048 m9324822 a013386 b044525 m8987131 B081016 M45678 BADc2345 [root@kevin~]#moresize.txt|grep-in'b1..*3' 1:b124230 9:b103303 15:B103303 [root@kevin~]#grep'[root@kevin~]#'/etc/init.d/nfs.server|wc-l 128 [root@kevin~]#grep'\[root@kevin~]#'/etc/init.d/nfs.server|wc–l#忽略正则表达式中特殊字符的原有含义 15 [root@kevin~]#grep'\$'/etc/init.d/nfs.server case"$1"in >/tmp/sharetab.$$ ["x$fstype"!=xnfs]&& echo"$path\t$res\t$fstype\t$opts\t$desc" >>/tmp/sharetab.$$ /usr/bin/touch-r/etc/dfs/sharetab/tmp/sharetab.$$ /usr/bin/mv-f/tmp/sharetab.$$/etc/dfs/sharetab if[-f/etc/dfs/dfstab]&&/usr/bin/egrep-v'^[]*(#|$)' if[$startnfsd-eq0-a-f/etc/rmmount.conf]&& if[$startnfsd-ne0];then elif[!-n"$_INIT_RUN_LEVEL"];then while[$wtime-gt0];do wtime=`expr$wtime-1` if[$wtime-eq0];then echo"Usage:$0{start|stop}" [root@kevin~]#moresize.txt thetestfile theirarefiles Theend [root@kevin~]#grep'the'size.txt thetestfile theirarefiles [root@kevin~]#grep'\<the'size.txt thetestfile theirarefiles [root@kevin~]#grep'the\>'size.txt thetestfile [root@kevin~]#grep'\<the\>'size.txt thetestfile [root@kevin~]#grep'\<[Tt]he\>'size.txt thetestfile 多个文件查询 [root@kevin~]#grep"sort"*.txt#见文件名的匹配 行匹配:输出匹配行的计数 [root@kevin~]#grep-c"48"kevin.txt#输出文档中含有48字符的行数 显示匹配行和行数 [root@kevin~]#grep-n"48"kevin.txt#显示所有匹配48的行和行号 显示非匹配的行 [root@kevin~]#grep-vn"48"kevin.txt#输出所有不包含48的行 显示非匹配的行 [root@kevin~]#grep-vn"48"kevin.txt#输出所有不包含48的行 大小写敏感 [root@kevin~]#grep-i"ab"kevin.txt#输出所有含有ab或Ab的字符串的行 ==================================== 正则表达式的应用(注意:最好把正则表达式用单引号括起来) [root@kevin~]#grep'[239].'kevin.txt#输出所有含有以2,3或9开头的,并且是两个数字的行 不匹配测试 [root@kevin~]#grep'^[^48]'kevin.txt#不匹配行首是48的行 使用扩展模式匹配 [root@kevin~]#grep-E'219|216'kevin.txt 使用类名 可以使用国际模式匹配的类名: [[:upper:]][A-Z] [[:lower:]][a-z] [[:digit:]][0-9] [[:alnum:]][0-9a-zA-Z] [[:space:]]空格或tab [[:alpha:]][a-zA-Z] [root@kevin~]#grep'5[[:upper:]][[:upper:]]'kevin.txt#查询以5开头以两个大写字母结尾的行 cat、more、less、tail、head命令 cat是一个文本文件(查看)和(连接)工具,通常与more搭配使用,与more不同的是cat可以合并文件。查看一个文件的内容,用cat比较简单, 就是cat后面直接接文件名。 cat[选项][文件]... 选项 -A,--show-all等价于-vET -b,--number-nonblank对非空输出行编号 -e等价于-vE -E,--show-ends在每行结束处显示$ -n,--number对输出的所有行编号 -s,--squeeze-blank不输出多行空行 -t与-vT等价 -T,--show-tabs将跳格字符显示为^I -u(被忽略) -v,--show-nonprinting使用^和M-引用,除了LFD和TAB之外 --help显示此帮助信息并离开 cat查看文件内容实例: [root@kevin~]#cat/etc/profile//查看/etc/目录下的profile文件内容; [root@kevin~]#cat-b/etc/fstab//查看/etc/目录下的profile内容,并且对非空白行进行编号,行号从1开始; [root@kevin~]#cat-n/etc/profile//对/etc目录中的profile的所有的行(包括空白行)进行编号输出显示; [root@kevin~]#cat-E/etc/profile//查看/etc/下的profile内容,并且在每行的结尾处附加$符号; cat加参数-n和nl工具差不多,文件内容输出的同时,都会在每行前面加上行号; [root@kevin~]#cat-n/etc/profile [root@kevin~]#nl/etc/profile cat可以同时显示多个文件的内容,比如我们可以在一个cat命令上同时显示两个文件的内容; [root@kevin~]#cat/etc/fstab/etc/profile cat对于内容极大的文件来说,可以通过管道|传送到more工具,然后一页一页的查看; [root@kevin~]#cat/etc/fstab/etc/profile|more cat的创建、连接文件功能实例: cat有创建文件的功能,创建文件后,要以EOF或STOP结束; [root@kevin~]#cat>kevin.txt<<EOF >我来测试cat创建文件,并且为文件输入内容; >北京是个好地方; >EOF [root@kevin~]#catkevin.txt 我来测试cat创建文件,并且为文件输入内容; 北京是个好地方; cat还有向已存在的文件追加内容的功能; [root@kevin~]#catgrace.txt IamBeiNanNanBeiFromgrace.Org. 我正在为cat命令写文档 [root@kevin~]#cat>>grace.txt<<EOF >我来测试cat向文档追加内容的功能; >OK? >OK~ >北京你好 >EOF [root@kevin~]#catgrace.txt//查看文件内容,看是否追回成功。 IamBeiNanNanBeiFromgrace.Org. 我正在为cat命令写文档 我来测试cat向文档追加内容的功能; OK? OK~ 北京你好 cat连接多个文件的内容并且输出到一个新文件中; 假设我们有sir01.txt、sir02.tx和sir03.txt,并且内容如下; [root@kevin~]#catsir01.txt 123456 iamtesting [root@kevin~]#catsir02.txt 56789 BeiNanTested [root@kevin~]#catsir03.txt 09876 grace.orgtesting 我想通过cat把sir01.txt、sir02.txt及sir03.txt三个文件连接在一起(也就是说把这三个文件的内容都接在一起)并输出到一个新的文件sir04.txt中。 注意: 其原理是把三个文件的内容连接起来,然后创建sir04.txt文件,并且把几个文件的内容同时写入sir04.txt中。特别值得一提的是,如果您输入到一个已经 存在的sir04.txt文件,会把sir04.txt内容清空。 [root@kevin~]#catsir01.txtsir02.txtsir03.txt>sir04.txt [root@kevin~]#moresir04.txt 123456 iamtesting 56789 BeiNanTested 09876 grace.orgtesting cat把一个或多个已存在的文件内容,追加到一个已存在的文件中 [root@kevin~]#catsir00.txt grace.orgforever [root@kevin~]#catsir01.txtsir02.txtsir03.txt>>sir00.txt [root@kevin~]#catsir00.txt grace.orgforever 123456 iamtesting 56789 BeiNanTested 09876 grace.orgtesting ====================================================== more是我们最常用的工具之一,最常用的就是显示输出的内容,然后根据窗口的大小进行分页显示,然后还能提示文件的百分比; 参数如下: +num从第num行开始显示; -num定义屏幕大小,为num行; +/pattern从pattern前两行开始显示; -c从顶部清屏然后显示; -d提示Pressspacetocontinue,'q'toquit.(按空格键继续,按q键退出),禁用响铃功能; -l忽略Ctrl+l(换页)字符; -p通过清除窗口而不是滚屏来对文件进行换页。和-c参数有点相似; -s把连续的多个空行显示为一行; -u把文件内容中的下划线去掉退出more的动作指令是q more的参数应用举例: [root@kevin~]#more-dc/etc/profile//显示提示,并从终端或控制台顶部显示; [root@kevin~]#more+4/etc/profile//从profile的第4行开始显示; [root@kevin~]#more-4/etc/profile//每屏显示4行; [root@kevin~]#more+/MAIL/etc/profile//从profile中的第一个MAIL单词的前两行开始显示; more的动作指令: 我们查看一个内容较大的文件时,要用到more的动作指令,比如ctrl+f(或空格键)是向下显示一屏,ctrl+b是返回上一屏;Enter键可以向下滚动显示n行,要通过定,默认为1行; 我们只说几个常用的;自己尝试一下就知道了; Enter向下n行,需要定义,默认为1行; Ctrl+f向下滚动一屏; 空格键向下滚动一屏; Ctrl+b返回上一屏; =输出当前行的行号; :f输出文件名和当前行的行号; v调用vi编辑器; !命令调用Shell,并执行命令; q退出more当我们查看某一文件时,想调用vi来编辑它,不要忘记了v动作指令,这是比较方便的; 其它命令通过管道和more结合的运用例子: 比如我们列一个目录下的文件,由于内容太多,我们应该学会用more来分页显示。这得和管道|结合起来,比如: [root@kevin~]#ls-l/etc|more ======================================================= less查看文件内容工具 less工具也是对文件或其它输出进行分页显示的工具,应该说是linux正统查看文件内容的工具,功能极其强大;您是初学者,我建议您用less。 由于less的内容太多,我们把最常用的介绍一下; 常用参数 -c从顶部(从上到下)刷新屏幕,并显示文件内容。而不是通过底部滚动完成刷新; -f强制打开文件,二进制文件显示时,不提示警告; -i搜索时忽略大小写;除非搜索串中包含大写字母; -I搜索时忽略大小写,除非搜索串中包含小写字母; -m显示读取文件的百分比; -M显法读取文件的百分比、行号及总行数; -N在每行前输出行号; -ppattern搜索pattern;比如在/etc/profile搜索单词MAIL,就用less-pMAIL/etc/profile -s把连续多个空白行作为一个空白行显示; -Q在终端下不响铃; 比如:我们在显示/etc/profile的内容时,让其显示行号; [root@kevin~]#less-N/etc/profile less的动作命令: 进入less后,我们得学几个动作,这样更方便我们查阅文件内容;最应该记住的命令就是q,这个能让less终止查看文件退出; 动作: 回车键向下移动一行; y向上移动一行; 空格键向下滚动一屏; b向上滚动一屏; d向下滚动半屏; hless的帮助; u向上洋动半屏; w可以指定显示哪行开始显示,是从指定数字的下一行显示;比如指定的是6,那就从第7行显示; g跳到第一行; G跳到最后一行; pn%跳到n%,比如10%,也就是说比整个文件内容的10%处开始显示; /pattern搜索pattern,比如/MAIL表示在文件中搜索MAIL单词; v调用vi编辑器; q退出less !command调用SHELL,可以运行命令;比如!ls显示当前列当前目录下的所有文件; 就less的动作来说,内容太多了,用的时候查一查manless是最好的。在这里就不举例子了; ========================================================== head工具,显示文件内容的前几行 head是显示一个文件的内容的前多少行; 用法比较简单; head-n行数值文件名; 比如我们显示/etc/profile的前10行内容,应该是: [root@kevin~]#head-n10/etc/profile ========================================================= tail工具,显示文件内容的最后几行 tail是显示一个文件的内容的最后多少行; 用法比较简单; tail-n行数值文件名; 比如我们显示/etc/profile的最后5行内容,应该是: [root@kevin~]#tail-n5/etc/profile tail-f/var/log/syslog显示文件syslog的后十行内容并在文件内容增加后,且自动显示新增的文件内容。 cut命令:打印每行特定范围内内容 cut是一个选取命令,就是将一段数据经过分析,取出我们想要的。一般来说,选取信息通常是针对“行”来进行分析的,并不是整篇信息分析的。 其语法格式为: cut[-bn][file]或cut[-c][file]或cut[-df][file] 使用说明 cut命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段写至标准输出。 如果不指定File参数,cut命令将读取标准输入。必须指定-b、-c或-f标志之一。 主要参数 -b:以字节为单位进行分割。这些字节位置将忽略多字节字符边界,除非也指定了-n标志。 -c:以字符为单位进行分割。 -d:自定义分隔符,默认为制表符。 -f:与-d一起使用,指定显示哪个区域。 -n:取消分割多字节字符。仅和-b标志一起使用。如果字符的最后一个字节落在由-b标志的List参数指示的<br/>范围之内,该字符将被写出;否则,该字符将被排除。 cut一般以什么为依据呢?也就是说,我怎么告诉cut我想定位到的剪切内容呢? cut命令主要是接受三个定位方法: 第一,字节(bytes),用选项-b 第二,字符(characters),用选项-c 第三,域(fields),用选项-f ========================================= cut在取列内容的时候和awk相识 awk-F""'{print$n}'以-F后的引号内的内容为列的分隔符,打印第n行 cut-d""-fn以-d后的引号内的内容为列的分隔符,打印第n行 比如打印a.txt文件中以空格为列的分隔符,打印第5行 awk-F""'{print$5}'a.txt当以空格为分隔符的时候,-F""可以省去 cut-d""-f5a.txt ========================================= 以“字节”定位 举个例子吧,当你执行ps命令时,会输出类似如下的内容: [root@kevin~]#who rocrocket:02009-01-0811:07 rocrocketpts/02009-01-0811:23(:0.0) rocrocketpts/12009-01-0814:15(:0.0) 如果我们想提取每一行的第3个字节,就这样: [root@kevin~]#who|cut-b3 c c c 如果“字节”定位中,我想提取第3,第4、第5和第8个字节,怎么办? -b支持形如3-5的写法,而且多个定位之间用逗号隔开就成了。看看例子吧: [root@kevin~]#who|cut-b3-5,8 croe croe croe 但有一点要注意,cut命令如果使用了-b选项,那么执行此命令时,cut会先把-b后面所有的定位进行从小到大排序,然后再提取。 可不能颠倒定位的顺序哦。这个例子就可以说明这个问题: [root@kevin~]#who|cut-b8,3-5 croe croe croe 还有哪些类似“3-5”这样的小技巧,列举一下吧! [root@kevin~]#who rocrocket:02009-01-0811:07 rocrocketpts/02009-01-0811:23(:0.0) rocrocketpts/12009-01-0814:15(:0.0) [root@kevin~]#who|cut-b-3 roc roc roc [root@kevin~]#who|cut-b3- crocket:02009-01-0811:07 crocketpts/02009-01-0811:23(:0.0) crocketpts/12009-01-0814:15(:0.0) -3表示从第一个字节到第三个字节,而3-表示从第三个字节到行尾。如果你细心,你可以看到这两种情况下,都包括了第三个字节“c”。 如果我执行who|cut-b-3,3-,你觉得会如何呢?答案是输出整行,不会出现连续两个重叠的c的。看: [root@kevin~]#who|cut-b-3,3- rocrocket:02009-01-0811:07 rocrocketpts/02009-01-0811:23(:0.0) rocrocketpts/12009-01-0814:15(:0.0) 给个以字符为定位标志的最简单的例子吧! 下面例子你似曾相识,提取第3,第4,第5和第8个字符: [root@kevin~]#who|cut-c3-5,8 croe croe croe 不过,看着怎么和-b没有什么区别啊?莫非-b和-c作用一样?其实不然,看似相同,只是因为这个例子举的不好,who输出的都是单字节字符, 所以用-b和-c没有区别,如果你提取中文,区别就看出来了,来,看看中文提取的情况: [root@kevin~]#catcut_ch.txt 星期一 星期二 星期三 星期四 [root@kevin~]#cut-b3cut_ch.txt � � � � [root@kevin~]#cut-c3cut_ch.txt 一 二 三 四 看到了吧,用-c则会以字符为单位,输出正常;而-b只会傻傻的以字节(8位二进制位)来计算,输出就是乱码。 既然提到了这个知识点,就再补充一句,如果你学有余力,就提高一下。 当遇到多字节字符时,可以使用-n选项,-n用于告诉cut不要将多字节字符拆开。例子如下: [root@kevin~]#catcut_ch.txt|cut-b2 � � � � [root@kevin~]#catcut_ch.txt|cut-nb2 [root@kevin~]#catcut_ch.txt|cut-nb1,2,3 星 星 星 星 域是怎么回事呢?解释解释:) 为什么会有“域”的提取呢,因为刚才提到的-b和-c只能在固定格式的文档中提取信息,而对于非固定格式的信息则束手无策。这时候“域”就派上用场了。 如果你观察过/etc/passwd文件,你会发现,它并不像who的输出信息那样具有固定格式,而是比较零散的排放。但是,冒号在这个文件的每一行中都 起到了非常重要的作用,冒号用来隔开每一个项。 cut命令提供了这样的提取方式,具体的说就是设置“间隔符”,再设置“提取第几个域”,就OK了! 以/etc/passwd的前五行内容为例: [root@kevin~]#cat/etc/passwd|head-n5 root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin [root@kevin~]#cat/etc/passwd|head-n5|cut-d:-f1 root bin daemon adm lp 用-d来设置间隔符为冒号,然后用-f来设置我要取的是第一个域,再按回车,所有的用户名就都列出来了! 当然,在设定-f时,也可以使用例如3-5或者4-类似的格式: [root@kevin~]#cat/etc/passwd|head-n5|cut-d:-f1,3-5 root:0:0:root bin:1:1:bin daemon:2:2:daemon adm:3:4:adm lp:4:7:lp [root@kevin~]#cat/etc/passwd|head-n5|cut-d:-f1,3-5,7 root:0:0:root:/bin/bash bin:1:1:bin:/sbin/nologin daemon:2:2:daemon:/sbin/nologin adm:3:4:adm:/sbin/nologin lp:4:7:lp:/sbin/nologin [root@kevin~]#cat/etc/passwd|head-n5|cut-d:-f-2 root:x bin:x daemon:x adm:x lp:x 如果遇到空格和制表符时,怎么分辨呢?我觉得有点乱,怎么办? 有时候制表符确实很难辨认,有一个方法可以看出一段空格到底是由若干个空格组成的还是由一个制表符组成的。 [root@kevin~]#cattab_space.txt thisistabfinish. thisisseveralspacefinish. [root@kevin~]#sed-nltab_space.txt thisistab\tfinish.$ thisisseveralspacefinish.$ 如果是制表符(TAB),那么会显示为\t符号,如果是空格,就会原样显示。 通过此方法即可以判断制表符和空格了。 注意,上面sed-n后面的字符是L的小写字母哦,不要看错。 我应该在cut-d中用什么符号来设定制表符或空格呢? 其实cut的-d选项的默认间隔符就是制表符,所以当你就是要使用制表符的时候,完全就可以省略-d选项,而直接用-f来取域就可以了。 如果你设定一个空格为间隔符,那么就这样: [root@kevin~]#cattab_space.txt|cut-d''-f1 this this 注意,两个单引号之间可确实要有一个空格哦,不能偷懒。 而且,你只能在-d后面设置一个空格,可不许设置多个空格,因为cut只允许间隔符是一个字符。 [root@kevin~]#cattab_space.txt|cut-d''-f1 cut:thedelimitermustbeasinglecharacter Try`cut--help'formoreinformation. cut有哪些缺陷和不足? 猜出来了吧?对,就是在处理多空格时。 如果文件里面的某些域是由若干个空格来间隔的,那么用cut就有点麻烦了,因为cut只擅长处理“以一个字符间隔”的文本内容。 tr命令:删除,去重,替换文本内容 可以把tr看作为一个简化的sed工具,tr表示为:translate。tr命令主要用于实现以下两个功能 替换操作的字符串转换。 删除操作的字符串转换,可以很容易的删除一些控制字符或者是空行。 tr命令能够实现的功能,都能够用sed命令来实现。但就具体的替换功能来说,tr用起来更容易,也比较简单。 一,命令格式 tr[option]["string1"]["string2"]<file 常用的选项有: 默认选项。就是没有任何选项的时候,tr默认为替换操作,就是将string1在文件中出现的字符替换为string2中的字符,这里要注意的是替换关系。 -c选项,用string1中字符的补集替换string1,这里的字符集为ASCII。 -d选项,删除文件中所有在string1中出现的字符。 -s选项,删除文件中重复并且在string1中出现的字符,只保留一个。 -c选项在使用时,只是将string1替换为现在的补集 [root@kevin~]#echo"helloworld,root,2012"|tr-c"0-9""*" *****************2012* 可以看出,我们使用0-9,添加-c选项后,会把0-9替换为其补集,这时补集自然不包含0-9,而包含很多其它的字符,接下来就把所有的其它字符都替换成*号, 但不包含数字。 如果只需要替换数字的话: [root@kevin~]#echo"helloworld,root,2012"|tr"0-9""*" helloworld,root,**** 二,字符串的取值范围 指定string或string2的内容时,只能使用单字符或字符串范围或列表。 [a-z]a-z内的字符组成的字符串。 [A-Z]A-Z内的字符组成的字符串。 [0-9]数字串。 \octal一个三位的八进制数,对应有效的ASCII字符。 [O*n]表示字符O重复出现指定次数n。因此[O*2]匹配OO的字符串。 三,控制字符的不同表达方式 速记符含义八进制方式 \aCtrl-G铃声\007 \bCtrl-H退格符\010 \fCtrl-L走行换页\014 \nCtrl-J新行\012 \rCtrl-M回车\015 \tCtrl-Itab键\011 \vCtrl-X\030注意这些控制字符,如果想在linux下输入,如我们可能需要输入^M这种字符,只需ctrl+V+M同时按下即可。 四,字符替换 这是tr的默认操作,先看下面的命令和输出 [root@kevin~]#echo"helloworld"|tr"a-z""A-Z" HELLOWORLD [root@kevin~]#echo"helloworld"|tr"a-l""A-Z" HELLoworLD [root@kevin~]#echo"helloworld"|tr"a-z""A-H" HEHHHHHHHD 第一行输出就是将小写换成大写。 第二行输出将小写中的a-l分别换成A-L,而将小写中的l以后的字符都不替换。 第三行输出将小写中的a-h换成A-H,而h以后的字符都换成H,因为后者的替换空间没有前面的字符空间大,所以就重复后面的H, 相当于后面的字符是A-HHH......HHHHH。 如果我们想要进行大小写转换,可以按下面的输入: tr"a-z""A-Z"<inputfile 五,去除重复字符 这个时候,所用的选项是-s选项,如: [root@kevin~]#echo"helloworld,root"|tr-s"ao" helloworld,rot [root@kevin~]#echo"helloworld,root"|tr-s"lo" heloworld,rot [root@kevin~]#echo"helloworld,root"|tr-s"a-z" heloworld,rot [root@kevin~]#echo"helloworld,root"|tr-s"0-9" helloworld,root 第一行表示将输入字符串中的包含在"ao"字符集中的重复字符去掉,只留一个。因为"helloworld,root",只有o满足条件,所以将root变成rot,把中间的两个o变成一个。 第二行将hello和root两个字符都压缩了。 第三行表示将a-z中的除复字符都去掉。 第三行表示将字符串中的重复的且重复字符在0-9字符集中的字符去掉,这里没有。 如果我们想要去掉空行,可以这样操作: tr-s"\n"<inputfile或者tr-s"\012"<inputfile//这两个是一样的。 就是将重复的换行符去掉,只留一个。 六,删除字符 -d选项和-s选项类似,只不过-d选项会删除所有出现的字符。 [root@kevin~]#echo"helloworld,root"|tr-d"a-h" lloworl,root [root@kevin~]#echo"helloworld,root,2012"|tr-d"a-z" ,,2012 [root@kevin~]#echo"helloworld,root,2012"|tr-d"0-9" sort/uniq/cut/wc命令 sort命令对File参数指定的文件中的行排序,并将结果写到标准输出。如果File参数指定多个文件,那么sort命令将这些文件连接起来,并当作一个文件进行排序。 sort语法 sort[-fbMnrtuk][fileorstdin] 选项与参数: -f:忽略大小写的差异,例如A与a视为编码相同; -b:忽略最前面的空格符部分; -M:以月份的名字来排序,例如JAN,DEC等等的排序方法; -n:使用『纯数字』进行排序(默认是以文字型态来排序的); -r:反向排序; -u:就是uniq,相同的数据中,仅出现一行代表; -t:分隔符,默认是用[tab]键来分隔; -k:以那个区间(field)来进行排序的意思 对/etc/passwd的账号进行排序 [root@kevin~]#cat/etc/passwd|sort adm:x:3:4:adm:/var/adm:/sbin/nologin apache:x:48:48:Apache:/var/www:/sbin/nologin bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin sort是默认以第一个数据来排序,而且默认是以字符串形式来排序,所以由字母a开始升序排序。 /etc/passwd内容是以:来分隔的,我想以第三栏来排序,该如何 [root@kevin~]#cat/etc/passwd|sort-t':'-k3 root:x:0:0:root:/root:/bin/bash uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin operator:x:11:0:operator:/root:/sbin/nologin bin:x:1:1:bin:/bin:/sbin/nologin games:x:12:100:games:/usr/games:/sbin/nologin 默认是以字符串来排序的,如果想要使用数字排序: [root@kevin~]#cat/etc/passwd|sort-t':'-k3n root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/bin/sh bin:x:2:2:bin:/bin:/bin/sh 默认是升序排序,如果要倒序排序,如下 [root@kevin~]#cat/etc/passwd|sort-t':'-k3nr nobody:x:65534:65534:nobody:/nonexistent:/bin/sh ntp:x:106:113::/home/ntp:/bin/false messagebus:x:105:109::/var/run/dbus:/bin/false sshd:x:104:65534::/var/run/sshd:/usr/sbin/nologin 如果要对/etc/passwd,先以第六个域的第2个字符到第4个字符进行正向排序,再基于第一个域进行反向排序。 [root@kevin~]#cat/etc/passwd|sort-t':'-k6.2,6.4-k1r sync:x:4:65534:sync:/bin:/bin/sync proxy:x:13:13:proxy:/bin:/bin/sh bin:x:2:2:bin:/bin:/bin/sh sys:x:3:3:sys:/dev:/bin/sh 查看/etc/passwd有多少个shell:对/etc/passwd的第七个域进行排序,然后去重: [root@kevin~]#cat/etc/passwd|sort-t':'-k7-u root:x:0:0:root:/root:/bin/bash syslog:x:101:102::/home/syslog:/bin/false daemon:x:1:1:daemon:/usr/sbin:/bin/sh sync:x:4:65534:sync:/bin:/bin/sync sshd:x:104:65534::/var/run/sshd:/usr/sbin/nologin ================================================================== uniq命令可以去除排序过的文件中的重复行,因此uniq经常和sort合用。也就是说,为了使uniq起作用,所有的重复行必须是相邻的。 uniq语法 uniq[-icu] 选项与参数: -i:忽略大小写字符的不同; -c:进行计数 -u:只显示唯一的行 [root@kevin~]#cattestfile hello world friend hello world hello 直接删除未经排序的文件,将会发现没有任何行被删除 [root@kevin~]#uniqtestfile hello world friend hello world hello 排序文件,默认是去重 [root@kevin~]#catwords|sort|uniq friend hello world 排序之后删除了重复行,同时在行首位置输出该行重复的次数 [root@kevin~]#sorttestfile|uniq-c 1friend 3hello 2world 仅显示存在重复的行,并在行首显示该行重复的次数 [root@kevin~]#sorttestfile|uniq-dc 3hello 2world 仅显示不重复的行 [root@kevin~]#sorttestfile|uniq-u friend =============================================== sort|uniq排序去重 sort|uniq-c|srot-rn排序去重,并降序 sort|uniq-c打印重复的行数 sort|uniq-d打印交集部分 sort|uniq-u打印交集以外的部分 ============================================== [root@kevin~]#cata.txt sdfsdf 123 123 1234 123 dasdfsd sdfsdf asfd34234 [root@kevin~]#cata.txt|sort|uniq 123 1234 asfd34234 dasdfsd sdfsdf [root@kevin~]#cata.txt|sort|uniq-c 3123 11234 1asfd34234 1dasdfsd 2sdfsdf [root@kevin~]#cata.txt|sort|uniq-d 123 sdfsdf [root@kevin~]#cata.txt|sort|uniq-u 1234 asfd34234 dasdfsd [root@kevin~]#cata.txt sdfsdf 123 123 1234 123 dasdfsd sdfsdf asfd34234 [root@kevin~]#catb.txt sdf 123 err 2345 123 gggg [root@kevin~]#cata.txtb.txt|sort|uniq 123 1234 2345 asfd34234 dasdfsd err gggg sdf sdfsdf [root@kevin~]#cata.txtb.txt|sort|uniq-c 5123 11234 12345 1asfd34234 1dasdfsd 1err 1gggg 1sdf 2sdfsdf [root@kevin~]#cata.txtb.txt|sort|uniq-d 123 sdfsdf [root@kevin~]#cata.txtb.txt|sort|uniq-u 1234 2345 asfd34234 dasdfsd err gggg sdf ======================================================= cut命令可以从一个文本文件或者文本流中提取文本列。 cut语法 cut-d'分隔字符'-ffields<==用于有特定分隔字符 cut-c字符区间<==用于排列整齐的信息 选项与参数: -d:后面接分隔字符。与-f一起使用; -f:依据-d的分隔字符将一段信息分割成为数段,用-f取出第几段的意思; -c:以字符(characters)的单位取出固定字符区间; PATH变量如下 [root@kevin~]#echo$PATH /bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/X11R6/bin:/usr/games #1|2|3|4|5|6|7 将PATH变量取出,我要找出第五个路径。 [root@kevin~]#echo$PATH|cut-d':'-f5 /usr/local/bin 将PATH变量取出,我要找出第三和第五个路径。 [root@kevin~]#echo$PATH|cut-d':'-f3,5 /sbin:/usr/local/bin 将PATH变量取出,我要找出第三到最后一个路径。 [root@kevin~]#echo$PATH|cut-d':'-f3- /sbin:/usr/sbin:/usr/local/bin:/usr/X11R6/bin:/usr/games 将PATH变量取出,我要找出第一到第三个路径。 [root@kevin~]#echo$PATH|cut-d':'-f1-3 /bin:/usr/bin:/sbin: 将PATH变量取出,我要找出第一到第三,还有第五个路径。 [root@kevin~]#echo$PATH|cut-d':'-f1-3,5 /bin:/usr/bin:/sbin:/usr/local/bin 实用例子:只显示/etc/passwd的用户和shell [root@kevin~]#cat/etc/passwd|cut-d':'-f1,7 root:/bin/bash daemon:/bin/sh bin:/bin/sh ==================================================== wc 统计文件里面有多少单词,多少行,多少字符。 wc语法 [root@kevin~]#wc[-lwm] 选项与参数: -l:仅列出行; -w:仅列出多少字(英文单字); -m:多少字符; 默认使用wc统计/etc/passwd [root@kevin~]#wc/etc/passwd 40451719/etc/passwd 40是行数,45是单词数,1719是字节数 wc的命令比较简单使用,每个参数使用如下: [root@kevin~]#wc-l/etc/passwd#统计行数,在对记录数时,很常用 40/etc/passwd#表示系统有40个账户 [root@kevin~]#wc-w/etc/passwd#统计单词出现次数 45/etc/passwd [root@kevin~]#wc-m/etc/passwd#统计文件的字节数 1719 split命令:切分文件 split命令用于将一个文件分割成数个。 该指令将大文件分割成较小的文件,在默认情况下将按照每1000行切割成一个小文件。 语法 split[--help][--version][-<行数>][-b<字节>][-C<字节>][-l<行数>][要切割的文件][输出文件名] 参数说明: -<行数>:指定每多少行切成一个小文件.如split-3a.txt -b<字节>:指定每多少字节切成一个小文件 -l,--lines=NUMBER:对file进行切分,每个文件有NUMBER行。 --help:在线帮助 --version:显示版本信息 -C<字节>:与参数"-b"相似,但是在切割时将尽量维持每行的完整性 [输出文件名]:设置切割后文件的前置文件名,split会自动在前置文件名后再加上编号 示例1: 使用指令split将文件a.txt每3行切割成一个文件,输入如下命令: 注意:是按照a.txt文件中的行数进行分割的,每3行切分到一个文件中,切割成多个以"x"开头的小文件。直至所有行数被分完。 [root@kevin~]#cata.txt sdfsdf 123123123 sdfasdf2r345345 kljljkl sjkdfjsdofopf sadfsd2343 123123 asdf4555 66666 888888 [root@kevin~]#split-3a.txt [root@kevin~]#ls anaconda-ks.cfga.txtxaaxabxacxad [root@kevin~]#catxaa sdfsdf 123123123 sdfasdf2r345345 [root@kevin~]#catxab kljljkl sjkdfjsdofopf sadfsd2343 [root@kevin~]#catxac 123123 asdf4555 66666 [root@kevin~]#catxad 888888 示例2: 有个文件要处理,因为很大,所以想把它切成若干份,每份N行,以便并行处理。 参数说明: -b,--bytes=SIZE:对file进行切分,每个小文件大小为SIZE。可以指定单位b,k,m。 -l,--lines=NUMBER:对file进行切分,每个文件有NUMBER行。 prefix:分割后产生的文件名前缀。 示例: 假设要切分的文件为test.2012-08-16_17,大小1.2M,12081行。 1) [root@kevin~]#split-l5000test.2012-08-16_17 生成xaa,xab,xac三个文件。 [root@kevin~]#wc-l#看到三个文件行数如下: 5000xaa 5000xab 2081xac 12081总计 2) [root@kevin~]#split-b600ktest.2012-08-16_17 生成xaa,xab两个文件 [root@kevin~]#ls-lh#看到两个文件大小如下: 600Kxaa 554Kxab 3) [root@kevin~]#split-b500ktest.2012-08-16_17example 得到三个文件,文件名的前缀都是example [root@kevin~]#ls-lh#看到文件信息如下: 500Kexampleaa 500Kexampleab 154Kexampleac 示例3: 将一个大文件分成若干个小文件方法 例如将一个BLM.txt文件分成前缀为BLM_的1000个小文件,后缀为系数形式,且后缀为4位数字形式 [root@kevin~]#wc-lBLM.txt#读出BLM.txt文件一共有多少行 [root@kevin~]#split-l2482../BLM/BLM.txt-d-a4BLM_ 将文件BLM.txt分成若干个小文件,每个文件2482行(-l2482),文件前缀为BLM_,系数不是字母而是数字(-d),后缀系数为四位数(-a4) ===================================================== Linux下文件分割可以通过split命令来实现,可以指定按行数分割和安大小分割两种模式。Linux下文件合并可以通过cat命令来实现,非常简单。 在Linux下用split进行文件分割: 模式一:指定分割后文件行数 对与txt文本文件,可以通过指定分割后文件的行数来进行文件分割。 命令:split-l300large_file.txtnew_file_prefix 模式二:指定分割后文件大小 split-b10mserver.logwaynelog 对二进制文件我们同样也可以按文件大小来分隔。 在Linux下用cat进行文件合并: 命令:catsmall_files*>large_file 将a.txt的内容输入到b.txt的末尾 cata.txt>>b.txt comm命令:对于两个已排序文件,逐行比对 一、常用用法 commFILE1FILE2 二、含义与选项 2.1、含义 对于两个已排序的文件,逐行比对。 打印结果有3列:第1列,只属于“FILE1”的行;第2列,只属于“FILE2”的行;第3列,既属于“FILE1”,又属于“FILE2”的行。 2.2、选项表示的意思 “FILE1,FILE2”:指代已排序文件“FILE1”和“FILE2” 三、其他 3.1、“LC_COLLATE”等环境变量 由于涉及到两个字符串的比较等,故而程序实现中使用“LC_COLLATE”等环境变量,最终结果受到“LC_COLLATE”等环境变量的控制。 3.2、排序策略 comm命令实现设定的排序策略是“按照字典序排序”。两个已排序文件使用的排序策略组合共有3种情况。 3.2.1、情况1 一个排序文件按照字典序排序,另外一个排序文件按照非字典序(其他排序策略)排序。显而易见,在这种情况下,comm命令的执行结果会比较奇怪。 [root@localhost~]#cata.txt 001 02 3 10 [root@localhost~]#catb.txt 001 02 5 06 007 10 即已按照“数值大小”排序,执行“逐行比对”过程,我们的预期结果是:“3”只属于“c.txt”,“5,06,007”只属于“d.txt”,“001,02,10”共属于两个文件。 现在执行comma.txtb.txt命令,得到如图1所示结果,不能达到预期。 [root@localhost~]#comma.txtb.txt 001 02 3 comm:file1isnotinsortedorder 10 5 comm:file2isnotinsortedorder 06 007 10 执行comm--nocheck-ordera.txtb.txt命令,得到如图2所示结果,也不能达到预期。 [root@localhost~]#comm--nocheck-ordera.txtb.txt 001 02 3 10 5 06 007 10 两个文件都已按照字典序排序,这符合comm命令实现的设定,comm命令的执行结果能够达到预期。执行下述命令,得到如图3所示结果,结果符合预期。 [root@localhost~]#sorta.txt>aa.txt [root@localhost~]#sortb.txt>bb.txt [root@localhost~]#commaa.txtbb.txt 001 007 02 06 10 3 5 [root@localhost~]#cataa.txt 001 02 10 3 [root@localhost~]#catbb.txt 001 007 02 06 10 5 join命令:根据两行中具有相同值的两个字段,将该两行内容拼接成一行打印输出 一、常用用法 join[-tCHAR][-i][--header][-1FIELD][-2FIELD][-eSTR]FILE1FILE2 二、含义与选项 2.1、含义 存在两个已排序文件,假如文件1中的某条记录的某个字段值(默认是第一个字段,从1开始计数)与文件2中的某条记录的某个字段值 (默认是第一个字段,从1开始计数)一致,那么在最终打印结果中,将这两条记录拼接成一条记录。 2.2、选项表示的意思 “-tCHAR”:以“CHAR”字符作为记录内字段间的分隔符,默认的分隔符是“空格符” “-i”:两个字段值比较时,忽略大小写 “–header”:两个文件的第一行作为说明行,不参与比较 “-1FIELD”:FILE1中以第“FIELD”个字段作为比较字段 “-2FIELD”:FILE2中以第“FIELD”个字段作为比较字段 “-eSTR”:在最终的拼接记录中,如果某个字段的值为空,那么以“STR”替换 “FILE1”:文件1 “FILE2”:文件2 示例一 有文件“a.txt”和“b.txt”,内容分别如下: [root@localhost~]#cata.txt a1 b2 [root@localhost~]#catb.txt a3 b4 执行以下命令,得到如下结果: [root@localhost~]#joina.txtb.txt a13 b24 示例二 有文件“a.txt”和“b.txt”,内容分别如下: [root@localhost~]#cata.txt a;1 b;2 [root@localhost~]#catb.txt a;3 b;4 执行以下命令,得到如下结果: [root@localhost~]#join-t';'a.txtb.txt a;1;3 b;2;4 示例三 有文件“a.txt”和“b.txt”,内容分别如下: [root@localhost~]#cata.txt A1 b2 [root@localhost~]#catb.txt a3 b4 执行以下命令,得到如下结果: [root@localhost~]#join-ia.txtb.txt A13 b24 示例四 有文件“a.txt”和“b.txt”,内容分别如下: [root@localhost~]#cata.txt Col1Col2 a1 b2 [root@localhost~]#catb.txt Col3Col4 a3 b4 执行以下命令,得到如下结果: [root@localhost~]#join--headera.txtb.txt Col1Col2Col4 a13 b24 示例五 有文件“a.txt”和“b.txt”,内容分别如下: [root@localhost~]#cata.txt a1f b2g [root@localhost~]#catb.txt f35 g46 执行以下命令,得到如下结果: [root@localhost~]#join-13-21a.txtb.txt fa135 gb246 示例六 有文件“a.txt”和“b.txt”,内容分别如下: [root@localhost~]#cata.txt a b2 [root@localhost~]#catb.txt a3 b4 执行以下命令,得到如下结果: [root@localhost~]#join-e"helloworld"a.txtb.txt ahelloworld3 b24 四、其他 4.1、“LC_COLLATE”等环境变量 由于涉及到两个字符串的比较等,故而程序实现中使用“LC_COLLATE”等环境变量,最终结果受到“LC_COLLATE”等环境变量的控制。 4.2、排序策略 跟“comm”命令一样,join命令实现设定的排序策略是“按照字典序排序”。因而,两个文件“已排序”应该是按照字典序已排序,否则执行join命令得到的结果很有可能不能符合预期。

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

Nightingale 2.2.0 发布,滴滴开源运维监控系统

Nightingale从正式发布到今天5.21号,差不多两个月左右的时间,社区用户参与热情很高,发布了多个版本,最新版本已经到了2.2.0,这里罗列一下相关改进,供大家参考,欢迎大家参与到Nightingale的建设中来,我们希望与社区一起,把监控这个事情,做到极致。 进程采集不但支持采集进程数目,也支持采集进程cpu和mem占用 页面上支持了plugin的配置,可以给plugin脚本传参,通过配置也可以指定只启用部分节点下的plugin 服务端接收到监控数据之后,可以同时转发一份到OpenTSDB或者InfluxDB,转发到Thanos的支持也在开发中 客户端可以用更易用的方式来忽略某些分区的监控数据采集,对docker的/var/lib分区排除有帮助 数据缺失告警支持同时把tag报出来,便于了解具体是哪个指标有问题 看图增加了同环比看图能力,对于周期性的有规律的图形,可以很方便看出趋势 数据模型做了增强,支持了Extra字段,可以用来放置traceid或者日志,打开更多想象空间 客户端与服务端之间的通信从短连接改成长连接,提升性能 优化端口监控策略,先尝试连接127.0.0.1,如果无法连通再尝试连identity中配置的ip,适用面更广 支持了中英文两个语种的界面 在客户端支持了COUNTER类型的指标,这样Open-Falcon的绝大部分插件和采集器都可以复用 支持LDAP获取邮箱、手机号等信息,并回灌数据库 更多优化项就不罗列了,当然,也修复了一些bug,2.2.0这个版本是一个非常稳定的版本,推荐大家试用。

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

标记 (TAG) 您的运维编排(OOS)资源

标签的基本知识 标签是资源Meta信息,标签是一些充当元数据的词和短语,支持用户自定义和系统预制。每个标签都包含一个键(Key)和一个值(Value)。标签是一种资源的属性描述。 标签与资源是 多对多的关系。 标签可让您按各种标准(例如用途、所有者或环境)对 阿里云 资源进行分类。这在您具有相同类型的许多资源时会很有用,您可以根据分配给资源的标签快速识别特定资源。 标签对阿里云资源没有任何语义意义,应严格按字符串进行解析。同时,标签不会自动分配至您的资源。您可以修改标签的key和value,还可以随时删除资源的标签。您可以将标签的值设为空的字符串,但是不能将其设为空值。如果您添加的标签的值与该实例上现有标签的值相同,新的值就会覆盖旧值。如果删除资源,资源的所有标签也会被删除。 可以使用管理控制台 和 API 处理标签。 标签设计详情见最佳实践

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

运维编排场景系列-----如何使用jq

本文主要讲解在OOS如何对任务中的值进行筛选,任务中值的筛选主要依赖模版中两个常见字段,一个是ValueSelector,另一个是PropertySelector,且这两个字段必须配合jq表达式使用。那么接下来就分别讲下jq是什么,两个筛选字段何时需要定义、在哪定义和作用,以及各场景下jq表达式使用的分析。 jq介绍 jq是一个开源的数据处理工具,它可处理JSON格式的数据,比如按照您指定的jq表达式,筛选出JSON中你想要的部分。筛选时,jq把JSON格式的数据作为input,并根据指定的jq表达式进行筛选,然后返回一个output。jq有很多灵活的使用方法,详见后附的jq语法手册。 OOS中的筛选字段 先说下OOS任务中值的筛选目的,无非两种,一种是筛出期待的结果,并将其赋值给某个参数,供其他任务使用该参数;另一种则是筛选出期待的结果,在任务中将结果值与预先指定的值进行比较,用来检查某种条件。所以OOS中有两个用来筛选的字段,分别是ValueSelector和PropertySelector,前者用在给参数赋值前,后者用在检查某个条件前。 当任务有具体Outputs时,需要在Outputs中定义ValueSelector字段,该字段用来筛选任务动作返回的值,并且将筛选结果赋值给Outputs输出的参数。具体讲,如任务的动作为API类动作,则动作返回值即任务调用API后返回的JSON值;若任务的动作为事件触发器,则动作返回值为触发器监控事件发生的JSON消息通知体。筛选方式是jq把动作返回值作为输入参数,通过字段的jq表达式进行筛选,筛选结果作为任务的Outputs输出参数值。 当任务的动作为ACS::WaitFor或ACS::CheckFor时,需要在任务的Properties部分定义PropertySelector字段,该字段用来筛选任务调用API返回的JSON值,筛选方式是jq把API返回的JSON作为输入参数,并通过字段的jq表达式进行筛选,最后OOS将筛选结果与Properties中的DesiredValues或NotDesiredValues字段内包含的值进行比较,比较结果作为任务等待或判断的参考,进而执行后面的逻辑。 jq在OOS中的使用 下面带大家分析下一些公共模版中jq表达式的使用。 ValueSelector 场景1 FormatVersion: OOS-2019-06-01 Description: Adds backend servers by specifying tag. Parameters: loadBalancerId: Description: The ID of the SLB instance. Type: String AllowedPattern: lb-[A-Za-z0-9]* MaxLength: 30 MinLength: 1 tagKey: Description: The specific tag key. Type: String MinLength: 1 tagValue: Description: The specific tag value. Type: String MaxLength: 30 MinLength: 1 OOSAssumeRole: Description: The RAM role to be assumed by OOS. Type: String Default: OOSServiceRole RamRole: '{{ OOSAssumeRole }}' Tasks: - Name: describeRunningInstancesByTag Action: ACS::ExecuteApi Description: Views the ECS instances by specifying tag. Properties: Service: ECS API: DescribeInstances Parameters: Status: Running Tags: - Key: '{{ tagKey }}' Value: '{{ tagValue }}' Outputs: instanceIds: Type: List ValueSelector: .Instances.Instance[].InstanceId 我们来看下上面的模版,请直接看Tasks部分的describeRunningInstancesByTag任务,该任务是有具体Outputs的,其定义了输出名称为instanceIds的参数,参数Type为List,同时也定义了ValueSelector字段,并且该字段的jq表达式为.Instances.Instance[].InstanceId。就如Outputs中参数名 instanceIds字面意思,其表示输出API返回结果中所有ECS实例ID,那么该任务调用的API是DescribeInstances,API返回的JSON结果样例如下。结合此JSON样例,我们看下在.Instances.Instance[].InstanceId作用下,instanceIds最终返回值的获取过程。首先筛选出JSON中Key为Instances的结果,然后对结果继续筛选,获取Key为Instance的结果,该结果是一个数组,此时又对所得结果进行迭代,并将每个迭代结果中Key为InstanceId的值以List类型进行返回,于是得到最终返回值["id-001","id-002"],即'{{describeRunningInstancesByTag.instanceIds}}'的值为["id-001","id-002"]'。 API调用返回样例(JSON) { "PageNumber":"1", "TotalCount":"1", "PageSize":"10", "RequestId":"14A07460-EBE7-47CA-9757-12CC4761D47A", "Instances":{ "Instance":[ { "ImageId":"centos6u5_64_20G_aliaegis_20150130.vhd", "InnerIpAddress":{ "IpAddress":[ "10.170.XX.XXX" ] }, "InstanceId":"id-001", "EipAddress":{}, "InternetMaxBandwidthIn":"-1", "ZoneId":"cn-shenzhen-a", "InstanceNetworkType":"classic", "PublicIpAddress":{ "IpAddress":[ "120.25.XX.XXX" ] }, "InternetChargeType":"PayByTraffic", "HostName":"iZ94t3s0j***", "InstanceType":"ecs.s2.large", "SerialNumber":"51d1353b-22bf-4567-a176-8b3e12e43135", "IoOptimized":"false", "CreationTime":"2015-07-27T07:08Z", "Status":"Running", "VpcAttributes":{ "PrivateIpAddress":{ "IpAddress":[] } }, "InternetMaxBandwidthOut":"1", "SecurityGroupIds":{ "SecurityGroupId":[ "sg-94kd0c***" ] }, "RegionId":"cn-shenzhen", "OperationLocks":{ "LockReason":[] }, "InstanceChargeType":"PostPaid", "ExpiredTime":"2011-09-08T16:00Z", "InstanceName":"FinanceJoshua1" }, { "ImageId":"centos6u5_64_20G_aliaegis_20150130.vhd", "InnerIpAddress":{ "IpAddress":[ "10.170.XX.XXX" ] }, "InstanceId":"id-002", "EipAddress":{}, "InternetMaxBandwidthIn":"-1", "ZoneId":"cn-shenzhen-a", "InstanceNetworkType":"classic", "PublicIpAddress":{ "IpAddress":[ "120.25.XX.XXX" ] }, "InternetChargeType":"PayByTraffic", "HostName":"iZ94t3s0j***", "InstanceType":"ecs.s2.large", "SerialNumber":"51d1353b-22bf-4567-a176-8b3e12e43135", "IoOptimized":"false", "CreationTime":"2015-07-27T07:08Z", "Status":"Running", "VpcAttributes":{ "PrivateIpAddress":{ "IpAddress":[] } }, "InternetMaxBandwidthOut":"1", "SecurityGroupIds":{ "SecurityGroupId":[ "sg-94kd0c***" ] }, "RegionId":"cn-shenzhen", "OperationLocks":{ "LockReason":[] }, "InstanceChargeType":"PostPaid", "ExpiredTime":"2011-09-08T16:00Z", "InstanceName":"FinanceJoshua2" } ] } } 场景2 FormatVersion: OOS-2019-06-01 Description: Resets system disks to its initial state by specifying instance IDs. The specified ECS instances must be in stopped status. Parameters: instanceIds: Description: The ID list of the ECS instance. Type: List maxErrors: Description: The maximum number of errors allowed during task execution. Type: Number Default: 0 concurrency: Description: Concurrency ratio of task execution. Type: Number Default: 1 OOSAssumeRole: Description: The RAM role to be assumed by OOS. Type: String Default: OOSServiceRole RamRole: '{{ OOSAssumeRole }}' Tasks: - Name: checkInstanceReady Action: ACS::CheckFor Description: Checks ECS instances is in the stopped status. Properties: Service: ECS API: DescribeInstances Parameters: InstanceIds: - '{{ ACS::TaskLoopItem }}' DesiredValues: - Stopped PropertySelector: Instances.Instance[].Status Loop: MaxErrors: '{{ maxErrors }}' Concurrency: '{{ concurrency }}' Items: '{{ instanceIds }}' - Name: querySystemDisks Action: ACS::ExecuteAPI Description: Views system disk of the ECS instance. Properties: Service: ECS API: DescribeDisks Parameters: InstanceId: '{{ ACS::TaskLoopItem }}' DiskType: system Loop: Items: '{{ instanceIds }}' Outputs: diskIds: AggregateType: Fn::ListJoin AggregateField: diskId Outputs: diskId: Type: String ValueSelector: .Disks.Disk[].DiskId 我们来看下上面的模版,请直接看Tasks部分的querySystemDisks任务,该任务是有具体Outputs的,其定义了输出名称为 diskId的参数,参数Type为 String,同时也定义了ValueSelector字段,并且该字段的jq表达式为 .Disks.Disk[].DiskId。就如Outputs中参数名diskId字面意思,其表示输出API返回结果中的磁盘ID,那么该任务调用的API是DescribeDisks,API返回的JSON结果样例如下。结合此JSON样例,我们看下在 .Disks.Disk[].DiskId作用下,diskId最终返回值的获取过程。首先筛选出JSON中Key为Disks的结果,然后对结果继续筛选,获取Key为Disk的结果,该结果是一个数组,此时又对所得结果进行迭代,并将每个迭代结果中Key为DiskId的值以String类型进行返回,于是得到最终返回值 'd-28m5zb1sz',即'{{querySystemDisks.diskId}}'的值为'd-28m5zb1sz'。 上面可能有疑问,该场景的jq表达式和场景一的类似,且处理的数据结构也一样,为何此处最后只返回了一个String,而不像场景一返回了List。简单解释下,其实返回参数的Type是不同的,当Type为List时,OOS最后会把返回的一个或多个结果装到List中作为最终结果返回;当Type为String时,OOS最后会取返回的一个或多个结果中的第一个来作为最终结果。 API调用返回样例(JSON) { "PageNumber":1, "TotalCount":9, "PageSize":2, "RequestId":"ACD9BBB0-A9D1-46D7-9630-B7A69889E110", "Disks":{ "Disk":[ { "ImageId":"", "Description":"", "Device":"", "ProductCode":"", "Portable":true, "DetachedTime":"2014-07-23T08:28:48Z", "Type":"data", "InstanceId":"", "ZoneId":"cn-qingdao-b", "EnableAutoSnapshot":false, "DiskName":"", "AttachedTime":"2014-07-23T07:47:35Z", "SourceSnapshotId":"", "CreationTime":"2014-07-23T02:44:07Z", "Status":"Available", "DeleteAutoSnapshot":true, "Category":"cloud", "RegionId":"cn-qingdao", "DeleteWithInstance":false, "OperationLocks":{ "OperationLock":[] }, "DiskId":"d-28m5zb1sz", "Size":5 }, { "ImageId":"", "Description":"", "Device":"", "ProductCode":"", "Portable":true, "DetachedTime":"", "Type":"data", "InstanceId":"", "ZoneId":"cn-qingdao-b", "EnableAutoSnapshot":false, "DiskName":"", "AttachedTime":"", "SourceSnapshotId":"", "CreationTime":"2014-07-23T02:44:06Z", "Status":"Available", "DeleteAutoSnapshot":true, "Category":"cloud", "RegionId":"cn-qingdao", "DeleteWithInstance":false, "OperationLocks":{ "OperationLock":[] }, "DiskId":"d-28zfrmo13", "Size":5 } ] } } 场景3 --- FormatVersion: OOS-2019-06-01 Description: Start ECS instance when instance is stopped. Parameters: accessToken: Description: Dingtalk access_token to be notified. Type: String AllowedPattern: '[A-Za-z0-9]*' regionId: Description: The Region Id of SLB and Instance. Type: String MinLength: 1 MaxLength: 30 OOSAssumeRole: Description: The RAM role to be assumed by OOS. Type: String Default: OOSServiceRole loadBalancerId: Description: The ID of the SLB instance. Type: String AllowedPattern: lb-[A-Za-z0-9]* MaxLength: 30 MinLength: 1 RamRole: '{{OOSAssumeRole}}' Tasks: - Name: whenInstanceStopped Action: 'ACS::EventTrigger' Properties: Product: ECS Name: - 'Instance:StateChange' Level: - INFO Content: state: - Stopped Outputs: instanceId: ValueSelector: content.resourceId Type: String - Name: checkNeedRemoveOrNot Action: ACS::CheckFor Description: check the interrupted Instance is being added on SLB or Not. OnError: ACS::END OnSuccess: ACS::NEXT Properties: Service: SLB API: DescribeLoadBalancerAttribute Parameters: RegionId: '{{ regionId }}' LoadBalancerId: '{{ loadBalancerId }}' DesiredValues: - "{{whenInstanceStopped.instanceId}}" PropertySelector: 'BackendServers.BackendServer[].ServerId|select(.=="{{whenInstanceStopped.instanceId}}")' - Name: queryLoadBalancerAttribute Action: ACS::ExecuteApi Description: Views ECS instances to backend servers. Properties: Service: SLB API: DescribeLoadBalancerAttribute Parameters: RegionId: '{{ regionId }}' LoadBalancerId: '{{ loadBalancerId }}' Outputs: removeOrNot: Type: List ValueSelector: 'BackendServers.BackendServer[]|select(.ServerId=="{{whenInstanceStopped.instanceId}}")' backendServersToRemove: Type: List ValueSelector: 'BackendServers.BackendServer[]|select(.ServerId=="{{whenInstanceStopped.instanceId}}")|del(.Type)' 我们来看下上面的模版,先看Tasks部分的whenInstanceStopped任务,它会输出一个名为 instanceId的参数,关于这个任务知道这些就够了。然后看Tasks部分的 queryLoadBalancerAttribute任务,该任务是有具体Outputs的,比如其定义了输出名称为 backendServersToRemove的参数,参数Type为 List,同时也在参数中定义了ValueSelector字段,并且该字段的jq表达式为.BackendServers.BackendServer[]|select(.ServerId=="{{whenInstanceStopped.instanceId}}")|del(.Type),表达式好长,没关系,我们分析完,您就会发现它很简单。就如Outputs中参数名backendServersToRemove字面意思,其表示输出API返回结果中的后端服务器列表,那么该任务调用的API是DescribeLoadBalancerAttribute,API返回的JSON结果样例如下。结合此JSON样例,我们看下在这个很长的jq表达式作用下,backendServersToRemove最终返回值的获取过程。首先筛选出JSON中Key为BackendServers的结果,然后对结果继续筛选,获取Key为BackendServer的结果,该结果是一个数组,此时对所得结果进行迭代,然后我们看到的管道符 |,也就是把迭代获取的所有结果交到下一段操作,操作是,将每个迭代结果中Key为ServerId的值与whenInstanceStopped任务输出参数instanceId的值进行比较。如果比较结果是相等,则拿到该ServerId所在的这个Mapping,并将该Mapping中Key为的Type的key-val对剔除,再把该Mapping返回;如果比较结果为不相等,则忽略掉这个ServerId所在的Mapping。比较完后做下整理把所有返回的Mapping放在一个List中返回。假如whenInstanceStopped.instanceId值是"i-bp1234",得到最终返回值则为 [{"ServerId":"i-bp1234","Weight":100 }],即'{{queryLoadBalancerAttribute.backendServersToRemove}}'的值为[{"ServerId":"i-bp1234","Weight":100 }]。 API调用返回样例(JSON) { "CreateTimeStamp":1541679713000, "RegionIdAlias":"cn-hangzhou", "HasReservedInfo":"false", "BackendServers":{ "BackendServer":[ { "ServerId":"i-bpxccv123456jo7v", "Weight":100, "Type":"ecs" } ] }, "ListenerPorts":{ "ListenerPort":[] }, "VSwitchId":"vsw-bp1ccv123456jk9bmlj", "InternetChargeType":"paybytraffic", "VpcId":"vpc-bp1ccv123456j1qc5cm", "SlaveZoneId":"cn-hangzhou-d", "NetworkType":"vpc", "LoadBalancerSpec":"slb.s2.small", "ListenerPortsAndProtocol":{ "ListenerPortAndProtocol":[] }, "PayType":"PayOnDemand", "Bandwidth":5120, "LoadBalancerName":"abc1", "ResourceGroupId":"rg-acfmxazb4ph6aiy", "AddressIPVersion":"ipv4", "LoadBalancerId":"lb-bp23456jfuca5", "EndTimeStamp":32493801600000, "MasterZoneId":"cn-hangzhou-b", "ListenerPortsAndProtocal":{ "ListenerPortAndProtocal":[] }, "Address":"192.168.0.6", "RegionId":"cn-hangzhou", "RequestId":"35D745B3-1567-4855-9EF1-F5CED3C1670C", "CreateTime":"2018-11-08T12:21:53Z", "EndTime":"2999-09-08T16:00:00Z", "AddressType":"intranet", "LoadBalancerStatus":"active" } PropertySelector 场景1(CheckFor) FormatVersion: OOS-2019-06-01 Description: Creates a disk and attaches a data disk to an ECS instance. Parameters: diskName: Description: The name of the disk. Type: String zoneId: Description: The zone ID that is available in the specified region. Type: String diskCategory: Description: The category of the data disk. Type: String instanceId: Description: Creates a subscription disk and the system automatically attaches it to a subscription instance with the InstanceId you specified. Type: String AllowedPattern: i-[A-Za-z0-9]* MinLength: 1 MaxLength: 30 size: Description: The size of the disk. Type: String Tasks: - Name: checkInstanceReady Action: ACS::CheckFor Description: Checks whether the ECS instance status is running or stopped. Properties: Service: ECS API: DescribeInstances Parameters: InstanceIds: - '{{ instanceId }}' DesiredValues: - Running - Stopped PropertySelector: .Instances.Instance[].Status 我们来看下上面的模版,请直接看Tasks部分的checkInstanceReady任务,该任务的动作是 ACS::CheckFor,其Properties部分定义了DesiredValues的值为 ['Running','Stopped'],同时也定义了PropertySelector字段,并且该字段的jq表达式为 .Instances.Instance[].Status。该任务中,DesiredValues和PropertySelector两个字段会被联合起来,用来验证指定的条件即['Running','Stopped'],验证过程为先把API返回的JSON结果通过jq表达式筛选处理,再检查处理得到的筛选结果是否在DesiredValues字段的List中。如果在List中,则该任务执行结果为Success,否则该任务执行结果为Failed。那么该任务调用的API是DescribeInstances,API返回的JSON结果样例如下。结合此JSON样例,我们看下在 .Instances.Instance[].Status作用下,最终返回值的获取过程。首先筛选出JSON中Key为Instances的结果,然后对结果继续筛选,获取Key为Instance的结果,该结果是一个数组,此时对所得结果进行迭代,迭代获取数组中的第一个元素,并将该元素中Key为 Status的值作为与指定的条件比较的值,即检查'Running'是否在['Running','Stopped']中。 API调用返回样例(JSON) { "PageNumber":"1", "TotalCount":"1", "PageSize":"10", "RequestId":"14A07460-EBE7-47CA-9757-12CC4761D47A", "Instances":{ "Instance":[ { "ImageId":"centos6u5_64_20G_aliaegis_20150130.vhd", "InnerIpAddress":{ "IpAddress":[ "10.170.XX.XXX" ] }, "InstanceId":"id-001", "EipAddress":{}, "InternetMaxBandwidthIn":"-1", "ZoneId":"cn-shenzhen-a", "InstanceNetworkType":"classic", "PublicIpAddress":{ "IpAddress":[ "120.25.XX.XXX" ] }, "InternetChargeType":"PayByTraffic", "HostName":"iZ94t3s0j***", "InstanceType":"ecs.s2.large", "SerialNumber":"51d1353b-22bf-4567-a176-8b3e12e43135", "IoOptimized":"false", "CreationTime":"2015-07-27T07:08Z", "Status":"Running", "VpcAttributes":{ "PrivateIpAddress":{ "IpAddress":[] } }, "InternetMaxBandwidthOut":"1", "SecurityGroupIds":{ "SecurityGroupId":[ "sg-94kd0c***" ] }, "RegionId":"cn-shenzhen", "OperationLocks":{ "LockReason":[] }, "InstanceChargeType":"PostPaid", "ExpiredTime":"2011-09-08T16:00Z", "InstanceName":"FinanceJoshua1" }, { "ImageId":"centos6u5_64_20G_aliaegis_20150130.vhd", "InnerIpAddress":{ "IpAddress":[ "10.170.XX.XXX" ] }, "InstanceId":"id-002", "EipAddress":{}, "InternetMaxBandwidthIn":"-1", "ZoneId":"cn-shenzhen-a", "InstanceNetworkType":"classic", "PublicIpAddress":{ "IpAddress":[ "120.25.XX.XXX" ] }, "InternetChargeType":"PayByTraffic", "HostName":"iZ94t3s0j***", "InstanceType":"ecs.s2.large", "SerialNumber":"51d1353b-22bf-4567-a176-8b3e12e43135", "IoOptimized":"false", "CreationTime":"2015-07-27T07:08Z", "Status":"Running", "VpcAttributes":{ "PrivateIpAddress":{ "IpAddress":[] } }, "InternetMaxBandwidthOut":"1", "SecurityGroupIds":{ "SecurityGroupId":[ "sg-94kd0c***" ] }, "RegionId":"cn-shenzhen", "OperationLocks":{ "LockReason":[] }, "InstanceChargeType":"PostPaid", "ExpiredTime":"2011-09-08T16:00Z", "InstanceName":"FinanceJoshua2" } ] } } 场景2(WaitFor) FormatVersion: OOS-2019-06-01 Description: Creates a custom image. Parameters: imageName: Description: The image name. Type: String instanceId: Description: The ID of the instance. Type: String AllowedPattern: i-[A-Za-z0-9]* MinLength: 1 MaxLength: 30 Tasks: - Name: checkInstanceReady Action: ACS::CheckFor Description: Checks whether the ECS instance status is running or stopped. Properties: Service: ECS API: DescribeInstances Parameters: InstanceIds: - '{{ instanceId }}' DesiredValues: - Running - Stopped PropertySelector: Instances.Instance[].Status - Name: createImage Action: ACS::ExecuteAPI Description: Creates a custom image. Properties: Service: ECS API: CreateImage Parameters: ImageName: '{{ imageName }}' InstanceId: '{{ instanceId }}' Outputs: imageId: Type: String ValueSelector: ImageId - Name: untilImageReady Action: ACS::WaitFor Description: Waits for the image to be available. Properties: Service: ECS API: DescribeImages Parameters: ImageId: '{{ createImage.imageId }}' DesiredValues: - Available PropertySelector: .Images.Image[].Status 我们来看下上面的模版,请直接看Tasks部分的untilImageReady任务,该任务的动作是 ACS::WaitFor,其Properties部分定义了DesiredValues的值为 ['Available'],同时也定义了PropertySelector字段,并且该字段的jq表达式为 .Images.Image[].Status。该任务中,DesiredValues和PropertySelector两个字段会被联合起来,用来验证指定的条件即['Available'],验证过程为先把API返回的JSON结果通过jq表达式筛选处理,再检查处理得到的筛选结果是否在DesiredValues字段的List中。如果在List中,则该任务不再继续等待,并结束该任务向下执行;否则该任务会隔段时间再次调用API,并检查结果是否满足条件,直至条件满足或超出最大检查次数。那么该任务调用的API是DescribeImages,API返回的JSON结果样例如下。结合此JSON样例,我们看下在 .Images.Image[].Status作用下,最终返回值的获取过程。首先筛选出JSON中Key为Images的结果,然后对结果继续筛选,获取Key为Image的结果,该结果是一个数组,此时对所得结果进行迭代,迭代获取数组中的第一个元素,并将该元素中Key为 Status的值作为与指定的条件比较的值,即检查'Available'是否在['Available']中。 API调用返回样例(JSON) { "PageNumber":1, "TotalCount":24, "PageSize":1, "RequestId":"49CBCED4-C9B9-4851-BEB5-8FB5E5169E30", "RegionId":"cn-hangzhou", "Images":{ "Image":[ { "ImageId":"suse11sp3_64_20G_aliaegis_20150428.vhd", "OSType":"linux", "Architecture":"x86_64", "OSName":"SUSE Linux Enterprise Server 11 SP3 64位", "DiskDeviceMappings":{ "DiskDeviceMapping":[ { "Device":"/dev/xvda", "Size":"20" } ] }, "ImageOwnerAlias":"system", "Progress":"100%", "Usage":"instance", "CreationTime":"2015-05-06T09:01:32Z", "Status":"Available", "ImageVersion":"1", "ImageName":"suse11sp3_64_20G_aliaegis_20150428.vhd", "IsCopied":false, "IsSubscribed":false, "Platform":"SUSE", "Size":20 } ] } } jq语法手册 基础用法 通过Key筛选 jq表达式:".foo"input: {"foo": 42, "bar": "less interesting data"} output: 42 通过Index筛选 jq表达式:".[0]"input: [{"name":"JSON", "good":true}, {"name":"XML", "good":false}] output: { "name": "JSON", "good": true } 通过Iterator筛选 jq表达式:".[]"input: ["hello","world"] output: "hello" "world" jq表达式:".[]"input: [{"name":"JSON", "good":true}, {"name":"XML", "good":false}] output: { "name": "JSON", "good": true } { "name": "XML", "good": false } 通过Pipe("|")筛选 jq表达式:".[]|.name"input: [{"name":"JSON", "good":true}, {"name":"XML", "good":false}] output: "JSON" "XML" 构造Array jq表达式:"[.user, .projects[]]"input: {"user":"stedolan", "projects": ["jq", "wikiflow"]} output: [ "stedolan", "jq", "wikiflow" ] 构造Mapping jq表达式:"{user, title: .titles}"input: {"user":"stedolan","titles":["JQ Primer", "More JQ"]} output: { "user": "stedolan", "title": [ "JQ Primer", "More JQ" ] } jq表达式:"{(.user): .titles}"input: {"user":"stedolan","titles":["JQ Primer", "More JQ"]} output: { "stedolan": [ "JQ Primer", "More JQ" ] } 内建操作符和函数 Addition(+) jq表达式:".a + 1"input: {"a": 7} output: 8 jq表达式:".a + .b"input: {"a": [1,2], "b": [3,4]} output: [ 1, 2, 3, 4 ] Subtraction(-) jq表达式:". - ["xml", "yaml"]"input: ["xml", "yaml", "json"] output: [ "json" ] Length jq表达式:"[.[]| length]"input: [[1,2], "string", {"a":2}, null] output: [ 2, 6, 1, 0 ] Keys jq表达式:"keys"input: {"abc": 1, "abcd": 2, "Foo": 3} output: [ "Foo", "abc", "abcd" ] In jq表达式:'.[] | in({"foo": 42})'input: ["foo", "bar"] output: true false map jq表达式:"map(.+1)"input: [1,2,3] output: [ 2, 3, 4 ] map_values jq表达式:"map_values(.+1)"input: {"a": 1, "b": 2, "c": 3} output: { "a": 2, "b": 3, "c": 4 } del jq表达式:"del(.foo)"input: {"foo": 42, "bar": 9001, "baz": 42} output: { "bar": 9001, "baz": 42 } select jq表达式:'.[] | select(.id == "second")'input: [{"id": "first", "val": 1}, {"id": "second", "val": 2}] output: { "id": "second", "val": 2 } jq表达式:"map(select(. >= 2))"input: [1,5,3,0,7] output: [ 5, 3, 7 ] any jq表达式:"any"input: [true, false] output: true jq表达式:"any"input: [false, false] output: false all jq表达式:"all"input: [true, false] output: false jq表达式:"all"input: [true, true] output: true jq表达式:"all"input: [] output: true jq表达式:"all"input: [] output: true min、max jq表达式:"min"input: [5,4,2,7] output: 2 sort、sort_by jq表达式:"sort"input: [8,3,null,6] output: [ null, 3, 6, 8 ] jq表达式:"sort_by(.foo)"input: [{"foo":4, "bar":10}, {"foo":3, "bar":100}, {"foo":2, "bar":1}] output: [ { "foo": 2, "bar": 1 }, { "foo": 3, "bar": 100 }, { "foo": 4, "bar": 10 } ] index jq表达式:'index(", ")'input: "a,b, cd, efg, hijk" output: 3 split jq表达式:'split(", ")'input: "a, b,c,d, e, " output: [ "a", "b,c,d", "e", "" ] join jq表达式:'join(", ")'input: ["a","b,c,d","e"] output: "a, b,c,d, e" jq表达式:'join(" ")'input: ["a",1,2.3,true,null,false] output: "a 1 2.3 true false" 条件判断 if-then-else jq表达式: 'if . == 0 then "zero"elif . == 1 then "one"else "many"end' input: 2 output: "many" >, <,>=, <=,==,!= jq表达式: '.<5' input: 2 output: true jq表达式:'.==5' input: 2 output: false 高级用法 变量 jq表达式:".bar as $x | .foo | . + $x"input: {"foo":10, "bar":200} output: 210 jq表达式:". as $i|[(.*2|. as $i| $i), $i]"input: 5 output: [ 10, 5 ] 自定义函数 jq表达式:"def addvalue(f): . + [f]; map(addvalue(.[0]))"input: [[1,2],[10,20]] output: [ [ 1, 2, 1 ], [ 10, 20, 10 ] ] jq表达式:"def addvalue(f): f as $x | map(. + $x); addvalue(.[0])"input: [[1,2],[10,20]] output: [ [ 1, 2, 1, 2 ], [ 10, 20, 1, 2 ] ]

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

运维技术之二(4)、docker安装jumpserver

CentOS 7 系统Docker CE 镜像源站 使用官方安装脚本自动安装 curl -fsSL https://get.docker.com | bash -s docker --mirror AliyunCentOS 7 (使用yum进行安装) step 1: 安装必要的一些系统工具 sudo yum install -y yum-utils device-mapper-persistent-data lvm2 Step 2: 添加软件源信息 sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo Step 3: 更新并安装 Docker-CE sudo yum makecache fastsudo yum -y install docker-ce Step 4: 开启Docker服务 sudo service docker start 安装校验 root@iZbp12adskpuoxodbkqzjfZ:$ docker versionClient: Version: 17.03.0-ce API version: 1.26 Go version: go1.7.5 Git commit: 3a232c8 Built: Tue Feb 28 07:52:04 2017 OS/Arch: linux/amd64 Server: Version: 17.03.0-ce API version: 1.26 (minimum version 1.12) Go version: go1.7.5 Git commit: 3a232c8 Built: Tue Feb 28 07:52:04 2017 OS/Arch: linux/amd64 Experimental: false 参考资料 其他关于旧版本Docker卸载以及测试开发版本Docker安装的帮助,可以参考官方文档的说明进行安装启动[root@jiaxin-ceshi-ceshi ~]# /bin/systemctl start docker.service[root@jiaxin-ceshi-ceshi ~]# docker images[root@jiaxin-ceshi-ceshi ~]# docker ps 安装/升级Docker客户端 推荐安装1.10.0以上版本的Docker客户端,参考文档 docker-ce 配置镜像加速器 针对Docker客户端版本大于 1.10.0 的用户 您可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器 sudo mkdir -p /etc/dockersudo tee /etc/docker/daemon.json <<-'EOF'{ "registry-mirrors": ["https://v2ltjwbg.mirror.aliyuncs.com"]}EOFsudo systemctl daemon-reloadsudo systemctl restart docker docker pull registry-vpc.cn-hangzhou.aliyuncs.com/wenty/jumpserver [root@jiaxin-ceshi-ceshi ~]# docker run -d -p 2222:2222 -p 8888:80 --restart=always --name jp_server registry-vpc.cn-hangzhou.aliyuncs.com/wenty/jumpserver 官方安装文档http://docs.jumpserver.org/zh/docs/dockerinstall.html

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

运维技术之二(2)、docker安装jumpserver

运行[root@jiaxin-ceshi-ceshi ~]# docker run -d -p 2222:2222 -p 8888:80 --restart=always --name jpsr jiaxiangkong/jumpserver_docker:0.3.2进入容器[root@jiaxin-ceshi-ceshi ~]# docker exec -it 88d7155de440 /bin/sh编辑配置文件/jumpserver # vi jumpserver.conf初始化数据库/jumpserver # cd install && python next.py5.5 访问 ip:8888登录安装成功,Web登录请访问http://ip:8000, 祝你使用愉快。请访问 https://github.com/jumpserver/jumpserver/wiki 查看文档

资源下载

更多资源
腾讯云软件源

腾讯云软件源

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

Spring

Spring

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

Sublime Text

Sublime Text

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

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册