Node.JS reading data from console command - node.js

I remember using something before in node.js that would allow me to run a command like
node appname.js text goes here
and then read the "text goes here" part with something like
console.log(console.text)
I can't remember what it is, and can't find it in any searches. Was this a real thing, or just me dreaming?

You can use process.argv to console the input from command line.
If you run below command in terminal/command line:
node appname.js text goes here.
You can print the command line arguments by:
console.log(process.argv)
Output of above console will be:
['node',
'/home/user/path/to/appname.js',
'text',
'goes',
'here' ]
If you dont want first two text, you can use:
console.log(process.argv.slice(2))
Output of above console will be:
['text',
'goes',
'here' ]
Read this link for more info.
Hope this helps you out!!!

Well there is lot's ways/packages around for reading from arguments.
the nodejs process is the base of it so check here
And also as i said lot's of packages there for parsing arguments.
yargs is one of them, minimist is also a populer one as far as i know.
If you don't want t use a package basicly it starts like this:
// inside node file
const args = process.argv.splice(2);
console.log(args);
// we are splice'ing from 2 cause
// process.argv[0] is your node-path
// process.argv[1] is your js file's full path
// Most of the time we are not using those so :)
So hope these would work for you ☺

Related

Process.stdout.write appends "true" to the console output

Using process process.stdout.write to print to the console returns the string with true appended to the end
process.stdout.write is appending true to the value I want to print to the console.
I tried running the same command using node in the cli - same result
Command: node -p "process.stdout.write('hello')"
Console: hellotrue
I expected hello to appear.
I think you need to take another look at your code. some of the common advice for programming forums is to get an example simplified enough that your problem still occurs.
In this case if I write process.stdout.write('hello') to a file, and then ask node to run that file, I get the correct response of hello back, the word true doesn't show up.
According to the options from node, using -p instead of -e means you're asking it to print the result of that function call, which was a success.
-e, --eval script evaluate script
-p, --print evaluate script and print result
For now try the -e flag with your code.

How to get mongo shell output(three dot) for unterminated command

When type a unterminated command in a mongo shell, it will return three dots indicating need more input to complete this command like below:
> db.test.find(
... {
...
I am using nodejs child_process.spawn to create a mongo shell process and listen on its output. I can get the standard and error output from the mongo shell but I can't get the ... output. Below is my nodejs code:
const shell = spawn('mongo', params);
shell
.stdout
.on('data', (data) => {
winston.debug('get output ' + data);
});
shell
.stderr
.on('data', (data) => {
const output = data + '';
winston.error('get error output ', data);
});
I run below code to send command on the shell:
shell.stdin.write('db.test.find(');
I wander why I can't get the ... output on above method. Is it a special output?
EDIT1
I tried to use node-pty and pty.js. They can get the ... output but they mix the input and output data together. It is not possible to separate them.
I also tried to use stdbuf and unbuffer to disable buffer but it still doesn't work.
It seems that nodejs child_process doesn't work well with interactive command.
Your code doesn't include anything that writes to the stdin of your child process so I would be surprised if you got the ellipsis that indicates incomplete command when in fact you don't send any command at all - incomplete or otherwise.
That having been said, many command line utilities behave differently when they discover a real terminal connected to their stdin/stdout. E.g. git log will page the results when you run it directly but not when you pipe the results to some other command like git log | cat so this may also be the case here.
This can also have to do with the buffering - if your stream is line-buffered then you won't see any line that is not ended with a newline right away.
The real question is: do you see the > prompt? Do you send any command to the mongo shell?
Scritping interactive CLI tools can be tricky. E.g. see what I had to do to test a very simple interactive program here:
https://github.com/rsp/rsp-pjc-c01/blob/master/test-z05.sh#L8-L16
I had to create two named pipes, make sure that stdin, stderr and stdout are not buffered, and then use some other tricks to make it work. It is a shell script but it's just to show you an example.

cannot create /dev/stdout: No such device or address

I'm want to run a shell command via node and capture the result of stdout. My script works fine on OSX, but not on Ubuntu.
I've simplified the problem and script to the following node script:
var execSync = require('child_process').execSync,
result = execSync('echo "hello world" >> /dev/stdout');
// Do something with result
Results in:
/bin/sh: 1: cannot create /dev/stdout: No such device or address
I have tried replacing /dev/stdout with /dev/fd/1
I have tried changing the shell to bash... execSync('echo ...', {shell : '/bin/bash'})
Like I said, the problem above is simplified. The real script accepts as a parameter the name of a file where results should be written, so I need to resolve this by providing access to the stdout stream as a file descriptor, i.e. /dev/stdout.
How can I execute a command via node, while giving the command access to its own stdout stream?
On /dev/stdout
I don't have access to an OSX box, but from this issue on phantomjs, it seems that while on both OSX/BSD and Linux /dev/stdout is a symlink, nonetheless it seems to work differently between them. One of the commenters said it's standard on OSX to use /dev/stdout but not for Linux. In another random place I read statements that imply /dev/stdout is pretty much an OSX thing. There might be a clue in this answer as to why it doesn't work on Linux (seems to implicitly close the file descriptor when used this way).
Further related questions:
https://unix.stackexchange.com/questions/36403/portability-of-dev-stdout
bash redirect to /dev/stdout: Not a directory
The solution
I tried your code on Arch and it indeed gives me the same error, as do the variations mentioned - so this is not related to Ubuntu.
I found a blog post that describes how you can pass a file descriptor to execSync. Putting that together with what I got from here and here, I wrote this modified version of your code:
var fs = require('fs');
var path = require('path');
var fdout = fs.openSync(path.join(process.cwd(), 'stdout.txt'), 'a');
var fderr = fs.openSync(path.join(process.cwd(), 'stderr.txt'), 'a');
var execSync = require('child_process').execSync,
result = execSync('echo "hello world"', {stdio: [0,fdout,fderr] });
Unless I misunderstood your question, you want to be able to change where the output of the command in execSync goes. With this you can, using a file descriptor. You can still pass 1 and 2 if you want the called program to output to stdout and stderr as inherited by its parent, which you've already mentioned in the comments.
For future reference, this worked on Arch with kernel version 4.10.9-1-ARCH, on bash 4.4.12 and node v7.7.3.

Nodejs Printing to Non standard output

node 5.4.1
windows 10
//program.js
console.log("hello world");
What i want to achieve is node program.js 3>file.txt
//file.txt
hello world
I have tried:
fs.createWriteStream(null,{fd:3})
//creates error bad file descriptor
fs.openSync(null,{fd:3})
//Another error
var tty = require("tty");
var out = new tty.WriteStream(3);
//Empty print
I don't know what else to try. Any advice.
What is the 3 in 3>file.
I don't even know the term to search using.
I have used:
File Descriptor
Non Standard Output
Output 3
If my question doesn't define clearly what i want please comment so i can correct where i have went wrong.
I have attempted to define:
What i want.
What i have tried.
Where I have look.
Any advice will be much appreciated.
This program should do what you need:
var fs = require('fs');
var stream = fs.createWriteStream(null, {fd: 3});
stream.write("OK\n");
If run without proper redirection, it gives the "EBADF: bad file descriptor" error:
$ node fd3.js
events.js:141
throw er; // Unhandled 'error' event
^
Error: EBADF: bad file descriptor, write
at Error (native)
When run with a redirection of FD 3, it prints OK:
$ node fd3.js 3>&1
OK
If it doesn't work on Windows then maybe it's a bug in Node or the fs module and you should report it or see if it was reported already:
https://github.com/nodejs/node/issues
You didn't actually show what errors do you get so it's really hard to answer your question in any more detail.
Update
As I wrote in the comments it would be very helpful to see what exact error message is printed to have some idea if it is a bug in Node or in the fs module or maybe a problem with bad invocation, or error in the program - in your question you show how you open the streams but you don't show how you actually attempt to print anything.
For example, I can run my example programs in those two ways:
node fd3.js 2>&1
or:
node fd3.js 3>&4
In both cases I can say that I get a "bad file descriptor" error but both of those errors are actually different errors, on different descriptors, reported by different subsystems during different steps in the invocation.
After reading here that it's a problem with Windows that may not even have a concept of file descriptors higher than 2, I've done some experiments by running this bat file on Windows 10:
#echo off
echo abc 1>&3
And it works just fine. When I invoke it as:
winfdtest 3>file.txt
I get abc written in file.txt. In fact, I don't even get a bad descriptor error when I don't redirect fd 3 to a file, in which case it gets printed to the console and no errors are shown. On the other hand when I run it as:
winfdtest 4>file.txt
the abc gets printed to the console and the file.txt is empty so it means that the correct descriptor gets redirected, and those that are not redirected get printed to the console.
My conclusion is that the same should work in Node and if it doesn't then it's a bug. Unfortunately no exact code and no exact error messages was shown in the question so it's hard to say what is going wrong exactly.

How do I set up a preload file for node?

Is there a way to preload some file before each time I run node (interactively), just like .vimrc, .bash_profile, etc.?
I use node mainly interactively, and I use the module CSV a lot, is there a way to avoid typing require('./csv') every time I start node?
Create an initialization file (for example ~/.noderc):
var csv = require('csv');
// put a blank line at the end of the file
Now add this line to your shell config (.bashrc / .zshrc / whatever shell you use):
alias nodei="cat ~/.noderc - | node -i"
Voilà!
#Ilan Frumer provided one way to do it. I think I'll give another choice here: build a REPL of your own.
From their documentation. You can find a way to write a repl of your own. You can add whatever scripts before and after the interations of it, and even use some advance API's.
For example, I created a file called .noderc.js under ~ as follows
repl = require('repl');
myFunc = function(){
console.log("Hello, there!");
};
repl.start("> ");
And you can go ahead and alias nodei="node ~/.noderc.js",
$ nodei
> myFunc()
Hello, there!
undefined

Resources