サーバー運用の現場では、「月次バックアップのファイル名に年月を入れたい」「次の第2火曜日がいつかターミナル上でさっと確認したい」「リリースまで何日か計算したい」という場面が定期的に発生します。こうした要件をブラウザを開かずにターミナルだけで完結させるのが、cal と date の組み合わせです。本記事ではコマンドのオプション一覧を眺めるのではなく、運用シナリオを起点に「いつ・なぜ・どう使うか」を整理します。
cal コマンドで月・週の全体像を把握する
まず確認しておきたいのが、2026年時点での cal の実体です。主要ディストリビューション(Ubuntu 24.04 LTS / Rocky Linux 9 / Debian 12)ではいずれも util-linux パッケージ同梱の cal が標準になっています。古い BSD 系の cal とはオプション体系が微妙に異なるため、他環境のドキュメントを参照する際は注意が必要です。インストール済みのバージョンは cal --version で確認できます。
最もシンプルな用途は「今月のカレンダーを今日強調表示で確認する」ことです。
# 今月を表示(今日の日付がハイライトされる)
cal
# 前月・今月・来月の3か月を並べて確認
cal -3
# 2026年の全カレンダーを表示
cal -y 2026
# 週の始まりを月曜日にする(ISO 8601 準拠)
cal -m
# 特定月を指定(2026年9月)
cal 9 2026
メンテナンス枠の調整では、cal -3 で前後月を並べたうえで「第何週の何曜日か」を視覚的に確認するのが現場では一般的です。週始まりを月曜にしたい場合は -m オプションを使うと、月〜金の業務週に合わせた見方ができます。
また -j オプションを指定すると年通算日(day-of-year)が表示されます。年をまたいだ稼働日数計算や、通算日を基点にしたスクリプトへの参照用途で使われることがあります。
date コマンドで日付・時刻を文字列として取り出す
date コマンドの実務上の最重要用途は「整形した日付文字列をスクリプトに渡す」ことです。バックアップファイルの命名規則や、ログのアーカイブ先ディレクトリ名に日付を入れるパターンは多くの現場で見られます。
# YYYYMMDD 形式
date +%Y%m%d
# 例: 20260713
# ISO 8601(ハイフン区切り)
date +%Y-%m-%d
# 例: 2026-07-13
# 日時まで含める(ファイル名に使いやすい形式)
date +%Y%m%d_%H%M%S
# 例: 20260713_143022
# Unix エポック秒(スクリプト内の経過時間計算に)
date +%s
バックアップスクリプトで典型的に使われるパターンを示します。
#!/bin/bash
DATESTAMP=$(date +%Y%m%d)
BACKUP_DIR="/var/backup/db/${DATESTAMP}"
mkdir -p "${BACKUP_DIR}"
pg_dump mydb > "${BACKUP_DIR}/mydb.sql"
日付を変数に格納しておくのには理由があります。スクリプトの実行が深夜0時をまたいだ場合、複数箇所で $(date +%Y%m%d) を直接呼ぶと処理途中に日付が変わり、ファイル名が不整合になるリスクがあります。冒頭で一度だけ取得して変数に入れるのが安全な書き方です。
date -d による日付演算と相対指定
GNU date(Linux 標準)には -d オプションがあり、相対的な日付指定が可能です。「〇日後」「先月末」「次の月曜日」といった計算をシェル上で完結させられます。
# 7日後の日付
date -d "+7 days" +%Y-%m-%d
# 先月の1日(月次バッチの対象期間算出によく使われる)
date -d "$(date +%Y-%m-01) -1 month" +%Y-%m-%d
# 先月末日(「今月1日の1日前」と表現するのが安全)
date -d "$(date +%Y-%m-01) -1 day" +%Y-%m-%d
# 特定日から何日経過したか(エポック秒を利用)
START=$(date -d "2026-01-01" +%s)
NOW=$(date +%s)
echo $(( (NOW - START) / 86400 )) days
# 次の日曜日
date -d "next sunday" +"%Y-%m-%d (%a)"
月末日をまたぐ演算は特に注意が必要です。-1 month を直接使うと、例えば3月31日の「1か月前」が2月31日(存在しない)として処理され、3月3日などに補正される場合があります。「先月末を求めたい」場合は「今月1日の1日前」と表現するほうが確実です。
また、macOS(BSD date)では -d オプションが存在せず、-v で同等の操作を行います。ローカル開発が Mac でサーバーが Linux というチームでは、この差異がスクリプト移植時の問題になることがあります。本番サーバー上で動かすスクリプトは GNU date の動作を前提に統一しておくと管理が楽になります。
timedatectl と chrony による時刻同期の確認(2026年現行標準)
date コマンドが返す時刻は、システムクロックが正確に同期されていることが前提です。2026年時点では、systemd 環境での時刻同期は chrony または systemd-timesyncd が担っており、旧来の ntpd はほとんどの主要ディストリビューションでデフォルト採用されていません。旧ドキュメントで見かける ntpdate コマンドも非推奨扱いで、パッケージがデフォルトでは入っていない環境が増えています。
# システムの時刻・タイムゾーン・同期状態を一覧確認
timedatectl status
# chrony を使っている場合の詳細確認(オフセットや参照サーバーが分かる)
chronyc tracking
# systemd-timesyncd の場合
timedatectl show-timesync --all
タイムゾーンの変更も timedatectl で行います。以前は /etc/localtime へのシンボリックリンクを手動で張り替えることもありましたが、systemd 環境では timedatectl set-timezone で一元管理するのが現行標準です。
# 利用可能なタイムゾーンを検索
timedatectl list-timezones | grep Asia/Tokyo
# タイムゾーンを Asia/Tokyo に設定
sudo timedatectl set-timezone Asia/Tokyo
# 設定後の確認
timedatectl status
スクリプト内でタイムゾーンを一時的に切り替えたい場合は、環境変数 TZ を使います。システム全体のタイムゾーンを変えることなく、特定のコマンドだけ別タイムゾーンで動作させられます。
# UTC での現在時刻を確認(システムの TZ を変えずに)
TZ=UTC date
# ニューヨーク時間で確認
TZ=America/New_York date +"%Y-%m-%d %H:%M:%S %Z"
運用スクリプトでよくある落とし穴と確認ポイント
日付を扱うスクリプトが本番でトラブルになるパターンは概ね決まっています。代表的なケースを整理します。
ゼロパディングと算術演算の衝突
date +%m が返す月は 08 や 09 のようにゼロパディングされています。これをシェルの算術演算にそのまま渡すと、古い sh 実装では8進数と解釈されてエラーになることがあります。10進数を明示する 10# プレフィックスで回避できます。
MONTH=$(date +%m)
# 08, 09 が8進数扱いになるリスクがある書き方
echo $(( MONTH + 1 ))
# 10進数を明示した安全な書き方
echo $(( 10#${MONTH} + 1 ))
cron 内での TZ 設定
cron ジョブ内では環境変数が最小限しか引き継がれません。TZ を cron 内で有効にしたい場合は、crontab の先頭行に TZ=Asia/Tokyo を記述するか、スクリプト内で明示的に export TZ=Asia/Tokyo を宣言する方法があります。後者のほうが移植性が高く、スクリプト単体でも意図が明確になります。
仮想環境でのクロックドリフト
仮想マシンやコンテナ環境では、ホストのサスペンド・レジュームや高負荷時にシステムクロックが大きく狂うことがあります。日付演算を含む重要なバッチ処理の前に chronyc tracking の System time 値を確認し、許容範囲内(通常 1 秒以内)であることをチェックする習慣が、長期運用では安定性に寄与します。
実務でそのまま使える組み合わせパターン
最後に、現場でよく使われるスニペットをまとめます。
# 今月の残り日数を表示
MONTH_END=$(date -d "$(date +%Y-%m-01) +1 month -1 day" +%d)
TODAY=$(date +%d)
echo $(( 10#${MONTH_END} - 10#${TODAY} )) days remaining
# ログローテーション用:90日前の日付(削除対象ディレクトリ特定に)
date -d "-90 days" +%Y%m%d
# 今週の月曜日(週次レポートのファイル名に)
date -d "last monday" +%Y-%m-%d
# 次回メンテナンス候補日(次の日曜日)をカレンダー確認と組み合わせる
NEXT_SUN=$(date -d "next sunday" +"%Y-%m-%d")
echo "次回候補: ${NEXT_SUN}"
cal $(date -d "next sunday" +"%m %Y")
cal によるカレンダー確認と date による日付文字列生成は、単体ではシンプルなコマンドです。しかし組み合わせとスクリプト化によって、バックアップ管理・ログ整理・定期メンテナンスの自動化をターミナルで完結させる基盤になります。GNU date の -d オプションによる相対指定と、timedatectl による時刻同期管理の2点を押さえておくと、日付処理にまつわるトラブルの大半を未然に防ぐことができます。
「コマンドは打てる。次は”現場で通用する型”を最短で身につけたい」——そんなあなたへ。
ネットの断片的なTipsをコピペするだけでは、体系的な運用スキルはなかなか積み上がりません。リナックスマスター.JPの無料メルマガ「リナマガ」では、現場で実際に使うLinuxサーバー運用の考え方を、順を追って実務目線でお届けしています。いま登録された方には、安全なサーバー構築の「型」をまとめた『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼント中です。
>> 図解60P『Linux入門マニュアル』を無料で受け取る
(メルマガ登録は10秒・いつでも解除OK)
※ 「独学の時間がもったいない」「プロから現場の技術を最短で学びたい」という本気の方には、2日で実務レベルが身につく初心者向けハンズオンセミナーもご用意しています。
PR・広告
コマンド操作から基本運用までを手を動かして学べる定番書。記事で触れた技術の土台固めに。
※ Amazonのアソシエイトとして、当サイトは適格販売により収入を得ています。
