Nodejs一键发布脚本

发布时间:2024年01月24日

背景

前端项目或者nodejs项目分开发、测试、生产环境,有的没有没有接入 jenkins。每次都需要进行本地打包, 手动压缩上传到服务器目录,ssh 登录服务器后备份旧文件, 手动删除文件再将包解压到指定目录,操作流程比较繁琐,需要提前了解服务器部署目录,不太友好。

目标

  • 根据packeage.json 的scripts 来配置测试和生产环境的脚本。

  • 根据运行脚本获取相关环境的配置

  • 在部署脚本里面处理环境配置,然后实现

    • SSH登陆服务器

    • 压缩目录

    • 上传文件到服务器

    • 备份并删除服务器上的原文件

    • 解压服务器上的文件

需要用到的包

npm install dotenv dotenv-cli node-ssh silly-datetime archiver

以下是对这几个包的简要说明:

  1. dotenv:dotenv是一个流行的Node.js库,用于从.env文件中加载环境变量,并使其在应用程序中可用。它可以帮助您在开发过程中轻松管理环境变量,而无需硬编码到代码中。
  2. dotenv-cli:dotenv-cli是dotenv的命令行工具,它允许您在命令行中运行脚本时加载.env文件中的环境变量。这对于在命令行中运行脚本或执行其他命令时,临时设置环境变量非常有用。
  3. node-ssh:node-ssh是一个用于在Node.js中执行SSH操作的库。它提供了一组API,使您可以连接到远程服务器,执行命令,上传和下载文件等。它对于在Node.js应用程序中与远程服务器进行交互非常有用。
  4. silly-datetime:silly-datetime是一个简单的日期和时间格式化工具。它提供了一些函数,可以帮助您格式化日期和时间,例如将日期格式化为指定的字符串,获取当前时间戳等。
  5. archiver:archiver是一个用于创建和提取归档文件(如zip、tar等)的库。它提供了一组API,使您可以创建压缩文件,添加文件或文件夹到压缩文件中,以及从压缩文件中提取文件。它对于在Node.js中处理归档文件非常有用。

代码

环境变量文件 .env.test

SERVER_IP=47.xx.xx.209
SERVER_USER_NAME=root
SERVER_PASSWORD=xxxxxxx
SERVER_PROJECT_PATH=/www/wwwroot/xxxx
DIST_PATH=dist

package.json

"scripts": {
    "build-deploy:test": "dotenv -e .env.test node deploy.js",
    "build-deploy:pro": "dotenv -e .env.production node deploy.js",
  }

部署代码 deploy.js

const fs = require('fs');
const path = require('path');
const archiver = require('archiver');
const {NodeSSH} = require('node-ssh');
const sd = require('silly-datetime');
// 加载配置文件
require('dotenv').config()
// 当前时间
const curTime = sd.format(new Date(), 'YYYYMMDDHH');
const distPath = path.resolve(__dirname, process.env.DIST_PATH);
const ssh = new NodeSSH();
// 远程服务器配置信息
let config = {
  host: process.env.SERVER_IP,
  username: process.env.SERVER_USER_NAME,
  password: process.env.SERVER_PASSWORD,
  pathUrl: process.env.SERVER_PROJECT_PATH,
}



// 本地文件上传至远程服务器
async function uploadFile() {
  try {
    await ssh.connect({
      host: config.host,
      username: config.username,
      password: config.password,
      port: 22,
    });
    console.log('SSH login success');
    await ssh.putFile(
      `${__dirname}/dist${curTime}.zip`,
      `${config.pathUrl}/dist${curTime}.zip`
    );
    console.log('The zip file is uploaded successfully');
    remoteFileUpdate();
  } catch (err) {
    console.log('The file upload failed:', err);
    process.exit(0);
  }
}

// 服务端远端文件解压,更新
async function remoteFileUpdate() {
  let cmd =`mv dist dist.bak${curTime} && unzip dist${curTime}.zip`;
  try {
    const result = await ssh.execCommand(cmd, {
      cwd: config.pathUrl,
    });
    console.log(`The update message is: ${result.stdout}`);
    if (!result.stderr) {
      console.log('Congratulations! Update success!');
      process.exit(0);
    } else {
      console.log('Something went wrong:', result);
      process.exit(0);
    }
  } catch (err) {
    console.log('SSH connection failed:', err);
    process.exit(0);
  }
}

// 本地文件压缩
function zipDirector() {
  try {
    const output = fs.createWriteStream(`${__dirname}/dist${curTime}.zip`);
    const archive = archiver('zip', {
      zlib: {level: 9},
    });
    output.on('close', (err) => {
      if (err) {
        console.log('Something went wrong with the zip process:', err);
        return;
      }
      uploadFile();//本地文件上传至远程服务器
      console.log(`${archive.pointer()} total bytes`);
      console.log('Archiver has been finalized and the output file descriptor has closed.');
    });
    output.on('end', () => {
      console.log('Data has been drained');
    });
    archive.pipe(output);
    //要压缩的文件夹路径,和输出路径
    // 设置本地 dist 文件路径
    console.log(distPath)
    // 将指定目录打包压缩到压缩包中,并且重命名为h5
    archive.directory(distPath, "dist");
    archive.finalize();
  } catch (e) {
    console.log(e)
  }
}

(function() {
  // 更新代码
  zipDirector();
})()

文章来源:https://blog.csdn.net/No_Name_Cao_Ni_Mei/article/details/135823122
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。