How to Pass a Command Line Argument in NodeJS? - javascript

I have a file structure, which I will enumerate for you in a moment. I have a web server, that initiates a command line process on a button press. I want to add in the option to run the server in a headless manner, using a command line argument. Is this the way I should be doing this? Here is my Project Structure.
/models
/model1
/model2
/model3
/routes
/index
/test
/users
/credentials
/adduser
/views
/same as routes. Route 'test' has no layout.
in index, or '/', I have a function, which takes several parameters, and is initiated via clicking a button on the index page. We are then forwarded through 'test/run', and render the 'index' view. The process continues to run in the terminal. I will now post an example of the function.
router.post('/run', ensureAuthenticated, function(req, res){
return res.redirect('/test/running')
});
// Get Homepage
router.get('/running', ensureAuthenticated, function(req, res){
console.log(res.locals.user);
// console.log(app.locals.user);
const var1 = res.locals.user.username;
const var2 = res.locals.user.username;
const var3 = res.locals.user.username;
const var4= res.locals.user.username;
const deets = {
var5,
var6
};
res.render('index');
dosomething(var1, var2, var3, var4, deets);
setInterval(dosomething, 10 * 1000);
})
});
So what do you guys think? How would I be able to implement the passing of var1-6, through the command line? I would greatly appreciate any help from here.
I am running on Windows right now, but the target server is for Ubuntu systems.

In node.js you can pass CLI arguments using build in process variable
for examples
// test.js
var args = process.argv;
console.log(args[0]); // it will give the node executable path
console.log(args[1]); // it will give current file name
console.log(args[2]); // cli arguments start index
now running the code
$ node test.js hello
/usr/bin/node
/home/blackdaemon/test.js
hello

If you like a pattern like "-arg" "value" try this:
var getArgs = function(){
var arr = {};
var last;
process.argv.forEach((a, idx) => {
if(idx > 1){
if(last){
arr[last] = a;
last = undefined;
}
else if(!last && a.match(/-\w+/))
last = a;
}
})
return arr;
}
The result should be:
$ node index no valid command -ar3 dsds -arg1 323
{ '-ar3': 'dsds', '-arg1': '323' }

Related

Store output of shell command in sqlite

If I execute a certain shell command in node js, the output is on the console. Is there a way I can save it in a variable so it can be POST to Sqlite database.
const shell = require('shelljs');
shell.exec('arp -a');
In this scenario, I want to store the IP address of a specific MAC/Physical address into the database. How can this be done?
Any help would be much appreciated. Thank you
You need to get the output of the command you're passing to exec. To do that, just call stdout, like this:
const shell = require('shelljs');
const stdout = shell.exec('arp -a').stdout;
Then just parse that output to get your ipaddress:
const entries = stdout.split('\r\n');
// entries sample
[ '',
'Interface: 10.17.60.53 --- 0xd',
' Internet Address Physical Address Type',
' 10.11.10.52 6c-4b-90-1d-97-b8 dynamic ',
' 10.10.11.254 xx-yy-53-2e-98-44 dynamic ']
Then you can filter your wanted address with some more manipulation.
EDIT:
To get the ip address, you could do:
let ipAddr = null;
for (let i = 0; i < entries.length; i++) {
if (entries[i].indexOf('6c-4b-90-1d-97-b8') > -1) {
ipAddr = entries[i].match(/\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/)[0];
break;
}
}
console.log(ipAddr); // '10.11.10.52'
I'm merely copy pasting from the docs. You should research more.
You need to add a listener to stdout
var child = exec('arp -a', {async:true});
child.stdout.on('data', function(data) {
/* ... do something with data ... */
});
Or adding the callback directly when calling exec
exec('some_long_running_process', function(code, stdout, stderr) {
console.log('Exit code:', code);
console.log('Program output:', stdout);
console.log('Program stderr:', stderr);
});
You can access the result of the command run using shell.exec with the .output property. Try the code below.
var shell = require('shelljs');
var result = shell.exec('arp -a').output;
If you don't want the result in the console, you can specify the silent option.
var result = shell.exec('arp -a', {silent: true}).output;
Now, you can use regular expressions to extract ip and mac address from the result.
I am getting the result of the command like below:
? (xxx.xxx.xxx.xxx) at xx:xx:xx:xx:xx:xx [ether] on eth0
? (yyy.yyy.yyy.yyy) at yy:yy:yy:yy:yy:yy [ether] on eth0
You can use the following code to extract ip and mac.
var res = result.split("\n").map(function(item){
return item.match(/\((\d+\.\d+\.\d+\.\d+)\) at (..:..:..:..:..:..)/);
});
console.log(res[0][1]); //IP of first interface
console.log(res[0][2]); //MAC of first interface
console.log(res[1][1]); //IP of second interface
console.log(res[1][2]); //MAC of second interface
NOTE
I was not able to find the .output property in the documentation but trying the shell.exec function in the node console revealed it.
The .stdout property or the exec function mentioned in other answers doesn't work for me. They are giving undefined errors.

Configuring mock-cli

I'm trying to use mock-cli to stub process.arv in mocha tests for a cli app. I want to test that a message is console.logged when an incorrect argument ("imit") is passed to process.argv (as defined by commands).
I'm trying to adapt the example from the documentation but i don't think i have set everything up correctly.
it passes when i comment out "stdin: require('../mocks/fakeInputStream'), // Hook up a fake input stream" though i know it's not working correctly
it fails with TypeError: sourceStream.on is not a function when run as described below
Can someone see what I'm missing?
/index.js
var commands = ['init'];
function getGitHeadArgs() {
return process.argv.slice(2, process.argv.length);
}
if (getGitHeadArgs().length) {
if (!commands.includes(getGitHeadArgs()[0])) {
console.log("Silly Githead! That's not a githead command");
}
eval(getGitHeadArgs()[0])();
} else {
console.log("You didn't tell githead to do anything!");
}
/testIndex.js
var assert = require('assert');
var index = require('../index.js');
var mockCli = require("mock-cli");
describe("incorrect argument", function() {
it("imit throws an error if an invalid command is raised", function() {
var argv = ['node', '../index.js', 'imit']; // Fake argv
var stdio = {
stdin: require('../mocks/fakeInputStream'), // Hook up a fake input stream
stdout: process.stdout, // Display the captured output in the main console
stderr: process.stderr // Display the captured error output in the main console
};
var kill = mockCli(argv, stdio, function onProcessComplete(error, result) {
var exitCode = result.code; // Process exit code
var stdout = result.stdout; // UTF-8 string contents of process.stdout
var stderr = result.stderr; // UTF-8 string contents of process.stderr
assert.equal(exitCode, 0);
assert.equal(stdout, "Silly Githead! That's not a githead command\n");
assert.equal(stderr, '');
});
// Execute the CLI task
require('../index.js');
// Kill the task if still running after one second
setTimeout(kill, 1000);
});
Is ../mocks/fakeInputStream a valid path?
Is the object at ../mocks/fakeInputStream a valid instance of ReadableStream?
The source code is avalible at GitHub.
Make sure you meet the requirements for the captureStdin(sourceStream, callback) function.
The module uses that function to capture your fakeInputStream and pipe it into a captureStream.

Node Js : Unable to find error in below file filter code

I have written small code to get files filtered by extension. And my point of view logic is fine but I am unable to point out why I am not getting expected output.
Please have a look.
CODE
var fs = require('fs')
var path = require('path')
path_name = process.argv[2]
ext_name = "."+process.argv[3]
var filter_function = function ( path_name,exthide_name,callback) {
fs.readdir(dirpath,function(err,list) {
if(err) return console.error(err)
for ( var i in list) {
if(path.extname(list[i]) == ext_name)
console.log(list[i])
}
})
}
module.exports=filter_function
Output :
linuxmen#linuxmen-fresh:~/test/test1$ node ownModuleNode.js /home/linuxmen/test/test1/ js
linuxmen#linuxmen-fresh:~/test/test1$
But I have so many files with js extension in that directory.
Proof:
linuxmen#linuxmen-fresh:~/test/test1$ ls *js
check_mod1.js ex1.js ex2.js ex3.js ex4.js ex5.js ex6.js ex7.js ex8.js filter.js filter_use.js modse.js ownModuleNode.js se.js use_mod1.js using_module.js
Could please help , what I am missing.
Update - 1 : I am using above code a module file and calling it here.
File using above code
var mymodule = require('./ownModuleNode')
mymodule.filter_function(process.argv[2],process.argv[3])
Update 2 :
var fs = require('fs')
var path = require('path')
path_name = process.argv[2]
ext_name = "."+process.argv[3]
console.log("path_name :",path_name,"extname:",ext_name)
var filter_function = function ( path_name,ext_name,callback) {
fs.readdir(path_name,function(err,list) {
if (err) console.error(err)
console.log(list)
for ( var i in list) {
if(path.extname(list[i]) == ext_name)
console.log(list[i])
}
})
}
module.exports=filter_function
Output:
linuxmen#linuxmen-fresh:~/test/test1$ node ownModuleNode.js /home/linuxmen/test/test1/ js
pathanme : /home/linuxmen/test/test1/ extname: .js
Thank you.
It looks like you are exporting the function directly. When you require() it, you just getting the function. You'll need to use your module in your application. Put this in 'app.js' in the same dir as ownModuleNode.js:
var filterFunction = require('./ownModuleNode');
filterFunction(process.argv[2], process.argv[3]);
Then call it with:
node app ~/Documents/dev/project .js
Outputs:
app.js
ownModuleNode.js
Note that when you pass the extension, you need the preceding dot because path.extname() returns the dot.

Executing mongodb scripts via mongoid Rails

I have a mongo db script in a js file:
query.js
//conn = new Mongo();
//db = conn.getDB("dbName");
functionFoo = function (arg){
//----process arg
}
also I have an array of args known as args_array, (that I fetch from database using mongoid) for which I want to do something like this:
args_array.each do |arg|
//some how call functionFoo(arg) from the query.js file
end
is this possible in rails?
I am able to execute the file from terminal but I want to wrap it in my application so that I can use it from rails console.
I know this old question but in case you still need answer or any one else. This answer works with gem mongo ~> 2.3.
The key to answer you do not need mongoid in this case - in my case I use it for rails model, so I use mongoid (5.1.0) only to get DB connection db = Mongoid.default_client.database - or you can get/create database using mongo gem.
To execute javascript on database you need to call command method db.command({ eval: 'js' }) or db.command({ eval: 'function(n){return db.projects.find({name: n}).toArray();}', args: ['beskhai'], nolock: true })
To get the result you can call .documents db.command(...).documents, The return is a hash {retval: it will be return of you script, ok: is 1 if success} the return object of command call is [Mongo::Operation::Result] https://github.com/mongodb/mongo-ruby-driver/blob/master/lib/mongo/operation/result.rb.
I'm using MongoID 6.0.1, and it easy to query everything you want like that:
db ||= Mongoid.default_client.database
f = """
functionFoo = function (arg){
//----process arg
}
"""
result = db.command({:$eval => f, args: [arg1, arg2, ...arg_n], nolock: true})
#result_data = result.first['retval']
It not only a function, just every thing you want to do with command.
My example is:
db ||= Mongoid.default_client.database
f = """
var collectionNames = db.getCollectionNames(), stats = [];
collectionNames.forEach(function (n) { stats.push(db[n].stats()); });
stats = stats.sort(function(a, b) { return b['size'] - a['size']; });
return stats;
"""
result = db.command({:$eval => f, args: [], nolock: true})
#result_data = result.first['retval']

How to get filename and line number of where a function is called in Node?

When working in Python I always have this simple utility function which returns the file name and line number from where the function is called:
from inspect import getframeinfo, stack
def d():
""" d stands for Debug. It returns the file name and line number from where this function is called."""
caller = getframeinfo(stack()[1][0])
return "%s:%d -" % (caller.filename, caller.lineno)
So in my code I simply put a couple debug lines like this to see how far we get before some error occurs:
print d()
# Some buggy code here
print d()
# More buggy code here
print d(), 'here is the result of some var: ', someVar
This works really well for me because it really helps debugging quickly.
I'm now looking for the equivalent in a node backend script. I was searching around but I can't find anything useful (maybe I'm looking for the wrong words?).
Does anybody know how I can create a Javascript/nodejs function which outputs the file name and line number from where the function is called? All tips are welcome!
You can create an Error to get where the Error is, and its stack trace. Then you can put that into a function, to get the line where it is.
function thisLine() {
const e = new Error();
const regex = /\((.*):(\d+):(\d+)\)$/
const match = regex.exec(e.stack.split("\n")[2]);
return {
filepath: match[1],
line: match[2],
column: match[3]
};
}
console.log(thisLine());
This works for me in Google Chrome.
And also in node.
Note to #j08691's comment:
Both this and this seem to be using lineNumber, which is not present (as far as I could test) in NodeJS.
Printing line number with custom string
const moment = require('moment');
const log = console.log;
const path = require('path');
function getTime(time) { return moment().format('YYYY-MM-DD HH:mm:ss') };
function line(num = 2) {
const e = new Error();
const regex = /\((.*):(\d+):(\d+)\)$/
const match = regex.exec(e.stack.split("\n")[num]);
const filepath = match[1];
const fileName = path.basename(filepath);
const line = match[2];
const column = match[3];
return {
filepath,
fileName,
line,
column,
str: `${getTime()} - ${fileName}:${line}:${column}`
};
}
log(line().str, "mylog1");
log(line().str, "mylog2");
log(line().str, "mylog3");
OUTPUT
2021-11-22 13:07:15 - test.js:44:5 mylog1
2021-11-22 13:07:15 - test.js:45:5 mylog2
2021-11-22 13:07:15 - test.js:46:5 mylog3
You can use this gulp plugin gulp-log-line . It Logs file and line number without the extra cost of reading the stack.
you just have to install gulp and gulp-log-line using the
npm install gulp --save and npm install gulp-log-line command. after that you need to create and write the below code in gulpfile.js and run
gulp log-line to create a duplicate file in the build folder :-
var gulp = require('gulp');
var logLine = require('gulp-log-line');
gulp.task('line-log', function() {
return gulp.src("file.js", {buffer : true})
//Write here the loggers you use.
.pipe(logLine(['console.log', 'winston.info']))
.pipe(gulp.dest('./build'))
})
gulp.task('default', ['line-log'])
Example
file.js :-
console.log('First log')
var someVariable
console.log('Second log')
Becomes
console.log('file.js:1', 'First log')
var someVariable
console.log('file.js:3', 'Second log')
The only way I've found to get anything relating to line numbers is to trap the window.onerror function, and when there's an error that will get passed the error message, the file URL and the line number:
window.onerror = function(msg, url, line) {
alert(msg + "\n" + url + ":" + line);
};
This works for me on Chrome - I don't know about other browsers.
EDIT when this answer was given in Feb' 15 there was no mention of NodeJS in the question. That was only added in November '17.

Categories