場景:線上服務因為某些原因宕機了n小時,導致一大堆的數(shù)據(jù)有問題,日志中有把關鍵信息打出來,問如何修復數(shù)據(jù)?
思路:把日志中所有的關鍵信息都找出來,然后重新處理消息,比如消費者重新消費。那么問題就是:怎么把所有的消息都找出來?下面根據(jù)日志的存儲介質分兩種情況講解。
一、日志在服務器的log文件中
1. 根據(jù)關鍵字定位某條日志
16:10:16.909 [ERROR] [Thread: http-nio-9530-exec-6340] com.xxx.xxx.xxx.xx.web.controller.PayController:165
- PAY refundOrderV3 fail, dbId = 11111, refundReq={"orderid":1111,"refundid":0,"refundFee":540,"reason":
"xxxx","payway":null,"mchid":null,"appid":null,"orderidPrefix":null}, responseMap = {"refundFee":"540",
"orderid":"1111","refundorderid":"1111","transactionid":"1111"}
假如我們根據(jù)相關的id定位到了這樣一段日志,現(xiàn)在我們要找出所有報這個錯的日志,并且把 refundReq=后面那串json給截取下來,有了這串json,我們就可以重新去請求 refundOrderV3方法。
2. 找出所有報這個錯的日志
cat xxx-error.log.xxx | grep 'PayController:165 - PAY refundOrderV3 fail'
我們直接cat對應日期的日志文件,然后grep關鍵字即可,這樣就會列出所有報這個錯的日志。
3. 截取日志
但其實我們要的不是這一整段日志,而是要refundReq=之后,responseMap之前的那一串json,所以要對日志進行截取。那么可以使用 awk和sed命令。
方式一:cat xxx-error.log.xxx | grep 'PayController:165 - PAY refundOrderV3 fail' | awk -F 'refundReq=' '{print $2}' | sed 's/, responseMap.*//'
方式二:cat xxx-error.log.xxx | grep 'PayController:165 - PAY refundOrderV3 fail' | awk -F 'refundReq=' '{print $2}' | awk -F ', responseMap' '{print $1}'
這里解釋一下這條命令的意思,先grep命令拿到所有報這個錯的日志,用 awk -F '分割標志' '{print $需要分割的第幾段}'命令進行分割,這里就是根據(jù)refundReq=分割,在它之前的是1,之后的是2,我們要取之后的,因此是{print $2},拿到的結果就是:
{"orderid":1111,"refundid":0,"refundFee":540,"reason":"xxxx","payway":null,"mchid":null,"appid":null,"orderidPrefix":null},
responseMap = {"refundFee":"540","orderid":"1111","refundorderid":"1111","transactionid":"1111"}
我們還想把, responseMap之后的內容去掉,兩種思路:
- 把
, responseMap之后的內容替換成空白字符,即用sed命令實現(xiàn)。sed 's/內容/新內容/',要替換的是, responseMap之后的所有內容,那就用, responseMap.*,新內容是空白字符,所以直接空著就行,因此就是:sed 's/, responseMap.*//'。 - 針對第一次
awk拿到的內容,再awk分割一下,根據(jù), responseMap分割,這次我們要取它之前的內容,因此是awk -F ', responseMap' '{print $1}'。
這樣就可以輕松拿到所有所需要的json串了。
4. 輸出到文件
直接用 > xxx.log命令,將剛才命令的執(zhí)行結果輸出到xxx.log文件中。
cat xxx-error.log.xxx | grep 'PayController:165 - PAY refundOrderV3 fail' | awk -F 'refundReq=' '{print $2}' | sed 's/, responseMap.*//' > xxx.log
拿到這個文件,就好處理了,可以用notepad++之類的工具,根據(jù)需要進行操作,比如在每一行的前面加 curl 之類的命令,然后文件名改成 xxx.sh,回傳到服務器執(zhí)行就好了。
二、日志在clickhouse中
有人可能要問了,日志在clickhouse中,用不了 linux 的命令,咋整?別慌,問題不大。
1. 查找日志,導出到文件

比如根據(jù)關鍵字找到的日志如上圖所示,我們要截取 msg=后面的那一串,首先點擊左上角的雙箭頭,進入如下頁面:

點擊搜索,就會出現(xiàn)一個表格,然后點左上角第四個圖標,就會導出一個文件。導出之后,其實我們只要
message那一列即可,所以我們復制那一列到一個新的excel中。
這個時候,我要截取
msg=之后,,errMsg之前的內容,那么可以用excel的mid和find函數(shù)實現(xiàn),mid函數(shù)語法:=MID(①在哪列截取,②從第幾個開始,③截取的長度);find函數(shù)語法:find("查找的內容", 查找的列)。直接在第二列輸入=MID(A1, FIND("msg=", A1) + LEN("msg="), FIND(", erroMsg:", A1) - FIND("msg=", A1) - LEN("msg=")),這個意思就是對A1列的內容做截取操作,FIND("msg=", A1) + LEN("msg=")表示從msg=后面開始截取,FIND(", erroMsg:", A1) - FIND("msg=", A1) - LEN("msg=")表示截取的長度就是:從開始到, erroMsg:的長度減去從開始到msg=的長度,最后還要減去msg=本身的長度。這樣就截取到了需要的內容了,接下來的操作就和上面一樣了。