find/grep/awkマスターシリーズ 実践編
組み合わせと実務活用
find、grep、awkを組み合わせた実践的なデータ処理パターンと業務での活用事例を詳しく解説。エンジニア・データアナリスト向けの実用技術を習得します。
📋 目次
6. 組み合わせテクニック
真のLinuxマスターは、find、grep、awkを組み合わせて使います。単体では難しい処理も、組み合わせることで強力な解決策になります。
🔗 パイプでつなぐ基本パターン
find + grep の組み合わせ
find /var/log -name "*.log" -exec grep -l "ERROR" {} \;
ログファイルからERRORを含むファイルを特定
find /home -name "*.txt" | xargs grep -n "password"
txtファイル群から"password"を行番号付きで検索
grep + awk の組み合わせ
grep "ERROR" /var/log/app.log | awk '{print $1, $2, $NF}'
エラー行から日付・時刻・最後のフィールドを抽出
ps aux | grep "nginx" | awk '{sum+=$4} END {print "CPU使用率合計:", sum "%"}'
nginxプロセスのCPU使用率を合計
find + awk の組み合わせ
find /var -name "*.log" -printf "%s %p\n" | awk '{size+=$1; count++} END {printf "総サイズ: %.2f MB ファイル数: %d\n", size/1024/1024, count}'
ログファイルの総サイズとファイル数を計算
🎯 実務レベルの複合処理
📊 シナリオ1: Webサーバーのアクセス解析
目的:過去1週間のアクセスログから、エラーが多いIPアドレスTOP10を抽出
解決策:
find /var/log/apache2 -name "access.log*" -mtime -7 | \
xargs grep " 5[0-9][0-9] " | \
awk '{print $1}' | \
sort | uniq -c | \
sort -rn | \
head -10 | \
awk '{printf "%-15s %d回\n", $2, $1}'
ステップ解説:
find: 1週間以内のアクセスログファイルを検索grep: 5xxエラー(サーバーエラー)の行を抽出awk: IPアドレス(1列目)のみを抽出sort | uniq -c: IPアドレス別にカウントsort -rn: カウント数で降順ソートhead -10: TOP10を取得awk: 見やすい形式で出力
🔍 シナリオ2: 古い一時ファイルの一括削除
目的:システム全体から30日以上古い一時ファイルを安全に削除
解決策:
# 1. まず対象ファイルを確認
find /tmp /var/tmp /home -name "*.tmp" -o -name "temp*" -o -name "*.temp" | \
grep -E "\.(tmp|temp)$|^temp" | \
xargs ls -la | \
awk '$6 " " $7 " " $8 < "'$(date -d "30 days ago" "+%b %d %H:%M")'" {print $NF}'
# 2. 安全性を確認したら削除実行
find /tmp /var/tmp /home -name "*.tmp" -mtime +30 -size +0 | \
xargs -I {} bash -c 'echo "削除: {}"; rm "{}"'
安全な削除手順:
- 削除対象ファイルをまず一覧表示して確認
- 30日以上古く、サイズが0より大きいファイルのみ対象
- 削除前にファイル名を表示(ログとして記録)
📈 シナリオ3: データベース接続ログの分析
目的:MySQLのログから時間帯別の接続数を分析
解決策:
find /var/log/mysql -name "*.log" -mtime -1 | \
xargs grep -h "Connect" | \
awk '{
# 時刻を抽出(例: 2025-01-15T14:30:25.123456Z)
match($0, /[0-9]{4}-[0-9]{2}-[0-9]{2}T([0-9]{2})/, time_parts);
hour = time_parts[1];
connections[hour]++;
}
END {
print "時間帯別MySQL接続数(過去24時間)";
print "================================";
for (h = 0; h < 24; h++) {
printf "%02d:00-%02d:59 | ", h, h;
count = (h in connections) ? connections[h] : 0;
printf "%5d回 ", count;
# 簡易グラフ表示
for (i = 0; i < count/10; i++) printf "▓";
printf "\n";
}
}'
高度な処理のポイント:
- 正規表現による時刻抽出
- 連想配列による時間帯別集計
- 視覚的なグラフ表示
- 0件の時間帯も含めた完全な24時間表示
⚡ ワンライナーテクニック集
よく使われる便利なワンライナー集です。そのまま使えて実用性抜群!
💾 ディスク・ファイル管理
find . -type f -exec du -h {} + | sort -rh | head -20
最も大きいファイルTOP20
find /var -name "*.log" -mtime +7 -exec ls -lh {} \; | awk '{size+=$5} END {print "削除可能サイズ:", size/1024/1024 "MB"}'
古いログファイルの総サイズを計算
🌐 ネットワーク・アクセス解析
grep "$(date '+%d/%b/%Y')" /var/log/apache2/access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10
今日のアクセス数が多いIPアドレスTOP10
find /var/log -name "*.log" | xargs grep -h "Failed password" | awk '{print $11}' | sort | uniq -c | sort -rn
SSH ログイン失敗が多いIPアドレス
📊 システム監視
find /proc -maxdepth 2 -name "status" 2>/dev/null | xargs grep -l "VmRSS" | xargs -I {} bash -c 'echo -n "$(basename $(dirname {})): "; grep VmRSS {}'
プロセスごとのメモリ使用量
find /var/log -name "syslog*" | xargs grep "$(date '+%b %d')" | grep -i "error\|warn\|fail" | awk '{print $5}' | sort | uniq -c | sort -rn
今日のシステムエラー・警告の発生元統計
🏗️ パイプライン設計パターン:データフロー設計の極意
複雑なデータ処理を効率的で保守しやすいパイプラインに設計するプロフェッショナルテクニックです。
🔄 エラーハンドリングと復旧パターン
本番環境では失敗が前提。エラーを適切に処理し、処理を継続する設計が重要です。
🛡️ 失敗しないパイプライン設計
# pipefail設定で途中失敗を検出
set -euo pipefail
# エラー時の処理関数
handle_error() {
echo "ERROR: パイプライン処理中にエラーが発生しました(行: $1)" >&2
echo "ERROR: 中間ファイルを確認してください: /tmp/pipeline_*" >&2
exit 1
}
# エラートラップ設定
trap 'handle_error $LINENO' ERR
# 安全なパイプライン処理
process_logs_safely() {
local input_pattern="$1"
local output_file="$2"
local temp_dir="/tmp/pipeline_$$"
# 一時ディレクトリ作成
mkdir -p "$temp_dir"
# ステップ1: ファイル収集(失敗時はスキップ)
echo "ステップ1: ログファイル収集中..."
find /var/log -name "$input_pattern" -type f 2>/dev/null > "$temp_dir/file_list" || {
echo "WARNING: 一部のファイルにアクセスできませんでした" >&2
}
# ファイルが見つからない場合の処理
if [[ ! -s "$temp_dir/file_list" ]]; then
echo "ERROR: 処理対象ファイルが見つかりません" >&2
rm -rf "$temp_dir"
return 1
fi
# ステップ2: データ処理(各ファイルを個別処理)
echo "ステップ2: データ処理中..."
while IFS= read -r logfile; do
if [[ -r "$logfile" ]]; then
grep -h "ERROR\|WARN" "$logfile" 2>/dev/null >> "$temp_dir/errors.log" || true
else
echo "WARNING: $logfile を読み込めませんでした" >&2
fi
done < "$temp_dir/file_list"
# ステップ3: 集計処理
echo "ステップ3: 集計処理中..."
if [[ -s "$temp_dir/errors.log" ]]; then
awk '
{
# エラーパターンの抽出と集計
if ($0 ~ /ERROR/) error_count++;
if ($0 ~ /WARN/) warn_count++;
# 時間帯別集計
if (match($0, /[0-9]{2}:[0-9]{2}:[0-9]{2}/, time_match)) {
hour = substr(time_match[0], 1, 2);
hourly_errors[hour]++;
}
}
END {
printf "エラー統計レポート\n";
printf "==================\n";
printf "ERROR: %d件\n", error_count;
printf "WARN: %d件\n", warn_count;
printf "\n時間帯別エラー数:\n";
for (h = 0; h < 24; h++) {
printf "%02d時: %d件\n", h, (h in hourly_errors) ? hourly_errors[h] : 0;
}
}' "$temp_dir/errors.log" > "$output_file"
else
echo "エラーログが見つかりませんでした" > "$output_file"
fi
# 一時ファイル削除
rm -rf "$temp_dir"
echo "処理完了: $output_file に結果を出力しました"
}
# 実行例
process_logs_safely "*.log" "/tmp/error_report.txt"
エラー処理、ファイル存在チェック、一時ファイル管理を含む堅牢なパイプライン
⚡ パフォーマンス最適化パターン
大容量データと高速処理を両立するパイプライン設計パターンです。
🚀 並列処理パイプライン
# CPU集約的処理の並列化
parallel_log_analysis() {
local log_pattern="$1"
local output_dir="$2"
local cpu_cores=$(nproc)
local max_parallel=$((cpu_cores - 1)) # システム負荷を考慮
echo "並列処理開始: 最大${max_parallel}プロセス"
# ログファイルを発見してワーカープロセスに分散
find /var/log -name "$log_pattern" -type f | \
xargs -n 1 -P "$max_parallel" -I {} bash -c '
logfile="$1"
output_dir="$2"
worker_id="$$"
echo "Worker $worker_id: 処理開始 $logfile"
# 集約処理(CPUインテンシブ)
result_file="$output_dir/result_$worker_id.tmp"
# 複雑な正規表現処理
grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" "$logfile" | \
awk "
BEGIN {
FS=\" \";
worker_id=\"$worker_id\";
}
{
# IP地域判定(簡易版)
ip = \$1;
if (match(ip, /^192\.168\./)) region = \"local\";
else if (match(ip, /^10\./)) region = \"internal\";
else if (match(ip, /^172\.(1[6-9]|2[0-9]|3[01])\./)) region = \"internal\";
else region = \"external\";
# 時間帯分析
if (match(\$4, /\[([0-9]{2})/, time_parts)) {
hour = time_parts[1];
access_by_region_hour[region][hour]++;
}
total_by_region[region]++;
}
END {
printf \"# Worker %s results\n\", worker_id;
for (region in total_by_region) {
printf \"region:%s total:%d\n\", region, total_by_region[region];
for (hour = 0; hour < 24; hour++) {
count = (region SUBSEP hour in access_by_region_hour) ?
access_by_region_hour[region][hour] : 0;
if (count > 0) {
printf \"region:%s hour:%02d count:%d\n\", region, hour, count;
}
}
}
}" > "$result_file"
echo "Worker $worker_id: 処理完了"
' -- {} "$output_dir"
# 全ワーカーの結果をマージ
echo "結果マージ中..."
merge_worker_results "$output_dir"
}
merge_worker_results() {
local output_dir="$1"
local final_report="$output_dir/final_analysis.txt"
# 全ワーカーの結果を集約
find "$output_dir" -name "result_*.tmp" | \
xargs cat | \
awk '
/^region:.*total:/ {
split($0, parts, " ");
region = substr(parts[1], 8); # "region:" を除去
total = substr(parts[2], 7); # "total:" を除去
region_totals[region] += total;
}
/^region:.*hour:.*count:/ {
split($0, parts, " ");
region = substr(parts[1], 8);
hour = substr(parts[2], 6);
count = substr(parts[3], 7);
region_hour_counts[region][hour] += count;
}
END {
print "=== 並列処理による地域別アクセス分析 ===";
print "";
for (region in region_totals) {
printf "地域: %s (総計: %d)\n", region, region_totals[region];
printf "時間帯別詳細:\n";
for (hour = 0; hour < 24; hour++) {
count = (region SUBSEP hour in region_hour_counts) ?
region_hour_counts[region][hour] : 0;
if (count > 0) {
# 簡易グラフ表示
bar_length = int(count / 10);
if (bar_length > 50) bar_length = 50;
printf " %02d時: %5d ", hour, count;
for (i = 0; i < bar_length; i++) printf "▓";
printf "\n";
}
}
printf "\n";
}
}' > "$final_report"
# 一時ファイルクリーンアップ
find "$output_dir" -name "result_*.tmp" -delete
echo "最終レポート生成完了: $final_report"
}
# 実行例
mkdir -p /tmp/parallel_analysis
parallel_log_analysis "access.log*" "/tmp/parallel_analysis"
マルチコア並列処理でログ解析を高速化し、結果をマージ
7. 実務での活用事例
理論より実践!実際の業務でどのように使われているかを職種別に紹介します。
💻 Webエンジニアの場合
🚨 急な本番障害対応
状況:「サイトが重い」との報告。原因を素早く特定する必要がある
対応手順:
1. エラーログの確認
find /var/log/apache2 /var/log/nginx -name "*.log" | xargs grep -E "$(date '+%d/%b/%Y')" | grep -E "5[0-9][0-9]|error|timeout" | tail -50
2. 重いクエリの特定
find /var/log/mysql -name "*slow.log" | xargs grep -A 5 "Query_time" | awk '/Query_time: [5-9]/ {getline; print}'
3. 異常なアクセスパターンの検出
grep "$(date '+%d/%b/%Y')" /var/log/apache2/access.log | awk '{print $1}' | sort | uniq -c | awk '$1 > 1000 {print "異常アクセス:", $2, "回数:", $1}'
⏱️ 効果:手動での確認なら30-60分かかる作業が5分で完了
📊 月次レポート作成
状況:先月のアクセス統計とエラー率をまとめる必要がある
# アクセス統計レポート生成スクリプト
#!/bin/bash
LAST_MONTH=$(date -d "last month" '+%b/%Y')
echo "=== $LAST_MONTH アクセス統計レポート ==="
echo
# 総アクセス数
TOTAL_ACCESS=$(find /var/log/apache2 -name "access.log*" | xargs grep "$LAST_MONTH" | wc -l)
echo "総アクセス数: $TOTAL_ACCESS"
# ユニークビジター数
UNIQUE_VISITORS=$(find /var/log/apache2 -name "access.log*" | xargs grep "$LAST_MONTH" | awk '{print $1}' | sort -u | wc -l)
echo "ユニークビジター: $UNIQUE_VISITORS"
# エラー率
ERROR_COUNT=$(find /var/log/apache2 -name "access.log*" | xargs grep "$LAST_MONTH" | grep -E " [45][0-9][0-9] " | wc -l)
ERROR_RATE=$(echo "scale=2; $ERROR_COUNT * 100 / $TOTAL_ACCESS" | bc)
echo "エラー率: $ERROR_RATE%"
# 人気ページTOP10
echo -e "\n=== 人気ページ TOP10 ==="
find /var/log/apache2 -name "access.log*" | xargs grep "$LAST_MONTH" | awk '{print $7}' | grep -v "\.css\|\.js\|\.png\|\.jpg" | sort | uniq -c | sort -rn | head -10 | awk '{printf "%-50s %d回\n", $2, $1}'
⏱️ 効果:Excel作業で半日かかっていた作業が3分で自動化
🛠️ インフラエンジニアの場合
🖥️ サーバー監視・メンテナンス
状況:複数サーバーの健康状態を定期的にチェック
# サーバー健康状態チェックスクリプト
#!/bin/bash
echo "=== サーバー健康状態レポート ==="
date
echo
# ディスク使用率警告
echo "=== ディスク使用率 (80%以上で警告) ==="
df -h | awk 'NR>1 {gsub(/%/, "", $5); if($5 > 80) printf "⚠️ %s: %s使用中 (%s%%)\n", $6, $3, $5}'
# メモリ使用率
echo -e "\n=== メモリ使用状況 ==="
free -m | awk 'NR==2{printf "メモリ使用率: %.1f%% (%dMB / %dMB)\n", $3*100/$2, $3, $2}'
# 高CPU使用プロセス
echo -e "\n=== CPU使用率TOP5 ==="
ps aux --no-headers | sort -rn -k3 | head -5 | awk '{printf "%-10s %5.1f%% %s\n", $1, $3, $11}'
# エラーログの急増チェック
echo -e "\n=== 直近1時間のエラー件数 ==="
find /var/log -name "*.log" -mmin -60 | xargs grep -h -E "$(date '+%b %d %H')|$(date -d '1 hour ago' '+%b %d %H')" | grep -ci error
⏱️ 効果:手動チェックで1時間かかる作業を自動化で24時間監視
📈 データアナリストの場合
📊 大量データの前処理
状況:数GBのCSVファイルをExcelで開けない。事前に加工が必要
# 大容量CSV分析・前処理スクリプト
#!/bin/bash
CSV_FILE="sales_data_2024.csv"
OUTPUT_DIR="processed_data"
mkdir -p $OUTPUT_DIR
echo "=== 大容量CSV分析開始 ==="
# ファイルサイズ・行数確認
echo "ファイルサイズ: $(du -h "$CSV_FILE" | cut -f1)"
echo "総行数: $(wc -l < "$CSV_FILE")"
# データ品質チェック
echo -e "\n=== データ品質チェック ==="
echo "空行数: $(grep -c '^$' "$CSV_FILE")"
echo "不正な行数: $(awk -F',' 'NF != 5 {count++} END {print count+0}' "$CSV_FILE")"
# 月別データに分割
echo -e "\n=== 月別ファイル分割中... ==="
awk -F',' 'NR==1 {header=$0; next}
{
month=substr($1,1,7); # YYYY-MM部分を抽出
if(!seen[month]) {
print header > "'$OUTPUT_DIR'/sales_" month ".csv";
seen[month]=1;
}
print $0 > "'$OUTPUT_DIR'/sales_" month ".csv"
}' "$CSV_FILE"
# 各月のサマリー作成
echo -e "\n=== 月別サマリー ==="
find $OUTPUT_DIR -name "sales_*.csv" | sort | while read file; do
month=$(basename "$file" .csv | cut -d'_' -f2)
total_sales=$(awk -F',' 'NR>1 {sum+=$4} END {print sum}' "$file")
record_count=$(expr $(wc -l < "$file") - 1)
printf "%s: %'d件, 売上合計: ¥%'d\n" "$month" "$record_count" "$total_sales"
done
⏱️ 効果:数時間のExcel作業が数分で完了、メモリ不足も解決
🏭 業界別ケーススタディ:プロフェッショナル実践例
各業界の実際のプロジェクトで使われているテクニックを詳しく解説します。
🎮 ゲーム開発業界:大規模ログ解析
📋 課題
オンラインゲームで1日100GBのプレイヤー行動ログから、チート検出とゲームバランス分析を行う
💡 解決策
# ゲームログ解析パイプライン
#!/bin/bash
# 1日分のログファイルから異常行動を検出
analyze_game_logs() {
local log_date="$1"
local output_dir="/analysis/$(date +%Y%m%d)"
mkdir -p "$output_dir"
echo "=== ゲームログ解析開始: $log_date ==="
# ステップ1: プレイヤー別行動パターン分析
find /game/logs -name "*${log_date}*.log" -type f | \
xargs grep -h "PLAYER_ACTION" | \
awk -F'|' '
{
player_id = $3;
action = $4;
timestamp = $2;
value = $5;
# 異常に短時間での大量アクション検出
if (action == "LEVEL_UP") {
player_levelups[player_id]++;
if (player_levelups[player_id] > 10) {
print "SUSPICIOUS_LEVELUP", player_id, player_levelups[player_id] > "/tmp/cheat_suspects.log";
}
}
# 金額の異常な増加
if (action == "GOLD_CHANGE" && value > 1000000) {
print "SUSPICIOUS_GOLD", player_id, value, timestamp > "/tmp/gold_anomaly.log";
}
# プレイヤー別統計
player_actions[player_id]++;
total_actions++;
}
END {
# 異常にアクション数が多いプレイヤー
avg_actions = total_actions / length(player_actions);
for (player in player_actions) {
if (player_actions[player] > avg_actions * 5) {
printf "HIGH_ACTIVITY_PLAYER: %s (%d actions, avg: %.1f)\n",
player, player_actions[player], avg_actions > "/tmp/high_activity.log";
}
}
}'
# 結果マージとレポート生成
{
echo "=== ゲーム不正行為検出レポート $(date) ==="
echo ""
if [[ -s "/tmp/cheat_suspects.log" ]]; then
echo "🚨 レベルアップ異常:"
sort "/tmp/cheat_suspects.log" | uniq -c | sort -rn | head -10
echo ""
fi
if [[ -s "/tmp/gold_anomaly.log" ]]; then
echo "💰 ゴールド異常:"
sort -k3 -rn "/tmp/gold_anomaly.log" | head -10
echo ""
fi
if [[ -s "/tmp/high_activity.log" ]]; then
echo "⚡ 高活動プレイヤー:"
head -20 "/tmp/high_activity.log"
fi
} > "$output_dir/cheat_detection_report.txt"
# 一時ファイル削除
rm -f /tmp/{cheat_suspects,gold_anomaly,high_activity}.log
echo "レポート生成完了: $output_dir/cheat_detection_report.txt"
}
# 実行例: 昨日のログを解析
analyze_game_logs "$(date -d yesterday +%Y%m%d)"
100GBのゲームログから不正行為を自動検出
📊 効果
- 手動調査: 数日 → 自動化: 30分
- チート検出精度: 95%以上
- 運営工数: 80%削減
🏪 EC・小売業界:顧客行動分析
📋 課題
ECサイトのアクセスログから顧客の購買パターンを分析し、パーソナライズ施策の効果測定を行う
💡 解決策
# ECサイト顧客行動分析
#!/bin/bash
analyze_customer_journey() {
local analysis_period="$1" # YYYY-MM-DD
local output_dir="/analytics/customer_journey"
mkdir -p "$output_dir"
echo "=== 顧客ジャーニー分析: $analysis_period ==="
# セッション構築とページ遷移分析
find /var/log/nginx -name "access.log*" | \
xargs grep "$analysis_period" | \
awk '
BEGIN {
# セッション境界: 30分間隔
session_timeout = 1800;
}
{
ip = $1;
url = $7;
# セッション管理とページ遷移記録
current_time = systime();
if (current_time - last_access[ip] > session_timeout) {
session_id = ip "_" current_time;
sessions[session_id]["start_time"] = current_time;
sessions[session_id]["pages"] = 0;
}
sessions[session_id]["pages"]++;
# 購入ページアクセス検出
if (url ~ /\/checkout|\/purchase/) {
purchase_sessions[session_id] = 1;
purchase_path_length[sessions[session_id]["pages"]]++;
}
# 商品ページ閲覧パターン
if (url ~ /\/products\/([0-9]+)/) {
match(url, /\/products\/([0-9]+)/, product_match);
product_id = product_match[1];
product_views[product_id]++;
user_product_views[ip][product_id]++;
}
last_access[ip] = current_time;
}
END {
# 結果出力
print "=== セッション統計 ===";
printf "総セッション数: %d\n", length(sessions);
printf "購入完了セッション数: %d\n", length(purchase_sessions);
printf "購入率: %.2f%%\n", (length(purchase_sessions) * 100.0) / length(sessions);
print "\n=== 購入パス分析 ===";
for (length in purchase_path_length) {
printf "%dページ経由での購入: %d件\n", length, purchase_path_length[length];
}
# レコメンデーション用データ生成
print "\n=== 商品共起分析(レコメンデーション用) ===";
for (user in user_product_views) {
products_viewed = "";
for (product in user_product_views[user]) {
products_viewed = products_viewed product " ";
}
if (length(user_product_views[user]) >= 2) {
print "USER_PRODUCTS:", user, products_viewed;
}
}
}' > "$output_dir/customer_journey_${analysis_period}.txt"
echo "顧客ジャーニー分析完了: $output_dir/customer_journey_${analysis_period}.txt"
}
# 実行例: 昨日の顧客行動を分析
analyze_customer_journey "$(date -d yesterday +%Y-%m-%d)"
ECサイトの顧客行動パターンを分析しレコメンデーション用データを生成
📊 効果
- データ分析工数: 70%削減
- パーソナライズ精度: 30%向上
- リアルタイム分析が可能に
8. パフォーマンス最適化
大容量データ処理で速度と効率を最大化するテクニックを学びます。
⚡ 基本的な高速化テクニック
🌐 ロケール設定の最適化
🐌 遅い方法
grep "pattern" large_file.txt
UTF-8処理でオーバーヘッド
⚡ 高速化
LC_ALL=C grep "pattern" large_file.txt
ASCII処理で最大10倍高速化
📁 ファイルアクセスの最適化
🐌 遅い方法
find /var -name "*.log" -exec grep "ERROR" {} \;
ファイルごとに新しいプロセスを起動
⚡ 高速化
find /var -name "*.log" | xargs grep "ERROR"
一括処理で大幅な高速化
💾 メモリ効率的な処理
🐌 メモリ大量消費
awk '{lines[NR]=$0} END {for(i=1;i<=NR;i++) print lines[i]}' huge.txt
全行をメモリに読み込み
⚡ ストリーミング処理
awk '{print $0}' huge.txt
1行ずつ処理でメモリ節約
🚀 上級最適化テクニック
🔄 並列処理活用
# 複数CPUコアを活用した並列検索
find /var/log -name "*.log" -type f | \
xargs -n 1 -P $(nproc) -I {} \
bash -c 'echo "Processing: {}"; grep -c "ERROR" "{}"'
利用可能なCPUコア数だけ並列処理
📊 効率的なデータパイプライン
# メモリ効率を重視した大容量ファイル処理
stream_process_large_file() {
local input_file="$1"
local chunk_size=10000
# チャンク単位でストリーミング処理
split -l "$chunk_size" "$input_file" /tmp/chunk_
# 各チャンクを並列処理
find /tmp -name "chunk_*" | \
xargs -n 1 -P 4 -I {} \
bash -c '
chunk_file="$1"
# 高速処理(LC_ALL=C環境)
LC_ALL=C awk "
{
# 必要な処理のみ実行
if (\$0 ~ /ERROR/) error_count++;
total_lines++;
}
END {
printf \"%s: errors=%d total=%d\n\", FILENAME, error_count, total_lines;
}" "$chunk_file"
# 処理済みチャンクは即削除
rm "$chunk_file"
' -- {}
}
# 実行例
stream_process_large_file "huge_log_file.txt"
大容量ファイルをチャンク分割して並列ストリーミング処理
⚡ 正規表現の最適化
❌ 非効率な正規表現
grep -E "(error|ERROR|Error|warning|WARNING|Warning)" logfile
複雑な選択肢で処理が重い
✅ 最適化された正規表現
grep -iE "(error|warning)" logfile
大文字小文字無視オプションで簡潔に
📈 パフォーマンス測定と監視
⏱️ 処理時間の測定
# 詳細なパフォーマンス測定
benchmark_command() {
local command="$1"
local description="$2"
echo "=== $description ==="
echo "コマンド: $command"
# 時間測定
time_result=$(time (eval "$command") 2>&1)
# メモリ使用量測定
/usr/bin/time -v eval "$command" 2>&1 | grep -E "(Maximum resident set size|User time|System time)"
echo "処理完了"
echo
}
# 使用例
benchmark_command "find /var/log -name '*.log' | xargs grep -c ERROR" "従来の方法"
benchmark_command "find /var/log -name '*.log' -print0 | xargs -0 grep -c ERROR" "NULL区切り最適化"
処理時間とメモリ使用量を詳細に測定
📊 リソース使用量の監視
# リアルタイムリソース監視付き処理
monitor_and_process() {
local log_pattern="$1"
local output_file="$2"
# バックグラウンドでリソース監視開始
{
while true; do
timestamp=$(date '+%H:%M:%S')
cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)
mem_usage=$(free | grep Mem | awk '{printf "%.1f", $3/$2 * 100.0}')
echo "$timestamp: CPU ${cpu_usage}%, Memory ${mem_usage}%"
sleep 5
done
} &
monitor_pid=$!
# メイン処理実行
echo "処理開始: $(date)"
find /var/log -name "$log_pattern" | \
xargs grep -h "ERROR" | \
awk '{
error_patterns[$0]++;
total_errors++;
}
END {
printf "総エラー数: %d\n", total_errors;
printf "ユニークエラーパターン数: %d\n", length(error_patterns);
print "\n=== 頻出エラー TOP5 ===";
PROCINFO["sorted_in"] = "@val_num_desc";
count = 0;
for (pattern in error_patterns) {
printf "%s: %d回\n", pattern, error_patterns[pattern];
if (++count >= 5) break;
}
}' > "$output_file"
# 監視プロセス終了
kill $monitor_pid 2>/dev/null
echo "処理完了: $(date)"
}
# 実行例
monitor_and_process "*.log" "/tmp/error_analysis.txt"
処理実行中のCPU・メモリ使用量をリアルタイム監視