NodeJs执行Linux脚本

(我们活着不能与草木同腐,不能醉生梦死,枉度人生,要有所作为。——方志敏)

在这里插入图片描述

为什么需要使用NodeJs执行Linux脚本

  1. linux的sh脚本命令编写复杂,在不熟悉linux交互式命令的情况下,使用高级编程语言来执行是最明智的选择
  2. 高级语言的生态较为完善,可以使用各种现成的工具包来完成脚本执行,比如NodeJs的npm,Java的maven等
  3. linux命令较为复杂,通常需要专业的运维来执行各种复杂的命令操作,但使用高级语言则屏蔽了linux底层命令,直接使用高级语言封装好的工具包即可

NodeJs执行脚本命令

应用场景举例

比如以下场景,在传统k8s容器化服务的架构下,每次服务的发布都需要重新安装依赖,快则两三分钟,慢则十分钟甚至更久,在没有专业运维的情况下,我们可以使用NodeJs来执行命令脚本,在每次发布前,对比两个版本的package.json文件,如果不一致,则再安装依赖,否则直接跳过安装阶段,使用当前目录下的node_moodules进行发布,这样在最优的情况下,就能省去依赖安装的时间,极大的提升了服务发布速度

场景细则
上一个版本的node_modules/package.json哪里来的
  • 在不使用容器化的情况下,我们在构建的目标目录下把上一个版本的node_modules/package.json复制来即可
  • 使用容器化的情况下,我们可以直接使用docker镜像生成一个node_modules/package.json缓存,然后加入新版本的Dockerfile下,使用相同的工作目录就可以复用

代码示例

// 在本地环境有nodejs的情况下 直接使用node xx.js执行即可
// 使用nodejs内置破快的exec执行linux命令
const { exec } = require('child_process');
// 本地的新json
const newJson = require('./package.json');
// 从上一个版本中复制来的旧json
const oldJson = require('./old.package.json');

// 安装依赖方法
const installDependencies = async (isInstall) => {
    return new Promise((resolve) =>{
		// 如果不需要安装则打印信息并跳出
        if(!isInstall){
            process.stdout.write('no need to install dependencies \n');
			// 结束promise
            return resolve();
        }
		// 执行yarn安装依赖命令
        const yarn = exec('yarn');
		// 实时监听该命令输入的信息并打印
        yarn.stdout.on('data', (data) => {
            process.stdout.write(data);
        });
		// 实时监听该命令的结束指令并打印
        yarn.stdout.on('end', () => {
            process.stdout.write('dependencies install complete \n');
            return resolve();
        })
		// 实时监听该命令的关闭指定并打印
        yarn.stdout.on('close', () => {
            process.stdout.write('dependencies install close \n');
            return resolve();
        });
    });
};

// 编译打包命令
const buildDist = async ()=>{
    return new Promise((resolve) =>{
		// 执行打包命令
        const yarn = exec('yarn run build');
        yarn.stdout.on('data', (data) => {
            process.stdout.write(data);
        });
        yarn.stdout.on('end', () => {
            process.stdout.write('build complete \n');
            return resolve();
        })
        yarn.stdout.on('close', () => {
            process.stdout.write('build close \n');
            return resolve();
        });
    });
};

// 立即执行函数,对比新旧两个依赖是否相同,然后执行依赖安装和打包编译操作
(async () => {

    const oldPro = oldJson.dependencies;
    const oldDev = oldJson.devDependencies;
    const oldProKeys = Object.keys(oldPro);
    const oldDevKeys = Object.keys(oldDev);

    const newPro = newJson.dependencies;
    const newdDev = newJson.devDependencies;
    const newProKeys = Object.keys(newPro);
    const newDevKeys = Object.keys(newdDev);

    let isInstall = false;

	// 对比新旧package.json的dependencies
    const loopProDependencies = () => {
        if (isInstall) {
            return;
        }
        /**
     * 对比新旧两个版本的安装包,出现以下情况的,需要重新安装依赖包
     * 1. 新的依赖在旧依赖中不存在的
     * 2. 新的依赖和旧依赖中版本号不同的
     */
        for (let i = 0; i < newProKeys.length; i++) {
            const prokey = newProKeys[i];
            const proKeyVersion = newPro[prokey];

            const oldKey = oldProKeys.find((v) => v === prokey);
            if (!oldKey) {
                process.stdout.write(`${prokey} no found, need install dependencies \n`);
                isInstall = true;
                break;
            }
            const oldKeyVersion = oldPro[oldKey];
            const isSameVersion = oldKeyVersion === proKeyVersion;
            if (!isSameVersion) {
                process.stdout.write(`${prokey} version difference, old_version:${oldKeyVersion} new_version:${proKeyVersion} \n`);
                isInstall = true;
                break;
            }
        }
    }

	// 对比新旧package.json的devDependencies
    const loopDevProDependencies = () => {
        if (isInstall) {
            return;
        }
        /**
     * 对比新旧两个版本的开发环境安装包,出现以下情况的,需要重新安装依赖包
     * 1. 新的依赖在旧依赖中不存在的
     * 2. 新的依赖和旧依赖中版本号不同的
     */
        for (let i = 0; i < newDevKeys.length; i++) {
            const devKey = newDevKeys[i];
            const devKeyVersion = newdDev[devKey];
            const oldKey = oldDevKeys.find((v) => v === devKey);
            if (!oldKey) {
                process.stdout.write(`${devKey} no found, need install dependencies \n`);
                isInstall = true;
                break;
            }
            const oldKeyVersion = oldDev[oldKey];
            const isSameVersion = oldKeyVersion === devKeyVersion;
            if (!isSameVersion) {
                process.stdout.write(`${devKey} version difference, old_version:${oldKeyVersion} new_version:${devKeyVersion} \n`);
                isInstall = true;
                break;
            }
        }
    }

    loopProDependencies();
    loopDevProDependencies();

    await installDependencies(isInstall);
    await buildDist();
})();






本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/66598.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【论文研读】MARLlib 的架构分析

【论文研读】MARLlib: A Scalable Multi-agent Reinforcement Learning Library 和尚念经 多智能体强化学习框架研究。 多智能体强化学习库。 多智能体强化学习算法实现。 多智能体强化学习环境的统一化&#xff0c;标准化。 多智能体强化学习算法解析。 多智能体强化学习 算法…

Android 面试重点之Framework (Handler篇)

近期在网上看到不少Android 开发分享的面试经验&#xff0c;我发现基本每个面经中多多少少都有Framework 底层原理的影子。它也是Android 开发中最重要的一个部分&#xff0c;面试官一般会通过 Framework底层中的一些逻辑原理由浅入深进行提问&#xff0c;来评估应聘者的真实水…

小型双轮差速底盘机器人实现红外跟随功能

1. 功能说明 本文示例将实现R023样机小型双轮差速底盘跟随人移动的功能。在小型双轮差速底盘前方按下图所示安装3个 近红外传感器&#xff0c;制作一个红外线发射源&#xff0c;实现当红外发射源在机器人的检测范围内任意放置或移动时&#xff0c;机器人能追踪该发射源。 2. 电…

Teams Room视频会议室方案

需求背景&#xff1a; 适合在40平米的会议室参加Teams视频会议&#xff0c;会议桌周围可以坐20人&#xff0c;要求&#xff1a; 1&#xff0c;操作简单&#xff0c;一键入会Teams Room&#xff1b; 2&#xff0c;任何人带上自己的笔记本电脑&#xff0c;可以分享电脑画面&#…

Linux CEF(Chromium Embedded Framework)源码下载编译详细记录

Linux CEF&#xff08;Chromium Embedded Framework&#xff09;源码下载编译 背景 由于CEF默认的二进制分发包不支持音视频播放&#xff0c;需要自行编译源码&#xff0c;将ffmpeg开关打开才能支持。这里介绍的是Linux平台下的CEF源码下载编译过程。 前置条件 下载的过程非…

搭建Repo服务器

1 安装repo 参考&#xff1a;清华大学开源软件镜像站:Git Repo 镜像使用帮助 2 创建manifest仓库 2.1 创建仓库 git init --bare manifest.git2.2 创建default.xml文件 default.xml文件内容&#xff1a; <?xml version"1.0" encoding"UTF-8" ?…

MySQL语法2

DQL语句介绍 DQL是数据查询语言&#xff0c;用来查询数据库中表的记录 DQL-基本查询语句 SELECT 字段列表 FROM 表名列表 WHERE 条件列表 GROUP BY 分组字段列表 HAVIMG 分组后条件列表 ORDER BY 排列字段列表 LIMIT 分页参数 讲解过程&#xff1a;基本查询、条件查询…

博客网站添加复制转载提醒弹窗Html代码

网站如果是完全禁止右键&#xff08;复制、另存为等&#xff09;操作&#xff0c;对用户来说体验感会降低&#xff0c;但是又不希望自己的原创内容直接被copy&#xff0c;今天飞飞和你们分享几行复制转载提醒弹窗Html代码。 效果展示&#xff1a; 复制以下代码&#xff0c;将其…

c语言每日一练(4)

五道选择题 1、有以下代码&#xff0c;程序的输出结果是( ) #include <stdio.h> int main() {int a 0, b 0;for (a 1, b 1; a < 100; a){if (b > 20) break;//1if (b % 3 1)//2{b b 3;continue;}b b-5;//3}printf("%d\n", a);return 0; } A.1…

一站式印度跨境电商平台开发--多用户购物商城搭建

搭建一个一站式印度跨境电商平台开发&#xff0c;需要考虑以下几个方面&#xff1a;平台设计&#xff0c;技术架构&#xff0c;多用户购物商城搭建。 一、平台设计&#xff1a; 1. 市场调研&#xff1a;了解印度电商市场的特点和需求&#xff0c;确定目标用户群体。 2. 平台功…

【CSS3】CSS3 动画 ④ ( 使用动画制作地图热点图 )

文章目录 一、需求说明二、动画代码分析1、地图背景设置2、热点动画位置测量3、热点动画布局分析4、动画定义5、小圆点实现6、波纹效果盒子实现7、延迟动画设置 三、代码示例 一、需求说明 实现如下效果 , 在一张地图上 , 以某个位置为中心点 , 向四周发散 ; 核心 是实现 向四周…

【Java Web基础】mvn命令、Maven的安装与配置

本文极大程度上来自Maven安装(超详解)&#xff0c;但是担心安的过程中遇到什么不一样的问题&#xff0c;顺便加深印象&#xff0c;所以还是打算自己弄一篇。 目录 第一步&#xff1a;Download Maven第二步&#xff1a;解压与安装2.1 解压2.2 安装 第一步&#xff1a;Download …

Three.js纹理贴图

目录 Three.js入门 Three.js光源 Three.js阴影 Three.js纹理贴图 纹理是一种图像或图像数据&#xff0c;用于为物体的材质提供颜色、纹理、法线、位移等信息&#xff0c;从而实现更加逼真的渲染结果。 纹理可以应用于Three.js中的材质类型&#xff0c;如MeshBasicMaterial…

ClickHouse(九):Clickhouse表引擎 - Log系列表引擎

进入正文前&#xff0c;感谢宝子们订阅专题、点赞、评论、收藏&#xff01;关注IT贫道&#xff0c;获取高质量博客内容&#xff01; &#x1f3e1;个人主页&#xff1a;含各种IT体系技术&#xff0c;IT贫道_Apache Doris,Kerberos安全认证,大数据OLAP体系技术栈-CSDN博客 &…

Clickhouse 数据存储

一、数据分区 数据是以分区目录的形式组织的&#xff0c;每个分区独立分开存储.这种形式&#xff0c;查询数据时&#xff0c;可以有效的跳过无用的数据文件。 1.1 数据分区的规则 分区键的取值&#xff0c;生成分区ID&#xff0c;分区根据ID决定。根据分区键的数据类型不同&am…

PoseiSwap 开启“Poseidon”池,治理体系或将全面开启

PoseiSwap曾在前不久分别以IDO、IEO的方式推出了POSE通证&#xff0c;但PoseiSwap DEX中并未向除Zepoch节点外的角色开放POSE资产的交易。而在前不久&#xff0c;PoseiSwap推出了全新的“Poseidon”池&#xff0c;该池将向所有用户开放&#xff0c;并允许用户自由的进行质押、交…

springboot(2)

springmvc 把软件系统分为3个基本部分&#xff1a;模型&#xff08;Model&#xff09;、视图&#xff08;View&#xff09;和控制器 &#xff08;Controller&#xff09;。 模型&#xff08;Model&#xff09;&#xff1a;Model是由一个实体Bean实现的&#xff0c;是数据的载体…

【Pytorch+torchvision】MNIST手写数字识别

深度学习入门项目&#xff0c;含代码详细解析 在本文中&#xff0c;我们将在PyTorch中构建一个简单的卷积神经网络&#xff0c;并使用MNIST数据集训练它识别手写数字。 MNIST包含70,000张手写数字图像: 60,000张用于培训&#xff0c;10,000张用于测试。图像是灰度&#xff08;即…

特殊符号的制作 台风 示例 使用第三方工具 Photoshop 地理信息系统空间分析实验教程 第三版

特殊符号的制作 首先这是一个含有字符的&#xff0c;使用arcgis自带的符号编辑器制作比较困难。所以我们准备采用Adobe Photoshop 来进行制作符号&#xff0c;然后直接导入符号的图片文件作为符号 我们打开ps&#xff0c;根据上面的图片的像素长宽比&#xff0c;设定合适的高度…