nodejs脚本部署到服务器自动运行

1. 安装宝塔

Linux服务器:https://www.bt.cn/new/download.html

cpp 复制代码
wget -O install_panel.sh https://download.bt.cn/install/install_panel.sh && sudo bash install_panel.sh ssl251104

2. 创建非root用户(sct_test)

bash 复制代码
# 创建一个新的用户组,组名为 sct_test
sudo groupadd sct_test
 
# 创建一个新的用户,用户名为 sct_test,并指定主组为 sct_test
sudo useradd -g sct_test sct_test
 
# 设置或更改用户密码
sudo passwd XXX

3. 用sct_test用户,安装nvm、node

bash 复制代码
cd /home
# 安装nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash
# 查看是否安装成功
nvm -v

# 成功后 安装node
nvm install 18.18.2
# 查看是否安装成功
node -v

4. 部署项目

后端项目

将自己写的nodejs后端脚本上传至'/home/wangdou/serve'

saveFile.js

bash 复制代码
const express = require('express');
const cors = require('cors');
const ExcelJS = require('exceljs');
const path = require('path');
const fs = require('fs');

const app = express();

app.use(cors({
  origin: '*',
//   methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
//   allowedHeaders: ['Content-Type', 'Authorization'],
}));



// 中间件, 允许所有跨域
// app.use(cors());
app.use(express.json({ limit: '50mb' }));

// 确保存储目录存在
const storageDir = path.join(__dirname, 'exports');
if (!fs.existsSync(storageDir)) {
  fs.mkdirSync(storageDir, { recursive: true });
}

// 将数组保存为Excel文件
app.post('/api/save-excel', async (req, res) => {
  try {
    const { 
      data, 
      fileName = `export_${Date.now()}.xlsx`,
      sheetName = 'Sheet1',
      headers = null,
      savePath = null
    } = req.body;

    if (!data || !Array.isArray(data)) {
      return res.status(400).json({ 
        error: 'Invalid data format. Expected array.' 
      });
    }

    // 创建工作簿
    const workbook = new ExcelJS.Workbook();
    const worksheet = workbook.addWorksheet(sheetName);

    // 如果有自定义表头,使用表头,否则使用数据的键作为表头
    if (headers && Array.isArray(headers)) {
      worksheet.addRow(headers);
      data.forEach(item => {
        const row = headers.map(header => item[header] || '');
        worksheet.addRow(row);
      });
    } else if (data.length > 0) {
      // 自动获取表头
      const firstRow = data[0];
      const autoHeaders = Object.keys(firstRow);
      worksheet.addRow(autoHeaders);
      
      // 添加数据行
      data.forEach(item => {
        const row = autoHeaders.map(header => item[header] || '');
        worksheet.addRow(row);
      });
    }

    // 设置列宽
    worksheet.columns.forEach(column => {
      column.width = 20;
    });

    // 设置保存路径
    const finalPath = savePath 
      ? path.join(storageDir, savePath) 
      : path.join(storageDir, fileName);

    // 确保目录存在
    const dir = path.dirname(finalPath);
    if (!fs.existsSync(dir)) {
      fs.mkdirSync(dir, { recursive: true });
    }

    // 保存文件
    await workbook.xlsx.writeFile(finalPath);

    res.json({
      success: true,
      message: 'Excel文件已保存',
      path: finalPath,
      fileName: path.basename(finalPath),
      downloadUrl: `/download/${path.basename(finalPath)}`
    });
  } catch (error) {
    console.error('保存Excel文件失败:', error);
    res.status(500).json({ 
      error: '保存文件失败', 
      details: error.message 
    });
  }
});

// 下载Excel文件
app.get('/download/:filename', (req, res) => {
  try {
    const filePath = path.join(storageDir, req.params.filename);
    
    if (!fs.existsSync(filePath)) {
      return res.status(404).json({ error: '文件不存在' });
    }

    res.download(filePath, req.params.filename, (err) => {
      if (err) {
        console.error('下载文件失败:', err);
      }
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// 获取已保存的文件列表
app.get('/api/files', (req, res) => {
  try {
    const files = fs.readdirSync(storageDir)
      .filter(file => file.endsWith('.xlsx') || file.endsWith('.xls'))
      .map(file => ({
        name: file,
        path: path.join(storageDir, file),
        size: fs.statSync(path.join(storageDir, file)).size,
        created: fs.statSync(path.join(storageDir, file)).birthtime
      }));

    res.json(files);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

const PORT = process.env.PORT || 8002;
app.listen(PORT, () => {
  console.log(`服务器运行在 http://localhost:${PORT}`);
  console.log(`Excel文件保存目录: ${storageDir}`);
});
bash 复制代码
# 查看serve文件夹所属的用户和组
ls -l

若serve文件夹所属的用户和组 非sct_test,则需修改

bash 复制代码
# 修改文件夹所属的用户和组
sudo chown sct_test sct_test ./serve
前端项目

a. 创建网站

b. 添加文件:将前端打包的文件 上传至对应网站的文件夹下

5. 安装插件

进入/home/wangdou/serve

bash 复制代码
npm install express xxx xxx

脚本能正常运行,则说明环境搭建成功

bash 复制代码
node saveFile.js

6. 创建自动运行服务

查看node安装路径

创建文件/etc/systemd/system/webUI.service

文件内容如下

bash 复制代码
[Unit]
Description=li laoshi web service
After=network.target

[Service]
Type=simple
User=sct_test
WorkingDirectory=/home/wangdou/serve
ExecStart=/home/sct_test/.nvm/versions/node/v18.18.2/bin/node /home/wangdou/serve/saveFile.js
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target

重新加载systemd

bash 复制代码
sudo systemctl daemon-reload

启动服务

bash 复制代码
sudo systemctl start webUI
sudo systemctl enable webUI  # 开机自启

查看状态

bash 复制代码
sudo systemctl status webUI
journalctl -u myapp -f  # 查看日志

active说明运行成功

7. 开放端口

阿里云开放8002

宝塔也需开放8002

8. 浏览网址,查看是否成功

相关推荐
嘿嘻哈呀1 天前
Node.js和包管理工具
node.js
winfredzhang1 天前
构建自动化 Node.js 项目管理工具:从文件夹监控到一键联动运行
chrome·python·sqlite·node.js·端口·运行js
winfredzhang1 天前
实战:从零构建一个支持屏幕录制与片段合并的视频管理系统 (Node.js + FFmpeg)
ffmpeg·node.js·音视频·录屏
shughui1 天前
2026最新版Node.js下载安装、版本选择 及 环境配置教程(详细图文附安装包)
node.js
小李子呢02111 天前
Node.js
开发语言·前端·学习·node.js
心.c1 天前
文件上传 - 入门篇
前端·javascript·vue.js·node.js·js
xiaoxue..1 天前
Nest.js 框架 企业级开发通关手册
面试·typescript·node.js·开发框架·nest.js
20年编程老鸟java+ai全栈2 天前
零基础搞定开发环境:PHP + Node.js + MongoDB + Python 一键安装全攻略
python·mongodb·node.js·php
ggaofeng2 天前
实践NPM打包和使用
前端·npm·node.js