先上效果图
总结一下上篇说的效果:是命令行的方式;可执行系统命令;可输入参数
接下来一个个需求分步实现
环境:macOS 10.15.2 node 12.16.1
命令行方式
先准备脚本目录
mkdir xlfdcli
cd xlfdcli
npm init
# 不需要后缀
touch x-cli
编辑x-cli
#!/usr/bin/env node
console.log('success')
到这一步,修改一下权限,其实已经可以运行了:
怎么去掉
./直接以x-cli执行?
在package.json中添加
添加"bin": {"x-cli": "x-cli"},当然也可以换其他的名字"bin": {"xlfdcli": "x-cli"}
{
"name": "xlfdcli",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"bin": {
"x-cli": "x-cli"
},
"author": "",
"license": "ISC"
}
npm link
执行npm link后即可在全局使用x-cli,这里执行 npm link 的时候,会有权限的问题,可以使用sudo:
sudo npm link
#npm WARN xlfdcli@1.0.0 No description
#npm WARN xlfdcli@1.0.0 No repository field.
#up to date in 2.007s
#found 0 vulnerabilities
#/usr/local/bin/x-cli -> /usr/local/lib/node_modules/xlfdcli/x-cli
#/usr/local/lib/node_modules/xlfdcli -> /Users/johndiamond/Documents/workspace/xlfdcli
x-cli
#success
执行系统命令
安装npm i --save shelljs后有三种方式可以执行:
#!/usr/bin/env node
// ### child_process ###
const { exec } = require('child_process')
exec(`echo 参数是:${process.argv[2]}`, (error, stdout, stderr) => {
if (error) throw error
})
// ### shelljs ###
const shelljs = require('shelljs')
shelljs.exec(`echo 参数:${process.argv[2]}`)
// ### shelljs/global ###
require('shelljs/global')
const dirName = 'global'
mkdir(dirName)
cd(dirName)
touch('creatbyglobal.txt')
echo('done')
输入参数
安装npm i --save yargs
#!/usr/bin/env node
const { argv } = require('yargs')
console.log(argv)
console.log(argv.type)
结合 一峰老师的命令行教程已经知道上面三个需求怎么实现了
命令行内容
基本思路:手动在ngin.conf中定义两类标识对应上面三个功能;根据脚本参数替换标识;重启使nginx配置生效
标识nginx.conf
又结合上面的知识,就很好实现我们上篇最后的需求了(小部分未完善)
因为代码比较简单,就不注释了
#!/usr/bin/env node
const Fs = require('fs')
const { argv } = require('yargs')
.usage('x-cli [options]')
.example('x-cli -t location -u /privacy')
.help('h')
.alias('h', 'help')
.epilog('creat by xlfd')
.option('t', {
alias: 'type',
demand: true,
type: 'string',
describe: '配置类型 server 和 location'
})
.option('u', {
alias: 'uri',
demand: true,
type: 'string',
describe: 'location的uri'
})
.option('a', {
alias: 'alias',
type: 'string',
describe: 'location的别名'
})
.option('r', {
alias: 'root',
type: 'string',
describe: 'server的根目录root'
})
.option('i', {
alias: 'index',
type: 'string',
describe: 'location的资源index'
})
.option('p', {
alias: 'port',
type: 'number',
describe: 'server的端口'
})
const nginxPath = '/usr/local/nginx/sbin'
const _type = argv.t
const _uri = argv.u
const _alias = argv.a
const _index = argv.i
const _port = argv.p
if (_type === 'location') {
addLocation({
path: './nginx.conf',
port: _port,
index: _index,
uri: _uri,
alias: _alias
} )
} else {
addServer({
path: './nginx.conf',
port: _port,
index: _index,
uri: _uri,
alias: _alias
} )
}
function addLocation ({path, port = 80, index, uri, alias} = {}) {
const markStr = `#jenkins-CI-newLocation${port}`
const locationStr = `location ${uri} {
${alias ? `alias ${alias}`: '#'};
index ${index ? index : 'index.html'} index.html;
}
${markStr}`
readFile(path, markStr, locationStr, 'location')
}
function addServer ({path, port = 80, index, uri, alias} = {}) {
const serverMarkStr = '#jenkins-CI-newServer'
const locationMarkStr = `#jenkins-CI-newLocation${port}`
const locationStr = `location ${uri} {
${alias ? `alias ${alias}`: '#'};
index ${index ? index : 'index.html'} index.html;
}
${locationMarkStr}`
const serverStr = `server {
listen ${port};
server_name localhost;
${locationStr}
}
${serverMarkStr}`
readFile(path, serverMarkStr, serverStr, 'server')
}
function readFile (path, source, target, type = 'location') {
Fs.readFile(path, (error, data) => {
if (error) throw error
let confStr = data.toString()
// 替换标识
confStr = confStr.replace(source, target)
Fs.writeFile(path, confStr, (err) => {
if(err) throw err
console.log(`${type === 'location' ? 'location' : 'server'} add success`)
// 重启nginx
reload(nginxPath)
})
})
}
function reload (path) {
const shelljs = require('shelljs')
shelljs.exec(`cd ${path}`)
shelljs.exec('./nginx -s reload')
console.log('nginx reloaded')
}
这个命令行可以嵌入到jenkins-CI 脚本里去实际使用,不过实际使用的时候要注意路径