- Authors

- Name
- Youngju Kim
- @fjvbn20031
1. なぜLinuxコマンドラインなのか?
開発者(かいはつしゃ)がGUIの代(か)わりにターミナルを使(つか)うべき理由(りゆう)は明確(めいかく)です。速度(そくど)、自動化(じどうか)、リモートサーバーアクセス。クラウドサーバーの90%以上がLinuxを使用しており、CI/CDパイプラインはすべてCLIベースです。コマンドラインを知(し)らなければサーバーでは何(なに)もできません。
この記事で扱う内容
- ファイルシステム探索と操作コマンド20種
- テキスト処理の三銃士:grep、awk、sed 実践例
- プロセスとサービス管理
- ネットワークデバッグとSSHマスター
- Bashスクリプティング基礎から実践まで
- tmuxとVim必須使用法
- システム監視とトラブルシューティング
2. ファイルシステム探索(Navigation)
2.1 基本探索コマンド
# 現在のディレクトリを確認
pwd
# /home/developer/projects
# ディレクトリ移動
cd /var/log # 絶対パス
cd ../config # 相対パス
cd ~ # ホームディレクトリ
cd - # 前のディレクトリ
# ディレクトリの内容を確認
ls -la # 隠しファイルを含む詳細リスト
ls -lhS # ファイルサイズ順でソート(読みやすい単位)
ls -lt # 更新日時順でソート
ls -R # 再帰的リスト
2.2 ファイル検索
# find: ディレクトリツリーでファイル検索
find /var/log -name "*.log" -mtime -7 # 7日以内に変更された.logファイル
find . -type f -size +100M # 100MB以上のファイル
find . -name "*.tmp" -exec rm -f {} \; # .tmpファイルを見つけて削除
find . -type f -name "*.js" ! -path "*/node_modules/*" # node_modules除外
# locate: インデックスベースの高速検索
sudo updatedb # データベース更新
locate nginx.conf # 高速ファイル検索
# which / whereis: 実行ファイルの場所
which python3 # /usr/bin/python3
whereis nginx # バイナリ、ソース、マニュアルの場所
# tree: ディレクトリ構造の視覚化
tree -L 2 -I "node_modules|.git" # 2階層、特定ディレクトリ除外
2.3 ディレクトリ管理
# ディレクトリ作成
mkdir -p project/src/components # 中間ディレクトリを自動作成
# ディレクトリスタックの活用
pushd /etc/nginx # 現在の位置を保存して移動
# ... 作業実行 ...
popd # 保存した位置に復帰
dirs -v # スタック確認
3. ファイル操作(File Manipulation)
3.1 コピー、移動、削除
# コピー
cp -r src/ backup/ # ディレクトリを再帰コピー
cp -p important.conf important.conf.bak # 権限/タイムスタンプを保持
# 移動/リネーム
mv old_name.txt new_name.txt # 名前変更
mv *.log /var/log/archive/ # 複数ファイルの移動
# 削除(注意!)
rm -rf build/ # ディレクトリの強制削除(要注意)
rm -i *.tmp # 削除前に確認
# 安全な代替手段
trash-put file.txt # ゴミ箱に移動(trash-cliパッケージ)
3.2 ファイル権限と所有権
# 権限変更
chmod 755 script.sh # rwxr-xr-x
chmod +x deploy.sh # 実行権限を追加
chmod -R 644 public/ # 再帰的に権限変更
# 所有権変更
chown www-data:www-data /var/www # オーナー:グループを変更
chown -R developer: project/ # 再帰的にオーナー変更
# 権限の数字を理解する
# r(4) + w(2) + x(1) = 7(オーナー)
# r(4) + x(1) = 5(グループ)
# r(4) + x(1) = 5(その他)
# 結果: 755
3.3 リンクとアーカイブ
# シンボリックリンク(ショートカット)
ln -s /usr/local/bin/python3.11 /usr/local/bin/python
ls -la /usr/local/bin/python # リンク確認
# ハードリンク
ln original.txt hardlink.txt # 同じinodeを共有
# アーカイブと圧縮
tar -czf backup.tar.gz project/ # gzip圧縮アーカイブ作成
tar -xzf backup.tar.gz # 解凍
tar -xjf archive.tar.bz2 # bzip2圧縮の解凍
zip -r project.zip project/ -x "*/node_modules/*" # node_modules除外でzip
unzip project.zip -d /tmp/ # 特定ディレクトリに解凍
4. テキスト処理(しょり)の三銃士(さんじゅうし):grep、awk、sed
4.1 grep - パターン検索
# 基本検索
grep "ERROR" /var/log/syslog # ERRORを含む行を検索
grep -i "warning" app.log # 大文字小文字を無視
grep -r "TODO" src/ --include="*.py" # Pythonファイルで再帰検索
grep -n "function" script.js # 行番号を表示
# 正規表現
grep -E "^[0-9]{4}-[0-9]{2}" access.log # 日付パターンで始まる行
grep -P "\d+\.\d+\.\d+\.\d+" access.log # IPアドレスパターン(Perl正規表現)
grep -v "^#" config.ini # コメント除外
# 実践:ログのエラーコンテキストを確認
grep -B 3 -A 5 "Exception" app.log # エラー前後の行を含む
# 実践:特定のHTTPステータスコードを抽出
grep -oP 'HTTP/\d\.\d" \K5\d{2}' access.log | sort | uniq -c | sort -rn
4.2 awk - テキスト処理プログラミング
# フィールド抽出
awk '{print $1, $4}' access.log # 1番目と4番目のフィールドを出力
awk -F: '{print $1, $3}' /etc/passwd # 区切り文字を指定
# 条件フィルタリング
awk '$9 >= 500' access.log # HTTP 5xxエラーのみ
awk '$3 > 1000 {print $1, $3}' data.txt # 3番目のフィールドが1000超過
# 計算
awk '{sum += $5} END {print "Total:", sum}' sales.txt # 合計
awk '{sum += $1; n++} END {print sum/n}' numbers.txt # 平均
# 実践:ログからIP別リクエスト数をカウント
awk '{print $1}' access.log | sort | uniq -c | sort -rn | head -20
# 実践:CSV処理
awk -F',' '{
if ($3 > 100) {
total += $3
count++
}
}
END {
printf "Average: %.2f\n", total/count
}' sales.csv
# 実践:特定時間帯のログをフィルタリング
awk '/2026-03-23 14:[0-5][0-9]/' application.log
4.3 sed - ストリームエディタ
# 文字列置換
sed 's/old/new/g' file.txt # すべてのoldをnewに
sed -i 's/localhost/0.0.0.0/g' config.yml # ファイルを直接修正(-i)
sed -i.bak 's/debug/info/g' app.conf # バックアップを作成して修正
# 行の削除
sed '/^$/d' file.txt # 空行を削除
sed '/^#/d' config.ini # コメント行を削除
sed '1,5d' file.txt # 1-5行目を削除
# 行の追加/挿入
sed '3a\New line after line 3' file.txt # 3行目の後に追加
sed '1i\Header Line' file.txt # 1行目の前に挿入
# 実践:設定ファイルから特定ブロックを抽出
sed -n '/\[database\]/,/\[/p' config.ini
# 実践:複数の置換を一度に
sed -e 's/foo/bar/g' -e 's/baz/qux/g' -e '/^$/d' input.txt
4.4 その他(た)のテキストツール
# cut: フィールドの切り出し
cut -d: -f1,3 /etc/passwd # 区切り文字でフィールド抽出
cut -c1-10 file.txt # 文字位置で抽出
# sortとuniq
sort -t: -k3 -n /etc/passwd # 3番目のフィールドで数値ソート
sort -u file.txt # ソート + 重複除去
uniq -c sorted.txt # 重複回数をカウント
# wc: カウント
wc -l *.py # ファイルごとの行数
find . -name "*.java" | xargs wc -l | tail -1 # Java全体の行数
# head / tail
head -20 file.txt # 最初の20行
tail -f /var/log/syslog # リアルタイムログ監視
tail -f app.log | grep --line-buffered "ERROR" # リアルタイムエラーフィルタリング
# diff: ファイル比較
diff -u old.conf new.conf # 統合diff形式
diff -rq dir1/ dir2/ # ディレクトリ比較(異なるファイルのみ)
# tr: 文字変換
echo "Hello World" | tr 'A-Z' 'a-z' # 小文字変換
cat file.txt | tr -d '\r' # Windowsの改行を除去
# xargs: パイプの結果を引数として渡す
find . -name "*.log" | xargs gzip # 見つかったファイルを圧縮
cat urls.txt | xargs -P 4 -I {} curl -sO {} # 4つ並列ダウンロード
5. プロセス管理(かんり)
5.1 プロセスの確認
# ps: プロセスリスト
ps aux # 全プロセス
ps aux | grep nginx # 特定プロセスの検索
ps -ef --forest # プロセスツリー
# top / htop: リアルタイム監視
top -o %MEM # メモリ使用量順
htop # インタラクティブ監視(より直感的)
# pgrep / pidof: PIDの検索
pgrep -f "python app.py" # 名前でPIDを検索
pidof nginx # プロセスPIDの確認
5.2 プロセス制御
# kill: プロセスの終了
kill -15 1234 # SIGTERM(正常終了リクエスト)
kill -9 1234 # SIGKILL(強制終了)
killall nginx # 名前で全プロセスを終了
pkill -f "node server" # パターンマッチで終了
# バックグラウンド実行
nohup python server.py > output.log 2>&1 & # ログアウトしても維持
disown %1 # 現在のシェルから分離
# jobs: バックグラウンドジョブ管理
jobs -l # 現在のシェルのバックグラウンドジョブ
fg %1 # フォアグラウンドに切り替え
bg %1 # バックグラウンドで続行
5.3 systemdサービス管理
# サービスの状態確認/制御
sudo systemctl status nginx # 状態確認
sudo systemctl start nginx # 起動
sudo systemctl stop nginx # 停止
sudo systemctl restart nginx # 再起動
sudo systemctl reload nginx # 設定リロード(無停止)
sudo systemctl enable nginx # ブート時に自動起動
# サービスログの確認
journalctl -u nginx -f # リアルタイムログ
journalctl -u nginx --since "1 hour ago" # 最近1時間のログ
journalctl -u nginx --no-pager -n 100 # 最近100行
journalctl -p err -b # 現在の起動のエラーログのみ
# サービスファイルの場所を確認
systemctl show nginx -p FragmentPath
6. ネットワークコマンド
6.1 HTTPリクエストとダウンロード
# curl: HTTPリクエスト
curl -s https://api.example.com/data # 基本GET
curl -X POST -H "Content-Type: application/json" \
-d '{"name":"test"}' https://api.example.com/users
curl -o file.zip https://example.com/file.zip # ファイルダウンロード
curl -I https://example.com # ヘッダーのみ確認
curl -w "@curl-format.txt" -o /dev/null -s https://example.com # レスポンス時間測定
# wget: ファイルダウンロード
wget -c https://example.com/large-file.iso # 再開ダウンロード
wget -r -np -l 2 https://example.com/docs/ # 再帰ダウンロード(2階層)
6.2 ネットワーク診断
# 接続確認
ss -tlnp # オープンTCPポートの確認
ss -tlnp | grep :8080 # 特定ポートを使用するプロセス
netstat -tulpn # netstatの代替(レガシー)
# DNS照会
dig example.com # DNS照会
dig +short example.com A # 簡単なAレコード照会
dig @8.8.8.8 example.com # 特定DNSサーバーで照会
nslookup example.com # 簡単なDNS照会
# 経路追跡
traceroute example.com # ネットワーク経路の追跡
mtr example.com # リアルタイムtraceroute + ping
# ファイアウォール(iptables / nftables)
sudo iptables -L -n -v # 現在のルールを確認
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT # HTTPポートを許可
sudo iptables -A INPUT -s 192.168.1.0/24 -j ACCEPT # 特定サブネットを許可
# ネットワークインターフェース
ip addr show # IPアドレスの確認
ip route show # ルーティングテーブル
7. SSHをマスターする
7.1 SSHの基本と設定
# SSHキーの生成
ssh-keygen -t ed25519 -C "dev@example.com"
# 公開鍵のコピー
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server
# SSH接続
ssh user@192.168.1.100
ssh -p 2222 user@server # 特定ポート
SSH設定ファイルで接続を便利に管理できます。
# ~/.ssh/config
Host production
HostName 10.0.1.50
User deploy
Port 22
IdentityFile ~/.ssh/prod_key
ForwardAgent yes
Host staging
HostName 10.0.2.50
User deploy
IdentityFile ~/.ssh/staging_key
Host bastion
HostName bastion.example.com
User admin
IdentityFile ~/.ssh/bastion_key
Host internal-*
ProxyJump bastion
User developer
7.2 SSHトンネリング
# ローカルポートフォワーディング:リモートサービスにローカルからアクセス
# ローカル5432ポート -> リモートサーバーのDB(5432)に接続
ssh -L 5432:db-server:5432 bastion-server
# リバースポートフォワーディング:ローカルサービスをリモートからアクセス
# リモートの8080 -> ローカルの3000
ssh -R 8080:localhost:3000 remote-server
# ダイナミックポートフォワーディング(SOCKSプロキシ)
ssh -D 1080 proxy-server
# 実践:複数のトンネルを一度に
ssh -L 5432:db:5432 -L 6379:redis:6379 -L 9200:elastic:9200 bastion
7.3 ファイル転送
# scp: シンプルなファイル転送
scp local-file.txt user@server:/remote/path/
scp -r local-dir/ user@server:/remote/path/
scp user@server:/remote/file.txt ./local/
# rsync: 効率的な同期(変更分のみ転送)
rsync -avz --progress local/ user@server:/remote/
rsync -avz --delete local/ user@server:/remote/ # ソースにないファイルを削除
rsync -avz --exclude "node_modules" --exclude ".git" \
project/ user@server:/deploy/
8. Bashスクリプティング
8.1 基本構文
#!/bin/bash
set -euo pipefail # エラー発生時に即座に中断、未宣言変数の使用防止
# 変数
APP_NAME="my-app"
VERSION="1.0.0"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
# 文字列操作
echo "App: $APP_NAME, Version: $VERSION"
echo "Length: ${#APP_NAME}" # 文字列の長さ
echo "${APP_NAME^^}" # 大文字変換(MY-APP)
echo "${APP_NAME/my/your}" # 置換(your-app)
8.2 条件文とループ
#!/bin/bash
# 条件文
if [ -f "/etc/nginx/nginx.conf" ]; then
echo "Nginx config exists"
elif [ -f "/etc/apache2/apache2.conf" ]; then
echo "Apache config exists"
else
echo "No web server config found"
fi
# ファイルテスト演算子
# -f: ファイルが存在
# -d: ディレクトリが存在
# -r: 読み取り権限
# -w: 書き込み権限
# -x: 実行権限
# -s: ファイルサイズが0より大きい
# forループ
for server in web1 web2 web3; do
echo "Deploying to $server..."
ssh "$server" "cd /app && git pull && systemctl restart app"
done
# ファイルリストの反復
for file in /var/log/*.log; do
echo "Processing: $file"
gzip "$file"
done
# whileループ
while read -r line; do
echo "Processing: $line"
done < input.txt
# カウンターループ
count=0
while [ $count -lt 10 ]; do
echo "Attempt $count"
((count++))
done
8.3 関数とエラー処理
#!/bin/bash
set -euo pipefail
# 関数定義
deploy() {
local environment="$1"
local version="$2"
echo "Deploying version $version to $environment..."
if ! docker pull "myapp:$version" 2>/dev/null; then
echo "Error: Image myapp:$version not found"
return 1
fi
docker stop myapp 2>/dev/null || true
docker run -d --name myapp "myapp:$version"
echo "Deploy complete!"
}
# エラーハンドリング
cleanup() {
echo "Cleaning up temporary files..."
rm -rf /tmp/deploy_*
}
trap cleanup EXIT # スクリプト終了時に必ず実行
# getoptsで引数パース
usage() {
echo "Usage: deploy.sh -e ENVIRONMENT -v VERSION [-d]"
exit 1
}
DRY_RUN=false
while getopts "e:v:dh" opt; do
case $opt in
e) ENVIRONMENT="$OPTARG" ;;
v) VERSION="$OPTARG" ;;
d) DRY_RUN=true ;;
h) usage ;;
*) usage ;;
esac
done
# 実行
deploy "$ENVIRONMENT" "$VERSION"
8.4 実践スクリプト:自動バックアップ
#!/bin/bash
set -euo pipefail
BACKUP_DIR="/backup"
DB_NAME="production"
RETENTION_DAYS=30
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/${DB_NAME}_$TIMESTAMP.sql.gz"
# ロギング関数
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}
# バックアップ実行
log "Starting backup of $DB_NAME..."
pg_dump "$DB_NAME" | gzip > "$BACKUP_FILE"
# バックアップ検証
if [ -s "$BACKUP_FILE" ]; then
SIZE=$(du -h "$BACKUP_FILE" | cut -f1)
log "Backup successful: $BACKUP_FILE ($SIZE)"
else
log "ERROR: Backup file is empty!"
exit 1
fi
# 古いバックアップの整理
log "Removing backups older than $RETENTION_DAYS days..."
find "$BACKUP_DIR" -name "${DB_NAME}_*.sql.gz" -mtime +$RETENTION_DAYS -delete
# 残りのバックアップ数を確認
REMAINING=$(find "$BACKUP_DIR" -name "${DB_NAME}_*.sql.gz" | wc -l)
log "Done. $REMAINING backups remaining."
9. tmux - ターミナルマルチプレクサ
9.1 基本的な使い方
# セッション管理
tmux new -s dev # 新しいセッションを作成
tmux ls # セッション一覧
tmux attach -t dev # セッションに接続
tmux kill-session -t dev # セッションを終了
9.2 主要ショートカット
tmuxのデフォルトプレフィックスキーは Ctrl+b です。
| 動作 | ショートカット |
|---|---|
| 水平分割 | Ctrl+b % |
| 垂直分割 | Ctrl+b " |
| ペイン移動 | Ctrl+b 方向キー |
| 新しいウィンドウ | Ctrl+b c |
| 次のウィンドウ | Ctrl+b n |
| 前のウィンドウ | Ctrl+b p |
| セッション分離 | Ctrl+b d |
| ペインサイズ調整 | Ctrl+b Alt+方向キー |
| ペインのズーム | Ctrl+b z |
9.3 推奨tmux設定
# ~/.tmux.conf
set -g mouse on # マウスサポート
set -g history-limit 50000 # スクロールバックバッファを拡大
set -g base-index 1 # ウィンドウ番号を1から開始
setw -g pane-base-index 1 # ペイン番号を1から開始
# プレフィックスキーの変更(Ctrl+a)
unbind C-b
set -g prefix C-a
# 直感的な分割キー
bind | split-window -h -c "#{pane_current_path}"
bind - split-window -v -c "#{pane_current_path}"
# Viモード
setw -g mode-keys vi
10. Vim必須(ひっす)の使い方
10.1 モードと基本コマンド
| モード | 入る方法 | 説明 |
|---|---|---|
| Normal | Esc | コマンド実行 |
| Insert | i, a, o | テキスト入力 |
| Visual | v, V | テキスト選択 |
| Command | : | Exコマンド |
10.2 サバイバル必須コマンド
# 移動
h/j/k/l 左/下/上/右
w / b 単語の前/後ろへ
0 / $ 行の先頭/末尾
gg / G ファイルの先頭/末尾
:42 42行目に移動
# 編集
dd 行を削除
yy 行をコピー
p ペースト
u 取り消し
Ctrl+r やり直し
. 最後のコマンドを繰り返す
# 検索/置換
/pattern 前方検索
?pattern 後方検索
n / N 次/前の結果
:%s/old/new/g 全体置換
:%s/old/new/gc 確認しながら置換
# 保存/終了
:w 保存
:q 終了
:wq 保存して終了
:q! 保存せずに終了
10.3 実践Vimのヒント
# 複数ファイルの編集
:e filename ファイルを開く
:bn / :bp 次/前のバッファ
:vs filename 垂直分割で開く
# マクロ
qa マクロa記録開始
q 記録停止
@a マクロa実行
100@a 100回繰り返し実行
# ブロック編集(複数行コメントなど)
Ctrl+v ブロック選択
I ブロックの前に挿入
Esc 適用
11. システム監視(かんし)
11.1 メモリとディスク
# メモリ
free -h # メモリ使用量
cat /proc/meminfo # 詳細メモリ情報
# ディスク
df -h # ディスク使用量
du -sh /var/log/* # ディレクトリごとのサイズ
du -h --max-depth=1 / | sort -rh | head -10 # 最も大きいディレクトリ
# ディスクI/O
iostat -x 1 # I/O統計(1秒間隔)
iotop # プロセスごとのI/O使用量
11.2 CPUとシステム性能
# CPU情報
lscpu # CPU情報
nproc # CPUコア数
uptime # ロードアベレージ
# vmstat: 仮想メモリ統計
vmstat 1 10 # 1秒間隔で10回
# sar: システムアクティビティレポーター
sar -u 1 5 # CPU使用率(1秒間隔で5回)
sar -r 1 5 # メモリ使用率
sar -n DEV 1 5 # ネットワークトラフィック
# lsof: 開いているファイルの一覧
lsof -i :8080 # 8080ポートを使用するプロセス
lsof -u developer # 特定ユーザーの開いているファイル
lsof +D /var/log/ # 特定ディレクトリの開いているファイル
# strace: システムコールの追跡(デバッグ用)
strace -f -e trace=network -p 1234 # ネットワーク関連のシステムコールを追跡
12. パッケージ管理
12.1 Debian/Ubuntu (apt)
sudo apt update # パッケージリストの更新
sudo apt upgrade # インストール済みパッケージのアップグレード
sudo apt install nginx # パッケージのインストール
sudo apt remove nginx # パッケージの削除
sudo apt autoremove # 不要なパッケージの整理
apt search keyword # パッケージの検索
apt show nginx # パッケージ情報
dpkg -l | grep nginx # インストール済みパッケージの確認
12.2 RHEL/CentOS (yum/dnf)
sudo yum update # 更新
sudo yum install httpd # インストール
sudo yum remove httpd # 削除
yum search keyword # 検索
rpm -qa | grep httpd # インストール済みパッケージの確認
12.3 macOS (brew)
brew update # Homebrewの更新
brew install jq # パッケージのインストール
brew upgrade # 全パッケージのアップグレード
brew list # インストール済みパッケージの一覧
brew cleanup # キャッシュの整理
13. Docker CLI必須コマンド
# イメージ管理
docker images # イメージ一覧
docker pull nginx:latest # イメージのダウンロード
docker build -t myapp:1.0 . # イメージのビルド
docker rmi myapp:1.0 # イメージの削除
# コンテナ管理
docker ps # 実行中のコンテナ
docker ps -a # すべてのコンテナ
docker run -d -p 8080:80 --name web nginx # バックグラウンドで実行
docker stop web # コンテナの停止
docker rm web # コンテナの削除
# デバッグ
docker logs -f web # リアルタイムログ
docker exec -it web /bin/bash # コンテナ内部にアクセス
docker inspect web # 詳細情報
# クリーンアップ
docker system prune -a # 未使用リソースの全体整理
docker volume prune # 未使用ボリュームの整理
14. パイプとリダイレクトの深掘(ふかぼ)り
# 基本リダイレクト
command > output.txt # 標準出力をファイルに(上書き)
command >> output.txt # 標準出力をファイルに(追記)
command 2> error.log # 標準エラーをファイルに
command > output.txt 2>&1 # 標準出力 + エラーを同じファイルに
command &> all.log # 上と同じ(Bash短縮形)
# パイプチェーンの実践
# メモリを最も多く使用するプロセス10個
ps aux --sort=-%mem | head -11
# ログからエラー頻度分析
cat app.log | grep "ERROR" | awk '{print $4}' | sort | uniq -c | sort -rn | head
# リアルタイムログで特定パターンをアラート
tail -f app.log | grep --line-buffered "CRITICAL" | while read line; do
echo "ALERT: $line" | mail -s "Critical Error" admin@example.com
done
# プロセス置換
diff <(ssh server1 cat /etc/config) <(ssh server2 cat /etc/config)
# ヒアドキュメント
cat <<'SCRIPT' > /tmp/setup.sh
#!/bin/bash
echo "Running setup..."
apt update && apt install -y nginx
SCRIPT
15. 10のトラブルシューティングシナリオ
シナリオ1:ディスク空間(くうかん)不足(ぶそく)
# 1. 全体ディスク使用量の確認
df -h
# 2. 大きなディレクトリの検索
du -h --max-depth=1 / 2>/dev/null | sort -rh | head -10
# 3. 大きなファイルの検索
find / -type f -size +500M 2>/dev/null | head -20
# 4. 削除されたがプロセスが保持しているファイルの確認
lsof +L1
# 5. ログファイルの整理
sudo journalctl --vacuum-size=500M
find /var/log -name "*.gz" -mtime +30 -delete
シナリオ2:サービスが応答(おうとう)しない
# 1. サービス状態の確認
sudo systemctl status myapp
# 2. ポートリスニングの確認
ss -tlnp | grep :8080
# 3. プロセス状態の確認
ps aux | grep myapp
# 4. 最近のログを確認
journalctl -u myapp --since "10 minutes ago" --no-pager
# 5. リソースの確認(OOM Killer)
dmesg | grep -i "oom\|killed"
シナリオ3:高(たか)いCPU使用率(しようりつ)
# 1. CPU消費プロセスの確認
top -o %CPU -bn1 | head -15
# 2. 特定プロセスのスレッド確認
top -H -p $(pgrep myapp)
# 3. システムコールの確認
strace -c -p $(pgrep myapp) -e trace=all
# 4. ロードアベレージの履歴
sar -u 1 10
シナリオ4:ネットワーク接続(せつぞく)の問題
# 1. DNS確認
dig api.example.com +short
# 2. ポート接続テスト
nc -zv api.example.com 443
# 3. 経路追跡
traceroute api.example.com
# 4. SSL証明書の確認
openssl s_client -connect api.example.com:443 -servername api.example.com </dev/null 2>/dev/null | openssl x509 -text -noout | grep -A2 "Validity"
シナリオ5:メモリリークの調査(ちょうさ)
# 1. メモリ使用量の推移を確認
watch -n 5 'free -h'
# 2. プロセスごとのメモリ使用量
ps aux --sort=-%mem | head -10
# 3. 特定プロセスのメモリ詳細
cat /proc/$(pgrep myapp)/status | grep -i "vm\|mem"
# 4. OOM Killerのログ
dmesg -T | grep -i "oom"
シナリオ6:遅(おそ)いディスクI/O
# 1. I/O待ちの確認
iostat -x 1 5
# 2. I/Oを多く使用するプロセス
iotop -oP
# 3. ディスク性能テスト
dd if=/dev/zero of=testfile bs=1G count=1 oflag=direct
シナリオ7:SSH接続の失敗(しっぱい)
# 1. 詳細デバッグモードで接続試行
ssh -vvv user@server
# 2. SSHサービスの状態確認(サーバー側)
sudo systemctl status sshd
# 3. ファイアウォールの確認
sudo iptables -L -n | grep 22
# 4. 認証ログの確認
sudo tail -50 /var/log/auth.log
シナリオ8:ファイル権限(けんげん)の問題
# 1. ファイル権限の確認
ls -la /path/to/file
namei -l /path/to/file # パス全体の権限を確認
# 2. SELinux / AppArmorの確認
getenforce # SELinuxの状態
ls -Z /path/to/file # SELinuxコンテキスト
# 3. ACLの確認
getfacl /path/to/file
シナリオ9:ログ分析(ぶんせき)による攻撃検知(こうげきけんち)
# 1. 異常なログイン試行の確認
grep "Failed password" /var/log/auth.log | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head
# 2. Webサーバーの異常アクセス確認
awk '$9 == 404' access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head
# 3. 同時接続数の確認
ss -tn | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head
シナリオ10:ゾンビプロセス
# 1. ゾンビプロセスの確認
ps aux | awk '$8 ~ /Z/ {print}'
# 2. 親プロセスの特定
ps -o ppid= -p ZOMBIE_PID
# 3. 親プロセスの再起動で整理
kill -SIGCHLD PARENT_PID
# または親プロセスを再起動
16. 便利(べんり)なワンライナー集
# カレントディレクトリで最も大きいファイル10個
find . -type f -exec du -h {} + | sort -rh | head -10
# 特定ポートを使用するプロセスを即座に終了
kill $(lsof -t -i:8080)
# Gitリポジトリで最も大きいファイルを見つける
git rev-list --objects --all | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | sed -n 's/^blob //p' | sort -snk2 | tail -10
# サーバーレスポンス時間の測定(10回繰り返し)
for i in $(seq 1 10); do curl -o /dev/null -s -w "%{time_total}\n" https://example.com; done
# JSONファイルの整形出力
cat data.json | python3 -m json.tool
# または
cat data.json | jq .
# ファイルエンコーディングの変換
iconv -f EUC-JP -t UTF-8 input.txt > output.txt
# 現在のシェルのすべての環境変数をソートして表示
env | sort
# 特定拡張子のファイルの総行数
find . -name "*.py" -exec wc -l {} + | tail -1
17. 面接質問(しつもん)15選
Q1. ハードリンクとシンボリックリンクの違いは?
ハードリンク: 同じinodeを指します。オリジナルが削除されてもアクセス可能です。ファイルシステムを跨げず、ディレクトリには使用できません。
シンボリックリンク: 別のinodeでパスを指します。オリジナルが削除されると壊れたリンクになります。ファイルシステムを跨いで使用可能で、ディレクトリにも使えます。
# ハードリンク:同じinodeを共有
ln original.txt hard.txt
ls -li original.txt hard.txt # 同じinode番号
# シンボリックリンク:異なるinode、パス参照
ln -s original.txt sym.txt
ls -li original.txt sym.txt # 異なるinode番号
Q2. プロセスとスレッドの違いは?
プロセス: 独立したメモリ空間を持ち、IPC(パイプ、ソケット等)で通信します。あるプロセスのクラッシュは他のプロセスに影響しません。
スレッド: 同じプロセス内でメモリを共有します。コンテキストスイッチが速いですが、1つのスレッドのエラーがプロセス全体に影響する可能性があります。
# スレッドを含むプロセス確認
ps -eLf | head # スレッド(LWP)を含むリスト
# NLWP列がスレッド数を示す
# 特定プロセスのスレッド数
ls /proc/PID/task/ | wc -l
Q3. ファイル権限755と644の意味は?
755: rwxr-xr-x - オーナー(読み/書き/実行)、グループ(読み/実行)、その他(読み/実行)。ディレクトリと実行ファイルに主に使用します。
644: rw-r--r-- - オーナー(読み/書き)、グループ(読み)、その他(読み)。一般ファイルに主に使用します。
計算方法: r=4、w=2、x=1。各位置(オーナー/グループ/その他)の合計で表現します。
Q4. SIGTERMとSIGKILLの違いは?
SIGTERM (15): プロセスに正常終了を要求します。プロセスはシグナルハンドラでクリーンアップ(ファイルのクローズ、一時ファイルの削除等)を実行してから終了できます。kill PIDのデフォルトです。
SIGKILL (9): カーネルが即座にプロセスを強制終了します。プロセスは無視もハンドリングもできません。クリーンアップなしで即座に終了するため、データ損失のリスクがあります。最終手段としてのみ使用すべきです。
Q5. grep、awk、sedの使い分けは?
- grep: パターン検索が目的の場合(特定の文字列を含む行を見つける)
- awk: フィールドベースのデータ処理が必要な場合(カラム抽出、計算、条件フィルタリング)
- sed: ストリーム編集が必要な場合(文字列置換、行の削除/追加)
実践ではこの3つのツールをパイプで繋いで使うことが多いです。
# ログから5xxエラーを発生させたURLの頻度分析
grep " 5[0-9][0-9] " access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head
Q6. パイプ(|)とリダイレクト(>)の違いは?
パイプ(|): あるコマンドの標準出力を別のコマンドの標準入力に接続します。プロセス間通信です。
リダイレクト(>): コマンドの出力をファイルに送ります。プロセスとファイル間の通信です。
# パイプ: lsの出力がgrepの入力に
ls -la | grep ".conf"
# リダイレクト: lsの出力がファイルに
ls -la > filelist.txt
Q7. inodeとは何ですか?
inodeはファイルシステムでファイルのメタデータを格納するデータ構造です。ファイル名を除くすべての情報(オーナー、権限、サイズ、タイムスタンプ、データブロック位置)を含みます。ディレクトリエントリがファイル名とinode番号をマッピングします。
# inode番号の確認
ls -i file.txt
stat file.txt # 詳細inode情報
# inode使用量の確認(ファイル数制限)
df -i
Q8. SSHトンネリングの3種類を説明してください。
-
ローカルポートフォワーディング(-L): ローカルポートを通じてリモートサービスにアクセス。
ssh -L 5432:db:5432 bastion- ローカルの5432に接続するとbastionを経由してdbの5432に接続。 -
リモートポートフォワーディング(-R): リモートからローカルサービスにアクセス。
ssh -R 8080:localhost:3000 server- serverの8080に接続するとローカルの3000に接続。 -
ダイナミックポートフォワーディング(-D): SOCKSプロキシの作成。
ssh -D 1080 server- ローカル1080をSOCKSプロキシとして使用し、serverを通じて全トラフィックを転送。
Q9. ゾンビプロセスとは?どう対処しますか?
ゾンビプロセスは実行が終了したが、親プロセスがwait()システムコールで終了ステータスをまだ回収していないプロセスです。PIDのみ占有しリソースは使用しませんが、多数蓄積するとPID枯渇問題が発生します。
対処方法: 親プロセスにSIGCHLDを送るか、親プロセスを終了するとinit/systemdが孤児プロセスを引き受けて整理します。
ps aux | awk '$8=="Z"' # ゾンビプロセスの確認
kill -SIGCHLD PARENT_PID # 親に子の終了を通知
Q10. /procファイルシステムとは?
/procはカーネルとプロセス情報をファイル形式で提供する仮想ファイルシステムです。ディスクに実際には存在せず、カーネルがリアルタイムで生成します。
cat /proc/cpuinfo # CPU情報
cat /proc/meminfo # メモリ情報
cat /proc/PID/status # 特定プロセスの状態
cat /proc/PID/fd/ # 開いているファイルディスクリプタ
cat /proc/loadavg # システム負荷
Q11. stdin、stdout、stderrのファイルディスクリプタ番号は?
- 0: stdin(標準入力)
- 1: stdout(標準出力)
- 2: stderr(標準エラー)
command > file.txt # 1番(stdout)をファイルに
command 2> error.log # 2番(stderr)をファイルに
command > file.txt 2>&1 # stderrをstdoutと同じ場所に
command < input.txt # 0番(stdin)をファイルから読み取り
Q12. cronとatの違いは?
cron: 繰り返しのスケジュールタスクに使用します。crontabファイルで管理します。
# 分 時 日 月 曜日 コマンド
crontab -e
0 2 * * * /backup/run.sh # 毎日午前2時
*/5 * * * * /check/health.sh # 5分ごと
at: 一回限りのタスクに使用します。
at now + 30 minutes
> /scripts/deploy.sh
> Ctrl+D
Q13. ロードアベレージ(Load Average)とは?
ロードアベレージは実行可能(Running)または待機(Waiting)状態のプロセスの平均数です。uptimeコマンドで1分、5分、15分の平均を確認します。
解釈: CPUコア数と比較します。4コアシステムでロードアベレージ4.0なら100%活用、8.0なら過負荷(プロセスが待機中)です。
uptime # load average: 2.50, 3.10, 2.80
nproc # CPUコア数を確認
Q14. swapメモリとは?サーバーではなぜ注意が必要ですか?
SwapはRAMが不足した場合にディスクをメモリのように使用する空間です。ディスクI/OはRAMより数千倍遅いため、サーバーがswapを活発に使用すると性能が急激に低下します。
free -h # swap使用量の確認
swapon --show # swapデバイスの確認
vmstat 1 # si/so値が大きいとswapを活発に使用中
cat /proc/sys/vm/swappiness # swap使用傾向(0-100、低いほどRAM優先)
Q15. set -euo pipefailは何をしますか?
Bashスクリプトの安全装置です。
- -e (errexit): コマンドが失敗(non-zero exit)するとスクリプトを即座に中断
- -u (nounset): 宣言されていない変数を使用するとエラー発生
- -o pipefail: パイプライン内の中間コマンドの失敗も検知
この3つのオプションなしではエラーが無視されて予期しない動作が発生する可能性があります。本番スクリプトでは常に使用することが推奨されます。
18. クイズ
Q1. 次のコマンドの出力結果は? echo "Hello" | tee output.txt | wc -c
答え: 6
teeはstdinをoutput.txtに書き込みながら同時にstdoutに渡します。wc -cはバイト数を数えます: "Hello\n" = 6バイトです。
Q2. chmod 4755 script.shの4は何を意味しますか?
答え: SetUIDビット
4はSetUID(Set User ID)ビットです。このファイルを実行すると、ファイル所有者の権限で実行されます。例えば/usr/bin/passwdはroot所有でSetUIDが設定されているため、一般ユーザーもパスワードを変更できます。SetGIDは2、Sticky Bitは1です。
Q3. ファイルをリアルタイムで監視しながら特定パターンをフィルタリングする正しい方法は?
A) grep "ERROR" < tail -f app.log
B) tail -f app.log | grep "ERROR"
C) tail -f app.log > grep "ERROR"
D) cat app.log | tail -f | grep "ERROR"
答え: B
tail -fの出力をパイプでgrepに渡します。Aは構文エラー、Cはリダイレクトの誤用、Dはcatが先に全体を読むためtail -fが無意味です。
Q4. ssh -L 3306:db-server:3306 bastionで実際に何が起こりますか?
答え: ローカルマシンの3306ポートに接続すると、SSH接続を通じてbastionサーバーを経由してdb-serverの3306ポート(MySQL)に接続されます。ローカルでmysql -h 127.0.0.1 -P 3306でリモートDBにアクセスできます。通信はSSHで暗号化されます。
Q5. 次のスクリプトのバグを見つけてください。
#!/bin/bash
for f in $(ls *.txt); do
mv "$f" "${f%.txt}.md"
done
答え: lsの出力をforループに使用すると、ファイル名にスペースがある場合に壊れます。正しい方法:
#!/bin/bash
for f in *.txt; do
[ -e "$f" ] || continue
mv "$f" "${f%.txt}.md"
done
globパターンを直接使用し、マッチするファイルがない場合に備えて存在確認を行います。
19. 参考(さんこう)資料
公式ドキュメント
- GNU Coreutils Manual - コアユーティリティ公式ドキュメント
- GNU Bash Manual - Bash公式リファレンス
- The Linux Documentation Project - Linux総合ドキュメントプロジェクト
- man7.org Linux Manual Pages - Linuxマニュアルページのオンライン版
- tmux Wiki - tmux公式Wiki
学習リソース
- Linux Journey - 初心者向けLinux学習サイト
- OverTheWire Bandit - ゲームで学ぶLinuxコマンド
- Vim Adventures - ゲームで学ぶVim
- ExplainShell - コマンドを入力すると各部分を説明してくれるツール
- ShellCheck - Bashスクリプトリンター/アナライザー
書籍
- The Linux Command Line (William Shotts) - Linux CLIバイブル
- Linux Pocket Guide (Daniel J. Barrett) - クイックリファレンス
- Bash Cookbook (Carl Albing) - Bashレシピ集
- sed and awk (Dale Dougherty) - テキスト処理の深堀り
チートシート
- devhints.io/bash - Bashチートシート
- tmux Cheat Sheet - tmuxショートカット集
- Vim Cheat Sheet - Vimコマンド集