const { Client } = require('ssh2'); const fs = require('fs'); const path = require('path'); const conn = new Client(); const localH5Dir = path.join(__dirname, 'dist', 'build', 'h5'); const remoteH5Dir = '/www/huishou/dist/build/h5'; console.log('本地目录:', localH5Dir); fs.readdir(localH5Dir, { withFileTypes: true }, (err, entries) => { if (err) { console.log('本地目录读取失败:', err); return; } console.log('本地文件:', entries.map(e => e.name).join(', ')); }); conn.on('ready', () => { console.log('\nSSH连接成功'); conn.exec(`rm -rf ${remoteH5Dir} && mkdir -p ${remoteH5Dir}`, (err) => { if (err) { console.log('创建目录失败:', err); } else { console.log('目录已准备'); } conn.sftp((err2, sftp) => { if (err2) { console.log('SFTP失败:', err2); conn.end(); return; } console.log('SFTP连接成功'); fs.readdir(localH5Dir, { withFileTypes: true }, (err3, entries) => { if (err3) { console.log('读取本地目录失败:', err3); sftp.end(); conn.end(); return; } console.log('待上传文件数:', entries.length); let uploaded = 0; entries.forEach(entry => { const localPath = path.join(localH5Dir, entry.name); const remotePath = remoteH5Dir + '/' + entry.name; if (entry.isDirectory()) { console.log('创建目录:', remotePath); sftp.mkdir(remotePath, { recursive: true }, (mkdirErr) => { if (mkdirErr && mkdirErr.code !== 4) { console.log('创建目录失败:', remotePath, mkdirErr); } fs.readdir(localPath, { withFileTypes: true }, (err4, subEntries) => { if (err4) { console.log('读取子目录失败:', localPath, err4); return; } subEntries.forEach(subEntry => { const subLocal = path.join(localPath, subEntry.name); const subRemote = remotePath + '/' + subEntry.name; if (subEntry.isFile()) { uploadOneFile(sftp, subLocal, subRemote); } }); }); }); } else { uploadOneFile(sftp, localPath, remotePath); } }); function uploadOneFile(sftp, lPath, rPath) { fs.readFile(lPath, (err, content) => { if (err) { console.log('读取文件失败:', lPath, err); return; } sftp.createWriteStream(rPath).on('close', () => { console.log('上传:', lPath, '->', rPath, content.length, 'bytes'); uploaded++; checkDone(); }).on('error', (e) => { console.log('写入失败:', rPath, e); uploaded++; checkDone(); }).end(content); }); } function checkDone() { if (uploaded >= 100) { console.log('\n=== 验证上传 ==='); conn.exec(`ls -la ${remoteH5Dir}/`, (err5, stream) => { if (err5) { console.log('验证失败:', err5); } else { stream.on('data', (d) => console.log(d.toString())); } stream.on('close', () => { console.log('\n=== 重启Nginx ==='); conn.exec('/www/server/nginx/sbin/nginx -s reload', (err6, stream2) => { stream2.on('close', () => conn.end()); }); }); }); } } }); }); }); }); conn.on('error', (err) => { console.log('连接错误:', err); }); conn.connect({ host: 'hs.yifenbao.cn', port: 22, username: 'root', password: 'Torch1112' });