サイトマップ(Sitemap)を秒速生成する
create sitemaps in the blink
これまでNode.jsやPythonのツールでサイトマップを作成していましたが、ネットワーク経由のクロールは時間がかかるし、リダイレクトエラーも頻発するし・・自作すれば早いと思いつつも面倒で後回しにしていたのですが、先週の休日を使ってようやく作成しました。ローカルで動作し、システム標準ツール(mariadb、grep、sed)のみで実行可能なようにシンプルに作りました。
※私のサイトのblog配下はWordPressで作成しているため、wp-config.phpからデータベース情報を取得し、記事データにアクセスする形になっています。 WordPress以外のCMSを使っている場合は、スクリプト内で直接データベースのログイン情報を記述する形に修正してください。
cat make-sitemap.sh
#!/bin/bash
OUTPUT_FILE="/srv/www/htdocs/sitemap.xml"
#OUTPUT_FILE="test_sitemap.xml"
WEBROOT="/srv/www/htdocs"
DOMAIN="https://bokumin.org"
WP_CONFIG="/srv/www/htdocs/blog/wp-config.php"
DB_NAME=$(grep "DB_NAME" "$WP_CONFIG" | cut -d "'" -f 4)
DB_USER=$(grep "DB_USER" "$WP_CONFIG" | cut -d "'" -f 4)
DB_PASSWORD=$(grep "DB_PASSWORD" "$WP_CONFIG" | cut -d "'" -f 4)
DB_HOST=$(grep "DB_HOST" "$WP_CONFIG" | cut -d "'" -f 4)
TABLE_PREFIX=$(grep '$table_prefix' "$WP_CONFIG" | cut -d "'" -f 2)
cat > "$OUTPUT_FILE" << 'EOF'
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
EOF
process_url() {
local path="$1"
local full_path="$WEBROOT$path"
if [[ -f "$full_path" ]]; then
lastmod=$(date -r "$full_path" +%Y-%m-%d)
elif [[ -d "$full_path" ]]; then
lastmod=$(date -r "$full_path" +%Y-%m-%d)
else
return
fi
cat >> "$OUTPUT_FILE" << EOF
<url>
<loc>$DOMAIN$path</loc>
<lastmod>$lastmod</lastmod>
</url>
EOF
}
process_url "/"
process_url "/art-works/"
process_url "/gpg-public-key.txt"
process_url "/others/"
process_url "/spam-check/"
process_url "/amedas-dashboard/"
process_url "/blog/"
mariadb -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASSWORD" -D "$DB_NAME" -N -e "
SELECT
CONCAT('/blog/', DATE_FORMAT(post_date, '%Y/%m/%d'), '/', post_name, '/'),
DATE_FORMAT(post_date, '%Y-%m-%d')
FROM ${TABLE_PREFIX}posts
WHERE post_status = 'publish'
AND post_type = 'post'
ORDER BY post_date DESC
" | while IFS=$'\t' read -r url lastmod; do
cat >> "$OUTPUT_FILE" << EOF
<url>
<loc>$DOMAIN$url</loc>
<lastmod>$lastmod</lastmod>
</url>
EOF
done
echo "</urlset>" >> "$OUTPUT_FILE"
chown wwwrun:wwwrun "$OUTPUT_FILE"
実行時間は以下の通りです。めちゃはやいですね。
time ./make-sitemap.sh
real 0m0.258s
user 0m0.149s
sys 0m0.114s
以前使っていたnode.js版がこちらですが、ネットワークへのアクセスがある分かなり処理に時間がかかっていることがわかります。
$ cat make-sitemap-past.sh
#!/bin/bash
/usr/local/bin/sitemap-generator -f sitemap.xml https://bokumin.org
$ time ./make-sitemap-past.sh
(node:458025) Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTPS requests insecure by disabling certificate verification.
(Use `node22 --trace-warnings ...` to show where the warning was created)
real 0m48.391s
user 0m9.989s
sys 0m0.225s
WordPress以外の静的ページの扱い
私のサイトは元々Apacheで静的ページを公開しているところに、後からWordPressを導入しました。そのため、静的ページがルートディレクトリ直下、WordPressが/blog配下という構成になっています。
WordPress以外でサイトマップに載せたいページは、手動で指定できるようになっています。見せたくないものを除外するより、載せたいものを指定する方が効率が良いと思い、そういうスクリプトの作りになっています。
process_url "/"
process_url "/art-works/"
process_url "/gpg-public-key.txt"
process_url "/others/"
process_url "/spam-check/"
process_url "/amedas-dashboard/"
process_url "/blog/"
今回はPriorityやその他の属性は入れず、シンプルにURLと最終更新日だけを取得しています。Googleのボットも基本的にこれらの情報しか見ていないため、細かく設定する必要はないと思います。
静的サイトの日付は、スクリプト内のprocess_url関数で取得しています。
process_url() {
local path="$1"
local full_path="$WEBROOT$path"
if [[ -f "$full_path" ]]; then
lastmod=$(date -r "$full_path" +%Y-%m-%d) # ファイルの更新日時
elif [[ -d "$full_path" ]]; then
lastmod=$(date -r "$full_path" +%Y-%m-%d) # ディレクトリの更新日時
else
return
fi
...
}
出力結果(サイトマップ)
出力されたサイトマップを確認していきます。期待通りの出力になっています。
cat /srv/www/htdocs/sitemap.xml
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
<url>
<loc>https://bokumin.org/</loc>
<lastmod>2025-10-31</lastmod>
</url>
<url>
<loc>https://bokumin.org/art-works/</loc>
<lastmod>2025-09-11</lastmod>
</url>
<url>
<loc>https://bokumin.org/gpg-public-key.txt</loc>
<lastmod>2024-10-19</lastmod>
</url>
<url>
<loc>https://bokumin.org/others/</loc>
<lastmod>2025-10-30</lastmod>
</url>
<url>
<loc>https://bokumin.org/spam-check/</loc>
<lastmod>2025-10-03</lastmod>
</url>
<url>
<loc>https://bokumin.org/amedas-dashboard/</loc>
<lastmod>2025-10-03</lastmod>
</url>
<url>
<loc>https://bokumin.org/blog/</loc>
<lastmod>2025-10-29</lastmod>
</url>
<url>
<loc>https://bokumin.org/blog/2025/10/28/btrfs%e3%81%a8opensuse%e3%81%a7raid%e3%82%92%e6%a7%8b%e7%af%89%e3%81%99%e3%82%8braid1-raid0-raid10/</loc>
<lastmod>2025-10-28</lastmod>
※実際に作成されたサイトマップは以下のページから確認できます。
https://bokumin.org/sitemap.xml
まとめ
今回作成したスクリプトは、完全ローカルで動作し、外部ツールを一切必要としません。システムに標準でインストールされているmariadb、grep、sedのみで実行できるのが良いところかなと思います。処理速度も高速で依存関係がゼロであるため、パッケージ管理やアップデートの手間もかかりません。WordPressのデータベースから直接記事情報を取得するため、クローラーを使う方式と比べて正確性も高く、サーバーへの負荷も最小限に抑えられます。
cronで短いスパンで実行しても問題ないほど軽量なので、新規投稿後すぐにサイトマップを更新することができます。
このスクリプトは、ドメイン名やパス、データベース情報などを少し手直しすれば、誰でも使えるようになっています。個人のウェブサイトでサイトマップを作りたいと考えている方の参考になれば幸いです。
おわり