strace
デバッグツール
strace
概要
straceは、Linuxのシステムコールトレーサーです。プログラムが実行するシステムコールとシグナルを監視し、システムレベルのデバッグに使用される強力なツールです。
詳細
strace(system call trace)は、1991年にLinuxに移植されて以来、Unix系システムにおけるシステムレベルデバッグの定番ツールとして発展してきました。プログラムの実行中に呼び出される全てのシステムコール、受信するシグナル、およびそれらの引数と戻り値をリアルタイムで監視・記録します。ptrace(2)システムコールを使用してターゲットプロセスにアタッチし、カーネルとユーザースペース間のインターフェースを詳細に分析できます。
straceの強力な機能は、アプリケーションの「ブラックボックス」的な動作を可視化することです。ソースコードが利用できない場合や、複雑なライブラリ間の相互作用を理解したい場合に特に有効です。ファイルシステムアクセス、ネットワーク通信、プロセス間通信(IPC)、メモリ管理、時間管理など、オペレーティングシステムとの全ての相互作用を追跡できます。
現代のコンテナ環境やマイクロサービス アーキテクチャにおいて、straceの重要性はさらに増しています。Dockerコンテナ内でのアプリケーション動作の分析、Kubernetesポッド間の通信問題の特定、サーバーレス環境でのリソースアクセス パターンの調査など、クラウドネイティブ環境でのトラブルシューティングに欠かせないツールとなっています。
また、セキュリティ分析の観点からも重要で、不審なプロセスの動作解析、権限昇格の検出、ファイルアクセス パターンの監査などに活用されています。パフォーマンス分析においても、システムコールの頻度や実行時間を測定することで、アプリケーションのボトルネック特定に役立ちます。
メリット・デメリット
メリット
- 包括的な監視: 全システムコールの詳細な追跡
- ソースコード不要: バイナリのみでも動作解析可能
- リアルタイム分析: 実行中のプロセスの即座な監視
- 軽量: システムへの影響が比較的小さい
- 豊富なフィルタリング: 特定のシステムコールやファイルに絞った分析
- 標準搭載: ほとんどのLinux ディストリビューションに含まれる
- セキュリティ分析: 不審な動作パターンの検出
- コンテナ対応: Docker/Kubernetes環境での問題調査
デメリット
- Linux限定: 主にLinux環境でのみ利用可能
- パフォーマンス影響: 大量のシステムコール発生時の性能低下
- 出力量の多さ: 詳細な情報による分析の複雑化
- 学習コスト: システムコールの理解が必要
- 権限要件: 一部の機能で管理者権限が必要
- プライバシー: 機密情報がトレース出力に含まれる可能性
- マルチスレッド: 複雑な並行処理の分析が困難
主要リンク
- strace公式サイト
- strace GitHubリポジトリ
- Linux Manual Page - strace(1)
- The Definitive Guide to Linux System Calls
- Using strace for debugging
- strace cookbook
書き方の例
基本的なstrace使用
# 基本的な使用方法
strace ls
# 特定のプログラムをtraceしながら実行
strace ./myprogram
# 引数付きプログラムのtrace
strace ./myprogram arg1 arg2
# 実行中のプロセスにアタッチ
strace -p <PID>
# 出力をファイルに保存
strace -o trace.log ./myprogram
# システムコール実行時間の測定
strace -T ./myprogram
# システムコール統計情報
strace -c ./myprogram
ファイルシステム操作の分析
# ファイル操作のみを追跡
strace -e trace=file ls /etc
# 特定のファイルへのアクセスを追跡
strace -e trace=openat,read,write cat /etc/passwd
# ファイル記述子の動作を詳細に追跡
strace -e trace=open,close,read,write,lseek ./file_processor
# ディレクトリ操作の追跡
strace -e trace=openat,getdents64 find /var/log -name "*.log"
# ファイルパーミッション関連のシステムコール
strace -e trace=access,stat,fstat,chmod,chown ls -la
# サンプルファイル処理プログラムのtrace例
# C言語サンプル: file_example.c
/*
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
int fd = open("test.txt", O_CREAT | O_WRONLY, 0644);
write(fd, "Hello, World!", 13);
close(fd);
fd = open("test.txt", O_RDONLY);
char buffer[100];
read(fd, buffer, 13);
close(fd);
return 0;
}
*/
# コンパイルと実行
gcc -o file_example file_example.c
strace -e trace=openat,write,read,close ./file_example
ネットワーク通信の分析
# ネットワーク関連システムコールの追跡
strace -e trace=network curl https://example.com
# ソケット操作の詳細追跡
strace -e trace=socket,connect,send,recv,close wget https://example.com
# DNS解決の追跡
strace -e trace=openat,connect,sendto,recvfrom nslookup google.com
# TCPサーバーの動作分析
strace -e trace=socket,bind,listen,accept,read,write ./tcp_server
# UDPパケットの送受信追跡
strace -e trace=socket,sendto,recvfrom ./udp_client
# サンプルネットワークプログラムのtrace
# Python HTTP クライアント例
python3 -c "
import urllib.request
response = urllib.request.urlopen('http://httpbin.org/json')
data = response.read()
print(f'Received {len(data)} bytes')
" &
# 上記プロセスの追跡
strace -p $! -e trace=network
プロセス・スレッド操作の分析
# プロセス作成・終了の追跡
strace -e trace=clone,fork,vfork,execve,exit,wait4 ./multi_process_app
# スレッド操作の追跡
strace -e trace=clone,futex,mmap,munmap ./multi_threaded_app
# シグナル処理の追跡
strace -e trace=signal,rt_sigaction,rt_sigprocmask,kill ./signal_handler
# 子プロセスも含めて追跡
strace -f ./parent_process
# サンプルマルチプロセスプログラム
# bash スクリプト例
#!/bin/bash
echo "Parent process starting"
sleep 1 &
CHILD_PID=$!
echo "Child process PID: $CHILD_PID"
wait $CHILD_PID
echo "Parent process ending"
# 実行とtrace
chmod +x multi_process.sh
strace -f -e trace=clone,wait4,execve ./multi_process.sh
メモリ管理の分析
# メモリ操作の追跡
strace -e trace=mmap,munmap,brk,mprotect ./memory_intensive_app
# 動的メモリ割り当ての分析
strace -e trace=brk,mmap,munmap ./malloc_example
# 共有メモリの使用追跡
strace -e trace=shmget,shmat,shmdt ./shared_memory_app
# サンプルメモリ操作プログラム
# C言語例: memory_example.c
/*
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
// 動的メモリ割り当て
char *buffer1 = malloc(1024);
strcpy(buffer1, "Hello, World!");
// 大きなメモリ割り当て
char *buffer2 = malloc(1024 * 1024); // 1MB
memset(buffer2, 'A', 1024 * 1024);
free(buffer1);
free(buffer2);
return 0;
}
*/
gcc -o memory_example memory_example.c
strace -e trace=brk,mmap,munmap ./memory_example
高度なフィルタリングと分析
# 複数システムコールの同時追跡
strace -e trace=openat,read,write,close,mmap ./complex_app
# 特定のファイルパスへのアクセスのみ追跡
strace -e trace=openat -e write=1 ./app 2>&1 | grep "/etc/"
# エラーが発生したシステムコールのみ表示
strace -e trace=all -e error=all ./app
# システムコール引数の詳細表示
strace -v -s 200 ./string_processor
# 実行時間の詳細測定
strace -T -tt ./performance_test
# システムコール統計とソート
strace -c -S time ./benchmark_app # 時間順
strace -c -S calls ./benchmark_app # 呼び出し回数順
# 関数呼び出し結果の詳細表示
strace -e trace=openat -e verbose=openat -e abbrev=none ./file_app
Docker コンテナ内でのstrace
# Dockerコンテナ内でのstrace実行
docker run --cap-add=SYS_PTRACE -it ubuntu:20.04 bash
# コンテナ内でstraceを使用
apt update && apt install -y strace
strace ls /etc
# ホストからコンテナプロセスをtrace
# 1. コンテナのPIDを取得
docker inspect --format='{{.State.Pid}}' container_name
# 2. ホストからコンテナプロセスにアタッチ
strace -p <container_pid>
# Docker Compose環境での使用例
# docker-compose.yml
version: '3.8'
services:
app:
image: myapp:latest
cap_add:
- SYS_PTRACE # strace使用に必要
volumes:
- ./logs:/logs
command: strace -o /logs/app_trace.log ./myapp
Kubernetes環境でのstrace
# k8s-debug-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: debug-pod
spec:
containers:
- name: debug
image: ubuntu:20.04
command: ["/bin/sleep", "3600"]
securityContext:
capabilities:
add:
- SYS_PTRACE # strace使用に必要
volumeMounts:
- name: proc
mountPath: /host/proc
readOnly: true
volumes:
- name: proc
hostPath:
path: /proc
# Kubernetesでのデバッグ手順
kubectl apply -f k8s-debug-pod.yaml
kubectl exec -it debug-pod -- bash
# デバッグポッド内でstrace使用
apt update && apt install -y strace procps
ps aux # ターゲットプロセスを特定
strace -p <target_pid>
パフォーマンス分析とボトルネック特定
# システムコール実行回数と時間の分析
strace -c -T ./performance_app
# 遅いシステムコールの特定
strace -T ./slow_app 2>&1 | grep -E '\<[0-9]+\.[0-9]{6}\>'
# 特定のシステムコールの詳細分析
strace -e trace=read,write -T ./io_intensive_app
# ファイルI/O パフォーマンス分析
strace -e trace=openat,read,write,close -T ./file_io_test | \
awk '/read|write/ {print $NF, $1}' | sort -n
# サンプルI/O集約的プログラム
# Python例: io_test.py
import time
import os
def io_benchmark():
# 大量の小さなファイル操作
for i in range(100):
with open(f'test_{i}.txt', 'w') as f:
f.write(f'Content {i}' * 100)
# ファイル読み取り
for i in range(100):
with open(f'test_{i}.txt', 'r') as f:
content = f.read()
# ファイル削除
for i in range(100):
os.unlink(f'test_{i}.txt')
if __name__ == '__main__':
io_benchmark()
# 実行とパフォーマンス分析
python3 io_test.py # 通常実行で時間測定
strace -c -T python3 io_test.py # システムコール統計
セキュリティ分析での使用
# 疑わしいプロセスの監視
strace -p <suspicious_pid> -o security_trace.log
# ファイルアクセス パターンの監査
strace -e trace=openat,unlink,rename -f ./security_sensitive_app
# ネットワーク接続の監視
strace -e trace=connect,sendto -f ./network_app
# 権限昇格の検出
strace -e trace=setuid,setgid,setresuid,setresgid ./privilege_app
# システムコール異常パターンの検出例
# 不正なファイルアクセスの検出
strace -e trace=openat ./app 2>&1 | grep -E '/etc/shadow|/etc/passwd'
# 異常なネットワーク接続の検出
strace -e trace=connect ./app 2>&1 | grep -E '443|80|22'
自動化とスクリプト化
#!/bin/bash
# strace_analyzer.sh - strace出力の自動分析スクリプト
APP_NAME="$1"
TRACE_FILE="/tmp/strace_${APP_NAME}_$(date +%Y%m%d_%H%M%S).log"
echo "Starting strace analysis for $APP_NAME"
# straceの実行
strace -f -T -o "$TRACE_FILE" "$@"
echo "Trace saved to: $TRACE_FILE"
# 基本統計
echo "=== System Call Statistics ==="
grep -E '^[0-9]+' "$TRACE_FILE" | \
awk '{print $2}' | cut -d'(' -f1 | sort | uniq -c | sort -nr | head -10
# エラーの検出
echo "=== Errors Detected ==="
grep -E 'ENOENT|EACCES|EPERM|EINVAL' "$TRACE_FILE" | head -5
# 遅いシステムコールの検出
echo "=== Slow System Calls (>100ms) ==="
grep -E '\<[0-9]*\.[1-9][0-9]{5}\>' "$TRACE_FILE" | head -5
# ファイルアクセス パターン
echo "=== File Access Patterns ==="
grep 'openat' "$TRACE_FILE" | grep -o '"[^"]*"' | sort | uniq -c | sort -nr | head -10
echo "Analysis complete. Full trace: $TRACE_FILE"
# 使用例
chmod +x strace_analyzer.sh
./strace_analyzer.sh myapp ./myapp --config config.json