はじめに
Linuxコマンドはエンジニアにとって必須のスキルです。サーバー管理、ログ解析、デプロイ作業など、様々な場面で活用されます。
この記事では、基本コマンドから実践的なワンライナーまで、現場で即使えるテクニックを紹介します。
ただし現場で本当に差が付くのは
- 早く見つけるより先に、壊さずに調べる
- コマンドの出力を「観測」として再現可能に残す
- 一発芸ワンライナーより、定番の型を体に入れる
の部分です。
この記事はコマンドの羅列ではなく、実務の型として整理します。
まず決める判断軸
本番サーバーで安全に調査する
- まず読み取り専用の操作で状況を掴む
-
rmkillsed -iのような破壊操作は、コピペ前に一呼吸置く - 可能なら対象を絞ってから実行する(パス、ユーザー、時間範囲)
ログ解析は パイプの型 を固定する
よく使うのは次の流れです。
- 絞る(grep)
- 形を整える(awk、cut)
- 並べる(sort)
- 数える(uniq -c)
- 上位を見る(head)
迷ったら 何を知りたいか を言語化する
- どのプロセスがCPUを食っているか
- どのリクエストが遅いか
- どのIPが増えているか
目的が決まると、コマンドが自然に決まります。
事故防止チェックリスト
- 本番で破壊操作をしていない(削除、上書き、強制終了)
- 対象が絞れている(ディレクトリ、時間、ユーザー)
- コマンドと結果を作業メモに残している
- 調査用ワンライナーに機密が混ざっていない
ファイル操作の基本
ファイル・ディレクトリの操作
# ディレクトリ作成(親ディレクトリも同時に作成)
mkdir -p path/to/directory
# ファイルコピー(再帰的に、属性を保持して)
cp -rp source/ destination/
# ファイル移動・リネーム
mv oldname.txt newname.txt
# ファイル削除(確認なし、再帰的に)
rm -rf directory/
# シンボリックリンク作成
ln -s /path/to/target /path/to/link
# ファイルの中身を空にする
: > filename.txt
# または
truncate -s 0 filename.txt
ファイル検索
# ファイル名で検索
find /path -name "*.log"
# 更新日時で検索(7日以内に更新されたファイル)
find /path -mtime -7
# サイズで検索(100MB以上のファイル)
find /path -size +100M
# 検索して削除
find /tmp -name "*.tmp" -mtime +30 -delete
# 検索して実行
find . -name "*.js" -exec wc -l {} \;
# 高速なファイル検索(locateコマンド)
sudo updatedb # データベース更新
locate filename.txt
テキスト処理
grepを使いこなす
# 基本的な検索
grep "error" logfile.log
# 大文字小文字を無視
grep -i "error" logfile.log
# 行番号を表示
grep -n "error" logfile.log
# 前後の行も表示
grep -B 3 -A 3 "error" logfile.log # 前後3行
# 再帰的に検索
grep -r "TODO" ./src/
# 正規表現
grep -E "error|warning|critical" logfile.log
# マッチしない行を表示
grep -v "DEBUG" logfile.log
# ファイル名のみ表示
grep -l "pattern" *.txt
# マッチした数をカウント
grep -c "error" logfile.log
awkでデータ処理
# 特定の列を抽出(スペース区切り)
awk '{print $1, $3}' file.txt
# CSVの特定列を抽出
awk -F',' '{print $2}' data.csv
# 条件でフィルタリング
awk '$3 > 100 {print $1, $3}' data.txt
# 合計を計算
awk '{sum += $2} END {print sum}' numbers.txt
# 列の入れ替え
awk '{print $2, $1, $3}' file.txt
# 特定の行を抽出(10行目から20行目)
awk 'NR>=10 && NR<=20' file.txt
# ユニークなカウント
awk '{count[$1]++} END {for (k in count) print k, count[k]}' access.log
# IPアドレスごとのアクセス数
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -20
sedでテキスト変換
# 文字列置換(最初の1つ)
sed 's/old/new/' file.txt
# 文字列置換(すべて)
sed 's/old/new/g' file.txt
# ファイルを直接編集
sed -i 's/old/new/g' file.txt
# 特定の行を削除
sed '10d' file.txt # 10行目を削除
sed '10,20d' file.txt # 10-20行目を削除
# 特定の行だけ置換
sed '5s/old/new/' file.txt # 5行目だけ置換
# 行の先頭・末尾に追加
sed 's/^/prefix: /' file.txt # 先頭に追加
sed 's/$/ suffix/' file.txt # 末尾に追加
# 空行を削除
sed '/^$/d' file.txt
# 複数の置換を実行
sed -e 's/foo/bar/g' -e 's/baz/qux/g' file.txt
ログ解析テクニック
リアルタイム監視
# ファイルの更新をリアルタイムで表示
tail -f logfile.log
# 複数ファイルを同時に監視
tail -f *.log
# 特定のパターンをハイライト
tail -f logfile.log | grep --color=auto -E "error|warning|$"
# 更新を監視しながらフィルタ
tail -f logfile.log | grep -E "ERROR|CRITICAL"
ログ解析ワンライナー
# エラーの出現回数をカウント
grep -c "ERROR" application.log
# 時間帯別のエラー数
grep "ERROR" application.log | awk '{print $1, $2}' | cut -d':' -f1-2 | uniq -c
# ステータスコード別のカウント
awk '{print $9}' access.log | sort | uniq -c | sort -rn
# 最もアクセスの多いURL
awk '{print $7}' access.log | sort | uniq -c | sort -rn | head -20
# レスポンスタイムの平均
awk '{sum += $NF; count++} END {print sum/count}' access.log
# 特定時間帯のログを抽出
awk '$4 >= "[01/Jan/2024:10:00:00" && $4 <= "[01/Jan/2024:11:00:00"' access.log
# エラーログをJSON形式に変換
grep "ERROR" app.log | awk '{print "{\"time\": \"" $1 "\", \"message\": \"" $0 "\"}"}'
プロセス管理
プロセスの確認
# 全プロセスを表示
ps aux
# 特定のプロセスを検索
ps aux | grep nginx
# ツリー形式で表示
ps auxf
# または
pstree -p
# リアルタイムでプロセス監視
top
# より高機能な監視(インストール必要)
htop
# メモリ使用量順にソート
ps aux --sort=-%mem | head -20
# CPU使用量順にソート
ps aux --sort=-%cpu | head -20
プロセス制御
# プロセスを終了
kill PID
kill -9 PID # 強制終了
# 名前でプロセスを終了
pkill -f "python script.py"
killall nginx
# バックグラウンド実行
command &
# nohupで実行(ログアウト後も継続)
nohup command > output.log 2>&1 &
# screenセッション
screen -S session_name # 新規セッション
screen -r session_name # 再接続
screen -ls # セッション一覧
# tmuxセッション
tmux new -s session_name # 新規セッション
tmux attach -t session_name # 再接続
tmux ls # セッション一覧
ネットワーク操作
接続確認
# 疎通確認
ping -c 4 google.com
# ポートの接続確認
nc -zv hostname 80
telnet hostname 80
# DNS確認
nslookup domain.com
dig domain.com
# ルーティング確認
traceroute google.com
# または
mtr google.com
# 開いているポートを確認
netstat -tlnp
ss -tlnp
# 特定ポートを使用しているプロセス
lsof -i :8080
HTTPリクエスト
# GETリクエスト
curl https://api.example.com/users
# POSTリクエスト
curl -X POST -H "Content-Type: application/json" \
-d '{"name": "test"}' \
https://api.example.com/users
# ヘッダーを表示
curl -I https://example.com
# 認証付きリクエスト
curl -u username:password https://api.example.com
# ファイルをダウンロード
curl -O https://example.com/file.zip
wget https://example.com/file.zip
# レスポンスタイムを計測
curl -w "@curl-format.txt" -o /dev/null -s https://example.com
# curl-format.txt
time_namelookup: %{time_namelookup}s\n
time_connect: %{time_connect}s\n
time_appconnect: %{time_appconnect}s\n
time_pretransfer: %{time_pretransfer}s\n
time_redirect: %{time_redirect}s\n
time_starttransfer: %{time_starttransfer}s\n
----------\n
time_total: %{time_total}s\n
ディスク・メモリ管理
ディスク使用量
# ディスク使用量の確認
df -h
# ディレクトリのサイズ確認
du -sh /path/to/directory
# サブディレクトリごとのサイズ
du -h --max-depth=1 /path
# 大きいファイルを探す
find / -type f -size +100M 2>/dev/null | head -20
# サイズ順にソート
du -h --max-depth=1 | sort -hr
# inode使用量
df -i
メモリ確認
# メモリ使用量
free -h
# 詳細なメモリ情報
cat /proc/meminfo
# キャッシュをクリア(rootで実行)
sync; echo 3 > /proc/sys/vm/drop_caches
# スワップ使用量
swapon -s
圧縮・解凍
# tar.gz
tar -czvf archive.tar.gz directory/ # 圧縮
tar -xzvf archive.tar.gz # 解凍
# tar.bz2
tar -cjvf archive.tar.bz2 directory/
tar -xjvf archive.tar.bz2
# zip
zip -r archive.zip directory/
unzip archive.zip
# gzip
gzip file.txt # 圧縮(元ファイルは削除される)
gunzip file.txt.gz # 解凍
gzip -k file.txt # 元ファイルを保持
# 圧縮ファイルの中身を確認
tar -tzvf archive.tar.gz
zipinfo archive.zip
# 圧縮しながらパイプ処理
mysqldump database | gzip > backup.sql.gz
zcat backup.sql.gz | mysql database
SSH活用
基本操作
# 接続
ssh user@hostname
# 鍵認証
ssh -i ~/.ssh/id_rsa user@hostname
# ポート指定
ssh -p 2222 user@hostname
# コマンド実行
ssh user@hostname "ls -la"
# ポートフォワーディング(ローカル)
ssh -L 8080:localhost:80 user@hostname
# ポートフォワーディング(リモート)
ssh -R 8080:localhost:80 user@hostname
# プロキシジャンプ
ssh -J jumphost user@destination
SSH設定ファイル
# ~/.ssh/config
Host myserver
HostName 192.168.1.100
User admin
Port 22
IdentityFile ~/.ssh/id_rsa
Host production
HostName prod.example.com
User deploy
ProxyJump bastion
Host bastion
HostName bastion.example.com
User admin
# 設定後は簡単に接続できる
ssh myserver
ssh production
ファイル転送
# ローカル→リモート
scp file.txt user@hostname:/path/to/destination/
# リモート→ローカル
scp user@hostname:/path/to/file.txt ./
# ディレクトリごと転送
scp -r directory/ user@hostname:/path/
# rsyncで差分同期
rsync -avz --progress source/ user@hostname:/destination/
# rsyncで削除も同期
rsync -avz --delete source/ user@hostname:/destination/
実践的なワンライナー
システム管理
# 現在のディレクトリの行数カウント
find . -name "*.py" | xargs wc -l | tail -1
# 重複ファイルを検索
find . -type f -exec md5sum {} \; | sort | uniq -w32 -D
# 最近更新されたファイル
find . -type f -mmin -60 -ls
# ディスク使用量トップ10
du -ah . | sort -rh | head -10
# システム起動時間
uptime
# 最後のリブート時刻
who -b
開発作業
# Gitリポジトリ内のTODOを検索
grep -rn "TODO\|FIXME" --include="*.py" .
# 特定のポートを使用しているプロセスを終了
kill $(lsof -t -i:3000)
# node_modulesを一括削除
find . -name "node_modules" -type d -prune -exec rm -rf {} +
# すべてのブランチで特定の文字列を検索
git branch -a | xargs -I {} git log {} --oneline --grep="keyword"
# 変更されたファイルだけをコピー
rsync -avz --files-from=<(git diff --name-only HEAD~1) . destination/
# JSONを整形
cat data.json | python -m json.tool
# または
cat data.json | jq '.'
# CSVの特定列を抽出
cut -d',' -f1,3 data.csv
監視・デバッグ
# ファイルの変更を監視
inotifywait -m -r -e modify,create,delete ./src/
# システムコールをトレース
strace -f -p PID
# ネットワークトラフィックをキャプチャ
tcpdump -i eth0 port 80
# 定期的にコマンドを実行
watch -n 5 'df -h'
# 特定の条件でアラート
tail -f logfile.log | grep --line-buffered "ERROR" | while read line; do
echo "$line" | mail -s "Error Alert" admin@example.com
done
シェルスクリプトの基本
よく使う構文
#!/bin/bash
# 変数
NAME="value"
echo $NAME
# コマンドの結果を変数に
TODAY=$(date +%Y-%m-%d)
# 条件分岐
if [ -f "$FILE" ]; then
echo "File exists"
elif [ -d "$FILE" ]; then
echo "Directory exists"
else
echo "Not found"
fi
# ループ
for file in *.txt; do
echo "Processing $file"
done
# while ループ
while read line; do
echo "$line"
done < input.txt
# 関数
function greet() {
echo "Hello, $1!"
}
greet "World"
# エラーハンドリング
set -e # エラーで即終了
set -u # 未定義変数でエラー
set -o pipefail # パイプのエラーを検知
# トラップ(終了時の処理)
trap 'echo "Script interrupted"; exit 1' INT TERM
trap 'rm -f $TMPFILE' EXIT
実用的なスクリプト例
#!/bin/bash
# バックアップスクリプト
BACKUP_DIR="/backup"
SOURCE_DIR="/var/www"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/backup_$DATE.tar.gz"
# バックアップ作成
tar -czf "$BACKUP_FILE" "$SOURCE_DIR"
# 古いバックアップを削除(7日以上前)
find "$BACKUP_DIR" -name "backup_*.tar.gz" -mtime +7 -delete
echo "Backup completed: $BACKUP_FILE"
#!/bin/bash
# デプロイスクリプト
set -e
APP_DIR="/var/www/app"
REPO_URL="git@github.com:user/repo.git"
BRANCH="${1:-main}"
echo "Deploying $BRANCH..."
cd "$APP_DIR"
git fetch origin
git checkout "$BRANCH"
git pull origin "$BRANCH"
npm install
npm run build
sudo systemctl restart app
echo "Deploy completed!"
まとめ
| カテゴリ | よく使うコマンド |
|---|---|
| ファイル操作 |
find, cp, mv, rm, ln
|
| テキスト処理 |
grep, awk, sed, cut, sort, uniq
|
| ログ解析 |
tail -f, grep, awk
|
| プロセス管理 |
ps, top, kill, nohup, screen
|
| ネットワーク |
curl, netstat, ss, lsof
|
| SSH |
ssh, scp, rsync
|
これらのコマンドを組み合わせることで、複雑な作業も効率的に処理できます。まずは基本コマンドをしっかり覚え、徐々にワンライナーやスクリプトにステップアップしていきましょう!