暗无天日

=============>DarkSun的个人博客

Emacs查看日志常用命令

1 Tramp

Emacs提供了tramp可以让你直接访问远程主机上的日志文件.

使用Tramp打开远程主机文件与打开本地主机文件一样的操作,只不过选择文件时使用一种特殊的语法格式来标示文件就行了.

tramp标示文件的语法为: /[protocol]:[user@]hostname[#port]:path-to-file.

例如 /ssh:cnaps2@10.8.6.10:~/tmp/t.log 会通过ssh协议,以cnaps2用户登录10.8.6.10这台机,并访问上面的~/tmp/t.log文件.

2 read-only-mode

若怕查看日志文件时不小心对它进行了修改,那么就可以进入只读模式,方法是执行 M-x read-only-mode.

当然你也可以在一开始就以只读的方式打开日志文件,方法是通过 C-x C-r 来打开文件就好.

你也可以通过 C-x C-q 来切换是否进入只读模式.

3 keep-lines/flush-lines

有时日志中的内容太多了,为了凸出重点就需要用 keep-linesflush-lines 来删除掉不用关注的内容.

例如有这么一段日志:

[4627|09:38:32:557462||         ./src/logger.cpp|0298|  eInfo]=========================================================================
[4627|09:38:32:576258||     ./src/recvmbwork.cpp|0085|  eInfo]enter CRecvMbWork::doWork
[4627|09:38:32:576560||     ./src/recvmbwork.cpp|0088| eDebug]Init CNAPS2DB cnaps2 1a119bb03ab93a12
[4627|09:38:37:542483||       ./src/mbcharge.cpp|1002|  eInfo]enter CMbCharge::requestEsbService
[4627|09:38:37:568181||       ./src/mbcharge.cpp|1005|  eInfo]cEsbMsgIn.m_sXml = [8826][<?xml version="1.0" encoding="UTF-8"?>
<service>
  <sys-header>
    <data name="SYS_HEAD" >
      <struct>
        <data name="SERVICE_CODE" >
          <field type="string" length="11" scale="0" >03001000002</field>
        </data>
        <data name="SERVICE_SCENE" >
          <field type="string" length="2" scale="0" >01</field>
        </data>
        <data name="SERVICE_VERSION" >
          <field type="string" length="2" scale="0" >03</field>
        </data>
        <data name="CONSUMER_ID" >
          <field type="string" length="6" scale="0" >100012</field>
        </data>
        ....很长一段XML
            <data name="PAYEE_ACCT_NO" >
              <field type="string" length="1" scale="0" >1</field>
            </data>
            <data name="POSTSCRIPT" >
              <field length="-1" scale="-1" />
            </data>
            <data name="REMARK" >
              <field length="-1" scale="-1" />
            </data>
          </struct>
        </data>
      </struct>
    </data>
  </body>
</service>]
[4627|09:38:37:569725||       ./src/mbcharge.cpp|1013|  eInfo]设置MQ同步msgid= [100012201611010002071172]
[4627|09:38:37:570005||       ./src/mbcharge.cpp|0053|  eInfo]enter CMbCharge::GetMQConnection
[4627|09:38:37:570799||       ./src/mbcharge.cpp|0066|  eInfo]获取已存在的MQ连接成功
[4627|09:38:37:571091||       ./src/mbcharge.cpp|0069|  eInfo]leave CMbCharge::GetMQConnection[正确退出]
[4627|09:38:37:612243||       ./src/mbcharge.cpp|1031|  eInfo]已发送报文
[4627|09:38:38:125382||       ./src/mbcharge.cpp|1074|  eInfo]cEsbMsgOut.m_sDwRET_STATUS = [F],cEsbMsgOut.m_sDwRET_CODE = [ESR0003]
[4627|09:38:38:126245||     ./src/recvmb0531.cpp|1207| eError]CRecvMb0531::ChargeMb--toMb0551记账超时, [2][交易超时[ESR0003][与AS400系统通讯发生异常,请联系系统管理员]!]
[4627|09:38:38:126521||     ./src/recvmb0531.cpp|1219|  eInfo]m_oEsbMsg0551o.m_sDwSERV_SEQ_NO []
[4627|09:38:38:126943||     ./src/recvmb0531.cpp|1222|  eInfo]leave CRecvMb0531::ChargeMb[正确退出]
[4627|09:38:38:127216||     ./src/recvmb0531.cpp|1290|  eInfo]enter CRecvMb0531::UpdateDb
[4627|09:38:38:127532|| ./src/pubfunchandler.cpp|0518|  eInfo]enter dbexecsqlwithexception
[4627|09:38:38:207476||     ./src/recvmb0531.cpp|0083|  eInfo]leave CRecvMb0531::doWorkSelf[正确退出]
[4627|09:38:38:223483||     ./src/recvmbbase.cpp|0185|  eInfo]leave CRecvMbBase::doWork[正确退出]
[4627|09:38:38:362975||     ./src/recvmbbase.cpp|0099|  eInfo]enter CRecvMbBase::~CRecvMbBase
[4627|09:38:38:363419||     ./src/recvmbbase.cpp|0102|  eInfo]leave CRecvMbBase::~CRecvMbBase[正确退出]
[4627|09:38:38:363743||     ./src/recvmbwork.cpp|0404|  eInfo]leave CRecvMbWork::doWork[正确退出]

里面包含了大量的XML报文信息,假设我们不关系XML报文的具体内容,那么可以用 flush-lines 把这些XML删掉:

  1. 按下 C-x h 选中所有日志内容
  2. 调用 M-x flush-lines
  3. 输入正则表达式 ^[^[] 表示 将非 [ 开头的行删掉,最后结果为

    [4627|09:38:32:557462||         ./src/logger.cpp|0298|  eInfo]=========================================================================
    [4627|09:38:32:576258||     ./src/recvmbwork.cpp|0085|  eInfo]enter CRecvMbWork::doWork
    [4627|09:38:32:576560||     ./src/recvmbwork.cpp|0088| eDebug]Init CNAPS2DB cnaps2 1a119bb03ab93a12
    [4627|09:38:37:542483||       ./src/mbcharge.cpp|1002|  eInfo]enter CMbCharge::requestEsbService
    [4627|09:38:37:568181||       ./src/mbcharge.cpp|1005|  eInfo]cEsbMsgIn.m_sXml = [8826][<?xml version="1.0" encoding="UTF-8"?>
    [4627|09:38:37:569725||       ./src/mbcharge.cpp|1013|  eInfo]设置MQ同步msgid= [100012201611010002071172]
    [4627|09:38:37:570005||       ./src/mbcharge.cpp|0053|  eInfo]enter CMbCharge::GetMQConnection
    [4627|09:38:37:570799||       ./src/mbcharge.cpp|0066|  eInfo]获取已存在的MQ连接成功
    [4627|09:38:37:571091||       ./src/mbcharge.cpp|0069|  eInfo]leave CMbCharge::GetMQConnection[正确退出]
    [4627|09:38:37:612243||       ./src/mbcharge.cpp|1031|  eInfo]已发送报文
    [4627|09:38:38:125382||       ./src/mbcharge.cpp|1074|  eInfo]cEsbMsgOut.m_sDwRET_STATUS = [F],cEsbMsgOut.m_sDwRET_CODE = [ESR0003]
    [4627|09:38:38:126245||     ./src/recvmb0531.cpp|1207| eError]CRecvMb0531::ChargeMb--toMb0551记账超时, [2][交易超时[ESR0003][与AS400系统通讯发生异常,请联系系统管理员]!]
    [4627|09:38:38:126521||     ./src/recvmb0531.cpp|1219|  eInfo]m_oEsbMsg0551o.m_sDwSERV_SEQ_NO []
    [4627|09:38:38:126943||     ./src/recvmb0531.cpp|1222|  eInfo]leave CRecvMb0531::ChargeMb[正确退出]
    [4627|09:38:38:127216||     ./src/recvmb0531.cpp|1290|  eInfo]enter CRecvMb0531::UpdateDb
    [4627|09:38:38:127532|| ./src/pubfunchandler.cpp|0518|  eInfo]enter dbexecsqlwithexception
    [4627|09:38:38:207476||     ./src/recvmb0531.cpp|0083|  eInfo]leave CRecvMb0531::doWorkSelf[正确退出]
    [4627|09:38:38:223483||     ./src/recvmbbase.cpp|0185|  eInfo]leave CRecvMbBase::doWork[正确退出]
    [4627|09:38:38:362975||     ./src/recvmbbase.cpp|0099|  eInfo]enter CRecvMbBase::~CRecvMbBase
    [4627|09:38:38:363419||     ./src/recvmbbase.cpp|0102|  eInfo]leave CRecvMbBase::~CRecvMbBase[正确退出]
    [4627|09:38:38:363743||     ./src/recvmbwork.cpp|0404|  eInfo]leave CRecvMbWork::doWork[正确退出]
    

类似的,假设我只想了解一个交易的耗时,即中间大段的日志内容都不要了,只需要日志中包含 CRecvMbWork::doWork 的那两行记录,可以这么做

  1. 按下 C-x h 选中所有日志
  2. 执行 M-x keep-lines
  3. 输入正则表达式 CRecvMbWork::doWork

最后的结果为

[4627|09:38:32:576258||     ./src/recvmbwork.cpp|0085|  eInfo]enter CRecvMbWork::doWork
[4627|09:38:38:363743||     ./src/recvmbwork.cpp|0404|  eInfo]leave CRecvMbWork::doWork[正确退出]

4 Highlights

我们还可以让Emacs依据某种条件高亮显示日志中的某些内容. 常用的高亮命令有以下几个

快捷键 功能
M-s h p Highlights a phrase
M-s h r Highlights a regular expression
M-s H . Highlights symbol at the point
M-s h u Removes highlighting under the point
M-s h l Highlights lines match regexp

还是以上面日志为例,假设我想以红色高亮显示日志级别为 eError 的内容,则可以这样

  1. 调用 M-x M-s h r
  2. 输入要高亮显示内容的正则表达式 .+eError.+ 表示高亮显示包含 eError 的整个行内容
  3. 选择要以那种颜色高亮显示, 选择=hi-red-b=

由于截图他麻烦,这里就不贴出结果了,有兴趣的同学可以自己试试.

5 auto-revert

在服务不停止的情况下,会不断往日志文件中加入新的内容. 若希望Emacs自动反映出这些改动那么就可以使用 M-x auto-revert-modeM-x auto-revert-tail-mode 了.

这两个mode就能让Emacs在探测到日志文件更新后自动重新载入整个日志文件,不同点在于 auto-revert-tail-mode 类似于 tail -f,总是将改动的内容附加到buffer的末尾.

需要注意的是,由于检查远程主机文件比较慢,因此默认情况下,这两个mode对tramp文件是没有效果的. 不过你可以通过配置 auto-revert-remote-files 来改变这一行为.