shell脚本攻略

年后在微信读书上面看到两本关于linux shell的书,分别是《linux shell脚本攻略》 和 《linux 性能优化》。涨了写奇怪的姿势,Mark在这里。


  1. tee 命令
    比如某条命令 既希望它可以输出到终端上,有希望可以输出到某个文件上记录结果。那么tee命令就非常方便了。
pidstat -p 2159985  1 10 | tee result.log
09:10:11 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
09:10:12 PM  1000   2159985    0.00    0.00    0.00    0.00    0.00     1  cpptools-srv
09:10:13 PM  1000   2159985    0.00    0.00    0.00    0.00    0.00     1  cpptools-srv
09:10:14 PM  1000   2159985    0.00    0.00    0.00    0.00    0.00     1  cpptools-srv
09:10:15 PM  1000   2159985    0.00    0.00    0.00    0.00    0.00     1  cpptools-srv
09:10:16 PM  1000   2159985    0.00    0.00    0.00    0.00    0.00     1  cpptools-srv
09:10:17 PM  1000   2159985    0.00    0.00    0.00    0.00    0.00     1  cpptools-srv
09:10:18 PM  1000   2159985    0.00    0.00    0.00    0.00    0.00     1  cpptools-srv

  1. 定义变量

在调试一些复杂的脚本的时候,在中间执行到某一句报错了。可以另开一个终端,对这一句中的shell变量快速定义一下,单独执行这一句,迅速定位到问题。比如:

  • 在终端上定义变量
SVN="svn"
OPTION="--version"

${SVN} ${OPTION} 
svn, version 1.6
compiled Nov 17 2021, 18:34:55 on x86_64-unknown-linux-gnu
  • export导入环境变量
echo $PATH
/usr/lib64/ccache:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin

# 临时导入一个新的path
export PATH=$PATH:~/dev_test

  1. 输出重定向

重定向是常见的shell操作了

  • 对于脚本的执行,可以把输出重定向到文件。
# 分别将标准输出重定向到某文件,将标准错误重定向到某文件
./exec.sh 1>std.out 2>std.err

# 把标准输出和标准错误都重定向到某文件
./exec.sh &>out.log

# 把标准错误也重定向到标准输出
./exec.sh 1>std.out 2>&1  

很多shell的教程或书里面,并没有介绍&的作用。其实,
在这里2>&1&的作用类似于转移符号,如果写为2>1那就是标准错误写入到名称是1文件中。


  1. 脚本调试命令 -x
    脚本开启debug模式,简直太方便了。在脚本执行的时候,会打印每一行脚本对应的命令,以及这行命令对应的结果。结果一目了然。(需要注意的是 调试信息的输出是被写入到stderr中的,如果重定向了,要注意一下看日志的位置。)

    1. 以调试模式执行脚本
    $ cat test.sh 
    #/bin/bash
    echo `date`
    
    $ bash -x test.sh 
    ++ date
    + echo Sun Mar 6 16:07:33 CST 2022
    Sun Mar 6 16:07:33 CST 2022
    
    1. 在脚本中开启调试
    #!/bin/bash -x 
    # todo
    
    1. 在脚本中的某一段中开启调试模式
    #/bin/bash 
    
    set -x   # 开启debug
    ...
    
    set +x  # 关闭debug
    

  1. 查找 find,grep ,sort ,xargs ,alias
  • 查看某个目录下,包含Item的文件
find . -name  "*Item*"         
find . -iname "*Item*"    -iname 表示忽略大小写
  • 查找某个目录下,包含malloc关键字的.c文件
find . -name "*.c" | xargs grep "malloc" --color
  • grep 递归查找 + color
grep -rn "ERROR" --color
  • grep 忽略大小写
grep -rn -i "error"  *.log
  • grep -v 排除某个类的关键字
grep "ERROR" *.log  | grep -v "Init"   # 查到error 并且排除init关键字
  • grep --exclude=
$ ll
total 8.0K
-rw-r--r-- 1  140 Mar  6 16:38 func.cpp
-rw-r--r-- 1  147 Nov 10 15:10 main.cpp

# 排除某个文件
$ grep "include" *.cpp --exclude="func.c*"
main.cpp:#include <iostream>

# 排除某个目录
$ grep -rn "include" . --exclude="func.c*" --exclude-dir test
./main.cpp:1:#include <iostream>
  • grep --include
grep -rn helloworld --include='*.xml' --include='*.h' .
  • grep -C

显示匹配记录的上下文

grep "hello" -C3
  • grep 区间
# 查询cpu 80~89之间的日志
grep "cpu : 8[0-9]%" *.log

  1. 文本处理 awk 和 sort
  • awk

awk基本格式:

awk 'BEGIN{STATEMENT}  {STATEMENT}  END{STATEMENT}'  filename

awk的几个特殊变量:

$0  表示这行全部内容
$1  表示被分隔符分割的第一个内容
$2  表示被分隔符分割的第二个内容
  • 查找日志中cpu利用率超过90%的时间段
awk -F'%' '{print $1}'| awk '{if ($NF > 90) print $0}'
  • 统计日志中出现FATAL的次数
grep FALAL log* | awk '{print $13}' | awk '{sum[$1]+=1} END{for (k in sum) print k ": " sum[k]}'
  • 统计日志中word出现的次数
cat /etc/fstab | awk '{for(i=1;i<NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}'
  • awk使用substr打印前n个字符
cat /etc/passwd | awk -F : '{print substr($1,0,3)}'
  • 统计msg id出现的次数
cat file 
msg id : 100
msg id : 200
msg id : 300
msg id : 200
msg id : 300
msg id : 300

方法1:
cat file | awk '{print $4}' | sort | uniq -c
      1 100
      2 200
      3 300

方法2:
cat file | awk '{a[$4]++} END{for( i in a) print i" "a[i]}'
100 1
200 2
300 3

  • sort 命令
    常用的几个参数:
    -n 表示按照数值排序
    -r 表示逆序排序
    -k 表示第x列
$ cat test_sort.txt 
1 twitter  300
2 apple    20
3 google   40
4 faceback 1000

# 根据第一列按照数值的大小 逆序排序
$ sort -nrk 1 test_sort.txt 
4 faceback 1000
3 google   40
2 apple    20
1 twitter  300

# 根据第三列按照数值的大小 逆序排序
$ sort -nrk 3 test_sort.txt 
4 faceback 1000
1 twitter  300
3 google   40
2 apple    20

  1. 比较方便的命令
  • ssh-copy-id命令
    自动将私钥拷贝到远程服务器上

    ssh-copy-id USER@IP
    
  • mktemp 命令
    可以为临时文件或目录创建唯一的名字

  • sshpass 命令
    在某台机器上面远程执行一条命令:

sshpass -p ${passwd}  ssh -p xxx -o StrictHostKeyChecking=no  dev@10.xxx.xx.1  'df -h'

Filesystem            Size  Used Avail Use% Mounted on
/dev/vda              99G   11G   84G  11% /

top重定向到文件

top -b > profile.log    # 记录某个时间的cpu和内存状态 

  1. 查看磁盘io,查看网络io
  • 如何定位到磁盘io高的进程

比如有个进程在io,怎么找到它?

[ ~]$ pidstat 1
Linux  (VM)     03/07/2022  _x86_64_    (16 CPU)
09:20:16 PM       PID    %usr %system  %guest    %CPU   CPU  Command
09:20:17 PM       412    0.99    3.96    0.00    4.95     1  svn

或者iotop

Total DISK READ: 10.69 M/s | Total DISK WRITE: 2.20 M/s
TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND                                                                                                                      
412  be/4    xxxx   10.61 M/s   10.77 M/s  0.00 % 89.59 % svn up .

  • 如果定位到网络io高的进程

iftop 命令

iftop -P
找到某个tcp连接的流量异常 
netstat -tunp | grep 端口
  • 内存
# 查看内存
free -g
# 按照内存排序
top 后输入M

查看oom

cat /var/log/message | grep Kill
  • cpu
    cpu占用率查看:
top

查看某一个进程:

pidstat 1 10 -p xxx

查看线程

top -H -p pid

  1. shell 多进程并行
    https://blog.51cto.com/yttitan/2409618

  1. alias
    利用alias组合一些常用命令,提高开发效率。
    alias + grep 大集合:
    # grep alias 
    alias ga='grep_all() { grep -n --color -ir $* ./; }; grep_all'
    
    // 查找xml
    alias gxml='grep_xml() { find . -iname "*.xml*" | xargs grep -n -ir $* --color}; grep_xml'
    
    // 查找c文件
    alias gc='grep_c() {find . -name "*.c" | xargs grep -n -ir $* --color}; grep_c'
    
    // 查找cpp文件和hpp文件
    alias gcpp='grep_cpp() {find . -name "*.cpp" | xargs grep -n -ir $* --color}; grep_cpp'
    alias ghpp='grep_hpp() {find . -name "*.h" | xargs grep -n -ir $* --color}; grep_hpp'
    alias gpp='grep_pp() {find . -name "*.[hc]p*" | xargs grep -n -ir $* --color}; grep_xml'
    
    // 到某个log目录下面 查某个关键字
    alias gtask='gtask() {find ~/workspace/task/log -iname "*.log" | xargs -t grep -n -ir $* --color}; gtask'
    

参考:
https://www.jianshu.com/p/14005462a9fc
网络io: https://blog.csdn.net/monkeynote/article/details/45867803
磁盘io: https://www.cnblogs.com/zhanglianghhh/p/12262009.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容