Node.js exec to build Marp markdowns doesn't work - javascript

I wrote this simple node.js script to build Marp markdown and convert them to PDF. But it doesn't do anything and doesn't terminate. I added a console.log("test") at the end I see that node.js doesn't wait for all the command executions to finish but exec also doesn't run the Marp build command.
If I run the "cmd" string from the terminal it all works. I think something is wrong with the way I use exec
var glob = require("glob");
var cp = require("child_process");
glob("lab*/*.marp.md", {}, function (err, files) {
files.forEach((file) => {
var destination = file.replace(".md", "");
var cmd = `marp ${file} --allow-local-files --pdf -o ${destination}.pdf`;
var dir = cp.exec(cmd, (err, stdout, stderr) => {
if (err) {
console.log("node couldn't execute the command");
return;
}
// the *entire* stdout and stderr (buffered)
console.log(`stdout: ${stdout}`);
console.log(`stderr: ${stderr}`);
});
dir.on("exit", function (code) {
// exit code is code
console.log(`finished building: ${file}`);
});
});
});

you can try the execSync() function It'll solve the issue
var glob = require("glob");
var cp = require("child_process");
glob("lab*/*.marp.md", {}, function (err, files) {
files.forEach((file) => {
var destination = file.replace(".md", "");
var cmd = `marp ${file} --allow-local-files --pdf -o ${destination}.pdf`;
var dir = cp.execSync(cmd, (err, stdout, stderr) => {
if (err) {
console.log("node couldn't execute the command");
return;
}
// the *entire* stdout and stderr (buffered)
console.log(`stdout: ${stdout}`);
console.log(`stderr: ${stderr}`);
});
dir.on("exit", function (code) {
// exit code is code
console.log(`finished building: ${file}`);
});
});
});

Related

'sed' Command doesn't work with java script

I want to exectue following Shell Command with the Execute Option form Javascript:
"sed -i 4r<(sed '1,5!d' /etc/wpa_supplicant/wpa_template.template) /etc/wpa_supplicant/wpa_supplicant.conf"
Then i try this command in the shell console it works perfektly. But after starting it with the .js programm nothing is happen. I just want to copy the first 5 lines in template and add them to the config file.
You can do with exec from child_process
const exec = require('child_process').exec
exec("sed -i 4r<(sed '1,5!d' /etc/wpa_supplicant/wpa_template.template) /etc/wpa_supplicant/wpa_supplicant.conf", (err, stdout, stderr) => {
if (err) {
return console.error(err)
}
console.log(`stdout: ${stdout}`)
console.log(`stderr: ${stderr}`)
})
You can use the below code to execute any shell command and replace the o/p to a new file(create a new file) everytime you run it. And, you should use the line-reader module to get the line from the files.
npm install --save line-reader
const fs = require('fs');
const lineReader = require('line-reader');
const { exec } = require('child_process');
const cmd = "sed -i 4r<(sed '1,5!d' /etc/wpa_supplicant/wpa_template.template) /etc/wpa_supplicant/wpa_supplicant.conf"
exec(cmd, (err, stdout, stderr) => {
if (err) {
//some err occurred
console.error(err)
} else {
// the *entire* stdout and stderr (buffered)
fs.writeFile('file path', stdout, (err) => {
// throws an error, you could also catch it here
if (err) throw err;
// success case, the file was saved
console.log('file saved');
readFile1();
});
}
});
const readFile1 = () => lineReader.eachLine('file path', function(line) {
//make logic to take number of lines you want to take.
console.log(line);
});

Run an installer inside my program

How can I run an installer of an independent program (exe file) from inside of my code?
The idea in general is program which install other programs.
Thanks!
Barak
use exec of node.js
const { exec } = require('child_process');
exec('path/to/exe', (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
return;
}
console.log(`stdout: ${stdout}`);
console.log(`stderr: ${stderr}`);
});

SSH into remote machine and execute commands in Node.js

I'm looking for a way to SSH into a virtual machine and then execute certain scripts inside the virtual machine using Node.js
So far I've created the shell script that automate the login to the virtual machine but i'm unable to figure out how to move forward.
My shell script for login to remote server
spawn ssh root#localhost
expect "password"
send "123456"
send "\r"
interact
This is my server.js
var http = require('http');
var execProcess = require("./exec_process.js");
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
execProcess.result("sh sshpass.sh", function(err, response){
if(!err){
res.end(response);
}else {
res.end("Error: ", err);
}
});
}).listen(3000);
console.log('Server listening on port 3000');
exec_process.js
var exec = require('child_process').exec;
var result = function(command, cb){
var child = exec(command, function(err, stdout, stderr){
if(err != null){
return cb(new Error(err), null);
}else if(typeof(stderr) != "string"){
return cb(new Error(stderr), null);
}else{
return cb(null, stdout);
}
});
}
exports.result = result;
Any help is appreciated thanks
Why dont you use simple-ssh ?
I made a simple example of how to load a file with a list of commands and execute them in chain.
exampleList : (commands must be separated in new lines)
echo "Testing the first command"
ls
sshtool.js : (it can be buggy, example: if any command contains \n)
const _ = require("underscore");
//:SSH:
const SSH = require('simple-ssh');
const ssh = new SSH({
host: 'localhost',
user: 'username',
pass: 'sshpassword'
});
//example usage : sshtool.js /path/to/command.list
function InitTool(){
console.log("[i] SSH Command Tool");
if(process.argv[2]){AutomaticMode();}
else{console.log("[missing argument : path to file containing the list of commands]");}
}
//:MODE:Auto
function AutomaticMode(){
const CMDFileName = process.argv[2];
console.log(" ~ Automatic Command Input Mode");
//Load the list of commands to be executed in order
const fs = require('fs');
fs.readFile(process.argv[2], "utf8", (err, data) => {
if(err){console.log("[!] Error Loading Command List File :\n",err);}else{
var CMDList = data.split("\n"); // split the document into lines
CMDList.length = CMDList.length - 1; //fix the last empty line
_.each(CMDList, function(this_command, i){
ssh.exec(this_command, {
out: function(stdout) {
console.log("[+] executing command",i,"/",CMDList.length,"\n $["+this_command+"]","\n"+stdout);
}
});
});
console.log("[i]",CMDList.length,"commands will be performed.\n");
ssh.start();
}
});
}
//:Error Handling:
ssh.on('error', function(err) {
console.log('[!] Error :',err);
ssh.end();
});
InitTool();
It uses underscore for looping through the command list.

Fs Module error

I'm using Node v6.7.0 trying to use 'fs' module but there is error as you see below. i Have tried to install it in addition but is not working(even if i add whole path). If i check in the site https://www.npmjs.com/package/fs you can see the message. Any ideas how can use the module?
var filename = process.argv[2];
var version = process.argv[3];
var fs = require('fs');
var prompt = require('C:/Program Files/nodejs/node_modules/prompt');
var p4 = require('C:/Program Files/nodejs/node_modules/p4');
p4.edit(filename, function(err, data) {
if (err) {
console.error(err.message);
}
fs.readFile(filename, 'utf8', function (err, data) {
if (err) {
return console.log(err);
}
var result = data.replace(/string to be replaced/g, version);
fs.writeFile(filename, result, 'utf8', function (err) {
if (err) return console.log(err);
});
});
console.log(data);
prompt.start();
prompt.get('p4 submit -c changelist', function (err, result) {
if(err) {
console.log(err.message);
}
console.log(result);
});
});
fs.js:303
binding.open(pathModule._makeLong(path),
^
TypeError: path must be a string or Buffer
at TypeError (native)
at Object.fs.readFile (fs.js:303:11)
at C:\WorkSpace\http.js:22:9
at C:\Program Files\nodejs\node_modules\p4\p4.js:13:24
at ChildProcess.exithandler (child_process.js:213:5)
at emitTwo (events.js:106:13)
at ChildProcess.emit (events.js:191:7)
at maybeClose (internal/child_process.js:877:16)
at Socket.<anonymous> (internal/child_process.js:334:11)
at emitOne (events.js:96:13)
Process finished with exit code 1
fs is a nodejs core module : here is the fs documentation
I found the answer it should be executed in node command line and var filename = process.argv[2]; must be filled up.

Running a command with gulp to start Node.js server

So I am using gulp-exec (https://www.npmjs.com/package/gulp-exec) which after reading some of the documentation it mentions that if I want to just run a command I shouldn't use the plugin and make use of the code i've tried using below.
var exec = require('child_process').exec;
gulp.task('server', function (cb) {
exec('start server', function (err, stdout, stderr) {
.pipe(stdin(['node lib/app.js', 'mongod --dbpath ./data']))
console.log(stdout);
console.log(stderr);
cb(err);
});
})
I'm trying to get gulp to start my Node.js server and MongoDB. This is what i'm trying to accomplish. In my terminal window, its complaining about my
.pipe
However, I'm new to gulp and I thought that is how you pass through commands/tasks. Any help is appreciated, thank you.
gulp.task('server', function (cb) {
exec('node lib/app.js', function (err, stdout, stderr) {
console.log(stdout);
console.log(stderr);
cb(err);
});
exec('mongod --dbpath ./data', function (err, stdout, stderr) {
console.log(stdout);
console.log(stderr);
cb(err);
});
})
For future reference and if anyone else comes across this problem.
The above code fixed my problem. So basically, I found out that the above is its own function and therefore, doesn't need to:
.pipe
I thought that this code:
exec('start server', function (err, stdout, stderr) {
was the name of the task I am running however, it is actually what command I will be running. Therefore, I changed this to point to app.js which runs my server and did the same to point to my MongoDB.
EDIT
As #N1mr0d mentioned below with having no server output a better method to run your server would be to use nodemon. You can simply run nodemon server.js like you would run node server.js.
The below code snippet is what I use in my gulp task to run my server now using nodemon :
// start our server and listen for changes
gulp.task('server', function() {
// configure nodemon
nodemon({
// the script to run the app
script: 'server.js',
// this listens to changes in any of these files/routes and restarts the application
watch: ["server.js", "app.js", "routes/", 'public/*', 'public/*/**'],
ext: 'js'
// Below i'm using es6 arrow functions but you can remove the arrow and have it a normal .on('restart', function() { // then place your stuff in here }
}).on('restart', () => {
gulp.src('server.js')
// I've added notify, which displays a message on restart. Was more for me to test so you can remove this
.pipe(notify('Running the start tasks and stuff'));
});
});
Link to install Nodemon : https://www.npmjs.com/package/gulp-nodemon
This solution has stdout/stderr shown as they occur and does not use 3rd party libs:
var spawn = require('child_process').spawn;
gulp.task('serve', function() {
spawn('node', ['lib/app.js'], { stdio: 'inherit' });
});
You can also create gulp node server task runner like this:
gulp.task('server', (cb) => {
exec('node server.js', err => err);
});
If you want your console to output everything that the child process outputs, as well as pass to the child process all environment variables you already have set:
const exec = require('child_process').exec;
function runCommand(command, cb) {
const child = exec(command, { env: process.env }, function (err) {
cb(err);
})
child.stdout.on('data', (data) => {
process.stdout.write(data);
});
child.stderr.on('data', (data) => {
process.stdout.write(`Error: [${data}]`);
});
}
Note that both out and err write to stdout, this is intentional for my case but you can adapt to whatever you need.

Categories