sed,awk

Linux shell编程从初学到精通

最近工作时遇到了一个问题,就是查看进行时,只查看某些进行的进程号,若直接用ps aux|grep sms 这样会得到一大堆的东东,所以同事推荐用awk,同
时也提及了sed。

这里抽时间对这两个命令做一个总结,仅为个人学习工作所用。

##sed、awk是什么?

它们是linux\unix系统中的两种功能强大的文本处理工具。
  • 有一个sed的编辑器,才有了sed(stream editor)这个名字,它是一个将一系列编辑命令作用于一个文本文件的理想工具。
  • 由于创建awk的三个作者名称 是Aho、Weinberger和Kernighan,所以得名为AWK,是一种能够对结构化数据进行操作并产生格式化报表的编程语言。

##sed的使用

###使用场合

  • 编辑相对交互式广西编辑器而言太大的文件
  • 编辑命令太复杂,在交互式文本编辑器中难以输入的情况
  • 对文件扫描一遍,但是需要执行多个编辑函数的情况

sed只对缓冲区中的原始文件的副本进行编辑,并不编辑原始的文件。so,若要保存个性后的文件,压根将输出重定向到另一个文件。如:

sed 'sed command' source-file > target-file

###调用方式
如何没有指定输入文件sed将从标准输入中接受输入

  • 在shell命令行输入命令调用sed,格式为:

    sed [option] ‘sed command’ 输入文件
    注意此处为单引号将命令引起来

  • 将sed命令插入脚本文件后,然后通过sed命令调用它,格式为:

    sed [option] -f sed脚本文件 输入文件

  • 将sed命令插入脚本文件后,最常用的方法是设置该脚本文件为可执行,然后直接执行该脚本,格式为:

    ./sed脚本文件 输入文件

但此命令脚本文件,应该以sha-bang(#!)开头,sha-bang后面是解析这个脚本的程序名。

####sed命令选项及其意义

  • -n:不打印所有行到标准输出
  • -e:将下一个字符串解析为sed编辑命令,如果只传递一个编辑命令给sed,-e选项可以省略
  • -f:表示正在调用sed脚本文件

###命令组成方式

定位文本行和编辑命令两部分组成

####定位文本

  • 使用行号,指定一行,或指定行号范围
  • 使用正则表达式

下面是sed命令定位文本的方法

  • x 为指定的行号
  • x,y 指定行号范围
  • /pattern/ 查询包含模式的行
  • /pattern/pattern/ 查询包含两个模式的行
  • /pattern/,x 从与模式匹配到x号行之间的行 反之类似
  • x,y!查询不包括x和y行号的行

####常用编辑命令

  • p 打印匹配行
  • = 打印文件行号
  • a\ 在定位行号之后追加文本信息
  • i\ 在定们行号之前插入文本信息
  • d 删除定位行
  • c\ 用新文本替换定位文本
  • s 使用替换模式替换相应模式
  • r 从另一个文件中读广西
  • w 将文本写入到一个文件
  • y 变换字符
  • q 第一个模式匹配完成后退出
  • l 显示与八进制ASCII码等价的控制字符
  • {} 在定位行执行的命令组
  • n 读取下一个输入行,用下一个命令处理新的行
  • h 将模式缓冲区的文本复制到保持缓冲区
  • H 将模式缓冲区的文本追加到保持缓冲区
  • x 互换模式缓冲区和保持缓冲区的内容
  • g 将保持缓冲区的内容复制到模式缓冲区
  • G 将保持缓冲区的内容追加到模式缓冲区

###实例
我们就用下面这个文件内容作为事例参考:

#!/usr/bin/env python
import os
import sys

if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test.settings")

    from django.core.management import execute_from_command_line

    execute_from_command_line(sys.argv)

-n 选项的使用

  • 使用-n 不输出所有的内容 1p 输出第一行
➜  linuxstudy  sed -n '1p' manage.py2
#!/usr/bin/env python
  • 打印3到6行
➜  linuxstudy  sed -n '3,6p' manage.py2
import sys

if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test.settings")
  • 模式匹配
➜  linuxstudy  sed -n '/environ/p' manage.py2
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test.settings")

- e 选项的使用

  • 打印行号:
    ➜  linuxstudy  sed -n '/env/=' manage.py2
    1
    6

添加e选项:

    ➜  linuxstudy  sed -n -e '/env/p' -e '/env/=' manage.py2 
    #!/usr/bin/env python
    1
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test.settings")
    6

    `sed不支持多个编辑命令的用法,带多个编辑命令的用法,一般格式为:`

    sed [option] -e 编辑命令 -e 编辑命令 ... -e 编辑命令 输入文件

    将下面命令操作存放到一个后缀为.sed的文件中,让其可执行
    #!/usr/bin/sed -f 
    /command/a\
    we append a new line

sed文本定位

  • 匹配元字符 $和.
    ➜  linuxstudy  sed -n '/\./p' manage.py2
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test.settings")
        from django$.core.management import execute_from_command_line
        execute_from_command_line(sys.argv)
    ➜  linuxstudy  sed -n '/\$/p' manage.py2
        from django$.core.management import execute_from_command_line
  • 元字符进行匹配
    $在正则中表示行尾,但在这里表示最后一行
    sed的基本命令,可以放在单引号外或内都行,根据自己的习惯
    ➜  linuxstudy  sed  '$p' manage.py2 得取最后一行

    ➜  linuxstudy sed  -n '/.*line/p' manage.py2 找出以line结尾的行
  • ! 符号,表示取反,但是不能用于模式匹配的取反

      ➜  linuxstudy  sed -n '2,4!p' manage.py2 不打印2到4行 
  • 使用行号与关键字匹配限定行范围

      /pattern/,x和x,/pattern/ 这两种形式其实与x,y一样的,只是将x或y代替罢了
    
      ➜  linuxstudy  sed -n '4,/mana/p' manage.py2  得到的是从第四行起到与mana匹配的行的内容
    
      if __name__ == "__main__":
          os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hwbuluo.settings")
    
          from django$.core.management import execute_from_command_line

sed文本编辑

  • 插入文本 i\

      在匹配行的前端插入
      sed '定位i\text' 文件
    
      修改上面的追加脚本:
      #!/usr/bin/sed -f 
      /command/i\
      we append a new line
  • 修改文本 modify.sed c\

      -------------------
      #!/usr/bin/sed -f
    
      /command/c\
      I modify the file.
      -------------------
    
      执行:./modify.sed
  • 删除文本 d 与追加和插入修改有所不同,这里在后面不需要添加\

      sed '1,3d' manage.py2
  • 替换文本 替换文本与修改文本类似,只是修改是对一整行的个性,替换则是对局部进行修改

      s/被替换的字符串/新字符串/[替换选项]
    
      替换选项及意义:
          g:替换文本中所有出现被替换字符串之处,若不使用此选项,则只替换每行的第一个匹配上的字符串
          p:与-n选项结合,只打印替换行
          w 文件名:表示将输出定向到一个文件
    
      ➜  linuxstudy  sed -n 's/command/============/p' manage.py2 
          from django$.core.management import execute_from_============_line
          execute_from_============_line(sys.argv)
    
      也可以 linuxstudy  sed -n 's/command/============/2p' manage.py2   来替换每行出现的第几个 

##awk的使用

###使用场合
###调用方式
###实例

awk -F ':' 'BEGIN {count=0;} {name[count] = $1;count++;};END {for (i=0;i<NR;i++) print i,name[i]}'   /etc/passwd

0 root
1 daemon
2 bin
3 sys
4 sync
5 games
6 man
7 lp
8 mail

ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is",size/1024/1024 ,"M"}'

[end]size is 0.098505 M

常用运维知识大杂烩

##日常系统操作

  • 将远程文件拷贝到本地
    scp username@ip:remote_filepath /local_dir
  • 同步目录

      rsync -avzr 172.xx.xx.11:/opt/jagent/tomcat* .
    
      sudo chown -R fsdevops.fsdevops sms-service/
  • linux 最大文件限制数 ulimit

      ulimit -n
  • 资源暂时不可用,资源已耗尽

        $ ps
            -bash: fork: retry: 资源暂时不可用
            -bash: fork: retry: 资源暂时不可用
            -bash: fork: retry: 资源暂时不可用
            -bash: fork: retry: 资源暂时不可用
    
        IT组哥们分析说是每个用户句柄数只有1024个,目前超了
    
        ulimit -a 即可查询linux相关的参数     
  • 查看进程号

    ps aux|grep sms|awk -F  ' ' '{print $2}'

    ps aux|grep sms|awk -F  ' ' '{kill $2}'
  • grep的使用
    cat rmq_bk_gc.log|grep -E -o '\w+'|sort|uniq -c|sort -k 2,1
    -E 正则
    -o 输出 -O 标示出 
    sort排序
    uniq group
  • 强制用sudo保存

      :w !sudo tee %
  • 设置服务自启动

    chkconfig

  • 查看某端口被谁占用

       netstat -apn
       netstat -apn|grep 8013
       ps -aux | grep 33514/java
  • 查看文件占用
    du -hs .

  • 监视指定网络的数据包

       监视指定主机和端口的数据包      
       tcpdump tcp port 23 and host 210.27.48.1
  • 防火墙

        hostname
        iptables -t filter -I INPUT -p tcp --dport 27107 -m state --state NEW -j ACCEPT
    
        sudo iptables -A INPUT -p tcp --dport 13710 -j ACCEPT
        sudo iptables -A OUTPUT -p tcp --sport 13710 -j ACCEPT
    
        service iptables save
        vim /etc/puppet/puppet.conf 
    
        service puppet restart
        iptables -L
        more /etc/sysconfig/iptables
        vim /etc/sysconfig/iptables
        service iptables reload
      停止防火墙

      sudo su
      service iptables stop
  • 安装telnet

        yum install -y telnet
  • 查询某类文件

        grep netty -R .
  • 查看内存

        free 
  • curl 发送请求

      目的1:通过脚本发送post请求。
      答案: curl -d "leaderboard_id=7778a8143f111272&score=19&app_key=8d49f16fe034b98b&_test_user=test01" "http://172.16.102.208:8089/wiapi/score"
    
      目的2:通过脚本发送post请求,顺便附带文本数据,比如通过"浏览"选择本地的card.txt并上传发送post请求
      答案:  curl  -F "blob=@card.txt;type=text/plain"  "http://172.16.102.208:8089/wiapi/score?leaderboard_id=7778a8143f111272&score=40&app_key=8d49f16fe034b98b&_test_user=test01"   
  • ssh免密码登陆

ssh-keygen -t rsa -P ''

将生成的文件拷到目标主机,交添加到keys文件中

cat sshnopw.pub >> /root/.ssh/authorized_keys
  • vmstat 相比top,我可以看到整个机器的CPU,内存,IO的使用情况,而不是单单看到各个进程的CPU使用率和内存使用率
    2表示每个两秒采集一次服务器状态,1表示只采集一次。
    procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
     r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
     0  0      0 779304  67972 706748    0    0   135    45  538 1117 10  3 86  2  0

     r 表示运行队列(就是说多少个进程真的分配到CPU),我测试的服务器目前CPU比较空闲,没什么程序在跑,当这个值超过了CPU数目,就会出现CPU瓶颈了。这个也和top的负载有关系,一般负载超过了3就比较高,超过了5就高,超过了10就不正常了,服务器的状态很危险。top的负载类似每秒的运行队列。如果运行队列过大,表示你的CPU很繁忙,一般会造成CPU使用率很高。

     b 表示阻塞的进程,这个不多说,进程阻塞,大家懂的。

     swpd 虚拟内存已使用的大小,如果大于0,表示你的机器物理内存不足了,如果不是程序内存泄露的原因,那么你该升级内存了或者把耗内存的任务迁移到其他机器。

     free   空闲的物理内存的大小,我的机器内存总共8G,剩余3415M。

     buff   Linux/Unix系统是用来存储,目录里面有什么内容,权限等的缓存,我本机大概占用300多M

     cache cache直接用来记忆我们打开的文件,给文件做缓冲,我本机大概占用300多M(这里是Linux/Unix的聪明之处,把空闲的物理内存的一部分拿来做文件和目录的缓存,是为了提高 程序执行的性能,当程序使用内存时,buffer/cached会很快地被使用。)

     si  每秒从磁盘读入虚拟内存的大小,如果这个值大于0,表示物理内存不够用或者内存泄露了,要查找耗内存进程解决掉。我的机器内存充裕,一切正常。

     so  每秒虚拟内存写入磁盘的大小,如果这个值大于0,同上。

     bi  块设备每秒接收的块数量,这里的块设备是指系统上所有的磁盘和其他块设备,默认块大小是1024byte,我本机上没什么IO操作,所以一直是0,但是我曾在处理拷贝大量数据(2-3T)的机器上看过可以达到140000/s,磁盘写入速度差不多140M每秒

     bo 块设备每秒发送的块数量,例如我们读取文件,bo就要大于0。bi和bo一般都要接近0,不然就是IO过于频繁,需要调整。

     in 每秒CPU的中断次数,包括时间中断

     cs 每秒上下文切换次数,例如我们调用系统函数,就要进行上下文切换,线程的切换,也要进程上下文切换,这个值要越小越好,太大了,要考虑调低线程或者进程的数目,例如在apache和nginx这种web服务器中,我们一般做性能测试时会进行几千并发甚至几万并发的测试,选择web服务器的进程可以由进程或者线程的峰值一直下调,压测,直到cs到一个比较小的值,这个进程和线程数就是比较合适的值了。系统调用也是,每次调用系统函数,我们的代码就会进入内核空间,导致上下文切换,这个是很耗资源,也要尽量避免频繁调用系统函数。上下文切换次数过多表示你的CPU大部分浪费在上下文切换,导致CPU干正经事的时间少了,CPU没有充分利用,是不可取的。

     us 用户CPU时间,我曾经在一个做加密解密很频繁的服务器上,可以看到us接近100,r运行队列达到80(机器在做压力测试,性能表现不佳)。

     sy 系统CPU时间,如果太高,表示系统调用时间长,例如是IO操作频繁。

     id  空闲 CPU时间,一般来说,id + us + sy = 100,一般我认为id是空闲CPU使用率,us是用户CPU使用率,sy是系统CPU使用率。

     wt 等待IO CPU时间。
  • jstat java虚拟机 垃圾回收状态查看
    命令格式
    jstat命令命令格式:
    jstat [Options] vmid [interval] [count]
    参数说明:
    Options,选项,我们一般使用 -gcutil 查看gc情况
    vmid,VM的进程号,即当前运行的java进程号
    interval,间隔时间,单位为秒或者毫秒
    count,打印次数,如果缺省则打印无数次
    示例说明
    示例
    通常运行命令如下:
    jstat -gc 12538 5000
    即会每5秒一次显示进程号为12538的java进成的GC情况,
    显示内容如下图:

    jstat -gc 19014 1000
     S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT   
    10752.0 10752.0  0.0   5293.9 65536.0  65224.5   175104.0     16.0    13056.0 12799.5 1536.0 1495.2      1    0.009   0      0.000    0.009
    10752.0 10752.0  0.0   5293.9 65536.0  65224.5   175104.0     16.0    13056.0 12799.5 1536.0 1495.2      1    0.009   0      0.000    0.009

    结果说明
    显示内容说明如下(部分结果是通过其他其他参数显示的,暂不说明):
             S0C:年轻代中第一个survivor(幸存区)的容量 (字节) 
             S1C:年轻代中第二个survivor(幸存区)的容量 (字节) 
             S0U:年轻代中第一个survivor(幸存区)目前已使用空间 (字节) 
             S1U:年轻代中第二个survivor(幸存区)目前已使用空间 (字节) 
             EC:年轻代中Eden(伊甸园)的容量 (字节) 
             EU:年轻代中Eden(伊甸园)目前已使用空间 (字节) 
             OC:Old代的容量 (字节) 
             OU:Old代目前已使用空间 (字节) 
             PC:Perm(持久代)的容量 (字节) 
             PU:Perm(持久代)目前已使用空间 (字节) 
             YGC:从应用程序启动到采样时年轻代中gc次数 
             YGCT:从应用程序启动到采样时年轻代中gc所用时间(s) 
             FGC:从应用程序启动到采样时old代(全gc)gc次数 
             FGCT:从应用程序启动到采样时old代(全gc)gc所用时间(s) 
             GCT:从应用程序启动到采样时gc用的总时间(s) 
             NGCMN:年轻代(young)中初始化(最小)的大小 (字节) 
             NGCMX:年轻代(young)的最大容量 (字节) 
             NGC:年轻代(young)中当前的容量 (字节) 
             OGCMN:old代中初始化(最小)的大小 (字节) 
             OGCMX:old代的最大容量 (字节) 
             OGC:old代当前新生成的容量 (字节) 
             PGCMN:perm代中初始化(最小)的大小 (字节) 
             PGCMX:perm代的最大容量 (字节)   
             PGC:perm代当前新生成的容量 (字节) 
             S0:年轻代中第一个survivor(幸存区)已使用的占当前容量百分比 
             S1:年轻代中第二个survivor(幸存区)已使用的占当前容量百分比 
             E:年轻代中Eden(伊甸园)已使用的占当前容量百分比 
             O:old代已使用的占当前容量百分比 
             P:perm代已使用的占当前容量百分比 
             S0CMX:年轻代中第一个survivor(幸存区)的最大容量 (字节) 
             S1CMX :年轻代中第二个survivor(幸存区)的最大容量 (字节) 
             ECMX:年轻代中Eden(伊甸园)的最大容量 (字节) 
             DSS:当前需要survivor(幸存区)的容量 (字节)(Eden区已满) 
             TT: 持有次数限制 
             MTT : 最大持有次数限制 
  • jstack pid java查看java程序的状态

  • grep 正则输出

    grep -o -E "[0-9]{11}" xx.log

    cat error.log |grep 'Failed to invoke the method'|grep '2015-12-08 20'|awk -F'Failed to invoke the method' '{print $2}'|awk '{print $1}'  |sort|uniq -c
  • 删除某些文件

      find ./ -name 'xx.log' |xargs rm -rf
  • 删除某个文件外的其它文件

      ls | grep -v keep | xargs rm #删除keep文件之外的所有文件
      说明: ls先得到当前的所有文件和文件夹的名字, grep -v keep,进行grep正则匹配查找keep,-v参数决定了结果为匹配之外的结果,也就是的到了keep之外的所有文件名,然后 xargs用于从 标准输入获得参数 并且传递给后面的命令,这里使用的命令是 rm,然后由rm删除前面选择的文件
  • 查看磁盘信息

    查看当前文件夹下所有文件大小(包括子文件夹)
       ➜  ~  du -sh
        47G    .
    查看指定文件夹大小
       # du -hs ftp
       6.3G    ftp

    查看磁盘空间大小命令
    df -h Df命令是linux系统以磁盘分区为单位查看文件系统,可以加上参数查看磁盘剩余空间信息,命令格式: df -hl 显示格式为: 文件系统 容量 已用 可用 已用% 挂载点 Filesystem Size Used Avail Use% Mounted on /dev/hda2 45G 19G 24G 44% / /dev/hda1 494

    df   -h

    Df命令是linux系统以磁盘分区为单位查看文件系统,可以加上参数查看磁盘剩余空间信息,命令格式:

    df -hl

    显示格式为: 

    文件系统              容量 已用 可用 已用% 挂载点 

    Filesystem            Size Used Avail Use% Mounted on

    /dev/hda2              45G   19G   24G 44% /
  • gz解压

      gzip -x ...     
  • proc 启动应用程序时,找不到log去哪了

      ls -l /proc/63220/fd|grep log
  • 查看内存信息

#linux 下安装软件

  • yum
    指定源进行安装
    yum install 软件名 --enablerepo=安装包地址
  • 重新安装JDK
    删除JDK:
        rpm -qa | grep jdk|xargs sudo rpm -e --nodeps
    download jdk
     wget -c -P ./ http://download.oracle.com/otn-pub/java/jdk/8u65-b17/jdk-8u65-linux-x64.rpm?AuthParam=1448637274_af870ccf6c2c78750a5977e6da301744

     安装

     以JDK1.8为例

     拷贝到/usr/share下,mv jdk-8u65-linux-x64.rpm /usr/share

     用rpm -ivh命令安装



     配置环境变量

     在/etc/profile下增加

     # set Java environment
     JAVA_HOME=/usr/share/jdk-8u65-linux-x64
     PATH=$JAVA_HOME/bin:$PATH
     CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
     export JAVA_HOME
     export PATH
     export CLASSPATH



     测试

     [root@localhost ~]# echo $JAVA_HOME
     /usr/share/jdk1.6.0_43
     [root@localhost ~]# echo $PATH
     /usr/share/jdk1.6.0_43/bin:/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
     [root@localhost ~]# echo $CLASSPATH
     .:/usr/share/jdk1.6.0_43/lib/dt.jar:/usr/share/jdk1.6.0_43/lib/tools.jar

     [root@localhost ~]# java -version
     java version "1.6.0_43"
     Java(TM) SE Runtime Environment (build 1.6.0_43-b01)
     Java HotSpot(TM) 64-Bit Server VM (build 20.14-b01, mixed mode)

    Managing Java

    sudo update-alternatives --config java
    有 2 个候选项可用于替换 java (提供 /usr/bin/java)。

数据库操作

  • mysql授权

      ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY 'root' WITH GRANT OPTION;

安装apt-get

http://everyday-tech.com/apt-get-on-centos/

lsof

lsof语法格式是:
lsof [options] filename
复制代码

lsof abc.txt 显示开启文件abc.txt的进程
lsof -c abc 显示abc进程现在打开的文件
lsof -c -p 1234 列出进程号为1234的进程所打开的文件
lsof -g gid 显示归属gid的进程情况
lsof +d /usr/local/ 显示目录下被进程开启的文件
lsof +D /usr/local/ 同上,但是会搜索目录下的目录,时间较长
lsof -d 4 显示使用fd为4的进程
lsof -i 用以显示符合条件的进程情况
lsof -i[46] [protocol][@hostname|hostaddr][:service|port]
46 –> IPv4 or IPv6
protocol –> TCP or UDP
hostname –> Internet host name
hostaddr –> IPv4地址
service –> /etc/service中的 service name (可以不止一个)
port –> 端口号 (可以不止一个)

traceroute IP

监控某台机器到某IP的链路的连通性

    nohup ping -W 1 172.31.xx.xx &>/tmp/ping.log &
    crontab -e
    * * * * *       echo "`date +%d-%H:%M`" >> /tmp/ping.log