常用的方式
child_process(原生)
Nodejs下引入模块child_process实现调用shell
调用的两种方式
代码语言:javascript复制child_process.exec(command[, options][, callback])
child_process.execFile(file[, args][, options][, callback])
Nodejs中通过 exec执行shell脚本,并打印查询到的信息
代码语言:javascript复制var child = require('child_process');
child.exec('ls', function(err, sto) {
console.log(sto);//sto才是真正的输出,要不要打印到控制台,由你自己啊
})
执行文件
代码语言:javascript复制const exec = require('child_process').execSync
exec('bash ./shell/shell1.sh hello')
对应的shell文件
代码语言:javascript复制#!/bin/bash
# This is our first script.
echo "$1" > log.txt
示例
代码语言:javascript复制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的兼容性更好,使用更灵活,这个插件的使用率很高。
安装
代码语言:javascript复制npm install shelljs
和child_process同样的调用方式
代码语言:javascript复制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地址。
代码语言:javascript复制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
官方示例
代码语言:javascript复制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地址)
- 在项目中引入插件后,调用simple-git/promise可执行异步git操作,方便结合async/await使用
- 它封装并支持了很多git的方法,比如clone、commit、status、pull等等,将cmd命令和参数,传入即可
- 甚至可以用
git.raw()
,解析前端输入的git命令
安装
代码语言:javascript复制npm install simple-git
示例
代码语言:javascript复制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的方式:
- child_process 原生nodeAPI,需根据需要选型
- shelljs Node的一个扩展插件、兼容性好,推荐使用
- simple-git 专为git命令打造的插件,轻量好用
常用的命令
NodeJS获取系统信息
http://nodejs.cn/api/os.html
操作系统类型
代码语言:javascript复制const os = require('os');
var platform=os.platform();
console.log(platform);
返回值有
- darwin
- freebsd
- linux
- sunos
- win32
操作系统版本
代码语言:javascript复制const os = require('os');
var release=os.release();
console.log(release);
负载
代码语言:javascript复制const os = require('os');
var loadavg = os.loadavg();
console.log(loadavg);
os.loadavg()
方法返回一个数组,包含 1、5 和 15 分钟平均负载。
平均负载是系统活动的测量,由操作系统计算得出,表达为一个分数。 一般来说,平均负载应该理想地比系统的逻辑 CPU 的数目要少。
平均负载是 UNIX 相关的概念,在 Windows 平台上没有对应的概念。 在 Windows 上,其返回值总是 [0, 0, 0]
。
CPU和内存
代码语言:javascript复制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');
网卡信息
代码语言:javascript复制const os = require('os');
console.log('网卡:', os.networkInterfaces());
分配的网络地址的对象上可用的属性包括:
address
分配的 IPv4 或 IPv6 地址。netmask
IPv4 或 IPv6 的子网掩码。family
IPv4
或IPv6
。mac
网络接口的 MAC 地址。internal
如果网络接口是不可远程访问的环回接口或类似接口,则为true
,否则为false
。scopeid
数值型的 IPv6 作用域 ID(仅当family
为IPv6
时指定)。cidr
以 CIDR 表示法分配的带有路由前缀的 IPv4 或 IPv6 地址。如果netmask
无效,则此属性会被设为null
。
硬盘
添加依赖
代码语言:javascript复制npm i diskinfo
查看硬盘
代码语言:javascript复制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 "rn" total "rn" used "rn" available "rn" capacity);
console.log("==================================================================");
}
});
解析Nginx配置
安装依赖
代码语言:javascript复制npm install nginx-conf
说明文档:https://www.npmjs.com/package/nginx-conf
生成静态项目配置
代码语言:javascript复制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);
});
}
生成反向代理配置
代码语言:javascript复制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
修改配置
代码语言:javascript复制// 当配置改变时不写到磁盘中
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();