第12章: 自動化とスクリプト作成
12.1 この章で解説する主要な技術・概念
Linuxサーバー運用において、手作業による設定やメンテナンスはヒューマンエラーが起こりやすく、大規模になるほど管理が複雑になります。自動化やスクリプト作成を推進することで、作業を効率化し、環境の一貫性を保ち、人的ミスを減らすことが可能です。本章では、以下のトピックを深掘りし、AlmaLinux 9での高度な運用自動化手法を学びます。
- シェルスクリプトの高度な書き方
- 関数、条件分岐、配列、エラー処理、デバッグ
- タスクの自動化 (cron, systemd timers, systemd-run)
- 定期実行やイベントドリブン実行のベストプラクティス
- 構成管理ツール (Ansible, Puppet, Chef など) の概要
- エージェントレス/エージェント型の違い、長所・短所
- Ansibleを使った実践的な運用例
- Playbookの設計、Roles、Inventory管理、Vault(機密情報の暗号化)
- SSHキー管理とセキュリティ
- パスワードレス運用時のリスクと対策、Authorized Keysの一括管理
- 自動化のユースケース
- サーバー初期設定、パッケージアップデート、バックアップ、サービス起動・停止、CI/CDとの連携
12.2 シェルスクリプトの高度な書き方
12.2.1 関数とモジュール化
#!/bin/bash
function backup_dir() {
local src=$1
local dest=$2
rsync -av --delete "$src" "$dest"
}
function main() {
backup_dir "/var/www" "/backup/www"
backup_dir "/home" "/backup/home"
}
main
- 関数化しておくと再利用・テスト・保守が楽になる
local
で変数スコープを限定し、グローバル汚染を防ぐ
12.2.2 条件分岐と配列
# 配列
servers=("web01" "web02" "db01")
for srv in "${servers[@]}"; do
echo "Deploying to $srv..."
# ssh $srv ...
done
# 条件分岐
if [ "$1" == "start" ]; then
systemctl start myapp
elif [ "$1" == "stop" ]; then
systemctl stop myapp
else
echo "Usage: $0 {start|stop}"
fi
- 文字列比較
[ "x" == "y" ]
や数値比較[ num -gt 0 ]
などさまざまな条件式を使う
12.2.3 エラー処理とデバッグ
set -euo pipefail
trap 'echo "Error on line $LINENO"' ERR
-e
: コマンドが失敗したらスクリプトを即終了-u
: 未定義変数の参照でエラー-o pipefail
: パイプ内のいずれかのコマンドが失敗したらスクリプトをエラー扱いtrap '...' ERR
: エラー時にライン番号などの情報を表示
# デバッグモード
bash -x myscript.sh
- 各行実行前にコマンドを表示してくれるため、ロジックの追跡が容易
12.2.4 スクリプト管理とリファクタリング
- リポジトリ管理: Gitなどのバージョン管理システムを導入し、レビューやロールバックを容易に
- ドキュメンテーション: スクリプト冒頭に概要や引数の説明、想定する実行環境などをコメントで残す
- テンプレート化: よく使うスクリプト構造(ロギング、引数解析、trap設定など)をテンプレ化し、プロジェクト全体で共通化
12.3 タスクの自動化 (cron, systemd timers, systemd-run)
12.3.1 cronの高度な活用
- cronは指定日時・周期でスクリプトを実行する仕組み
/etc/crontab
,/var/spool/cron/$USER
,/etc/cron.d/
など複数の配置先がある- MAILTO= 変数を活用すると、実行結果やエラーがメールで通知される
時間指定の工夫
# 例: 毎日深夜3:15に実行
15 3 * * * /usr/local/bin/backup_script.sh
# 例: 平日のみ(月~金)、2時間ごと
0 */2 * * 1-5 /usr/local/bin/report_script.sh
- crontab.guruなどを使って日付指定を可視化し、複雑なパターンでもミスを減らす
12.3.2 systemd timersの利点
- systemd timers はcronの代わりにsystemdユニットとして動作
OnCalendar=
で時間指定し、ログやリソース制御がsystemdに統合できる
例: /etc/systemd/system/db_backup.service
[Unit]
Description=Database Backup
[Service]
Type=oneshot
ExecStart=/usr/local/bin/db_backup.sh
例: /etc/systemd/system/db_backup.timer
[Unit]
Description=Run DB Backup every day at 03:15
[Timer]
OnCalendar=*-*-* 03:15:00
Unit=db_backup.service
[Install]
WantedBy=timers.target
sudo systemctl enable db_backup.timer
sudo systemctl start db_backup.timer
systemctl list-timers
でタイマー一覧が確認できる
12.3.3 systemd-runによる動的実行
sudo systemd-run --on-active=5 /usr/local/bin/cleanup_script.sh
--on-active
オプションで今から5秒後にワンショットのsystemdサービスとして実行- ロギングやリソース制御(systemd slice)を適用しやすい
12.4 構成管理ツールの概要
12.4.1 エージェントレス vs エージェント型
- エージェントレス (Ansible): SSHでターゲットに接続し、Playbookを実行。セットアップが簡単だが、ターゲットがSSHアクセス可能である必要がある。
- エージェント型 (Puppet, Chef, Salt): 各ターゲットにエージェントが常駐し、マスターサーバーと通信して設定を適用。リアルタイムに監視・設定が可能。
12.4.2 PuppetやChefの基本
- Puppet:
manifest
を記述し、Master-Client通信で定期的に設定を適用。 - Chef:
cookbook
でレシピを定義し、Chef Serverがクライアントに配信する仕組み。Rubyベースで柔軟だが学習コストあり。 - SaltStack: YAMLベースのステートファイルで管理し、エージェントかエージェントレスの両運用が可能。
注意: 大規模環境ではPuppetやChefが一時期主流だったが、近年はAnsibleやSaltStackがよりシンプルな運用で人気。
12.5 Ansibleによる実践的運用例
12.5.1 Ansibleの基本構成
sudo dnf install ansible
- Inventory: ターゲットホスト一覧 (
/etc/ansible/hosts
など) - Playbook: YAML形式でタスクを記述
- Roles: Playbookの機能をディレクトリ構成ごとに分割し、再利用性を高める
例: hosts
ファイル
[webservers]
192.168.10.101
192.168.10.102
[dbservers]
192.168.10.201
12.5.2 シンプルなPlaybook例
---
- name: Install Apache and start service
hosts: webservers
become: true # sudo権限
tasks:
- name: Install Apache
dnf:
name: httpd
state: present
- name: Enable and start Apache
systemd:
name: httpd
enabled: true
state: started
ansible-playbook -i hosts site.yml
- become: true でsudoを使ってroot権限でタスクを実行
- dnfモジュールやsystemdモジュールなど、Ansibleは多くのモジュールを標準搭載
12.5.3 Rolesとディレクトリ構成
ディレクトリ例:
site.yml
roles/
webserver/
tasks/main.yml
handlers/main.yml
templates/
files/
dbserver/
tasks/main.yml
...
inventories/
production
staging
ansible-galaxy init webserver
で雛形を作成可能roles/webserver/tasks/main.yml
でWebサーバー関連のタスクをまとめ、Playbookでは- role: webserver
として呼び出すだけ
12.5.4 Ansible Vaultで機密情報の暗号化
ansible-vault create secrets.yml
# パスワード設定し、YAMLファイルを暗号化して保管
ansible-vault edit secrets.yml
ansible-playbook -i hosts site.yml --ask-vault-pass
- DBパスワードやAPIキーを暗号化し、Gitリポジトリに安全にコミット可能
12.6 SSHキー管理とセキュリティ
12.6.1 パスワードレスSSHとリスク
- Ansibleや自動化スクリプトはSSH鍵認証を前提とすることが多い
ssh-copy-id
でターゲットに公開鍵を設置し、~/.ssh/authorized_keys
に追記- キーの紛失や漏洩に備えて定期的に鍵をローテーションする、秘密鍵をパスフレーズ付きで暗号化しておくなどの対策が必要
12.6.2 大規模環境での鍵管理
- ldapやADと連携して公開鍵を管理する仕組みを構築
- エージェント型構成管理 (Puppet, Chef) で鍵配布を集中管理
- バスワードレスは楽だが、踏み台サーバー経由で鍵が盗まれないようにport knockingやVPNなど多層防御を検討
12.7 自動化のユースケース
12.7.1 サーバー初期設定
- OSインストール直後にネットワーク設定、ホスト名変更、セキュリティ強化(firewall, selinuxポリシー)をAnsibleやシェルスクリプトで一括適用
- ユーザーアカウント作成、sudoers設定、SSH鍵配置など
12.7.2 パッケージアップデートとバックアップ
dnf update
をcronやsystemd timerで定期実行し、ログをメール通知- rsyncやtarスクリプトでバックアップを夜間に実施し、rcloneでクラウド転送
12.7.3 サービス起動・停止やデプロイ
- CI/CDパイプライン (GitLab CI, Jenkins など) からAnsible Playbookを呼び出し、新バージョンのアプリをデプロイ
- システム障害時の自動フェイルオーバー (Pacemaker, Keepalived) と組み合わせ、復旧手順を自動化
12.8 学習のまとめ
- シェルスクリプトの高度な書き方: 関数や配列、エラー処理を活用し、管理しやすく堅牢なスクリプトを実装。デバッグモードやtrapを使って開発・保守性を高める。
- タスクの自動化 (cron, systemd timers, systemd-run): 定期実行やワンショットの自動化を行い、スクリプトとの連携で反復作業を省力化。システムd経由でのリソース制御やロギングも視野に。
- 構成管理ツール: エージェントレスのAnsibleをはじめ、PuppetやChefなどのエージェント型ツールも含めて、大規模環境ではテンプレート化と自動適用を活用。
- Ansible運用: インベントリ、Playbook、Rolesを正しく使い分け、Vaultで秘密情報を保護する。デプロイやサーバー初期設定、パッケージ管理など幅広いタスクを一元化。
- SSHキー管理とセキュリティ: パスワードレス運用は便利だがリスクもあるので、鍵ローテーションや多層防御を検討。
- ユースケース: サーバー初期設定、バックアップ、デプロイ、障害対応など、実運用の多くを自動化し、安定稼働と工数削減を両立。
次章へのつながり
次の章(第13章)では、AlmaLinux 9でのコンテナ化(Docker/Podman)や仮想化(KVM, libvirt)にフォーカスし、モダンなアプリケーション運用やテスト環境の構築を効率化する技術を深掘りします。自動化と組み合わせることで、スケーラブルかつ柔軟なインフラを実現できるでしょう。