I have a simple method that executes exec method from child_process using rm -rf as command.
const exec = require('child_process').exec
const Foo = {
emptyDir: params => {
exec(`rm -rf ${params.path}`, (err, stdout, stderr) => {
console.log('test');
})
}
}
Foo.emptyDir({path:'./data/*'})
Method works and files do get deleted, however callback never gets executed. What am I missing?
Node version: v6.10.2
First of all, you may want to use one of those modules to remove files in Node:
https://www.npmjs.com/package/remove
https://www.npmjs.com/package/rimraf
Now, it's not possible that the console.log('test'); is not executed, because you don't even test for errors so it will be executed even if you don't have the rm command in PATH or if it fails.
What is possible is that you may not see the console.log() output if the STDOUT is redirected or even the console.log redefined. To really see if the callback is called you may try to write some message to a file.
Related
Let's say I want to run npm install inside a node.js and log the STDOUT. I could think of something like this:
var process = child_process.spawn("npm", ["install", package_name]);
process.stdout.on('data', function (chunk) {
console.log(chunk.toString());
});
While this kind of execution works for some cases, in some cases it errors out. It's not giving me enough information what exactly is causing the error so I can only guess.
One thing I noticed is, nowadays a lot of npm install program executions do NOT display the log in a serial manner but instead display animation inline and stuff.
Here's an example of what I'm talking about:
My question is:
Might this kind of animation why the stdout.on('data') is erroring out in some cases?
How do I deal with this situation? I just want to get the full stream of all the data
There is stdout and stderr. Maybe try to catch errors there? Here is part of my code where I use npm installer, but in a bit different way by utilizing npm-cli.js, which gives the option to use npm without its global installation on the server:
// Require child_process module
const { fork } = require('child_process');
// Working directory for subprocess of installer
const cwd = './path-where-to-run-npm-command';
// CLI path FROM cwd path! Pay attention
// here - path should be FROM your cwd directory
// to your locally installed npm module
const cli = '../node_modules/npm/bin/npm-cli.js';
// NPM arguments to run with
// If your working directory already contains
// package.json file, then just install it!
const args = ['install']; // Or, i.e ['audit', 'fix']
// Run installer
const installer = fork(cli, args, {
silent: true,
cwd: cwd
});
// Monitor your installer STDOUT and STDERR
installer.stdout.on('data', (data) => {
console.log(data);
});
installer.stderr.on('data', (data) => {
console.log(data);
});
// Do something on installer exit
installer.on('exit', (code) => {
console.log(`Installer process finished with code ${code}`);
});
In this case, I am using Node.js ChildProcess. Let's say the application file (index.js, for example) is in folder1. This folder also has folder2, which is where the class file is. So, when I call spawn from folder1, the command's current directory is folder1. However, I can't do java ./folder2/MyFile.
Here's what I tried:
async function run(path){
let child = spawn('java', [path], {
stdio: [process.stdin, process.stdout, process.stderr] //for testing purposes
})
}
Using function run on ./folder2/MyFile returns:
Error: could not find or load main class ..folder2.MyFile
I assume this has something to do with java and classpath. I saw an answer involving setting the classpath to the target directory (folder2) but it didn't do anything.
In short, how can I run a .class file from a different directory?
You can use exec instead of spawn so you can use two commands with & symbol which the second command runs when the first one finish without fail.
I think this might work for you.
const exec = require('child_process').exec;
exec("cd ./folder2 & java MyFile", function(
error: string,
stdout: string,
stderr: string
) {
console.log(stdout);
console.log(error);
console.log(stderr);
});
I have a gulp task that's hanging after completion.
Running --verbose on my command tells me that it completed the run, but it doesnt exit the process
// ./gulpfile.js/precon/index.js
const { preconMoveFile, preconExcelToMysql } = require('../../src/lib/preCon')
module.exports = async done => {
try {
await preconMoveFile()
await preconExcelToMysql()
done()
// return <-- doesnt work either per comment
} catch (e) {
throw e
}
}
below is the command line output, pardon my debug log output
C:\Users\ALilland\Documents\macros\experiments\forecast-scraper>set NODE_ENV=development& gulp precon --verbose
[12:33:57] Using gulpfile ~\Documents\macros\experiments\forecast-scraper\gulpfile.js
[12:33:57] Starting 'precon'...
[2019-07-30T19:33:57.264Z] DEBUG - [preCon.preconMoveFile] existing ./src/tmp/precon.xlsx removed
[2019-07-30T19:33:57.333Z] DEBUG - [preCon.preconMoveFile] copied new file to ./src/tmp/precon.xlsx
[2019-07-30T19:33:58.965Z] INFO - [initialize.db.caePreconForecast] created caePreconForecast
[2019-07-30T19:33:59.012Z] DEBUG - [preCon.preconExcelToMysql] added rows to db
[12:34:00] Finished 'precon' after 3.24 s
I tried several of the options shown in the docs with no success, and also tried several of the options here with no success
I have also tried calling process.exit(0) but that produces the Did you forget to signal async completion? warning that the docs mention
Edit:
I should also note my root index.js file that requires the precon task
// ./gulpfile.js/index.js
exports.default = require('./default')
exports.precon = require('./precon')
The hang does not result from gulp, there is a background process still running preventing gulp from closing
the culprit was an open mysql pool connection
const mysql = require('mysql')
const params = require('../config/mysql')
const db = mysql.createPool(params)
db.end() // <-- running this after each task resolves the issue
Here is my problem, I want to create a CLI that automatically runs a test. Without the CLI, I'm able to run everything perfectly with the node command:
node test.js
Basically, I want to do the exact same thing as the command before, so I googled for a technique that does this. I found this:
#!/usr/bin/env node
'use strict';
const options = process.argv;
const { execFile } = require('child_process');
const child = execFile('node', ['../dist/test.js'], (error, stdout, stderr) => {
if (error) {
throw error;
}
console.log(stdout);
});
This method doesn't work for me because, in the test.js file, I'm using the ora package. And because this package is making real-time animations, it doesn't come in stdout.
Is there any way of executing in real time (without subprocess) my test.js using Node? I'm open to other methods, but I want to publish the CLI on NPM, so keep in mind that it has to be in JavaScript 😊.
You can find every file that I've talked here on GitHub. Normally, you wouldn't need this link, but I'm giving it to you if you need to have a closer look.
You should simply call your test() function from your CLI code, after requiring the module that defines it. Have a look at mocha and jasmine: you will see that while both tools provide a CLI, they also provide instructions for invoking the test frameworks from arbitrary JS code.
I can't think of a way without a sub-process. but this may help.
The child process exec will not work with the continuous output commands as it buffers the output the process will halt when that buffer is full.
The suitable solution is spwan :
var spwan = require('child_process').spwan
var child = spwan('node', ['../dist/test.js'])
child.stdout.on('data', function(data) {
console.log(data)
})
child.stderr.on('data', function(data) {
console.log(data)
})
Here is my solution, you can use the fs library to get the code of the file, and then, you simply use eval to execute in the same process.
const fs = require("fs");
function run(file) {
fs.readFile(file, (err, data) => {
eval(data.toString('utf8'))
})
}
I need to check if a file exists in a gulp task, i know i can use some node functions from node, there are two:
fs.exists() and fs.existsSync()
The problem is that in the node documentation, is saying that these functions will be deprecated
You can use fs.access
fs.access('/etc/passwd', (err) => {
if (err) {
// file/path is not visible to the calling process
console.log(err.message);
console.log(err.code);
}
});
List of available error codes here
Using fs.access() to check for the accessibility of a file before calling fs.open(), fs.readFile() or fs.writeFile() is not recommended. Doing so introduces a race condition, since other processes may change the file's state between the two calls. Instead, user code should open/read/write the file directly and handle the error raised if the file is not accessible.
You could add
var f;
try {
var f = require('your-file');
} catch (error) {
// ....
}
if (f) {
console.log(f);
}
As of 2018, you can use fs.existsSync():
fs.exists() is deprecated, but fs.existsSync() is not. The callback parameter to fs.exists() accepts parameters that are inconsistent with other Node.js callbacks. fs.existsSync() does not use a callback.
See this answer for more details.
I believe fs-access package has been depreciated alternatively you may want to use:
path-exists.
file-exists.
Intracutions (path-exists):
npm install path-exists --save
const myFile = '/my_file_to_ceck.html';
const exists = pathExists.sync(myFile);
console.log(exists);
Intracutions (file-exists):
npm install file-exists --save
const fileExists = require('file-exists');
const myFile = '/my_file_to_ceck.html';
fileExists(myFile, (err, exists) => console.log(exists))
NPM Link: path exists
NPM Link: file exists
The node documentatión does not recommend using stat to check wether a file exists:
Using fs.stat() to check for the existence of a file before calling fs.open(), fs.readFile() or fs.writeFile() is not recommended.
Instead, user code should open/read/write the file directly and handle
the error raised if the file is not available.
To check if a file exists without manipulating it afterwards,
fs.access() is recommended.
If you don't need to read or write the file you should use fs.access, the simple and asynchronous way is:
try {
fs.accessSync(path)
// the file exists
}catch(e){
// the file doesn't exists
}