精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

最新 Linux awk 命令實(shí)戰(zhàn)教程:從日志分析到性能監(jiān)控

開發(fā) Linux
今天要介紹的是文本處理的"瑞士軍刀" —— awk。無論是分析日志、處理數(shù)據(jù),還是提取信息,它都能幫你輕松搞定。

大家好,我是小康。上次我們一起學(xué)習(xí)了 Linux 的 sed 命令,今天要介紹的是文本處理的"瑞士軍刀" —— awk。無論是分析日志、處理數(shù)據(jù),還是提取信息,它都能幫你輕松搞定。

第一部分: 初識(shí) awk

作為一名開發(fā)老兵,我整理了這些年和 awk 打交道的心得。希望能幫你少走彎路,快速掌握這個(gè)強(qiáng)大的工具。

記得剛?cè)胄心菚?huì)兒,面對(duì)成堆的日志文件,我跟大多數(shù)新手一樣一籌莫展。直到遇到了 awk 這個(gè)老伙計(jì),才算找到了"趁手的兵器"。

今天,就讓我用一個(gè)開發(fā)工程師的視角,帶你認(rèn)識(shí)這個(gè)陪伴了我 6 年多的老朋友。

1. 第一次相遇:awk 是個(gè)什么樣的角色?

就像一個(gè)心靈手巧的老師傅,awk 最擅長的就是把大段大段的文本"解剖"開來,精準(zhǔn)地找出你想要的信息。它的名字來自三位創(chuàng)始人(Aho、Weinberger、Kernighan)的首字母,雖然不好念,但本事真不小。

2. 從一個(gè)真實(shí)案例開始

還記得我遇到的第一個(gè)挑戰(zhàn):leader 讓我從一個(gè)幾GB的服務(wù)日志里找出造成系統(tǒng)故障的元兇。

當(dāng)時(shí)的日志大概長這樣:

2024-02-13 10:00:01 [192.168.1.100] "GET /api/users" 200 89ms
2024-02-13 10:00:02 [192.168.1.101] "POST /api/orders" 500 1230ms
2024-02-13 10:00:03 [192.168.1.102] "GET /api/products" 200 45ms

我需要:

  • 找出所有響應(yīng)時(shí)間超過1秒的請(qǐng)求
  • 分析高峰期的訪問量
  • ......

用 awk 的解決方案出奇簡單:

# 1、找出所有響應(yīng)時(shí)間超過1秒的請(qǐng)求
awk '
{
    # 提取并轉(zhuǎn)換響應(yīng)時(shí)間
    time = $7  # 取最后一個(gè)字段
    gsub(/ms/, "", time)  # 去掉ms
    time = time + 0  # 確保轉(zhuǎn)成數(shù)字
    
    # 只打印超過1秒(1000ms)的請(qǐng)求
    if(time >= 1000) {
        printf "時(shí)間: %s %s\nIP: %s\n請(qǐng)求: %s %s\n響應(yīng)時(shí)間: %dms\n----------\n", 
            $1, $2, substr($3, 2, length($3)-2), $4, $5, time
    }
}' access.log

# 輸出:
時(shí)間: 2024-02-13 10:00:02
IP: 192.168.1.101
請(qǐng)求: "POST /api/orders"
響應(yīng)時(shí)間: 1230ms
----------

# 2、分析高峰期的訪問量
awk '
BEGIN {
    print "每分鐘訪問量統(tǒng)計(jì):"
    print "-------------------"
}
{
    # 提取時(shí)分
    split($2, t, ":")
    minute = t[1] ":" t[2]     # 只取小時(shí)和分鐘
    count[minute]++
}
END {
    # 按時(shí)間排序輸出
    n = asorti(count, sorted)
    for(i=1; i<=n; i++) {
        printf "%s:00 - %d次訪問\n", sorted[i], count[sorted[i]]
    }
}' access.log

# 輸出:
每分鐘訪問量統(tǒng)計(jì):
-------------------
10:00:00 - 3次訪問
10:01:00 - 2次訪問
10:02:00 - 1次訪問

第二部分 : awk 基本功

老規(guī)矩,我們先來看看最常用的 awk 基礎(chǔ)命令。這些都是我這些年解決問題的"殺手锏",保證你學(xué)了就能用。

1. awk的基本結(jié)構(gòu)

在開始學(xué)習(xí)具體命令前,我們先來了解awk程序的基本結(jié)構(gòu):

awk 'BEGIN {動(dòng)作前}
    pattern {動(dòng)作}
    END {動(dòng)作后}' 文件名

就像一個(gè)完整的故事有開頭、主體和結(jié)尾,awk 也有三個(gè)主要部分:

(1) BEGIN塊:開場白

  • 在讀取文件前執(zhí)行
  • 常用來打印表頭、初始化變量
# 例如:輸出前先打印個(gè)表頭
BEGIN {print "=== 進(jìn)程列表 ==="}

(2) pattern {action}:主體部分

  • pattern:匹配條件,決定要處理哪些行
  • action:具體操作,決定要做什么
# 例如:找出root的進(jìn)程
$1=="root" {print $0}

(3) END塊:收尾工作

  • 在處理完所有行后執(zhí)行
  • 常用來輸出統(tǒng)計(jì)結(jié)果
# 例如:最后輸出總行數(shù)
END {print "共有"NR"個(gè)進(jìn)程"}

此外,awk 還提供了一些常用的內(nèi)置變量:

  • $0:整行內(nèi)容
  • 2..:第1、2列
  • NR:當(dāng)前行號(hào)
  • NF:當(dāng)前行的列數(shù)

2. 實(shí)例講解

理解了基本結(jié)構(gòu),我們來看些實(shí)際例子。假設(shè)我們有一個(gè)進(jìn)程列表 process.txt:

root     1234  5.0  2.5 mysql    running
admin    2345  3.2  1.5 nginx    running
root     3456  8.5  4.0 java     stopped
nobody   4567  2.1  1.0 nginx    running

(1) 提取特定列

# 看看誰在運(yùn)行這些進(jìn)程
awk '{print $1}' process.txt

# 輸出:
root
admin
root
nobody

# 查看進(jìn)程名和狀態(tài)
awk '{print $5, $6}' process.txt

# 輸出:
mysql running
nginx running
java stopped
nginx running

(2) 條件過濾(最常用)

# 找出 CPU 使用率超過5%的進(jìn)程
awk '$3 > 5 {print $5 "進(jìn)程CPU使用率:", $3"%"}' process.txt

# 輸出:
java進(jìn)程CPU使用率: 8.5%

# 找出狀態(tài)為 running 的進(jìn)程
awk '$6=="running" {print $1,$5}' process.txt

# 輸出:
root mysql
admin nginx
nobody nginx

2. 實(shí)用統(tǒng)計(jì)功能

(1) 常用統(tǒng)計(jì)

# 統(tǒng)計(jì)進(jìn)程數(shù)量, NR: NR 是 awk 的一個(gè)內(nèi)置變量,表示當(dāng)前已經(jīng)處理的記錄(行)數(shù)量。
awk 'END {print "總進(jìn)程數(shù):", NR}' process.txt

# 輸出:
總進(jìn)程數(shù): 4

# 我們也可以在處理過程中看到NR的變化
awk '{print "當(dāng)前處理第" NR "行"}' process.txt

# 輸出:
當(dāng)前處理第1行
當(dāng)前處理第2行
當(dāng)前處理第3行
當(dāng)前處理第4行

# 計(jì)算所有進(jìn)程的平均CPU使用率
awk '{sum += $3} END {print "平均CPU使用率:", sum/NR"%"}' process.txt

# 輸出:
平均CPU使用率: 4.7%

(2) 分組統(tǒng)計(jì)(特別常用)

# 看看每個(gè)用戶開了多少個(gè)進(jìn)程
awk '{count[$1]++} END {
    for(user in count) {
        print user "的進(jìn)程數(shù):", count[user]
    }
}' process.txt

# 輸出:
root的進(jìn)程數(shù): 2
admin的進(jìn)程數(shù): 1
nobody的進(jìn)程數(shù): 1

# 統(tǒng)計(jì)每種狀態(tài)的進(jìn)程數(shù)
awk '{states[$6]++} END {
    for(state in states) {
        print state, states[state]
    }
}' process.txt

# 輸出:
running 3
stopped 1

3. 實(shí)戰(zhàn)常用技巧

(1) 匹配特定內(nèi)容

# 找出 java 相關(guān)的進(jìn)程
awk '/java/ {print $0}' process.txt # $0 代表當(dāng)前行的整行內(nèi)容

# 輸出:
root     3456  8.5  4.0 java     stopped

# 找出包含特定字符的行并突出顯示重要信息
awk '/nginx/ {print "進(jìn)程ID:"$2, "內(nèi)存:"$4"%"}' process.txt

# 輸出:
進(jìn)程ID:2345 內(nèi)存:1.5%
進(jìn)程ID:4567 內(nèi)存:1.0%

(2) 多條件組合(經(jīng)常用到)

# 找出 CPU 高、狀態(tài)為 running 的進(jìn)程
awk '$3 > 3 && $6=="running" {
    print "警告 -", $5, "進(jìn)程CPU使用率:", $3"%"
}' process.txt

# 輸出:
警告 - mysql 進(jìn)程CPU使用率: 5.0%
警告 - nginx 進(jìn)程CPU使用率: 3.2%

4. 小貼士

(1) 實(shí)用的判斷方法:

# 找出異常的進(jìn)程(CPU或內(nèi)存使用過高)
awk '$3 > 5 || $4 > 3 {
    print $5 "進(jìn)程異常:"
    print "  CPU:", $3"%"
    print "  內(nèi)存:", $4"%"
}' process.txt

# 輸出:
java進(jìn)程異常:
  CPU: 8.5%
  內(nèi)存: 4.0%

(2) 累加統(tǒng)計(jì):

bash
# 計(jì)算 nginx 進(jìn)程的總內(nèi)存占用
awk '/nginx/ {total += $4} 
     END {print "nginx總內(nèi)存占用:", total"%"}' process.txt

# 輸出:
nginx總內(nèi)存占用: 2.5%

記住:

  • $1,$2,$3... 代表第幾列
  • NR 代表當(dāng)前行號(hào)
  • print 和 printf 都是打印命令
  • 用 $0 可以打印整行

這些都是我平時(shí)工作中最常用的簡單命令,基本夠用了。等你熟悉了這些,我們?cè)賹W(xué)更高級(jí)的用法。

第三部分: awk高級(jí)應(yīng)用指南(性能分析)

接下來我們來點(diǎn)高級(jí)的,帶大家用 awk 處理日常工作中最常見的幾個(gè)場景。每一步我們都從簡單的開始,循序漸進(jìn)地掌握。

1. 基礎(chǔ)日志處理

先從一個(gè)簡單的接口日志開始:

2024-02-14 10:00:01 [api=/user/login] cost=100ms status=200
2024-02-14 10:00:02 [api=/user/info] cost=50ms status=200
2024-02-14 10:00:03 [api=/user/login] cost=800ms status=500
2024-02-14 10:00:04 [api=/order/create] cost=150ms status=200

(1) 提取重要信息(簡單)

# 只看接口名和響應(yīng)時(shí)間
awk '{print $3, $4}' api.log

# 輸出:
[api=/user/login] cost=100ms
[api=/user/info] cost=50ms
[api=/user/login] cost=800ms
[api=/order/create] cost=150ms

(2) 查找異常請(qǐng)求(常用)

# 找出響應(yīng)時(shí)間超過500ms的慢請(qǐng)求
awk '
    {
        # 提取響應(yīng)時(shí)間的數(shù)字部分
        gsub(/cost=|ms/, "", $4)     # 去掉"cost="和"ms"
        
        # 如果響應(yīng)時(shí)間超過500ms
        if($4 > 500) {
            print "慢請(qǐng)求: " $0
        }
    }
' api.log

# 輸出:
慢請(qǐng)求: 2024-02-14 10:00:03 [api=/user/login] cost=800ms status=500

2. 接口性能分析

(1) 計(jì)算接口的平均響應(yīng)時(shí)間(入門級(jí))

# 計(jì)算每個(gè)接口的平均響應(yīng)時(shí)間
awk '
{
    # 提取接口名稱
    api=$3
    # 提取響應(yīng)時(shí)間的數(shù)字部分
    gsub(/.*=|ms.*/, "", $4)
    # 累加響應(yīng)時(shí)間
    sum[api] += $4
    # 統(tǒng)計(jì)請(qǐng)求次數(shù)
    count[api]++
}
END {
    print "接口平均響應(yīng)時(shí)間:"
    for(api in sum) {
        printf "%s: %.2fms\n", api, sum[api]/count[api]
    }
}' api.log

# 輸出:
接口平均響應(yīng)時(shí)間:
[api=/user/login]: 450.00ms
[api=/user/info]: 50.00ms
[api=/order/create]: 150.00ms

(2) 統(tǒng)計(jì)接口QPS(常用)

先從一個(gè)簡單的接口日志開始:

2024-02-14 10:00:01 [api=/user/login] cost=100ms status=200
2024-02-14 10:00:02 [api=/user/info] cost=50ms status=200
2024-02-14 10:00:03 [api=/user/login] cost=800ms status=500
2024-02-14 10:00:04 [api=/order/create] cost=150ms status=200

# 命令:計(jì)算每秒的請(qǐng)求數(shù)(QPS)
awk '{
    # 把時(shí)間列拼接起來: $1是日期,$2是時(shí)間
    # 例如: "2024-02-14 10:00:01"
    time = $1" "$2

    # substr 函數(shù)用于截取字符串
    # 從拼接的時(shí)間字符串中取前19位,精確到秒
    # 如: "2024-02-14 10:00:01"
    second = substr(time, 1, 19)

    # 用時(shí)間作為key,計(jì)數(shù)+1
    count[second]++
}
END {
    # 處理完所有行后,打印統(tǒng)計(jì)結(jié)果
    print "每秒請(qǐng)求數(shù)(QPS):"
    # 遍歷統(tǒng)計(jì)結(jié)果
    for(s in count) {
        print s ": " count[s] "次/秒"
    }
}' api.log

(3) 分析響應(yīng)時(shí)間分布(進(jìn)階)

# 按區(qū)間統(tǒng)計(jì)響應(yīng)時(shí)間分布
awk '
BEGIN {
    print "響應(yīng)時(shí)間分布統(tǒng)計(jì):"
}
{
    # 提取cost=后面的數(shù)字,去掉ms
    split($4, arr, "=|ms")    # 用=或ms分割,如:"cost=100ms" -> arr[2]="100"
    time = arr[2]             # 提取數(shù)字部分
    
    # 按區(qū)間統(tǒng)計(jì)請(qǐng)求數(shù)
    if(time <= 100) {
        range["0-100ms"]++       # 統(tǒng)計(jì)小于等于100ms的請(qǐng)求
    } else if(time <= 200) {
        range["101-200ms"]++     # 統(tǒng)計(jì)101ms到200ms的請(qǐng)求
    } else {
        range["200ms+"]++        # 統(tǒng)計(jì)大于200ms的請(qǐng)求
    }
    total++    # 總請(qǐng)求數(shù)加1
}
END {
    # 遍歷每個(gè)區(qū)間并打印統(tǒng)計(jì)結(jié)果
    for(r in range) {
        percent = range[r]/total*100
        printf "%s: %d個(gè)請(qǐng)求 (%.1f%%)\n", r, range[r], percent
    }
}' api.log

# 現(xiàn)在輸出應(yīng)該是:
響應(yīng)時(shí)間分布統(tǒng)計(jì):
0-100ms: 2個(gè)請(qǐng)求 (50.0%)
101-200ms: 1個(gè)請(qǐng)求 (25.0%)
200ms+: 1個(gè)請(qǐng)求 (25.0%)

3. 錯(cuò)誤分析

統(tǒng)計(jì)錯(cuò)誤率(常用)

2024-02-14 10:00:01 [api=/user/login] cost=100ms status=200
2024-02-14 10:00:02 [api=/user/info] cost=50ms status=200
2024-02-14 10:00:03 [api=/user/login] cost=800ms status=500
2024-02-14 10:00:04 [api=/order/create] cost=150ms status=200

# 計(jì)算接口錯(cuò)誤率
awk '
{
    api=$3
    status=$5
    gsub(/.*=/, "", status)
    
    # 統(tǒng)計(jì)總請(qǐng)求和錯(cuò)誤請(qǐng)求
    total[api]++
    if(status >= 400) {
        errors[api]++
    }
}
END {
    print "接口錯(cuò)誤率統(tǒng)計(jì):"
    for(api in total) {
        if(errors[api] > 0) {
            err_rate = errors[api]/total[api]*100
            printf "%s: %.1f%% (%d/%d)\n", 
                   api, err_rate, errors[api], total[api]
        }
    }
}' api.log

# 輸出:
接口錯(cuò)誤率統(tǒng)計(jì):
[api=/user/login]: 50.0% (1/2)

4. 生成性能報(bào)告(高級(jí))

把前面學(xué)到的都用上,生成一個(gè)完整的性能報(bào)告:

# 生成完整的接口性能分析報(bào)告
awk '
BEGIN {
    print "=== 接口性能分析報(bào)告 ==="
    print "時(shí)間范圍:" strftime("%Y-%m-%d %H:%M:%S")
    print "\n1. 總體統(tǒng)計(jì)"
}
{
    # 記錄基礎(chǔ)信息
    api=$3
    gsub(/.*=|ms.*/, "", $4)
    cost=$4
    gsub(/.*=/, "", $5)
    status=$5
    
    # 統(tǒng)計(jì)總請(qǐng)求
    total_reqs++
    
    # 按接口統(tǒng)計(jì)
    reqs[api]++
    total_cost[api] += cost
    
    # 記錄最大最小響應(yīng)時(shí)間
    if(cost > max_cost[api]) max_cost[api] = cost
    if(min_cost[api] == 0 || cost < min_cost[api]) 
        min_cost[api] = cost
    
    # 統(tǒng)計(jì)錯(cuò)誤
    if(status >= 400) errors[api]++
}
END {
    # 1. 打印總體統(tǒng)計(jì)
    printf "總請(qǐng)求數(shù):%d\n", total_reqs
    
    # 2. 打印接口詳情
    print "\n2. 接口詳情"
    for(api in reqs) {
        printf "\n接口:%s\n", api
        printf "  總調(diào)用次數(shù):%d\n", reqs[api]
        printf "  平均響應(yīng)時(shí)間:%.2fms\n", 
               total_cost[api]/reqs[api]
        printf "  最大響應(yīng)時(shí)間:%dms\n", max_cost[api]
        printf "  最小響應(yīng)時(shí)間:%dms\n", min_cost[api]
        if(errors[api] > 0) {
            printf "  錯(cuò)誤率:%.1f%%\n", 
                   errors[api]/reqs[api]*100
        }
    }
}' api.log

# 輸出:
=== 接口性能分析報(bào)告 ===
時(shí)間范圍:2024-02-14 10:00:00

1. 總體統(tǒng)計(jì)
總請(qǐng)求數(shù):4

2. 接口詳情

接口:[api=/user/login]
  總調(diào)用次數(shù):2
  平均響應(yīng)時(shí)間:450.00ms
  最大響應(yīng)時(shí)間:800ms
  最小響應(yīng)時(shí)間:100ms
  錯(cuò)誤率:50.0%

接口:[api=/user/info]
  總調(diào)用次數(shù):1
  平均響應(yīng)時(shí)間:50.00ms
  最大響應(yīng)時(shí)間:50ms
  最小響應(yīng)時(shí)間:50ms

接口:[api=/order/create]
  總調(diào)用次數(shù):1
  平均響應(yīng)時(shí)間:150.00ms
  最大響應(yīng)時(shí)間:150ms
  最小響應(yīng)時(shí)間:150ms

5. 實(shí)用小技巧

(1) 處理大文件時(shí)先取樣分析:

head -1000 big_log.txt | awk '你的命令'

(2) 實(shí)時(shí)監(jiān)控錯(cuò)誤和慢請(qǐng)求:

測試用例:
? cat api.log
# api.log 示例數(shù)據(jù):
2024-02-14 10:00:01 [api=/user/login] cost=100ms status=200    # 正常請(qǐng)求
2024-02-14 10:00:02 [api=/user/info] cost=550ms status=200     # 慢請(qǐng)求(>500ms)
2024-02-14 10:00:03 [api=/user/login] cost=800ms status=500    # 慢請(qǐng)求且報(bào)錯(cuò)
2024-02-14 10:00:04 [api=/order/create] cost=150ms status=404  # 錯(cuò)誤請(qǐng)求
2024-02-14 10:00:05 [api=/user/profile] cost=200ms status=200  # 正常請(qǐng)求

# 監(jiān)控命令:
tail -f api.log | awk '
$4 ~ /cost=[5-9][0-9][0-9]ms/ || $5 ~ /status=[45][0-9][0-9]/ {
    # 檢查是否是慢請(qǐng)求
    if($4 ~ /cost=[5-9][0-9][0-9]ms/) {
        msg="慢請(qǐng)求"
    }
    
    # 檢查是否有錯(cuò)誤狀態(tài)碼
    if($5 ~ /status=[45][0-9][0-9]/) {
        msg=msg?msg" 且 狀態(tài)碼異常":"狀態(tài)碼異常"
    }
    
    # 打印告警信息
    print "\033[31m告警:" $0 " # " msg "\033[0m"
    
    # 重置消息變量
    msg=""
}'

# 輸出(紅色顯示):
告警:2024-02-14 10:00:02 [api=/user/info] cost=550ms status=200        # 因?yàn)轫憫?yīng)時(shí)間>500ms
告警:2024-02-14 10:00:03 [api=/user/login] cost=800ms status=500       # 因?yàn)轫憫?yīng)時(shí)間>500ms且狀態(tài)碼500
告警:2024-02-14 10:00:04 [api=/order/create] cost=150ms status=404     # 因?yàn)闋顟B(tài)碼404

記住:

  • 先從簡單的統(tǒng)計(jì)開始
  • 需要時(shí)再加更多的統(tǒng)計(jì)維度
  • 復(fù)雜的分析可以分步驟進(jìn)行
  • 多用print調(diào)試你的統(tǒng)計(jì)邏輯

學(xué)會(huì)了這些,你就能應(yīng)對(duì)大部分的日志分析工作了!

第四部分:實(shí)戰(zhàn)篇 - 應(yīng)用日志分析

接著我們來分析實(shí)際工作中最常見的幾種應(yīng)用日志。咱們由淺入深,一步步來。

1. 基礎(chǔ)日志分析

(1) 簡單的應(yīng)用日志

先來看一個(gè)最基礎(chǔ)的應(yīng)用日志:

2024-02-14 10:00:01 [INFO] UserService - 用戶登錄成功,用戶名=admin
2024-02-14 10:00:02 [ERROR] OrderService - 訂單創(chuàng)建失敗:數(shù)據(jù)庫連接超時(shí)
2024-02-14 10:00:03 [WARN] UserService - 密碼錯(cuò)誤,用戶名=test
2024-02-14 10:00:04 [ERROR] PaymentService - 支付失敗:余額不足

(2) 基礎(chǔ)日志過濾(最簡單的用法)

# 命令1:顯示所有ERROR日志
awk '/ERROR/' app.log

# 輸出:
2024-02-14 10:00:02 [ERROR] OrderService - 訂單創(chuàng)建失敗:數(shù)據(jù)庫連接超時(shí)
2024-02-14 10:00:04 [ERROR] PaymentService - 支付失敗:余額不足

# 命令2:查看特定服務(wù)的日志
awk '/UserService/' app.log

# 輸出:
2024-02-14 10:00:01 [INFO] UserService - 用戶登錄成功,用戶名=admin
2024-02-14 10:00:03 [WARN] UserService - 密碼錯(cuò)誤,用戶名=test

(3) 統(tǒng)計(jì)日志級(jí)別(常用功能)

# 命令:統(tǒng)計(jì)每種日志級(jí)別的數(shù)量
awk '
    # 匹配有方括號(hào)的行
    /\[.*\]/ {
        # 提取方括號(hào)中的內(nèi)容,存入arr數(shù)組
        match($0, /\[(.*?)\]/, arr)
        # 對(duì)應(yīng)的日志級(jí)別計(jì)數(shù)加1
        level[arr[1]]++
    }
    # 所有行處理完后執(zhí)行
    END {
        print "日志級(jí)別統(tǒng)計(jì):"
        # 遍歷統(tǒng)計(jì)結(jié)果并打印
        for(l in level) {
            print l ": " level[l] "條"
        }
    }
' app.log

# 輸出:
日志級(jí)別統(tǒng)計(jì):
INFO: 1條
ERROR: 2條
WARN: 1條

2. 接口調(diào)用日志分析

(1) 接口日志示例

2024-02-14 10:00:01 [api=/user/login] cost=120ms status=200
2024-02-14 10:00:02 [api=/order/create] cost=500ms status=500
2024-02-14 10:00:03 [api=/user/info] cost=80ms status=200

(2) 分析接口響應(yīng)時(shí)間

# 命令:統(tǒng)計(jì)每個(gè)接口的平均響應(yīng)時(shí)間
awk '
{
    # 提取接口名和響應(yīng)時(shí)間
    api=$3                      # 獲取接口名稱列
    gsub(/\[|\]/, "", api)     # 去掉方括號(hào)
    gsub(/.*=|ms/, "", $4)     # 提取響應(yīng)時(shí)間的數(shù)字部分
    
    # 統(tǒng)計(jì)數(shù)據(jù)
    apis[api] += $4            # 累加響應(yīng)時(shí)間
    count[api]++               # 統(tǒng)計(jì)調(diào)用次數(shù)
}
END {
    print "接口平均響應(yīng)時(shí)間:"
    for(a in apis) {
        printf "%s: %.2fms\n", a, apis[a]/count[a]
    }
}' api.log

# 輸出:
接口平均響應(yīng)時(shí)間:
api=/user/login: 120.00ms
api=/order/create: 500.00ms
api=/user/info: 80.00ms

3. 錯(cuò)誤日志分析

(1) 異常堆棧日志

> cat Service.log
2024-02-14 10:00:01 [ERROR] NullPointerException: 空指針異常
    at com.example.UserService.getUser(UserService.java:15)
    at com.example.UserController.login(UserController.java:10)
2024-02-14 10:00:02 [ERROR] SQLException: 數(shù)據(jù)庫連接失敗
    at com.example.OrderService.create(OrderService.java:25)

(2) 提取完整異常信息

# 命令:提取異常信息及其堆棧
awk '
    # 匹配錯(cuò)誤行
    /ERROR/ {
        print "\n發(fā)現(xiàn)異常:"
        print $0            # 打印錯(cuò)誤行
        print "異常堆棧:"
    }
    # 匹配堆棧信息(以空格開頭的行)
    /^[[:space:]]/ {
        print $0           # 打印堆棧行
    }
' Service.log

# 輸出:
發(fā)現(xiàn)異常:
2024-02-14 10:00:01 [ERROR] NullPointerException: 空指針異常
異常堆棧:
    at com.example.UserService.getUser(UserService.java:15)
    at com.example.UserController.login(UserController.java:10)

發(fā)現(xiàn)異常:
2024-02-14 10:00:02 [ERROR] SQLException: 數(shù)據(jù)庫連接失敗
異常堆棧:
    at com.example.OrderService.create(OrderService.java:25)

4. 性能問題分析

(1) 數(shù)據(jù)庫慢查詢?nèi)罩?/p>

2024-02-14 10:00:01 [SLOW_QUERY] cost=2.5s sql="SELECT * FROM orders WHERE user_id=123"
2024-02-14 10:00:05 [SLOW_QUERY] cost=1.8s sql="UPDATE users SET status=1"
2024-02-14 10:00:10 [SLOW_QUERY] cost=3.1s sql="SELECT * FROM order_items"

(2) 分析慢查詢

# 命令:分析超過2秒的慢查詢
awk '
{
    # 提取執(zhí)行時(shí)間,去掉s得到純數(shù)字
    time_str = $4
    gsub("cost=|s", "", time_str)  # 將cost=和s都替換為空
    time = time_str + 0            # 轉(zhuǎn)換為數(shù)字
    
    # 提取完整SQL語句
    sql = substr($0, index($0, "sql="))
    
    # 如果查詢時(shí)間超過2秒
    if(time > 2) {
        printf "\n時(shí)間:%s %s\n", $1, $2
        printf "耗時(shí):%.1f秒\n", time
        printf "SQL:%s\n", sql
        printf "----------\n"
    }
}' slow_query.log

# 輸出:
時(shí)間:2024-02-14 10:00:01
耗時(shí):2.5秒
SQL:"SELECT * FROM orders WHERE user_id=123"
----------

時(shí)間:2024-02-14 10:00:10
耗時(shí):3.1秒
SQL:"SELECT * FROM order_items"
----------

5. 監(jiān)控告警分析

(1) 告警日志

2024-02-14 10:00:01 [ALERT] service=order-service type=cpu_high value=92%
2024-02-14 10:00:05 [ALERT] service=user-service type=memory_high value=85%
2024-02-14 10:00:10 [ALERT] service=order-service type=disk_usage value=95%

(2) 統(tǒng)計(jì)告警情況

# 命令:按服務(wù)統(tǒng)計(jì)告警
awk '
BEGIN {
    print "=== 告警分析報(bào)告 ==="
    print "分析時(shí)間:" strftime("%Y-%m-%d %H:%M:%S")
    print "-------------------"
}
/\[ALERT\]/ {    # 只處理包含[ALERT]的行
    # 提取基本信息
    gsub(/service=|type=|value=|%|threshold=/, " ", $0)
    for(i=1; i<=NF; i++) {
        if($i == "[ALERT]") {
            service = $(i+1)    # 服務(wù)名
            type = $(i+2)       # 告警類型
            value = $(i+3)      # 當(dāng)前值
            threshold = $(i+4)  # 閾值
        }
    }
    
    # 計(jì)算超出閾值的百分比
    exceed = value - threshold
    
    # 根據(jù)超出程度分級(jí)
    if(exceed >= 20) {
        level = "嚴(yán)重"
    } else if(exceed >= 10) {
        level = "警告"
    } else {
        level = "注意"
    }
    
    # 統(tǒng)計(jì)信息
    services[service]++
    types[type]++
    levels[level]++
    
    # 記錄最大值和時(shí)間
    if(max_value[type] < value) {
        max_value[type] = value
        max_time[type] = $1 " " $2
    }
    
    # 保存詳細(xì)信息
    details[++count] = sprintf("時(shí)間:%s %s\n服務(wù):%-15s 類型:%-12s 當(dāng)前值:%d%% (超出閾值:%d%%) 級(jí)別:%s",
        $1, $2, service, type, value, exceed, level)
}
END {
    # 1. 告警級(jí)別統(tǒng)計(jì)
    print "\n1. 告警級(jí)別分布:"
    for(l in levels) {
        printf "%-6s: %d次\n", l, levels[l]
    }
    
    # 2. 服務(wù)告警統(tǒng)計(jì)
    print "\n2. 服務(wù)告警統(tǒng)計(jì):"
    for(svc in services) {
        printf "%-20s: %d次告警\n", svc, services[svc]
    }
    
    # 3. 告警類型統(tǒng)計(jì)
    print "\n3. 告警類型統(tǒng)計(jì):"
    for(t in types) {
        printf "%-15s: %d次\n", t, types[t]
        printf "  最大值: %d%% (發(fā)生時(shí)間: %s)\n", max_value[t], max_time[t]
    }
    
    # 4. 詳細(xì)告警記錄
    print "\n4. 詳細(xì)告警記錄:"
    print "-------------------"
    for(i=1; i<=count; i++) {    # 使用count而不是NR
        print details[i] "\n----------"
    }
}' alert.log

# 輸出:
告警統(tǒng)計(jì):
=== 告警分析報(bào)告 ===
分析時(shí)間:2025-02-14 21:34:52
-------------------

1. 告警級(jí)別分布:
注意    : 3次
警告    : 2次

2. 服務(wù)告警統(tǒng)計(jì):
order-service       : 3次告警
user-service        : 2次告警

3. 告警類型統(tǒng)計(jì):
memory_high    : 2次
  最大值: 95% (發(fā)生時(shí)間: 2024-02-14 10:00:20)
cpu_high       : 2次
  最大值: 92% (發(fā)生時(shí)間: 2024-02-14 10:00:01)
disk_usage     : 1次
  最大值: 95% (發(fā)生時(shí)間: 2024-02-14 10:00:10)

4. 詳細(xì)告警記錄:
-------------------
時(shí)間:2024-02-14 10:00:01
服務(wù):order-service   類型:cpu_high     當(dāng)前值:92% (超出閾值:12%) 級(jí)別:警告
----------
時(shí)間:2024-02-14 10:00:05
服務(wù):user-service    類型:memory_high  當(dāng)前值:85% (超出閾值:5%) 級(jí)別:注意
----------
時(shí)間:2024-02-14 10:00:10
服務(wù):order-service   類型:disk_usage   當(dāng)前值:95% (超出閾值:5%) 級(jí)別:注意
----------
時(shí)間:2024-02-14 10:00:15
服務(wù):user-service    類型:cpu_high     當(dāng)前值:88% (超出閾值:8%) 級(jí)別:注意
----------
時(shí)間:2024-02-14 10:00:20
服務(wù):order-service   類型:memory_high  當(dāng)前值:95% (超出閾值:15%) 級(jí)別:警告
----------

這些是日常工作中最常用到的日志分析場景。我們從最簡單的日志過濾開始,逐步深入到了復(fù)雜的統(tǒng)計(jì)分析。記住,解決復(fù)雜的問題時(shí),可以先拆分成小步驟,一步一步來處理。

總結(jié)

看到這里,相信你已經(jīng)掌握了 awk 這個(gè)文本處理利器的基本使用。從最初的字段提取,到復(fù)雜的日志分析,再到性能監(jiān)控,只要靈活運(yùn)用,awk 幾乎能解決所有的文本處理需求。

不過,真實(shí)的工作環(huán)境中,往往需要 多個(gè)命令配合使用 才能達(dá)到最好的效果。就像武俠小說里的武功招式,單招玩得再熟,也不如組合技來得實(shí)用。

比如:

# 先用grep找出錯(cuò)誤日志,再用awk分析
grep "ERROR" app.log | awk '{print $1,$2}'

# 用sed處理格式,再用awk統(tǒng)計(jì)
sed 's/"http://g' access.log | awk '{count[$1]++} END{for(ip in count) print ip,count[ip]}'

下一篇,我將為大家?guī)?nbsp;grep、sed、awk 這三劍客的組合應(yīng)用,教你如何在實(shí)戰(zhàn)中發(fā)揮它們的最大威力。相信這些實(shí)用的"組合技",一定能幫你在日常工作中事半功倍。

責(zé)任編輯:趙寧寧 來源: 跟著小康學(xué)編程
相關(guān)推薦

2025-06-03 08:35:00

命令Linux日志分析

2013-02-22 09:49:29

Nagios監(jiān)控性能評(píng)測

2025-03-25 09:00:00

2019-03-21 14:30:15

Linux文本分析命令

2023-12-10 21:35:45

Linux服務(wù)器日志分析

2017-06-15 12:42:07

Linux常用性能分析命令

2016-12-23 10:56:34

linuxshellawk

2025-05-12 10:15:00

Linuxdiff系統(tǒng)

2022-07-26 10:28:00

Linux監(jiān)控命令

2022-03-23 08:45:20

系統(tǒng)性能CPU

2021-03-15 07:39:48

LinuxAwk 語言

2019-07-31 10:18:17

Web 開發(fā)Python

2023-06-28 11:49:56

Linux命令

2025-07-09 07:10:00

2025-02-08 10:54:02

2025-09-08 11:00:00

2025-07-17 13:52:57

通配符Linux命令行

2024-10-17 16:47:05

磁盤I/O計(jì)算機(jī)

2025-05-14 08:15:00

MongoDB操作命令Docker

2025-10-31 00:17:39

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

亚洲色大成网站www久久九九| 午夜一级久久| 欧美久久久影院| av影院在线播放| 三级网站在线看| 三级欧美在线一区| 中文字幕免费精品一区| 三大队在线观看| 中老年在线免费视频| 国产精品萝li| 国产精品视频免费一区| 国产性生活视频| 久久久久久免费视频| 精品国产免费久久| 熟女少妇精品一区二区| av毛片在线| 久久女同互慰一区二区三区| 国产精品尤物福利片在线观看| 免费视频一二三区| 精品成av人一区二区三区| 欧美放荡的少妇| 日韩av在线第一页| 成人日韩欧美| 国产欧美日本一区视频| 99久久精品免费看国产一区二区三区| 自拍偷拍欧美亚洲| 66视频精品| 亚洲精选中文字幕| 亚洲 自拍 另类 欧美 丝袜| 中文日产幕无线码一区二区| 亚洲免费观看高清完整版在线观看熊| 精品久久蜜桃| 99精品视频免费看| 秋霞国产午夜精品免费视频| 97精品免费视频| 农村妇女精品一区二区| re久久精品视频| 日韩精品视频观看| 女性生殖扒开酷刑vk| **精品中文字幕一区二区三区| 色综合天天综合狠狠| 欧美一区二区视频在线播放| 欧美成年黄网站色视频| 久久精品一区二区三区不卡牛牛| 国产精品免费一区二区三区四区| 91精品国产乱码久久久久| 久久人人超碰| 91sa在线看| 日本中文字幕免费观看| 欧美~级网站不卡| 日韩一区视频在线| 美国一级黄色录像| 波多野结衣在线播放一区| 精品国产亚洲在线| 能看毛片的网站| 日韩成人综合网站| 欧美人妇做爰xxxⅹ性高电影| aaa毛片在线观看| 日本乱码一区二区三区不卡| 性欧美大战久久久久久久久| 国产制服91一区二区三区制服| 日本不卡不卡| 成人免费在线视频观看| 不卡中文字幕在线| 国产在线观看a| 自拍偷拍国产亚洲| 中文字幕在线观看一区二区三区| 在线a免费看| 国产精品日产欧美久久久久| 午夜精品区一区二区三| 在线观看黄色av| 中文字幕一区二区三区蜜月| 黄色网址在线免费看| 欧美天天影院| 亚洲激情自拍偷拍| 欧美性潮喷xxxxx免费视频看| 男人天堂亚洲| 精品动漫一区二区三区| 国产福利视频在线播放| 欧美大片1688网站| 9191久久久久久久久久久| 青青草原播放器| 99久久人爽人人添人人澡| 亚洲国产日韩欧美在线图片 | 蜜臀精品一区二区三区在线观看| 国产精品xxx视频| 一级全黄裸体免费视频| 国产丶欧美丶日本不卡视频| 国产精品免费看一区二区三区| 污视频在线免费| 亚洲国产精品成人综合色在线婷婷| 亚洲一二三区精品| 天堂8中文在线| 福利精品视频在线| 一级做a免费视频| 国产精品网站在线看| 国产午夜精品视频| 免费在线观看av网址| 噜噜噜躁狠狠躁狠狠精品视频| 国产一区二区在线免费视频| 精品国产亚洲av麻豆| 97aⅴ精品视频一二三区| 夜夜春亚洲嫩草影视日日摸夜夜添夜| 少女频道在线观看免费播放电视剧 | 成人资源av| 九色网友自拍视频手机在线| 亚洲天堂av老司机| 各处沟厕大尺度偷拍女厕嘘嘘| 国产成人精品一区二区三区视频| 日韩片之四级片| 中文字幕免费在线看线人动作大片| 国产精品二区不卡| 青青久久aⅴ北条麻妃| 国产黄频在线观看| 国产日韩欧美电影| 亚洲国产精品无码观看久久| 95精品视频| 亚洲乱码一区av黑人高潮| 日本a级片视频| 日本vs亚洲vs韩国一区三区| 九九九热999| 好吊日av在线| 欧美精品久久99久久在免费线 | 成人在线视频你懂的| 色老头一区二区三区| 天天爽夜夜爽夜夜爽精品| 精品一区二区久久久| 免费av在线一区二区| 伊人在我在线看导航| 欧美性极品少妇| 久久亚洲AV成人无码国产野外| 亚洲中无吗在线| 国产欧美精品久久久| 人人九九精品| 午夜精品视频一区| 一起草最新网址| 一本一道久久综合狠狠老| 国产精品美女久久久久av超清| 亚欧洲精品视频| 亚洲不卡在线观看| 在线xxxxx| 欧美天堂亚洲电影院在线观看| 成人福利网站在线观看11| 国产专区在线| 日本道免费精品一区二区三区| av黄色一级片| 亚洲激情网站| 国产综合动作在线观看| av资源在线看片| 亚洲精品在线三区| 欧美成人黄色网| 国产高清精品网站| 免费极品av一视觉盛宴| 亚洲高清999| 欧美高清视频在线播放| 亚洲精品中文字幕成人片 | 日韩精品在线视频| 精品成人久久久| 26uuu精品一区二区在线观看| 少妇高潮喷水在线观看| 日韩大片在线免费观看| 国产91精品不卡视频| 久久久久久女乱国产| 在线观看免费成人| 在线观看亚洲大片短视频| 日韩电影一二三区| 亚洲免费久久| 欧美成人精品午夜一区二区| 色综合色综合久久综合频道88| 后进极品白嫩翘臀在线视频| 午夜欧美一区二区三区在线播放| 波多野结衣影院| 老司机免费视频久久| 午夜午夜精品一区二区三区文| jvid一区二区三区| 久久视频国产精品免费视频在线| 精品人妻伦一区二区三区久久| 亚洲一区二区在线播放相泽| 中文乱码人妻一区二区三区视频| 噜噜爱69成人精品| 一区二区高清视频| 51亚洲精品| 国产97免费视| 毛片在线看网站| 精品国产免费视频| 国产午夜无码视频在线观看| 中文字幕亚洲视频| jjzz黄色片| 美女诱惑黄网站一区| 亚洲国产欧美不卡在线观看 | 91精品国产欧美一区二区成人| 欧美黄色一区二区三区| 久久综合九色综合97婷婷| 污视频免费在线观看网站| 午夜久久99| 欧洲一区二区日韩在线视频观看免费| vam成人资源在线观看| 国内精久久久久久久久久人| 爱久久·www| 日韩精品一区二区三区视频| 91丨九色丨海角社区| 一区二区三区在线视频观看 | 国产精品久久久久久久久晋中| 无套白嫩进入乌克兰美女| 在线视频免费在线观看一区二区| 亚洲欧美日韩国产成人综合一二三区| 亚洲日本视频在线| 国产噜噜噜噜噜久久久久久久久| 变态调教一区二区三区| 精品国产欧美一区二区五十路| 手机看片福利在线| 91麻豆精品91久久久久久清纯 | 999在线观看免费大全电视剧| 午夜不卡影院| 久久99热精品| 在线观看免费版| 亚洲人成五月天| 欧美一区,二区| 51精品视频一区二区三区| 天堂а√在线中文在线新版| 一区二区三区欧美久久| 国产一二三四区在线| 99精品久久免费看蜜臀剧情介绍| 中文av字幕在线观看| 日韩电影免费一区| 国模无码视频一区二区三区| 欧美日韩91| 综合久久国产| 精品欧美激情在线观看| 国产不卡一区二区三区在线观看| 欧美日韩精品免费观看视欧美高清免费大片| 欧美国产在线电影| 精品黄色免费中文电影在线播放 | 醉酒壮男gay强迫野外xx| 国产成人精品综合在线观看| 在线一区二区不卡| 麻豆精品在线观看| 黄色aaa级片| 视频一区二区三区入口| 人妻有码中文字幕| 国产欧美综合一区二区三区| 国产不卡一区二区视频| 精品电影一区| 国产在线视频在线| 欧美精品导航| www.国产在线播放| 韩国精品一区二区三区| 国内少妇毛片视频| 亚洲小说欧美另类婷婷| 国产中文字幕乱人伦在线观看| 欧美日韩hd| 蜜臀av无码一区二区三区| 在线不卡亚洲| 无码中文字幕色专区| 国产日韩1区| 日日碰狠狠添天天爽超碰97| 国产一区二区你懂的| 日本成年人网址| 久久国产精品久久w女人spa| av五月天在线| 久久精品免费观看| 色偷偷中文字幕| 国产91精品在线观看| 国产一级免费片| 99久久精品国产网站| 波多野结衣av在线免费观看| 久久久久久99久久久精品网站| 影音先锋男人在线| 中文字幕亚洲综合久久菠萝蜜| 无码人妻精品一区二区三区夜夜嗨| 亚洲欧美成aⅴ人在线观看| 久久黄色小视频| 精品日韩中文字幕| 波多野结衣视频网址| 欧美精品一二三| 性做久久久久久久| 日韩精品视频免费专区在线播放| 久青草国产在线| 日韩天堂在线视频| 欧美videossex| 欧洲成人在线观看| 亚洲精品成a人ⅴ香蕉片| 99中文视频在线| 九九综合在线| 中国成人亚色综合网站| 好看的日韩av电影| 久久国产乱子伦免费精品| 久久se这里有精品| 熟女人妻一区二区三区免费看| 91蜜桃婷婷狠狠久久综合9色| 五月婷婷欧美激情| 亚洲国产成人91porn| 69亚洲精品久久久蜜桃小说| 在线不卡中文字幕| 手机在线观看免费av| 中文国产成人精品| 久草免费在线色站| 国产美女主播一区| 玖玖玖免费嫩草在线影院一区| 少妇特黄a一区二区三区| 欧美理论在线| 亚洲欧美激情网| 成人av网站免费观看| 网站永久看片免费| 精品国产91久久久久久| 国产内射老熟女aaaa∵| 亚洲精品视频网上网址在线观看 | 99久久国产热无码精品免费| 日韩精品在线看| 牛牛电影国产一区二区| 91精品久久久久久久久久| 日本一区福利在线| 久久久久福利视频| 美女国产一区二区三区| 精品影片一区二区入口| 亚洲婷婷国产精品电影人久久| 福利网址在线观看| 精品粉嫩超白一线天av| 欧美成人视屏| 国产精品入口福利| 自拍亚洲一区| 久操网在线观看| 国产精品一区二区三区99 | 亚洲免费观看视频| 日本一二三区视频在线| 国产黄色片在线| 亚洲一区二区三区四区在线 | 久久精品动漫| 又黄又色的网站| 亚洲日本在线看| 中文字幕一区二区三区免费看| 日韩精品久久久久| 国产丝袜精品丝袜| 97久久人人超碰caoprom欧美 | 在线视频免费一区二区| 久久sese| 久久青青草原| 亚洲毛片av| 天天躁日日躁狠狠躁免费麻豆| 亚洲精品视频在线| 国产乱码一区二区| 久久精品国产成人| 亚洲成人高清| 正在播放一区二区三区| 久88久久88久久久| 亚洲欧洲综合网| 欧美精品九九99久久| 色多多视频在线观看| 国产精品视频成人| 99久久99久久精品国产片果冰| 福利在线一区二区三区| 国产日本欧洲亚洲| 蜜臀尤物一区二区三区直播| 亚洲欧洲中文天堂| 亚洲va中文在线播放免费| 日本一区精品| 欧美aⅴ一区二区三区视频| 天堂资源在线视频| 欧美日本高清视频在线观看| 欧美三级黄网| 亚洲在线免费观看| 亚洲午夜久久久久久尤物| 亚洲麻豆一区二区三区| 午夜精品久久久久久久| 欧美孕妇孕交xxⅹ孕妇交| 国产极品jizzhd欧美| 97精品一区| 少妇性l交大片7724com| 香蕉加勒比综合久久| 欧美zzoo| 国产色婷婷国产综合在线理论片a| 99精品综合| 2018国产精品| 日韩欧美亚洲一二三区| 第三区美女视频在线| 91精品免费视频| 亚洲经典三级| 亚洲无人区码一码二码三码的含义| 欧美三级日本三级少妇99| 国产激情在线观看| 精品国产乱码久久久久久88av| 久久久青草婷婷精品综合日韩| 亚洲综合图片一区| 精品剧情在线观看| 欧美中文字幕精在线不卡| 中日韩在线视频| 不卡av在线免费观看| 99re热视频| 欧美国产日本高清在线 | 中文字幕在线观看成人| 日韩大片在线观看视频| 国产福利亚洲| 草草视频在线免费观看| 国产精品视频麻豆| 蜜桃av中文字幕| 国产精品极品在线| 激情婷婷亚洲| 亚洲一级二级片| 精品视频一区在线视频| 亚洲图片小说区|