diff --git a/SCRIPTS.md b/SCRIPTS.md new file mode 100644 index 0000000..80805ed --- /dev/null +++ b/SCRIPTS.md @@ -0,0 +1,193 @@ +# CodiMD 管理腳本使用說明 + +這個目錄包含一系列腳本來簡化 CodiMD 的管理。 + +## 🚀 快速開始 + +給所有腳本執行權限: + +```bash +chmod +x *.sh +``` + +## 📜 可用腳本 + +| 腳本 | 功能 | 說明 | +|------|------|------| +| `start.sh` | 啟動服務 | 啟動 CodiMD 和資料庫 | +| `stop.sh` | 停止服務 | 停止所有服務 | +| `restart.sh` | 重啟服務 | 重啟所有服務 | +| `logs.sh` | 查看日誌 | 顯示即時日誌 | +| `status.sh` | 檢查狀態 | 顯示服務狀態和資源使用 | +| `backup.sh` | 備份資料 | 備份資料庫和上傳檔案 | +| `restore.sh` | 還原備份 | 從備份還原資料 | +| `update.sh` | 更新服務 | 更新 Docker 映像 | +| `cleanup.sh` | 清理資源 | 清理未使用的 Docker 資源 | + +## 📖 詳細說明 + +### start.sh - 啟動服務 + +```bash +./start.sh +``` + +功能: +- 檢查 `.env` 是否存在(不存在則複製 `.env.example`) +- 啟動所有 Docker 服務 +- 顯示服務狀態和訪問地址 + +### stop.sh - 停止服務 + +```bash +./stop.sh +``` + +功能: +- 優雅地停止所有服務 +- 保留資料和容器 + +### restart.sh - 重啟服務 + +```bash +./restart.sh +``` + +功能: +- 重啟所有服務 +- 等待服務完全啟動 +- 顯示服務狀態 + +### logs.sh - 查看日誌 + +```bash +# 查看 CodiMD 日誌(預設) +./logs.sh + +# 查看資料庫日誌 +./logs.sh database +``` + +功能: +- 即時顯示服務日誌 +- 按 `Ctrl+C` 離開 + +### status.sh - 檢查狀態 + +```bash +./status.sh +``` + +功能: +- 顯示容器運行狀態 +- 顯示最近 20 行日誌 +- 顯示磁碟空間 +- 顯示 Docker 資源使用 + +### backup.sh - 備份資料 + +```bash +./backup.sh +``` + +功能: +- 備份 PostgreSQL 資料庫 +- 備份上傳檔案 +- 備份環境設定(`.env`) +- 自動清理超過 30 天的舊備份 + +備份位置:`./backups/` + +### restore.sh - 還原備份 + +```bash +./restore.sh +``` + +功能: +- 列出可用的備份 +- 選擇要還原的備份 +- 可選擇還原資料庫、上傳檔案、環境設定 + +### update.sh - 更新服務 + +```bash +./update.sh +``` + +功能: +- 執行備份 +- 拉取最新的 Docker 映像 +- 可選擇立即重啟服務 + +### cleanup.sh - 清理資源 + +```bash +./cleanup.sh +``` + +功能: +- 清理未使用的 Docker 映像 +- 清理停止的容器 +- 清理未使用的網路 +- 清理建置快取 + +## 🔧 設置 Crontab 自動備份 + +編輯 crontab: + +```bash +crontab -e +``` + +添加以下內容(每天凌晨 2 點備份): + +```cron +0 2 * * * cd /path/to/codimd && ./backup.sh >> backups/cron.log 2>&1 +``` + +## 📊 備份範例 + +備份檔案命名格式: + +``` +backups/ +├── database_20260317_020000.sql # 資料庫備份 +├── uploads_20260317_020000.tar.gz # 上傳檔案備份 +├── env_20260317_020000.env # 環境設定備份 +└── backup_20260317_020000.txt # 備份資訊 +``` + +## 🛠️ 故障排除 + +### 腳本無法執行 + +```bash +chmod +x *.sh +``` + +### Docker 未運行 + +```bash +sudo systemctl start docker +``` + +### 權限問題 + +```bash +sudo usermod -aG docker $USER +# 然後重新登入 +``` + +## 📝 注意事事項 + +1. **備份前先測試**:第一次使用建議先手動測試備份和還原 +2. **定期檢查備份**:確認備份檔案完整且可還原 +3. **監控磁碟空間**:定期清理舊備份以節省空間 +4. **保持腳本更新**:更新 CodiMD 時也要檢查腳本是否需要更新 + +## 🔗 相關文件 + +- [README.md](README.md) - 完整部署指南 +- [SSL-SETUP.md](SSL-SETUP.md) - SSL 設置指南 +- [TROUBLESHOOTING.md](TROUBLESHOOTING.md) - 故障排除指南 diff --git a/backup.sh b/backup.sh new file mode 100755 index 0000000..2f54740 --- /dev/null +++ b/backup.sh @@ -0,0 +1,78 @@ +#!/bin/bash +# CodiMD 備份腳本 + +set -e + +# 備份目錄 +BACKUP_DIR="./backups" +TIMESTAMP=$(date +"%Y%m%d_%H%M%S") + +# 建立備份目錄 +mkdir -p "$BACKUP_DIR" + +echo "💾 開始備份 CodiMD..." +echo "📅 備份時間: $(date)" +echo "" + +# 1. 備份資料庫 +echo "📦 備份 PostgreSQL 資料庫..." +docker-compose exec -T database pg_dump -U codimd codimd > "$BACKUP_DIR/database_$TIMESTAMP.sql" + +if [ $? -eq 0 ]; then + DB_SIZE=$(du -h "$BACKUP_DIR/database_$TIMESTAMP.sql" | cut -f1) + echo "✅ 資料庫備份完成 ($DB_SIZE)" +else + echo "❌ 資料庫備份失敗" + exit 1 +fi + +# 2. 備份上傳檔案 +echo "📁 備份上傳檔案..." +UPLOAD_BACKUP="$BACKUP_DIR/uploads_$TIMESTAMP.tar.gz" + +if [ -d "upload-data" ] && [ "$(ls -A upload-data)" ]; then + tar -czf "$UPLOAD_BACKUP" upload-data/ + UPLOAD_SIZE=$(du -h "$UPLOAD_BACKUP" | cut -f1) + echo "✅ 上傳檔案備份完成 ($UPLOAD_SIZE)" +else + echo "⚠️ 沒有上傳檔案需要備份" +fi + +# 3. 備份環境設定 +echo "📝 備份環境設定..." +cp .env "$BACKUP_DIR/env_$TIMESTAMP.env" +echo "✅ 環境設定備份完成" + +# 4. 建立備份資訊文件 +cat > "$BACKUP_DIR/backup_$TIMESTAMP.txt" << EOF +CodiMD 備份資訊 +================ +備份時間: $(date) +備份類型: 完整備份 + +檔案清單: +- 資料庫: database_$TIMESTAMP.sql +- 上傳檔案: uploads_$TIMESTAMP.tar.gz +- 環境設定: env_$TIMESTAMP.env + +還原方式: +1. 資料庫: cat database_$TIMESTAMP.sql | docker-compose exec -T database psql -U codimd codimd +2. 上傳檔案: tar -xzf uploads_$TIMESTAMP.tar.gz +3. 環境設定: cp env_$TIMESTAMP.env .env +EOF + +echo "" +echo "✅ 備份完成!" +echo "" +echo "📂 備份位置: $BACKUP_DIR/" +ls -lh "$BACKUP_DIR" | grep "$TIMESTAMP" +echo "" +echo "💡 還原備份請查看: $BACKUP_DIR/backup_$TIMESTAMP.txt" + +# 清理超過 30 天的舊備份 +echo "" +echo "🧹 清理舊備份(超過 30 天)..." +find "$BACKUP_DIR" -name "database_*.sql" -mtime +30 -delete 2>/dev/null || true +find "$BACKUP_DIR" -name "uploads_*.tar.gz" -mtime +30 -delete 2>/dev/null || true +find "$BACKUP_DIR" -name "env_*.env" -mtime +30 -delete 2>/dev/null || true +echo "✅ 清理完成" diff --git a/cleanup.sh b/cleanup.sh new file mode 100755 index 0000000..8733cfc --- /dev/null +++ b/cleanup.sh @@ -0,0 +1,31 @@ +#!/bin/bash +# CodiMD 清理腳本 + +set -e + +echo "🧹 清理 Docker 資源..." +echo "" + +# 1. 清理未使用的映像 +echo "🗑️ 清理未使用的 Docker 映像..." +docker image prune -f + +# 2. 清理未使用的容器 +echo "🗑️ 清理停止的容器..." +docker container prune -f + +# 3. 清理未使用的網路 +echo "🗑️ 清理未使用的網路..." +docker network prune -f + +# 4. 清理建置快取 +echo "🗑️ 清理建置快取..." +docker builder prune -f + +echo "" +echo "✅ 清理完成!" +echo "" + +# 顯示釋放的空間 +echo "💾 目前 Docker 磁碟使用:" +docker system df diff --git a/logs.sh b/logs.sh new file mode 100755 index 0000000..942be9f --- /dev/null +++ b/logs.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# CodiMD 日誌查看腳本 + +SERVICE=${1:-codimd} + +echo "📋 顯示 $SERVICE 服務日誌(按 Ctrl+C 離開)..." +echo "" + +docker-compose logs -f "$SERVICE" diff --git a/restart.sh b/restart.sh new file mode 100755 index 0000000..1c24e94 --- /dev/null +++ b/restart.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# CodiMD 重啟腳本 + +set -e + +echo "🔄 重啟 CodiMD 服務..." + +# 重啟服務 +docker-compose restart + +echo "" +echo "⏳ 等待服務完全啟動..." +sleep 5 + +# 顯示服務狀態 +echo "" +echo "📊 服務狀態:" +docker-compose ps + +echo "" +echo "✅ CodiMD 已重啟" diff --git a/restore.sh b/restore.sh new file mode 100755 index 0000000..faefca7 --- /dev/null +++ b/restore.sh @@ -0,0 +1,80 @@ +#!/bin/bash +# CodiMD 還原腳本 + +set -e + +BACKUP_DIR="./backups" + +echo "🔄 CodiMD 還原腳本" +echo "" + +# 列出可用的備份 +if [ ! -d "$BACKUP_DIR" ] || [ -z "$(ls -A $BACKUP_DIR/*.sql 2>/dev/null)" ]; then + echo "❌ 找不到備份檔案" + exit 1 +fi + +echo "📂 可用的備份:" +ls -lht "$BACKUP_DIR"/*.sql 2>/dev/null | head -10 +echo "" + +# 詢問要還原的備份 +read -p "請輸入要還原的備份檔案名稱 (例如: database_20260317_120000.sql): " BACKUP_FILE + +if [ ! -f "$BACKUP_DIR/$BACKUP_FILE" ]; then + echo "❌ 找不到檔案: $BACKUP_DIR/$BACKUP_FILE" + exit 1 +fi + +# 提取時間戳記 +TIMESTAMP=$(echo "$BACKUP_FILE" | sed 's/database_\(.*\).sql/\1/') + +echo "" +echo "⚠️ 警告:還原資料庫會覆蓋現有資料!" +read -p "確定要還原嗎?(yes/no): " CONFIRM + +if [ "$CONFIRM" != "yes" ]; then + echo "❌ 取消還原" + exit 0 +fi + +echo "" +echo "🔄 開始還原..." + +# 1. 還原資料庫 +echo "📦 還原資料庫..." +docker-compose exec -T database psql -U codimd codimd < "$BACKUP_DIR/$BACKUP_FILE" + +if [ $? -eq 0 ]; then + echo "✅ 資料庫還原完成" +else + echo "❌ 資料庫還原失敗" + exit 1 +fi + +# 2. 詢問是否還原上傳檔案 +UPLOAD_FILE="$BACKUP_DIR/uploads_$TIMESTAMP.tar.gz" +if [ -f "$UPLOAD_FILE" ]; then + read -p "是否還原上傳檔案?(yes/no): " RESTORE_UPLOAD + if [ "$RESTORE_UPLOAD" = "yes" ]; then + echo "📁 還原上傳檔案..." + rm -rf upload-data/* + tar -xzf "$UPLOAD_FILE" + echo "✅ 上傳檔案還原完成" + fi +fi + +# 3. 詢問是否還原環境設定 +ENV_FILE="$BACKUP_DIR/env_$TIMESTAMP.env" +if [ -f "$ENV_FILE" ]; then + read -p "是否還原環境設定?(yes/no): " RESTORE_ENV + if [ "$RESTORE_ENV" = "yes" ]; then + echo "📝 還原環境設定..." + cp "$ENV_FILE" .env + echo "✅ 環境設定還原完成" + echo "⚠️ 請執行 ./restart.sh 以套用新設定" + fi +fi + +echo "" +echo "✅ 還原完成!" diff --git a/start.sh b/start.sh new file mode 100755 index 0000000..5848581 --- /dev/null +++ b/start.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# CodiMD 啟動腳本 + +set -e + +echo "🚀 啟動 CodiMD 服務..." + +# 檢查 .env 是否存在 +if [ ! -f .env ]; then + echo "⚠️ .env 檔案不存在,從 .env.example 複製..." + cp .env.example .env + echo "✅ 已建立 .env 檔案" + echo "⚠️ 請編輯 .env 檔案,設定強密碼和域名" + echo " nano .env" + echo "" + read -p "按 Enter 繼續或 Ctrl+C 取消..." +fi + +# 檢查 Docker 是否運行 +if ! docker info > /dev/null 2>&1; then + echo "❌ Docker 未運行,請先啟動 Docker" + exit 1 +fi + +# 啟動服務 +docker-compose up -d + +echo "" +echo "⏳ 等待服務啟動..." +sleep 5 + +# 顯示服務狀態 +echo "" +echo "📊 服務狀態:" +docker-compose ps + +echo "" +echo "✅ CodiMD 已啟動!" +echo "" +echo "🌐 訪問地址:" +echo " 本地: http://localhost:3000" +echo " 外部: http://$(hostname -I | awk '{print $1}'):3000" +echo "" +echo "📝 查看日誌: ./logs.sh" +echo "🛑 停止服務: ./stop.sh" +echo "🔄 重啟服務: ./restart.sh" diff --git a/status.sh b/status.sh new file mode 100755 index 0000000..c86e818 --- /dev/null +++ b/status.sh @@ -0,0 +1,33 @@ +#!/bin/bash +# CodiMD 狀態檢查腳本 + +echo "🔍 檢查 CodiMD 服務狀態..." +echo "" + +# 顯示容器狀態 +echo "📊 Docker 容器狀態:" +docker-compose ps +echo "" + +# 檢查服務是否正常 +if docker-compose ps | grep -q "Up (healthy)"; then + echo "✅ 所有服務運行正常" +else + echo "⚠️ 部分服務可能未正常運行" +fi + +echo "" + +# 顯示最近日誌 +echo "📋 最近日誌(最後 20 行):" +docker-compose logs --tail=20 +echo "" + +# 檢查磁碟空間 +echo "💾 磁碟空間:" +df -h | grep -E "Filesystem|/$" +echo "" + +# 檢查 Docker 資源使用 +echo "📊 Docker 資源使用:" +docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}" 2>/dev/null || echo "無法取得資源使用資訊" diff --git a/stop.sh b/stop.sh new file mode 100755 index 0000000..7e193d3 --- /dev/null +++ b/stop.sh @@ -0,0 +1,14 @@ +#!/bin/bash +# CodiMD 停止腳本 + +set -e + +echo "🛑 停止 CodiMD 服務..." + +# 停止服務 +docker-compose down + +echo "" +echo "✅ CodiMD 已停止" +echo "" +echo "💡 重新啟動: ./start.sh" diff --git a/update.sh b/update.sh new file mode 100755 index 0000000..d955100 --- /dev/null +++ b/update.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# CodiMD 更新腳本 + +set -e + +echo "🔄 更新 CodiMD..." +echo "" + +# 1. 備份現有資料 +echo "💾 更新前備份..." +./backup.sh +echo "" + +# 2. 拉取最新映像 +echo "📥 拉取最新 Docker 映像..." +docker-compose pull +echo "" + +# 3. 詢問是否重啟 +read -p "是否現在重啟服務以套用更新?(yes/no): " RESTART + +if [ "$RESTART" = "yes" ]; then + echo "🔄 重啟服務..." + docker-compose down + docker-compose up -d + + echo "" + echo "⏳ 等待服務啟動..." + sleep 10 + + echo "" + echo "📊 服務狀態:" + docker-compose ps + + echo "" + echo "✅ 更新完成!" + echo "" + echo "📝 查看日誌: ./logs.sh" +else + echo "" + echo "⚠️ 映像已下載,但服務尚未重啟" + echo "💡 稍後可執行 ./restart.sh 來套用更新" +fi