guest 1 неделю назад
Родитель
Сommit
6a8ce818f3
5 измененных файлов: 4043 добавлений и 3848 удалений
  1. 35
    0
      cliverse.js
  2. 3812
    3815
      index.js
  3. 13
    3
      linux/centos/elxr/setup.sh
  4. 136
    0
      nodeshell.js
  5. 47
    30
      win_verse.js

+ 35
- 0
cliverse.js Просмотреть файл

@@ -1,3 +1,6 @@

// cliverse.js

const { spawn, spawnSync } = require('child_process');
const fs = require('fs')

@@ -110,6 +113,38 @@ function nodeShellExec() {
return p;
}


function isWin(){ return /^win/.test(process.platform) }
try {

if(isWin()) {
var win_verse = require('./win_verse')
var shell_verse = win_verse;
}
else {
var lin_verse = require('./lin_verse')
var shell_verse = lin_verse;
}
}
catch(e) {
console.dir(e);
console.error('cli environment detection failed')
}

const BUILD_VERSION = '[VI]Version: {version} - built on {date}[/VI]';
shell_verse.getVersion = function getVersion() { return BUILD_VERSION; }



console.log('----------------------')
// console.dir(c)
console.log('----------------------')
// process.exit()

const fs = require('fs')

var {nodeShellExec, createTask} = require('./nodeshell')

var prompt = function(choices, label, defaultchoice, selectedchoice){
// prompt accepts either an array or an object as choices.
var choices = choices || [];

+ 3812
- 3815
index.js
Разница между файлами не показана из-за своего большого размера
Просмотреть файл


+ 13
- 3
linux/centos/elxr/setup.sh Просмотреть файл

@@ -3,9 +3,6 @@
# sudo passwd {{newuser}}

# Add the User to the sudoers File
# sudo visudo
# In the file opened add to the bottom and saveit
# {{newuser}} ALL=(ALL) ALL
# usermod -aG wheel {{newuser}}
# Switch to the new user
# su - {{newuser}}
@@ -25,6 +22,19 @@
# comment out mirrorlist line, mirrorlist=http:/{{}}
# Uncomment the baseurl line and change http://mirror.centos.org{{}} to http://vault.centos.org{{}}

# FOR REDIS
# sudo dnf install redis
# sudo vi /etc/redis.conf
# Comment bind 127.0.0.1 line with # and save the file
# requirepass your_secure_password # set the password to connect

# sudo systemctl start redis
# sudo systemctl enable redis
# sudo systemctl status redis
# TO test redis run the below
# redis-cli and then type ping, we should get back pong as response
# sudo firewall-cmd --zone=public --add-port=6379/tcp --permanent
# sudo firewall-cmd --reload

# Download steps
# wget http://git.bbh.org.in/chess/elxr/raw/branch/master/linux/centos/elxr/setup.sh

+ 136
- 0
nodeshell.js Просмотреть файл

@@ -0,0 +1,136 @@

const fs = require('fs')

const { spawn, spawnSync } = require('child_process');
function nodeShellExec() {

var args = Array.from(arguments);
if(args.length > 1){
var opts = args[2] = args[2] || {}
opts.title ? null : opts.title = `${args[0]} ${args[1] }`
}
else {
var opts = {
title : `${args[0]}`
// , inherit: true, shell: true
}
}
opts.stdin = 'pipe';
// // const spawn = require('child_process').spawn;
// const s = spawn(
// 'C:\\Program Files\\Git\\bin\\sh.exe'
// , ['notepad', 'index'], { cwd: __dirname });



// var interval = null;
// var t = setTimeout(function(){
// interval = setInterval(function(){
// console.log('Awaiting close : ' + child.spawnargs)
// }, 1500)
// // console.log('Awaiting close : ' + child.spawnargs)

// }, 0)

// child.on('close', (code) => {
// console.error('Prematurely closed even before promise...')
// })
// D:\chess\instances\elixir_01\elxr/.elxr/run-1630002739610/download.bat https://github.com/git-for-windows/git/releases/download/v2.33.0.windows.2/Git-2.33.0.2-64-bit.exe D:\\chess\\instances\\elixir_01\\elxr/Downloads/Git-2.33.0.2-64-bit.exe
// D:\\chess\\instances\\elixir_01\\elxr/.elxr/run-1630002923584/download.bat https://github.com/git-for-windows/git/releases/download/v2.33.0.windows.2/Git-2.33.0.2-64-bit.exe D:\\chess\\instances\\elixir_01\\elxr/Downloads/Git-2.33.0.2-64-bit.exe
// console.dir(args[2])
console.log('nodeshellexec ::: ')
console.log(`${args[0]} ${args[1].join(' ') } ${args[args.length-1].cwd}`)

const child = spawn(...args);
var p = new Promise(function(resolve, reject){
// console.log(...args)
if(!opts.detached) {
var messages = []; // PB : TODO -- Explore stream for Task level aggregation to prevent interleaved messages from multiple tasks...
var success = true;
if(opts.stdio !== 'ignore') {
child.stdout.setEncoding('utf8');
child.stderr.setEncoding('utf8');
child.stdout.on('data', (chunk) => {
chunk.trim() === '' ? null : messages.push(chunk); /* console.log('d: ' + chunk) */
process.stdout.write( chunk )
});
child.on('error', (chunk) => { success = false; messages.push(chunk); /* console.error('e: ' + chunk) */
console.error('Error exit not handled.')
});
child.stderr.on('data', (chunk) => {
if(messages.join('').indexOf('fatal: not a git repository') > -1) opts.haserrors = true;
messages.push(chunk);
// process.stdout.write( chunk )
// console.error('stderr e: ' + chunk)
});
}
child.on('close', (code) => {
// console.log('Proper close was fired')
var logEntry = { code, success }
if(+code !== 0 || opts.haserrors) {
success = false; logEntry = { messages, result: `${opts.title} exited with code ${code}`, success, code }
};
if(opts.stdio !== 'ignore') {
logEntry = { result: `${opts.title} exited with code ${code}`, messages, code }
logEntry.success = success;
if(opts.evaluateResult) logEntry = opts.evaluateResult(success, logEntry);
if(opts.runas){
// success ? logEntry.success = true : null;
// fs.writeFileSync('run.log', ', ' + JSON.stringify(logEntry), {'flag':'a+'} )
}
else {
// console.log( messages.join('') )
// process.stdout.write( JSON.stringify(logEntry) )
}
}
else if(opts.evaluateResult) {
try { logEntry = opts.evaluateResult(false, logEntry); }
catch(e){ reject(e) }
}
// clearInterval(interval)
if(code !== 0 || opts.haserrors) {
args[2].benign || args[2].ignorefailures ? (logEntry.benign = true, logEntry.ignorefailures = true) : null
return reject(logEntry)
}
resolve(logEntry)
});
}
else {
child.unref()
// clearInterval(interval)
resolve(true);
}
});
p.process = child;
return p;
}

module.exports = {
nodeShellExec
, createTask(task, str){

var tasks = {
getTaskCheckExists : (str)=>{
return (command, options) => {
options = options || {}
return () => {
var p = nodeShellExec.apply(null, [str, [command]])
if (options.ignorefailures) {
return p.then(() => { return true }).catch(e => { // Ignore. Not a major error.
return false;
})
}
else return p.then(() => { return true });
}
}
}
}
return tasks[task](str)
}
}

+ 47
- 30
win_verse.js Просмотреть файл

@@ -1,9 +1,11 @@
const { any } = require('bbhverse');
// win_verse

const { any, Traq } = require('bbhverse');
const fs = require('fs')
var path = require('path');

var cli = require('./cliverse')
var nodeShellExec = cli.nodeShellExec;
var {nodeShellExec, createTask} = require('./nodeshell');

function elevatedRunIPCWriteMessage( target, m ) {
fs.writeFileSync(target, ', ' + JSON.stringify( m ), { 'flag': 'a+' })
@@ -25,7 +27,6 @@ var __isElevated = null;
var shell_verse = {
// getCommonTask is agnostic of whether we are running in an elevated shell or not. It runs in either case.
init( o ){ Object.assign(this, o) }
, downloadsdir : '../Downloads'
, getCommonTask( taskToRun ){ return ()=>{ return shell_verse.runTask(taskToRun) }}
, runTask : ( taskToRun ) => {
@@ -41,21 +42,21 @@ var shell_verse = {
return taskToRun().then((r)=>{
// PB : TODO -- Every elevation should have its own messaging file. Async writes from multiple processes are a problem here...
elevatedRunIPCWriteMessage( runlogjson, { info : taskToRun.info, success: true } )
if(!inBatch) fs.writeFileSync('run.done', 'success') // PB : TODO -- This should be done conditionally if we are running inproc.
if(!inBatch) fs.writeFileSync(`${this.tempRunDir()}\\run.done`, 'success') // PB : TODO -- This should be done conditionally if we are running inproc.
return __runasresult = r;
})
.catch((e) => {
elevatedRunIPCWriteMessage( runlogjson, e)
if(!inBatch)fs.writeFileSync('run.done', 'failure')
if(!inBatch)fs.writeFileSync(`${this.tempRunDir()}\\run.done`, 'failure')
console.error(e)
})
.finally(() => {
// if(__runasresult && !__runasresult.skipped) fs.unlinkSync('run.done')
// if(__runasresult && !__runasresult.skipped) fs.unlinkSync(`${this.tempRunDir()}\\run.done`)
})
}
catch (e) {
console.error('Error Invalid command : ' + e)
if(!inBatch) fs.writeFileSync('run.done', 'error')
if(!inBatch) fs.writeFileSync(`${this.tempRunDir()}\\run.done`, 'error')
}
finally {
}
@@ -66,12 +67,13 @@ var shell_verse = {
if (__isElevated) return shell_verse.elevatedRunner(taskToRun, true)
else return shell_verse.requestElevation(shell_verse.elevatedRunner, taskToRun)
}
, runElevated : ( taskToRun ) => {
, runElevated : function( taskToRun ){
fs.writeFileSync( `${this.tempRunDir()}\\run.log`, ', ' + JSON.stringify({ taskstart : true }), {'flag':'a+'} )

// Let shell_verse decide whether to Elevate Out of Proc or In Proc
// taskToRun by default is the launched command and args. Specially in windows out of proc.
// taskToRun = taskToRun || (()=>{ return op[processedArgs.label || processedArgs._[0] || 'undefined'](processedArgs) })

if(taskToRun.processedArgs.skipelevated) return Promise.resolve({ skipped : true });


@@ -92,16 +94,16 @@ var shell_verse = {
return any(batchToRun).then((r)=>{
// PB : TODO -- Every elevation should have its own messaging file. Async writes from multiple processes are a problem here...
// fs.writeFileSync('run.log', ', ' + JSON.stringify( { info : taskToRun.info, success: true }), { 'flag': 'a+' })
fs.writeFileSync('run.done', 'success') // PB : TODO -- This should be done conditionally if we are running inproc.
fs.writeFileSync(`${this.tempRunDir()}\\run.done`, 'success') // PB : TODO -- This should be done conditionally if we are running inproc.
return __runasresult = r;
})
.catch((e) => {
// fs.writeFileSync('run.log', ', ' + JSON.stringify(e), { 'flag': 'a+' })
fs.writeFileSync('run.done', 'failure')
fs.writeFileSync(`${this.tempRunDir()}\\run.done`, 'failure')
console.error(e)
})
// .finally(() => {
// if(__runasresult && !__runasresult.skipped) fs.unlinkSync('run.done')
// if(__runasresult && !__runasresult.skipped) fs.unlinkSync(`${this.tempRunDir()}\\run.done`)
// });
}
else {
@@ -155,12 +157,14 @@ var shell_verse = {
__isElevated = true;
shell_verse.acquireElevationState = ()=> Promise.resolve(__isElevated);
shell_verse.isElevated = () => { return Promise.resolve(__isElevated)}
// fs.writeFileSync( `${this.tempRunDir()}\\run.log`, ', ' + JSON.stringify({ elevated : true}), {'flag':'a+'} )
return __isElevated
}).catch((e) => {
__isElevated = false;
shell_verse.acquireElevationState = ()=> Promise.resolve(__isElevated);
shell_verse.isElevated = () => { return Promise.resolve(__isElevated)}
console.log('Not Elevated');
// fs.writeFileSync( `${this.tempRunDir()}\\run.log`, ', ' + JSON.stringify({ elevated : false}), {'flag':'a+'} )
return __isElevated
})
// .finally(()=>{
@@ -170,24 +174,29 @@ var shell_verse = {
// })
}
, getTaskCheckExists : cli.createTask('getTaskCheckExists', 'where')
, getTaskCheckExists : createTask('getTaskCheckExists', 'where')

, getbash : ()=>{ return "C:\\Program Files\\Git\\bin\\sh.exe" }

, createJuntionOrLink : (dirOrFile, target, opts) =>{
return nodeShellExec('mklink', ['/J', dirOrFile, target], opts).catch((e) => { console.error(e) })
return nodeShellExec('mklink', ['/J', dirOrFile, target], opts).catch((e) => { console.error(e)
fs.writeFileSync( `${this.tempRunDir()}\\run.log`, ', ' + JSON.stringify({ e }), {'flag':'a+'} )
})
}
, removeJuncionOrLink : ( junctionOrLink )=>{
return nodeShellExec('rmdir', [junctionOrLink], { inherit: true, shell: true, env: process.env })
}

, tempRunDir : function(){ return `${this.selectedinstance.root}\\.elxr\\run-${this.runtimestamp}`}
, requestElevation(elevatedRunner, taskToRun) {
// PB : TODO -- Multiple parallel request elevations should be queued into a batch and serialized as a single promise.

var processedArgs = taskToRun.processedArgs, statuslog = taskToRun.statuslog
var processedArgs = taskToRun.processedArgs, statuslog = taskToRun.statuslog || Traq
// Wait for the runas to complete before we read it.
try {
fs.unlinkSync('run.done') // Need a unique file for aech elevated run.
fs.unlinkSync(`${this.tempRunDir()}\\run.done`) // Need a unique file for aech elevated run.
}
catch (e) { } //Ignore

@@ -225,7 +234,8 @@ var shell_verse = {
args.push('--runas=self');
// args.debug = true
if(args.debug) args.push(`--debug=${args.debug}`);
args.push(`--runtimestamp=${spawntimestamp}`);
args.push(`--runtimestamp=${this.runtimestamp}`);
args.push(`--spawntimestamp=${spawntimestamp}`);
// args.push(`--wd=${options.cwd}`);

// args.push('--nodepath=' + r.messages[r.messages.length - 1])
@@ -240,20 +250,23 @@ var shell_verse = {
// runas returned.
try {
// PB : TODO -- Log is comma prefixed. Needs to be proper JSON.
var runlogjson = `${taskToRun.selectedinstance.root}/.elxr/run-${spawntimestamp}/run.log`
var runaslog = JSON.parse('[' + fs.readFileSync(runlogjson, { flags: 'a+' }) + ']');
var runlogjson = `${taskToRun.selectedinstance.root}/.elxr/run-${this.runtimestamp}/run.log`
var runaslog = JSON.parse('[ { "MSHTA" : "done", "success" : true }, ' + fs.readFileSync(runlogjson, { flags: 'a+' }) + ']');
try { fs.unlinkSync(runlogjson) } catch(e){ } // PB : TODO -- Have a unique file for each elevated run.
// console.log( "runaslog : " + runaslog.length )
// Assemble elevated run results into the main run log
runaslog.forEach((logEntry) => {
statuslog.statuslog(logEntry.success ? null : logEntry, logEntry)
logEntry.success ? (console.log(['success :' + (logEntry.result || logEntry.success)]), console.log((logEntry.messages || []).join(' '))) : (console.error(['error :' + logEntry.result]), console.error((logEntry.messages || []).join(' ')))
logEntry.error ? (console.error(['error :' + logEntry.result]), console.error((logEntry.messages || []).join(' '))) :
(console.log(['success :' + (logEntry.result || logEntry.success)]), console.log((logEntry.messages || []).join(' ')))
})
if(statuslog) fs.writeFileSync( `${this.tempRunDir()}\\run.log`, ', ' + JSON.stringify(statuslog), {'flag':'a+'} )
}
catch (e) {
// We must have a runas log
statuslog.statuslog(e)
console.error('Run log error probably was not created by runas : ' + e)
fs.writeFileSync( `${this.tempRunDir()}\\run.log`, ', ' + JSON.stringify(statuslog), {'flag':'a+'} )
}
})
.catch(err => console.error('Elevation failed : ' + JSON.stringify(err)));
@@ -266,7 +279,7 @@ var shell_verse = {
var processedArgs = this.processedArgs
// Wait for the runas to complete before we read it.
try {
fs.unlinkSync('run.done') // Need a unique file for aech elevated run.
fs.unlinkSync(`${this.tempRunDir()}\\run.done`) // Need a unique file for aech elevated run.
}
catch (e) { } //Ignore

@@ -285,7 +298,8 @@ var shell_verse = {
namedArgs.length > 0 ? args = args.concat(namedArgs.join(' ')) : null;
// args.push('--runas=self');
var spawntimestamp = (new Date()).getTime()
args.push(`--runtimestamp=${spawntimestamp}`);
args.push(`--runtimestamp=${this.runtimestamp}`);
args.push(`--spawntimestamp=${spawntimestamp}`);

// args.push('--nodepath=' + r.messages[r.messages.length - 1])
// if (!processedArgs.node_env) args.push('--node_env=' + ENV.NODE_ENV)
@@ -307,7 +321,7 @@ var shell_verse = {
// runas returned.
try {
// PB : TODO -- Log is comma prefixed. Needs to be proper JSON.
var runlogjson = `${this.selectedinstance.root}/.elxr/run-${spawntimestamp}/run.log`
var runlogjson = `${this.selectedinstance.root}/.elxr/run-${this.runtimestamp}/run.log`
var runaslog = JSON.parse('[' + fs.readFileSync(runlogjson, { flags: 'a+' }) + ']');
try { fs.unlinkSync(runlogjson) } catch(e){ } // PB : TODO -- Have a unique file for each elevated run.
// console.log( "runaslog : " + runaslog.length )
@@ -404,7 +418,9 @@ var shell_verse = {
// alert(objENV('wd'))
// PB : TODO -- Convert all the cli args back to string.
// __filename will sure we are launhed using the same entry point.
var cargs = (processedArgs.debug ? '--inspect-brk=9226' : '') + ' ${__filename.replace(/\\/g, '\\\\').replace("win_verse", "index")} ' + processedArgs._.join(' ') + ' ' + namedArgs.join(' ');
var cargs = (processedArgs.debug ? '--inspect-brk=9226' : '') + ' ${this.selectedinstance.launchscript.replace(/\\/g, '\\\\')}' + ' ' + processedArgs._.join(' ') + ' ' + namedArgs.join(' ');
// cargs = (processedArgs.debug ? '--inspect-brk=9226' : '') + ' ${__filename.replace(/\\/g, '\\\\').replace("win_verse", "index")}' + processedArgs._.join(' ') + ' ' + namedArgs.join(' ');
// alert(cargs)
var shell = new ActiveXObject('shell.application');
// alert('launching node privilged. ' + processedArgs['nodepath'])
// shell.ShellExecute('cmd.exe', '/k where node', '', '', 10);
@@ -424,8 +440,8 @@ var shell_verse = {

function endconsole(from){
// alert('endconsole ' + from)
if(fso.FileExists("run.done")) {
fso.DeleteFile('run.done') // PB : TODO -- IPC through files is needed only for windows we need to do it per run...
if(fso.FileExists('${(this.tempRunDir()+'\\run.done').replace(/\\/g, '\\\\')}')) {
fso.DeleteFile('${(this.tempRunDir()+'\\run.done').replace(/\\/g, '\\\\')}') // PB : TODO -- IPC through files is needed only for windows we need to do it per run...
}
// alert('closing window')
window.close();
@@ -433,10 +449,11 @@ var shell_verse = {
var timer = function(){
// alert('here')
l('.');
if(fso.FileExists("run.done")) {
l('endconsole ' + ' ' + '${(this.tempRunDir()+'\\run.done').replace(/\\/g, '\\\\')} <br/>')
if(fso.FileExists('${(this.tempRunDir()+'\\run.done').replace(/\\/g, '\\\\')}')) {
endconsole('timer')
}
else window.setTimeout(timer, 1000);
else window.setTimeout(timer, 3000);
};

// alert('/k node ' + cargs + '')
@@ -541,7 +558,7 @@ var shell_verse = {
else throw 'regread failed'
})
}
, iswin(){ return true}
, isWin(){ return true}
, islin(){ return false}
}


Загрузка…
Отмена
Сохранить