Shell 小技能

这也是一种编程。

Shell 是一门短小精悍的胶水型语言,可以组合各种 Linux 实用工具进行日常临时任务处理。Shell 就像一把匕首,其强大之处,在于能够灵活组合能力。

掌握 Shell命令组合方式也是一个实用编程小技能。

Shell 组合

Shell 命令组合主要有如下方式:

  • | : 管道符号,将上一个命令的结果写入一个临时文件,然后读取每一行作为输入传递到下一个命令的参数里。
  • >, < : 重定向符号,将输出重定向到文件( 或标准输入输出)里,或者重定向指向文件输入(标准输入输出)。
  • && : 组合执行多个命令。
  • $(cmd) 将 cmd 的命令执行结果原地替换到其所在的位置。
  • 正则表达式:通常用于 grep, sed, awk 程序中,筛选、替换满足条件的文本。
  • cut:根据指定字段、指定列筛选指定的列或列集合。
  • awk:根据指定字段或指定条件筛选列或列集合;生成格式化内容。
  • grep : 根据指定正则表达式筛选满足正则表达式的行。
  • sed: 根据指定正则表达式替换文本。
  • find: 筛选满足条件的文件并输出文件路径。
  • xargs: 批量处理命令,将上一个命令的执行结果的每一行通过管道传递给 xargs 指定的命令的参数。{} 作为参数占位符。
  • sort: 根据指定列排序。

以下给出日常开发工作中的一些实际任务及例子,读者可以在自己的工作中多练习多体会,逐渐掌握。如果有不懂不会的,就问 AI 吧。

文本处理

文本处理常用工具:cat, grep, awk, sed, cut, sort, uniq

提取关键字并组成数组查询条件

排查问题或故障修复时,常常需要从日志里提取所需要的内容,并拼成数据库的 in 条件。

解读:

  • cat : 读取和显示文件内容;
  • awk: 筛选指定分隔符后面的字段内容;根据指定格式生成行内容;
  • grep: 筛选含有指定关键字或匹配正则的行;
  • sed: 文本替换。
  • | : 管道符号,将上一个命令的结果作为输入传递到下一个命令的参数里。
cat webfileexist.txt | awk -F 'existDetectionId: ' '{print $2}' | grep -v "^$" | awk '{printf "%s%s", (NR>1?",":""), "\""$0"\""} END{print "]"}'  | sed 's/^/[/'

webfileexist.txt

 webfile is exist        existDetectionId: abcdeft
 webfile is exist        existDetectionId: ggwsdf

输出

["abcdeft", "ggwsdf"]

筛选/排序匹配的列

可以打印日志耗时,然后从日志中提取耗时信息,生成数据和图表。

awk -F'=' ' $4 > 50 {print } ' rt_costs.txt > rt_50_costs.txt 

awk -F'=' '  {print $3} ' rt_costs.txt | sed 's/, cost_time//g' | sort | uniq -c | awk '{print $2" "$1}' | sort -rnk2

rt_costs.txt

2023-04-26 16:29:16.392 [INFO]: [ids_detection_kafka-worker-24] - c.q.i.d.p.MethodMeasureAspect - detectionId=3f347c3e36d04feb939ac783931d5070252, method=DetectionDoSaver_process, cost_time=94
2023-04-26 16:29:16.392 [INFO]: [ids_detection_kafka-worker-27] - c.q.i.d.p.MethodMeasureAspect - detectionId=90661520f1fa47269d6ea930041e8a23255, method=DetectionDoSaver_process, cost_time=93
2023-04-26 16:29:16.397 [INFO]: [ids_detection_kafka-worker-26] - c.q.i.d.p.MethodMeasureAspect - detectionId=62163fa11af840a584286d322575ef7e254, method=DetectionFixedFilter_process, cost_time=2

日志查看和处理

tail -100f info.log | grep "method="  
grep -E "A|B" info.log

ls info.20220616.* | xargs -I {} grep "cdcCheckCache hit is black" {} > /home/blackhit.log

ls info.20220615.* | xargs -I {} grep "send webshell cdc task to kafka, size" {} | cut -f 5 -d ":" | sed 's/^[ \t]*//g' | awk '{sum += $1};END {print sum}'

grep -r "cdcCheckCache hit is black" info.20220616.*

kubectl logs -f $(kubectl get po -A | grep ids-detect | awk '{print $2}') -n $(kubectl get po -A | grep ids-detect | awk '{print $1}') main | grep --color=auto "cost_time" | awk -F"=" ' $3 > 50 {print } '

文件处理

通常用 find 查找到满足指定条件的文件集合,然后用 xargs -I {} 命令 {} 来逐一处理。其中 {} 是将 find 命令查到的结果逐个取出的值。

找到满足指定条件的文件集合中的重复文件

find . -name "*.java" > /tmp/javafile.txt &&  sed -E  's?^\./.+/([a-zA-Z]+\.java).*$?\1?g' /tmp/javafile.txt | sort | uniq -d

复制或删除大量文件

避免 shell argument too long 报错。

find . -name "*.java" | xargs -I {} cp {} /tmp
find . -name "*.java" | xargs -I {} rm -rf {}

查找和删除文件

find ~/[0-9]* -name "*.csv" -mtime +29 -type f|while read file; do rm -f $file; done

find ~/ -size +100M -mtime +27 -type f | while read file; do rm -f $file; done

find . -size +100M | xargs -I {} ls -hl {}

查看目录占用空间情况

磁盘快满,需要看看磁盘空间占用情况,考虑可以清理哪些文件。

du -ahx | sort -rh | head -5
du -d 1 -h  | sort -rh | head -20

du -ah /var/  | sort -rh | head -10

日常任务管理

查看占用80端口的进程

有时部署应用时,会报 80 端口已占用。此时,需要找到占用 80 端口的进程并杀死进程。注意:必须加 sudo 才会展示进程PID。

sudo kill -9 $(sudo netstat -lnp | grep :80)

批量杀死指定关键字的进程

ps aux | grep "$1" | awk '{print $2}' | xargs -I {} sudo kill -9 {}

supervisorctl

启动和重启命令。

这里主要展示如何筛选指定条件的结果中的字段、生成命令内容、写入文件和执行文件的方法。

grep 根据关键字筛选行; cut 根据分隔符和指定字段位置筛选列; awk 根据结果生成命令; > 将内容写入文件; && 用于连接多个命令。


sudo supervisorctl status | grep RUNNING | cut -f 1 -d' ' | grep '\-8' | awk '{print "sudo supervisorctl stop " $0"\n" }' > /tmp/stop.sh && sh /tmp/stop.sh 

sudo supervisorctl status | grep STOPPED |cut -f 1 -d' ' | grep '\-8' | awk '{print "sudo supervisorctl start " $0"\n" }' > /tmp/restart.sh && sh /tmp/restart.sh 


批量调用 API

用文件里的数据填充 curl 里的占位符,生成命令内容。

bcurl.sh

#!/bin/bash
 
file=$1
while read line
do
    echo '\n\n'$line
    curl -H "Content-Type: x-www-form-urlencoded" -X POST -d '{"c_version":"1.0", "c_appid":"xxx", "c_action": "TiInfo", "key": "'$line'", "type":"ipIngress"}' http://127.0.0.1:9900/api/v1/
done < $file

sh bcurl.sh ips.txt

AI 来帮忙

如果你不熟悉 Shell ,也没关系,让 AI 来帮忙。 你只负责出题即可。

出题:

我有一个命令文件,每一行都是一个命令,写一个 linux 命令组合,读取文件里的每一个命令并执行。必须是能够在 shell 上单行输入的。

cmd.txt
ls -1 ~/ | wc -l
ls -1 ~/workspace | wc -l
ls -1 ~/joy | wc -l

AI 就会给出回复。然后尝试执行下即可。

你还可以添加更多要求:希望能输出每一行及对应的命令结果;并发执行这些命令等。

小结

如果把一个个 Linux 实用命令看作是一个 API, 那么组合这些实用命令完成实际任务,跟日常软件开发已经很接近了。

如果不想总是从字符开始写程序,那么学习 linux 命令,创建实用工具,倒也不失为一种乐趣。

posted @ 2024-05-26 12:04  琴水玉  阅读(15)  评论(0编辑  收藏  举报