目录
一、获取机器当前所有开放端口
for i in $(netstat -anopt|grep LISTEN|awk '{print $4}'); do curl -I -m 3 -o /dev/null -s -w "%{http_code} %{url_effective}\n" $i'/'; done
- -I 仅测试http头
- -m 3 每次请求查询最多3秒
- -o /dev/null 屏蔽原有输出信息
- -s silent模式 ,不输出任何东西
- -w %{http_code} 控制额外输出, 当前为状态码和url
这里可以衍生下,检测所有开放trace请求方法的http服务端口(判断条件以状态码405和403为例)
这是判断不存在的命令,当状态码为405或者403时,打印查看信息
for i in $(netstat -anopt | grep LISTEN | awk '{print $4}'); do response=$(curl -I -m 3 -o /dev/null -s -w "%{http_code}" -X TRACE $i'/'); if [[ $response == "405" || $response == "403" ]]; then echo "Resonse for $i: $response"; curl -X TRACE $i'/' -v; echo; fi; done
判断存在开放trace请求方法的web服务端口,判断条件为状态码为200,可以选择不打印信息,去掉-v 属性,回归开始的 -w "${http_code} ${url_effective}\n"
for i in $(netstat -anopt | grep LISTEN | awk '{print $4}'); do response=$(curl -I -m 3 -o /dev/null -s -w "%{http_code}" -X TRACE $i'/'); if [[ $response == "200" ]]; then echo "Resonse for $i: $response"; curl -I -X TRACE $i'/' -w "%{http_code} " ; echo; fi; done
二、docker 容器日志保存位置以及映射端口关系批量获取
1、获取所有Docker容器保存日志的位置
(1)只展示日志文件路径,不罗列和容器的对应关系
docker ps |awk 'NR>1{print $1}'|xargs -I {} docker inspect --format="{{json .LogPath}}" {} | sed 's/"//g'
(2)将容器ID和容器的日志路径对应起来,分两列展示
docker ps | awk 'NR>1{print $1}' | xargs -I {} sh -c 'echo -n "{} "; docker inspect --format="{{json .LogPath}}" {}' | sed 's/"//g'
释义:
-I {}
: 将{}
作为占位符,代表传递的参数。sh -c 'echo -n "{} "; docker inspect --format="{{json .LogPath}}" {}'
: 在子shell中执行命令,输出容器ID和使用docker inspect
命令获取的日志路径。
echo -n "{} "
: 打印容器ID,-n
参数表示不换行。docker inspect --format="{{json .LogPath}}" {}
: 使用docker inspect
命令获取容器的日志路径,使用--format
参数指定输出格式为JSON,并使用{{json .LogPath}}
获取日志路径的值。sed 's/"//g'
: 使用sed
命令去除输出结果中的双引号。
's/"//g'
: 替换命令,将双引号替换为空,g
表示全局替换。
2、获取所有docker容器映射端口的关系
命令基本同上,只是改变--format 字段
获取全部端口信息
docker ps | awk 'NR>1{print $1}'|xargs -I {} docker inspect --format="{{json .NetworkSettings.Ports}}" {} |sed 's/[{}]//g'
获取端口对应容器id信息
docker ps | awk 'NR>1{print $1}'|xargs -I {} sh -c 'echo -n "{} "; docker inspect --format="{{json .NetworkSettings.Ports}}" {}'|sed 's/[{}]//g'
三、grep实现匹配两个字符串之间的字符
这里需要引入 “ grep -P ”的使用
Interpret PATTERN as a Perl regular expression. This is highly experimental and grep -P may warn of nimplemented features.
-P, –perl-regexp
这意思是,-P 可以让grep使用perl的正则表达式语法,因为perl的正则更加多元化,能实现更加复杂的场景。
最典型的用法就是,匹配指定字符串之间的字符。比如, 我们想在一句话中" Hello, my name is aming. ” 中匹配中间的一段字符串(my name is) ,可以这么写正则表达式
echo "Hello, my name is aming." | grep -P '(?<=Hello,).*(?=amin.)'
释义:
- ?<=字符串1 : 表示只匹配字符串1后面的内容
- ?=字符串2 :表示只匹配字符串2前面的内容
上面的操作还是会显示所有内容,只是匹配内容做了高亮显示,如果只需要匹配正则的部分,可以加上 “ -o ” 选项
echo "Hello, my name is aming." | grep -Po '(?<=Hello,).*(?=aming.)'
扩展:(用sed命令实现)
echo "hello, my name is youzi" | sed -n 's/.*\(name is\).*/\1/p'
这里的正则表达式
.*\(name is\).*
匹配整个字符串,并将 "name is" 捕获到分组中。使用\1
表示引用第一个捕获分组的内容,即 "name is"。
四、xargs实现for循环(输出两列)
命令参数简单释义:
- -a file 从文件中读入作为 stdin
- -e flag ,注意有的时候可能会是-E,flag必须是一个以空格分隔的标志,当xargs分析到含有flag这个标志的时候就停止。
- -p 当每次执行一个argument的时候询问一次用户。
- -n num 后面加次数,表示命令在执行的时候一次用的argument的个数,默认是用所有的。
- -t 表示先打印命令,然后再执行。
- -i 或者是-I,这得看linux支持了,将xargs的每项名称,一般是一行一行赋值给 {},可以用 {} 代替。
- -r no-run-if-empty 当xargs的输入为空的时候则停止xargs,不用再去执行了。
- -s num 命令行的最大字符数,指的是 xargs 后面那个命令的最大命令行字符数。
- -L num 从标准输入一次读取 num 行送给 command 命令。
- -l 同 -L。
- -d delim 分隔符,默认的xargs分隔符是回车,argument的分隔符是空格,这里修改的是xargs的分隔符。
- -x exit的意思,主要是配合-s使用。。
- -P 修改最大的进程数,默认是1,为0时候为as many as it can
1、一般情况下,使用for循环只能输出一列
for i in $(cat /etc/passwd | awk -F: '{print $1,$NF}'); do echo $i; done
2、使用xargs 实现循环输出两列
最后cc可自定义
cat /etc/passwd | awk -F: '{print $1,$NF}' | xargs -n2 bash -c 'echo $1 $2' cc
或者作为变量都单独做输出(这里的效果可不是循环套循环)
cat /etc/passwd | awk -F: '{print $1,$NF}' | xargs -n2 bash -c 'for i in $1; do for j in $2; do echo $i $j; done; done' ff
注:末尾的ff为随机输入,为的是设定$0,及脚本自身,但这里并不需要,以及bash -c后面需要接‘,而不是”,因为”会把$1和$2识别成系统变量
五、sed命令实现在文件中取多个参数值
假如有如下数据,想要取domain,port,Password的值,并且只取第一个,要如何实现呢?
{"Duration":"2ffff","Data":{"domain":"xxx.xxx.com","port":18733,"userList":[{"ID":2,"Username":"aaa","Password":"abcdefg==","EncryptPass":"9a1717dafdafda6716a130f3d5f91320b91d74aefdc3aaaf","Quota":85899345920,"Download":54948906599,"Upload":1155713256,"UseDays":0,"ExpiryDate":""},{"ID":3,"Username":"fff","Password":"12345678","EncryptPass":"ad598156e5afadadf86b1c632609df6ee628611d66ee3567819c5ab91307ba","Quota":53687091200,"Download":2281521385,"Upload":73704813,"UseDays":0,"ExpiryDate":""},{"ID":4,"Username":"bbb","Password":"fffaefwe","EncryptPass":"6fb8b743165dfadfefe41d877942fd5ace1c241c70a79248e53209cd57aaf934","Quota":53687091200,"Download":4730791904,"Upload":23340061,"UseDays":0,"ExpiryDate":""}
首先将文件写入到22.txt中
cat 2.txt | grep Duration | sed -r -e 's/("|,|:)/ /g' -e 's/\s+/\n/g'| sed -rn '/domain|port|Password/{n;p}'
释义:
1、sed -r -e 's/("|,|:)/ /g' -e 's/\s+/\n/g'
:使用sed
命令进行字符串替换和处理,具体有两个部分:
-r
:启用扩展正则表达式模式匹配。
-e 's/("|,|:)/ /g'
:第一个-e
表示接下来的是一个替换操作。s/("|,|:)/ /g
表示将双引号"
、逗号,
和冒号:
替换为空格。
-e 's/\s+/\n/g'
:第二个-e
表示接下来的是另一个替换操作。s/\s+/\n/g
表示将连续的空格替换为换行符\n
。
2、sed -rn '/domain|port|Password/{n;p}'
:再次使用sed
命令进行处理,具体有两个部分:
-rn
:启用扩展正则表达式模式匹配,并禁用默认的输出。
'/domain|port|Password/{n;p}'
:使用正则表达式匹配包含 "domain"、"port" 或 "Password" 的行,并执行以下操作:
n
:读取下一行到模式空间。
p
:打印模式空间的内容。
PS:这里是贪婪匹配,导致会取所有的密码
对上述命令进行了优化,实现了输出和参数名匹配
cat 2.txt | grep Duration | sed -r -e 's/("|,|:)/ /g' -e 's/\s+/\n/g' | awk '/domain/ { domain = $0; getline; print "domain:", $0 } /port/ { port = $0; getline; print "port:", $0 } /Password/ { password = $0; getline; print "password:", $0 }'
/domain/ { domain = $0; getline; print "domain:", $0 }
:当遇到匹配domain
的行时,将该行的值存储到变量domain
中,然后使用getline
读取下一行并打印。/port/ { port = $0; getline; print "port:", $0 }
:当遇到匹配port
的行时,将该行的值存储到变量port
中,然后使用getline
读取下一行并打印。/Password/ { password = $0; getline; print "password:", $0 }
:当遇到匹配Password
的行时,将该行的值存储到变量password
中,然后使用getline
读取下一行并打印。通过以上命令,我们在匹配到关键词后,将关键词本身和下一行的值打印出来,实现了将
domain
、port
和Password
分别取第一个的需求。