gongxiangp2/scripts/check-missing-files-via-ssh.sh

152 lines
4.9 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# 通过SSH检查缺失的源文件并生成CSV报告
SERVER_IP="${SERVER_IP:-192.168.58.20}"
SERVER_USER="${SERVER_USER:-root}"
SERVER_UPLOADS_PATH="${SERVER_UPLOADS_PATH:-/mnt/PoolOne/apps/youyidian-3d/uploads}"
SSH_KEY_PATH="${SSH_KEY_PATH:-$HOME/.ssh/id_rsa}"
SSH_PORT="${SSH_PORT:-22}"
OUTPUT_FILE="${1:-missing-source-files-$(date +%Y%m%d-%H%M%S).csv}"
echo "============================================================"
echo "检查素材源文件缺失情况"
echo "============================================================"
echo "服务器: ${SERVER_USER}@${SERVER_IP}:${SSH_PORT}"
echo "服务器路径: ${SERVER_UPLOADS_PATH}"
echo "输出文件: ${OUTPUT_FILE}"
echo ""
# 测试SSH连接
echo "🔌 测试SSH连接..."
if ! ssh -i "${SSH_KEY_PATH}" -p ${SSH_PORT} -o ConnectTimeout=10 -o StrictHostKeyChecking=no ${SERVER_USER}@${SERVER_IP} "hostname" > /dev/null 2>&1; then
echo "❌ SSH连接失败"
exit 1
fi
echo "✅ SSH连接成功"
echo ""
# 在服务器上执行检查(通过Docker容器连接数据库)
echo "📋 查询数据库并检查文件..."
ssh -i "${SSH_KEY_PATH}" -p ${SSH_PORT} -o StrictHostKeyChecking=no ${SERVER_USER}@${SERVER_IP} << 'EOF'
cd /mnt/PoolOne/apps/youyidian-3d
# 使用Docker容器执行Node.js脚本
docker exec youyidian-3d-material node -e "
const { PrismaClient } = require('@prisma/client');
const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');
const prisma = new PrismaClient();
const uploadsPath = '/mnt/PoolOne/apps/youyidian-3d/uploads';
async function checkFiles() {
const materials = await prisma.material.findMany({
where: { deletedAt: null },
select: {
id: true,
materialType: true,
productModel: true,
authorName: true,
categoryName: true,
sceneName: true,
platformName: true,
productCategoryName: true,
renderer: true,
zipFilePath: true,
zipFileName: true,
zipFileSize: true,
createdAt: true,
updatedAt: true,
},
orderBy: { createdAt: 'desc' },
});
const results = [];
let checked = 0;
for (const m of materials) {
checked++;
let fileExists = false;
if (m.zipFilePath && (m.zipFilePath.startsWith('uploads/') || m.zipFilePath.startsWith('/app/uploads/'))) {
const fileName = path.basename(m.zipFilePath);
const filePath = path.join(uploadsPath, fileName);
try {
fs.accessSync(filePath, fs.constants.F_OK);
fileExists = true;
} catch {
fileExists = false;
}
} else if (m.zipFilePath && (m.zipFilePath.startsWith('http://') || m.zipFilePath.startsWith('https://'))) {
fileExists = true; // HTTP URL标记为存在
}
if (!fileExists) {
results.push({
id: m.id,
materialType: m.materialType || '',
productModel: m.productModel || '',
authorName: m.authorName || '',
categoryName: m.categoryName || '',
sceneName: m.sceneName || '',
platformName: m.platformName || '',
productCategoryName: m.productCategoryName || '',
renderer: m.renderer || '',
zipFilePath: m.zipFilePath || '',
zipFileName: m.zipFileName || '',
zipFileSize: m.zipFileSize ? m.zipFileSize.toString() : '',
createdAt: m.createdAt.toISOString(),
updatedAt: m.updatedAt.toISOString(),
});
}
if (checked % 100 === 0) {
console.error(\`已检查: \${checked}/\${materials.length}\`);
}
}
// 生成CSV
const headers = ['素材ID', '素材类型', '产品型号(SPU)', '作者', '使用店铺', '场景类别', '平台分类', '品类分类', '渲染器', '源文件路径', '源文件名', '源文件大小(字节)', '创建时间', '更新时间'];
const csvRows = [headers.join(',')];
for (const r of results) {
const escape = (s) => {
if (s === null || s === undefined) return '';
const str = String(s);
if (str.includes(',') || str.includes('\"') || str.includes('\n')) {
return '\"' + str.replace(/\"/g, '\"\"') + '\"';
}
return str;
};
csvRows.push([
r.id, r.materialType, r.productModel, r.authorName, r.categoryName,
r.sceneName, r.platformName, r.productCategoryName, r.renderer,
r.zipFilePath, r.zipFileName, r.zipFileSize,
r.createdAt, r.updatedAt
].map(escape).join(','));
}
console.log(csvRows.join('\n'));
await prisma.\$disconnect();
}
checkFiles().catch(console.error);
" > /tmp/missing-files.csv
EOF
# 下载CSV文件到本地
echo "📥 下载CSV报告..."
scp -i "${SSH_KEY_PATH}" -P ${SSH_PORT} ${SERVER_USER}@${SERVER_IP}:/tmp/missing-files.csv "${OUTPUT_FILE}"
echo ""
echo "✅ CSV报告已生成: ${OUTPUT_FILE}"
echo ""
# 显示统计信息
echo "📊 统计信息:"
ssh -i "${SSH_KEY_PATH}" -p ${SSH_PORT} -o StrictHostKeyChecking=no ${SERVER_USER}@${SERVER_IP} "wc -l /tmp/missing-files.csv"