Shell 三剑客之 grep
1. grep 概述
1.1 grep 是什么
在我们日常 Linux 运维过程中,最多的就是对 Linux 文件进行处理,grep(global search regular expression (RE) and print out the line)作为一款非常方便且强大的文本搜索工具,其能使用正则表达式搜索文本,并把匹配的行打印出来,其使用对象为 Linux 系统的所有用户,使得我们日常操作更加方便简单。
1.2 为什么要用 grep
在 Linux 系统中一切皆文件,我们日常的工作就是与文件打交道,能够运用 grep 这款文件搜索工具,可以大大提高我们的工作效率,我们上节课学习了正则表达式,grep 配合正则表达式能够作出 1+1 大于 2 的效果,灵活使用使得我们的工作更加高效快捷。
2. grep 详解
2.1 grep 分类
Unix 的 grep 家族包括 grep、egrep 和 fgrep。egrep 和 fgrep 的命令跟 grep 只有很小不同。
- egrep 是 grep 的扩展,其支持更多 re 元字符,和扩展正则表达式等。
- fgrep 就是 fixed grep 或 fast grep,它们把所有的字母都看作单词,也就是说,正则表达式中的元字符表示其自身的字面意义,不再特殊。
- linux 使用 GNU 版本的 grep。它功能更强,可以通过 - G、-E、-F 命令行选项来使用 egrep 和 fgrep 的功能。
2.2 grep 工作方式
grep 的工作方式为将一个或多个文件中搜索字符串模版。如果模版包括空格,则必须被引用,模板后的所有字符串被看作文件名。搜索的结果被送到屏幕,不影响原文件内容。
grep 命令结束后通过一个状态值来说明搜索状态,如果为 0 则意味着搜索成功,反之则为失败,我们可以利用其对文件自动化处理。
2.3 grep 语法
grep [OPTION]... PATTERN [FILE]
其中 OPTION
有很多方式,例如 - A3 表示显示符合范本样式的那一行之外,并显示该行之后的 3 行内容。
PATTERN
表示:匹配的模式,通常为一个表达式。
FilE
为具体的需要处理的问题,当然也可以为标准输入。
2.3 参数详解
在上一节中我们详细讲解了正则表达式,它就可以用在 grep 命令的 PATTERN
字段中,使得 grep 更加强大,本章节我们着重来讲解 grep 命令的 OPTION
。
不加参数,匹配 /etc/passwd 文件中的 root 行,例如:
[root@master grep]# grep "root" /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
- -A:显示模式匹配后的几行
查找 /etc/passwd 文件中以 root 开头的后两行,例如:
[root@master grep]# grep -A2 "^root" /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
- -B:显示模式匹配行的前几行
查找 /etc/passwd 文件中以 bin 开头的前一行,例如:
[root@master grep]# grep -B1 "^bin" /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
- -C:显示模式匹配的前后各几行
查找 /etc/passwd 文件中以 ftp 开头的前后各 2 行,例如:
[root@master grep]# grep -C2 "^ftp" /etc/passwd
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
- -i:忽略大小写匹配
匹配 /etc/passwd 包含 "Nobody" 的行,例如:
[root@master grep]# grep -i "Nobody" /etc/passwd
nobody:x:99:99:Nobody:/:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
- -o :只显示匹配到的字符串
匹配出 /etc/passwd 文件中字符串长度最少 10 位的字符 ,例如:
[root@master grep]# grep -o "[[:alnum:]]\{10,\}" /etc/passwd
Management
Kubernetes
- -n:输出匹配到的行的行号
匹配出 /etc/passwd 文件中包含 root 的字符串的行,例如:
[root@master grep]# grep -n "root" /etc/passwd
1:root:x:0:0:root:/root:/bin/bash
10:operator:x:11:0:operator:/root:/sbin/nologin
- -v:反向选择,即显示除过 匹配’搜寻字符串’ 内容的那一行
匹配出 /etc/passwd 中不包含 bash 的行,例如:
[root@master grep]# grep -v "nologin" /etc/passwd
root:x:0:0:root:/root:/bin/bash
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
- -c : 计算找到 ‘搜寻字符串’ 的次数
计算 /etc/passwd 文件中 root 字符串出现的次数,例如:
[root@master grep]# grep -c "root" /etc/passwd
2
- -E: 开启正则表达式,相当于使用命令
egrep
查找 /etc/passwd 文件中包含三位数字的行,例如:
[root@master grep]# grep -E "[[:digit:]]{3}" /etc/passwd
games:x:12:100:games:/usr/games:/sbin/nologin
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
polkitd:x:999:997:User for polkitd:/:/sbin/nologin
ceph:x:167:167:Ceph daemons:/var/lib/ceph:/sbin/nologin
kube:x:998:996:Kubernetes user:/home/kube:/sbin/nologin
etcd:x:997:993:Etcd user:/var/lib/etcd:/bin/nologin
gluster:x:996:992:GlusterFS daemons:/run/gluster:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
chrony:x:995:991::/var/lib/chrony:/sbin/nologin
redis:x:994:990:Redis Database Server:/var/lib/redis:/sbin/nologin
3. 实例
3.1 需求
编写一个脚本,获取 Linux 系统的服务信息,将结果保存到文件中。
3.2 思路
可以利用函数来编写获取 Linux 服务相关信息,最后利用重定向将信息输出到文件中。
3.3 实现
#!/bin/bash
# Description: service check
# Auth: kaliarch
# Email: kaliarch@163.com
# function: sys check
# Date: 2020-04-11 14:00
# Version: 1.0
[ $(id -u) -gt 0 ] && echo "请用root用户执行此脚本!" && exit 1
sysversion=$(rpm -q centos-release|cut -d- -f3)
line="-------------------------------------------------"
[ -d logs ] || mkdir logs
service_check_file="logs/service-`date +%Y%m%d`.txt"
# 获取服务信息
function get_service_info() {
port_listen=$(netstat -lntup|grep -v "Active Internet")
kernel_config=$(sysctl -p 2>/dev/null)
if [ ${sysversion} -gt 6 ];then
service_config=$(systemctl list-unit-files --type=service --state=enabled|grep "enabled")
run_service=$(systemctl list-units --type=service --state=running |grep ".service")
else
service_config=$(/sbin/chkconfig | grep -E ":on|:启用" |column -t)
run_service=$(/sbin/service --status-all|grep -E "running")
fi
cat <<EOF
服务启动配置:
${service_config}
${line}
运行的服务:
${run_service}
${line}
监听端口:
${port_listen}
${line}
内核参考配置:
${kernel_config}
EOF
}
function sys_check() {
get_service_info
echo ${line}
}
# 执行主函数将输出重定向到文件中
sys_check > ${sys_check_file}
# 执行测试
[root@xuel-terraform-cvm-0 ~]# bash sys_check.sh
[root@xuel-terraform-cvm-0 ~]# cat logs/10.0.1.15-20200329.txt
[root@master grep]# cat logs/service-20200411.txt
服务启动配置:
auditd.service enabled
autovt@.service enabled
ceph-mon@.service enabled
ceph-osd@.service enabled
chronyd.service enabled
crond.service enabled
dbus-org.freedesktop.NetworkManager.service enabled
dbus-org.freedesktop.nm-dispatcher.service enabled
docker.service enabled
etcd.service enabled
gapd.service enabled
getty@.service enabled
irqbalance.service enabled
kdump.service enabled
kubelet.service enabled
microcode.service enabled
NetworkManager-dispatcher.service enabled
NetworkManager.service enabled
postfix.service enabled
rpcbind.service enabled
rsyslog.service enabled
smarteye-server-agent.service enabled
sshd.service enabled
systemd-readahead-collect.service enabled
systemd-readahead-drop.service enabled
systemd-readahead-replay.service enabled
tuned.service enabled
-------------------------------------------------
运行的服务:
auditd.service loaded active running Security Auditing Service
ceph-mon@master.service loaded active running Ceph cluster monitor daemon
ceph-osd@0.service loaded active running Ceph object storage daemon
chronyd.service loaded active running NTP client/server
crond.service loaded active running Command Scheduler
dbus.service loaded active running D-Bus System Message Bus
docker.service loaded active running Docker Application Container Engine
etcd.service loaded active running etcd docker wrapper
gapd.service loaded active running guest agent for pitrix
getty@tty1.service loaded active running Getty on tty1
gssproxy.service loaded active running GSSAPI Proxy Daemon
irqbalance.service loaded active running irqbalance daemon
kubelet.service loaded active running Kubernetes Kubelet Server
NetworkManager.service loaded active running Network Manager
polkit.service loaded active running Authorization Manager
postfix.service loaded active running Postfix Mail Transport Agent
rpcbind.service loaded active running RPC bind service
rsyslog.service loaded active running System Logging Service
smarteye-server-agent.service loaded active running The Smarteye Monitoring of server
sshd.service loaded active running OpenSSH server daemon
systemd-journald.service loaded active running Journal Service
systemd-logind.service loaded active running Login Service
systemd-udevd.service loaded active running udev Kernel Device Manager
tuned.service loaded active running Dynamic System Tuning Daemon
-------------------------------------------------
监听端口:
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:9099 0.0.0.0:* LISTEN 10444/calico-node
tcp 0 0 172.16.60.2:2379 0.0.0.0:* LISTEN 1321/etcd
tcp6 0 0 :::9353 :::* LISTEN 2058/node-cache
udp 0 0 0.0.0.0:37811 0.0.0.0:* 610/dhclient
udp 0 0 169.254.25.10:53 0.0.0.0:* 2058/node-cache
udp 0 0 0.0.0.0:68 0.0.0.0:* 610/dhclient
udp 0 0 0.0.0.0:111 0.0.0.0:* 1/systemd
udp 0 0 0.0.0.0:123 0.0.0.0:* 530/chronyd
udp 0 0 127.0.0.1:323 0.0.0.0:* 530/chronyd
udp 0 0 0.0.0.0:703 0.0.0.0:* 535/rpcbind
udp6 0 0 :::35267 :::* 610/dhclient
udp6 0 0 :::111 :::* 1/systemd
udp6 0 0 ::1:323 :::* 530/chronyd
udp6 0 0 :::703 :::* 535/rpcbind
-------------------------------------------------
内核参考配置:
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_local_reserved_ports = 30000-32767
net.bridge.bridge-nf-call-arptables = 1
-------------------------------------------------
可以看到利用了一个函数来获取系统的信息,主函数将输出利用重定向方式保存到文件中。
4. 注意事项
- grep 对于文件搜索效率非常高,其不会对源文件作出修改;
- 默认 Linux 系统 grep 可以使用参数 - E,-F 来使用 egrep/fgrep;
- 对于复杂的条件可以利用 grep 配合管道多匹配来达到目的。
5. 小结
grep 命令是 Linux 系统非常强大的文本搜索工具,可以配合正则表达式及其丰富的选项来灵活处理,同时对于复杂的文件搜索,可以配合管道多次匹配来达到搜索的目的,特殊情况下可以利用选项 - E,开启正则表达式来提供强大的模式匹配处理。