how do you run a commamd say npm install or rake as part of a node js application? - node.js

I have a node app in which i want to run a command or task like npm install or rake or git clone . I tried using child process exec , but is not running the npm install task. Is there a alternative way?

If you want to execute a shell (or cmd if you're on Windows) command you can do it by using child_process.exec()
https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback
Here is an example:
var exec = require('child_process').exec;
var child;
child = exec("pwd", function (error, stdout, stderr) {
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if (error !== null) {
console.log('exec error: ' + error);
}
});
Just put npm install or git clone or whatever you want to execute instead of pwd when calling the exec function.

You can do the following to get npm install work inside a node script,
Execute npm install npm --save (This will take some time)
Now since npm is inside the node_modules folder, you can import it inside your script.
Sample script below which installs 'foobar' package
var npm = require("npm");
npm.load(function (err) {
npm.commands.install(["foobar"], function (err, data) {
});
npm.on("log", function (message) {
// progress of the npm install
console.log(message);
});
});
This is just an alternative. Use child_process as suggested by Lucian

Related

How to test an node file, receiving an 'EACCES' error when spawning the function

When creating a CLI I would like to test my function. For that I'm using the module child_process.
const path = require('path');
const { execFile } = require('child_process');
describe('cli test', () => {
test('thing', () => {
const myCli = execFile(
`${path.resolve(__dirname, '..')}/cli.js`, ['--foo', 'Bar'],
(err, stdout, stderr) => {
if (err) {
console.log('err: ', err);
}
});
});
But this produces the following error:
Attempted to log "err: { Error: spawn /projects/cli/src/cli.js EACCES
at Process.ChildProcess._handle.onexit (internal/child_process.js:240:19)
at onErrorNT (internal/child_process.js:415:16)
at process._tickCallback (internal/process/next_tick.js:63:19)
errno: 'EACCES',
code: 'EACCES',
Running this script directly in the terminal via the command: $ node cli.js --foo Bar works perfectly.
Now a suggestion is to chmod +x <file> that file (source). But the test should also work on CI, and on a different computer which pulls the Git repo.
Any idea?
I'd suggest using fork instead of execFile.
The child_process.fork() method is a special case of child_process.spawn() used specifically to spawn new Node.js processes.
This will allow you to execute JS files without needing them to be shell executable.
To the best of my knowledge, git actually tracks the executable bit for files. There are some things to consider though as pointed out in this article: https://medium.com/#tahteche/how-git-treats-changes-in-file-permissions-f71874ca239d
Another solution would be to not rely on the ./ execution syntax (which requires the executable bit to be turned on for the respective file) but instead to explicitly use the shell command:
const path = require('path');
const { execFile } = require('child_process');
describe('cli test', () => {
test('thing', () => {
const myCli = execFile(
`sh ${path.resolve(__dirname, '..')}/cli.js`, ['--foo', 'Bar'],
(err, stdout, stderr) => {
if (err) {
console.log('err: ', err);
}
});
});
Notice the sh prefix I added to your code, This way you thell the sh command (which should be available in all of your environments e.g. the CI) to execute the contents of the file, regardless of whether the file itself can be executed or not!
I was receiving an EACCESS -13 error from child_process.spawn when trying to run a the command line mysql command.
There was something wrong with my PATH and updating it to add /usr/local/mysql/bin/ resolved the problem.
The temporary fix is to run export PATH=$PATH:/usr/local/mysql/bin/.
The permanent fix is to:
type: sudo nano /etc/paths
Add /usr/local/mysql/bin at the end
Ctrl + X
Yes
Enter key
type hash -r # command line or close the terminal app and open it again
NOTE: I got the temporary fix from a site ... I don't know why it has a / on the end of the bin but all of the mysql executables appear to be available without it in the /etc/paths file

Changing command prompt directory from Node.js script

I'm trying to change the directory of terminal using with Node.js program but not able to achieve it. Script is run as node app.js dir_name so first I'm creating the directory and then trying to change into that directory using cd command. Directory is created but the directory for terminal is not changed.
#!/usr/bin/env node
var platform = process.platform;
var figlet = require('figlet');
var chalk = require('chalk');
if(process.argv.length < 3){
console.log(
chalk.green(
figlet.textSync('mdcd', { horizontalLayout: 'full' })
)
);
console.log(chalk.red("Please provide a directory name"));
}else{
if(platform.includes("win")){
//console.log("Its Windows");
}else {
var exec = require('child_process').exec;
var command_1 = "mkdir "+process.argv[2];
var command_2 = "cd "+process.cwd()+"/"+process.argv[2];
exec(command_1, function (error, stdout, stderr) {
if(error){
console.log("Something bad happened"+error);
}else {
exec(command_2, function (error, stdout, stderr) {
if(error){
console.log("Something bad happened"+error);
}
});
}
});
}
}
command prompt directory from Node.js script
You cannot change the command prompt directory. Basically you have the process tree:
cmd / term
| -> NodeJs
You shouldn't change the working dir for cmd. However there are command you can execute to change the working dir of any process e.g. https://unix.stackexchange.com/a/282009
More
You can however change the the working dir for the nodejs process (which is what I suspect you want to do) using process.chdir https://nodejs.org/api/process.html#process_process_chdir_directory

How to run shell script file using nodejs?

I need to run a shell script file using nodeJS that executes a set of Cassandra DB commands. Can anybody please help me on this.
inside db.sh file:
create keyspace dummy with replication = {'class':'SimpleStrategy','replication_factor':3}
create table dummy (userhandle text, email text primary key , name text,profilepic)
You could use "child process" module of nodejs to execute any shell commands or scripts with in nodejs. Let me show you with an example, I am running a shell script(hi.sh) with in nodejs.
hi.sh
echo "Hi There!"
node_program.js
const { exec } = require('child_process');
var yourscript = exec('sh hi.sh',
(error, stdout, stderr) => {
console.log(stdout);
console.log(stderr);
if (error !== null) {
console.log(`exec error: ${error}`);
}
});
Here, when I run the nodejs file, it will execute the shell file and the output would be:
Run
node node_program.js
output
Hi There!
You can execute any script just by mentioning the shell command or shell script in exec callback.
You can execute any shell command using the shelljs module
const shell = require('shelljs')
shell.exec('./path_to_your_file')
you can go:
var cp = require('child_process');
and then:
cp.exec('./myScript.sh', function(err, stdout, stderr) {
// handle err, stdout, stderr
});
to run a command in your $SHELL.
Or go
cp.spawn('./myScript.sh', [args], function(err, stdout, stderr) {
// handle err, stdout, stderr
});
to run a file WITHOUT a shell.
Or go
cp.execFile();
which is the same as cp.exec() but doesn't look in the $PATH.
You can also go
cp.fork('myJS.js', function(err, stdout, stderr) {
// handle err, stdout, stderr
});
to run a javascript file with node.js, but in a child process (for big programs).
EDIT
You might also have to access stdin and stdout with event listeners. e.g.:
var child = cp.spawn('./myScript.sh', [args]);
child.stdout.on('data', function(data) {
// handle stdout as `data`
});
Also, you can use shelljs plugin.
It's easy and it's cross-platform.
Install command:
npm install [-g] shelljs
What is shellJS
ShellJS is a portable (Windows/Linux/OS X) implementation of Unix
shell commands on top of the Node.js API. You can use it to eliminate
your shell script's dependency on Unix while still keeping its
familiar and powerful commands. You can also install it globally so
you can run it from outside Node projects - say goodbye to those
gnarly Bash scripts!
An example of how it works:
var shell = require('shelljs');
if (!shell.which('git')) {
shell.echo('Sorry, this script requires git');
shell.exit(1);
}
// Copy files to release dir
shell.rm('-rf', 'out/Release');
shell.cp('-R', 'stuff/', 'out/Release');
// Replace macros in each .js file
shell.cd('lib');
shell.ls('*.js').forEach(function (file) {
shell.sed('-i', 'BUILD_VERSION', 'v0.1.2', file);
shell.sed('-i', /^.*REMOVE_THIS_LINE.*$/, '', file);
shell.sed('-i', /.*REPLACE_LINE_WITH_MACRO.*\n/, shell.cat('macro.js'), file);
});
shell.cd('..');
// Run external tool synchronously
if (shell.exec('git commit -am "Auto-commit"').code !== 0) {
shell.echo('Error: Git commit failed');
shell.exit(1);
}
Also, you can use from the command line:
$ shx mkdir -p foo
$ shx touch foo/bar.txt
$ shx rm -rf foo

Node, copy file from module to project

I try to create a node module and make a postinstall script (into package.json) who copy a js file into the current project like this :
fs.copy(appDir + "/schedule.js", appDir + "/../../config/schedule.js", function (err)
{
if (err)
{
console.log(err);
}
else
{
fs.chmod(appDir + "/../../config/schedule.js", 0755, function (err, succ)
{
console.log(err, succ);
});
console.log("done write schedule.js base config");
}
});
The problem is the file correctly copy but it's lock and can't be edited... Chmod doesn't return error.
I'm under max OS X with node js 0.10.33 (IDE IntelliJ)
Found it :) if the module is install like this :
sudo npm install mymodule
The file is not editable but if module is install without sudo everything is fine
npm install mymodule

Node JS - child_process spawn('npm install') in Grunt task results in ENOENT error

I'm having some difficulty with a Grunt task I'm authoring. I'm trying to execute npm install, followed by bower install, followed by a grunt hub target (to trigger a build command for multiple sub-projects).
The problem I'm encountering lies with child_process. I get spawn ENOENT error if I run the following commands in my grunt task, with the npm install spawn command that's currently commented out:
var path = require('path'),
projectPath = path.resolve(process.cwd(), this.data.activity );
grunt.log.debug('project path computed as: ', projectPath);
process.chdir( projectPath );
console.log('current dir is: ', process.cwd());
console.log('EVN is: ', process.env);
var spawnProcess = spawn('ls');
// var spawnProcess = spawn('npm install');
spawnProcess.stdout.on('data', function (data) {
console.log('' + data);
});
spawnProcess.stderr.on('data', function(data) {
console.log('something went wrong installing deps for ' + path + '. Error: ', data);
});
spawnProcess.on('close', function (exitCode) {
console.log( 'ls has finished with Exit Code: ' + exitCode);
});
the current code (with ls instead of npm install) results in:
running "install:projects" (install) task[D] Task source: /Users/zedd45/proj/Gruntfile.js
Verifying property install.projects exists in config...OK
File: [no files]
[D] project path computed as: /Users/zedd45/proj/activity/web/client
current dir is: /Users/zedd45/proj/activity/web/client
EVN (abbreviated) is: {
TERM_PROGRAM: 'iTerm.app',
SHELL: '/bin/bash',
PWD: '/Users/zedd45/proj',
...
OLDPWD: '/Users/zedd45/proj/activity/web/client',
_: '/usr/local/bin/grunt' }
GruntFile.js
bower.json
package.json
this_is_the_directory_you_are_looking_for.txt
ls has finished with Exit Code: 0
but if I change 'ls' to 'npm install' I get instead
``Fatal error: spawn ENOENT
immediately following the ENV print.
I have tried chmod 777 for that directory, which doesn't seem to help.
I have also tried:
// var spawnProcess = spawn('npm install', {'cwd': projectPath});
and
// var spawnProcess = spawn('npm install', [], {'cwd': projectPath});
The former results in
Warning: Object # has no method 'slice' Use --force to
continue.
the later still results in the ENOENT error.
Any help with exactly what this ENOENT error is would probably help a great deal; I haven't had much success with Googling it nor with the child process API docs
Double check the docs on child_process.spawn again. The first argument should be only the command to run and the second is the arguments:
var npm = spawn('npm', ['install'], { cwd: projectPath });

Resources