前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >NodeJS运行Shell的方式及搭建运维平台

NodeJS运行Shell的方式及搭建运维平台

作者头像
码客说
发布2021-04-13 16:06:17
8.8K0
发布2021-04-13 16:06:17
举报
文章被收录于专栏:码客码客

常用的方式

child_process(原生)

Nodejs下引入模块child_process实现调用shell

调用的两种方式

child_process.exec(command[, options][, callback])
child_process.execFile(file[, args][, options][, callback])

Nodejs中通过 exec执行shell脚本,并打印查询到的信息

var child = require('child_process');

child.exec('ls', function(err, sto) {
    console.log(sto);//sto才是真正的输出,要不要打印到控制台,由你自己啊
})

执行文件

const exec = require('child_process').execSync
exec('bash ./shell/shell1.sh hello')

对应的shell文件

#!/bin/bash
# This is our first script.
echo "$1" > log.txt

示例

const util = require('util');
const path = require('path');
const child_process = require('child_process');
// 调用util.promisify方法,返回一个promise,如const { stdout, stderr } = await exec('rm -rf build')
const exec = util.promisify(child_process.exec);
const appPath = path.join(__dirname, 'app');

const runClean = async function () {
  // cwd指定子进程的当前工作目录 这里的rm -rf build为删除指定目录下的一个文件夹
  await exec(`rm -rf build`, {
    cwd: appPath
  });
  await exec(`rm -rf test`, {
    cwd: appPath
  });
}
runClean();

注意

util.promisify是在node.js 8.x版本中新增的一个工具,用于将老式的Error first callback转换为Promise对象,让老项目改造变得更为轻松。

shelljs(三方)

shelljs是j基于nodeAPI的一个扩展,要引入插件:(npm地址);

它比原生的child_process的兼容性更好,使用更灵活,这个插件的使用率很高。

安装

npm install shelljs

和child_process同样的调用方式

var shell = require('shelljs');
var version = shell.exec('node --version', {
  silent: true
}).stdout;
console.info("version", version);

var child = shell.exec('pwd', {
  async: true
});

child.stdout.on('data', function (data) {
  console.log('data:', data);
});

shell.exec('pwd', function (code, stdout, stderr) {
  console.log('Exit code:', code);
  console.log('Program output:', stdout);
  console.log('Program stderr:', stderr);
});

这个插件不仅可以调用exec执行shell命令,也封装了一些快捷操作指令,具体使用文档请参考github地址。

var shell = require('shelljs');
// cat 返回文件内容
const mdres = shell.cat(' * .md')

// pwd 获取当前目录
const res = shell.pwd();

// 查找文件
shell.find('src', 'lib');
shell.find(['src', 'lib']); // same as above
shell.find('.').filter(function (file) {
  return file.match(/.js$/);
});

// 创建目录
shell.mkdir('-p', '/tmp/a / b / c / d', '/tmp/e / f / g');
shell.mkdir('-p', ['/tmp/a / b / c / d', '/tmp/e / f / g']);

// 复制
shell.cp('file1', 'dir1');
shell.cp('-R', 'path/to/dir/', '~/newCopy/');
shell.cp('-Rf', '/tmp/*', '/usr/local/*', '/home/tmp');
shell.cp('-Rf', ['/tmp/*', '/usr/local/*'], '/home/tmp'); // same as above

官方示例

var shell = require('shelljs');
if (!shell.which('git')) {
  shell.echo('Sorry, this script requires git');
  shell.exit(1);
}
 
// Copy files to release dir
shell.rm('-rf', 'out/Release');
shell.cp('-R', 'stuff/', 'out/Release');
 
// Replace macros in each .js file
shell.cd('lib');
shell.ls('*.js').forEach(function (file) {
  shell.sed('-i', 'BUILD_VERSION', 'v0.1.2', file);
  shell.sed('-i', /^.*REMOVE_THIS_LINE.*$/, '', file);
  shell.sed('-i', /.*REPLACE_LINE_WITH_MACRO.*\n/, shell.cat('macro.js'), file);
});
shell.cd('..');
 
// Run external tool synchronously
if (shell.exec('git commit -am "Auto-commit"').code !== 0) {
  shell.echo('Error: Git commit failed');
  shell.exit(1);
}

simple-git(GIT)

执行shell脚本操作git,其实对于复杂的git命令语句,写起来还是很不方便,最后介绍一个专为git设计的插件:simple-git(npm地址)

  1. 在项目中引入插件后,调用simple-git/promise可执行异步git操作,方便结合async/await使用
  2. 它封装并支持了很多git的方法,比如clone、commit、status、pull等等,将cmd命令和参数,传入即可
  3. 甚至可以用git.raw(),解析前端输入的git命令

安装

npm install simple-git

示例

const simpleGit = require('simple-git/promise');
const path = require('path');

async function gitinit() {
  const projectPath = path.join(__dirname);
  const cmd = "init";
  const args = "";
  const git = simpleGit(projectPath);

  try {
    const res = await git[cmd](args);
    console.info("res:", res);
  } catch (e) {
    console.error('执行 simple-git 命令时发生错误', {
      projectPath,
      cmd,
      args
    }, e);
    throw e;
  }
}

gitinit();

总结

这里总结了几种基于node的方式:

  1. child_process 原生nodeAPI,需根据需要选型
  2. shelljs Node的一个扩展插件、兼容性好,推荐使用
  3. simple-git 专为git命令打造的插件,轻量好用

常用的命令

NodeJS获取系统信息

http://nodejs.cn/api/os.html

操作系统类型

const os = require('os');
var platform=os.platform();
console.log(platform);

返回值有

  • darwin
  • freebsd
  • linux
  • sunos
  • win32

操作系统版本

const os = require('os');
var release=os.release();
console.log(release);

负载

const os = require('os');
var loadavg = os.loadavg();
console.log(loadavg);

os.loadavg() 方法返回一个数组,包含 1、5 和 15 分钟平均负载。

平均负载是系统活动的测量,由操作系统计算得出,表达为一个分数。 一般来说,平均负载应该理想地比系统的逻辑 CPU 的数目要少。

平均负载是 UNIX 相关的概念,在 Windows 平台上没有对应的概念。 在 Windows 上,其返回值总是 [0, 0, 0]

CPU和内存

const os = require('os');
console.log('剩余内存(M):' + parseInt(os.freemem() / 1024 / 1024));
console.log('总内存(M):' + parseInt(os.totalmem() / 1024 / 1024));
console.log('CPU 架构:' + os.arch());
var cpus = os.cpus();
console.log('CPU:' + cpus.length + '核 ' + cpus[0].speed + 'mHz');

网卡信息

const os = require('os');
console.log('网卡:', os.networkInterfaces());

分配的网络地址的对象上可用的属性包括:

  • address分配的 IPv4 或 IPv6 地址。
  • netmask IPv4 或 IPv6 的子网掩码。
  • family IPv4IPv6
  • mac 网络接口的 MAC 地址。
  • internal 如果网络接口是不可远程访问的环回接口或类似接口,则为 true,否则为 false
  • scopeid 数值型的 IPv6 作用域 ID(仅当 familyIPv6 时指定)。
  • cidr 以 CIDR 表示法分配的带有路由前缀的 IPv4 或 IPv6 地址。如果 netmask 无效,则此属性会被设为 null

硬盘

添加依赖

npm i diskinfo

查看硬盘

var diskinfo = require('diskinfo');
//获得所有磁盘空间
diskinfo.getDrives(function (err, aDrives) {
  //遍历所有磁盘信息
  for (var i = 0; i < aDrives.length; i++) {
    //盘符号
    var mounted = 'mounted ' + aDrives[i].mounted;
    //总量
    var total = 'total ' + (aDrives[i].blocks / 1024 / 1024 / 1024).toFixed(1) + "gb";
    //已使用
    var used = 'used ' + (aDrives[i].used / 1024 / 1024 / 1024).toFixed(1) + "gb";
    //可用
    var available = 'available ' + (aDrives[i].available / 1024 / 1024 / 1024).toFixed(1) + "gb";
    //使用率
    var capacity = 'capacity ' + aDrives[i].capacity;
    console.log(mounted + "\r\n" + total + "\r\n" + used + "\r\n" + available + "\r\n" + capacity);
    console.log("==================================================================");
  }
});

解析Nginx配置

安装依赖

npm install nginx-conf

说明文档:https://www.npmjs.com/package/nginx-conf

生成静态项目配置

const NginxConfFile = require('nginx-conf').NginxConfFile;
var fs = require('fs');

//配置项
let conf_path = `${__dirname}/nginx/`;
let server_name = "test.psvmc.cn";
let cert_pem = "/etc/nginx/cert/xhkjedu.pem";
let cert_key = "/etc/nginx/cert/xhkjedu.key";
let root_path = "/data/web_front/psvmc.com";
let useSSL = true;

const filename = `${conf_path}${server_name}.conf`;

fs.access(filename, fs.constants.F_OK, (err) => {
  if (!err) {
    fs.unlinkSync(filename);
  }
  fs.writeFile(filename, '', {
    'flag': 'a'
  }, function (err) {
    if (err) {
      throw err;
    }
    readconf();
  });
});

function readconf() {
  let server_name = "www.psvmc.cn";
  NginxConfFile.create(filename, function (err, conf) {
    if (err || !conf) {
      console.log(err);
      return;
    }

    // server
    conf.nginx._add('server');

    conf.nginx.server[0]._add('listen', '80');
    conf.nginx.server[0].listen[0]._comments.push('http');
    conf.nginx.server[0]._add('server_name', server_name);
    conf.nginx.server[0]._add('client_max_body_size', '200m');

    if (useSSL) {
      // SSL
      conf.nginx.server[0]._add('listen', '443');
      conf.nginx.server[0].listen[1]._comments.push('https');
      conf.nginx.server[0]._add('ssl', 'on');
      conf.nginx.server[0]._add('ssl_certificate', cert_pem);
      conf.nginx.server[0]._add('ssl_certificate_key', cert_key);
      conf.nginx.server[0]._add('ssl_session_timeout', '5m');
      conf.nginx.server[0]._add('ssl_ciphers', 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4');
      conf.nginx.server[0]._add('ssl_protocols', 'TLSv1 TLSv1.1 TLSv1.2');
      conf.nginx.server[0]._add('ssl_prefer_server_ciphers', 'on');
    }


    // location
    conf.nginx.server[0]._add('location', '/');
    conf.nginx.server[0].location[0]._comments.push('location');
    conf.nginx.server[0].location[0]._add('root', root_path);
    conf.nginx.server[0].location[0]._add('index', 'index.html');

    console.info("server_name", conf.nginx.server[0].server_name[0]._value);
  });
}

生成反向代理配置

const NginxConfFile = require('nginx-conf').NginxConfFile;
var fs = require('fs');

//配置项
let conf_path = `${__dirname}/nginx/`;
let server_name = "test.psvmc.cn";
let upstream_name = server_name.split(".").join("_");
let server_arr = ['110.110.110.110:8080', '120.120.120.120:8080'];
let cert_pem = "/etc/nginx/cert/xhkjedu.pem";
let cert_key = "/etc/nginx/cert/xhkjedu.key";
let useSSL = true;

const filename = `${conf_path}${server_name}.conf`;

fs.access(filename, fs.constants.F_OK, (err) => {
  if (!err) {
    fs.unlinkSync(filename);
  }
  fs.writeFile(filename, '', {
    'flag': 'a'
  }, function (err) {
    if (err) {
      throw err;
    }
    readconf();
  });
});

function readconf() {
  NginxConfFile.create(filename, function (err, conf) {
    if (err || !conf) {
      console.log(err);
      return;
    }

    // upstream
    conf.nginx._add('upstream', upstream_name);
    for (const server_item of server_arr) {
      conf.nginx.upstream[0]._add('server', server_item);
    }

    // server
    conf.nginx._add('server');

    conf.nginx.server[0]._add('listen', '80');
    conf.nginx.server[0].listen[0]._comments.push('http');
    conf.nginx.server[0]._add('server_name', server_name);
    conf.nginx.server[0]._add('client_max_body_size', '200m');

    if (useSSL) {
      // SSL
      conf.nginx.server[0]._add('listen', '443');
      conf.nginx.server[0].listen[1]._comments.push('https');
      conf.nginx.server[0]._add('ssl', 'on');
      conf.nginx.server[0]._add('ssl_certificate', cert_pem);
      conf.nginx.server[0]._add('ssl_certificate_key', cert_key);
      conf.nginx.server[0]._add('ssl_session_timeout', '5m');
      conf.nginx.server[0]._add('ssl_ciphers', 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4');
      conf.nginx.server[0]._add('ssl_protocols', 'TLSv1 TLSv1.1 TLSv1.2');
      conf.nginx.server[0]._add('ssl_prefer_server_ciphers', 'on');
    }


    // location
    conf.nginx.server[0]._add('location', '/');
    conf.nginx.server[0].location[0]._comments.push('location');
    conf.nginx.server[0].location[0]._add('proxy_pass', 'http://' + upstream_name + '/');
    conf.nginx.server[0].location[0]._add('proxy_cookie_path', '/ /');
    conf.nginx.server[0].location[0]._add('proxy_redirect', '/ /');
    conf.nginx.server[0].location[0]._add('proxy_set_header', 'Host $host');
    conf.nginx.server[0].location[0]._add('proxy_set_header', 'X-Real-IP $remote_addr');
    conf.nginx.server[0].location[0]._add('proxy_set_header', 'X-Forwarded-For $proxy_add_x_forwarded_for');
    conf.nginx.server[0].location[0]._add('client_max_body_size', '200 m');
    conf.nginx.server[0].location[0]._add('client_body_buffer_size', '128k');
    conf.nginx.server[0].location[0]._add('proxy_connect_timeout', '300s');
    conf.nginx.server[0].location[0]._add('proxy_send_timeout', '300s');
    conf.nginx.server[0].location[0]._add('proxy_read_timeout', '300s');
    conf.nginx.server[0].location[0]._add('proxy_busy_buffers_size', '64k');
    conf.nginx.server[0].location[0]._add('proxy_temp_file_write_size', '64k');
    conf.nginx.server[0].location[0]._add('proxy_buffer_size', '64k');
    conf.nginx.server[0].location[0]._add('proxy_buffers', '8 64k');
    conf.nginx.server[0].location[0]._add('fastcgi_buffer_size', '128k');
    conf.nginx.server[0].location[0]._add('fastcgi_buffers', '4 128k');
    conf.nginx.server[0].location[0]._add('send_timeout', '60');
    console.info("server_name", conf.nginx.server[0].server_name[0]._value);
  });
}

注意

所有添加的属性都要以数组的方式来获取 比如 conf.nginx.server[0].server_name[0]._value

修改配置

// 当配置改变时不写到磁盘中
conf.die('/etc/nginx.conf');
// 将内存中的配置写到另一个文件中
conf.live('/etc/nginx.conf.bak');
// 修改内存中的值
conf.nginx.events.connections[0]._value = 2000; //change remains local, not in /etc/nginx.conf
// 强行将内存中的配置刷到磁盘中
conf.flush();
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-04-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 常用的方式
    • child_process(原生)
      • shelljs(三方)
        • simple-git(GIT)
          • 总结
          • 常用的命令
            • 操作系统类型
              • 操作系统版本
                • 负载
                  • CPU和内存
                    • 网卡信息
                      • 硬盘
                        • 解析Nginx配置
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档