How to run multiple shell commands incluiding Node.js server? Ubuntu - node.js

I have a script that sequentially executes 2 instructions as following:
node server.js
node tests.js
Server.js initializes a local Node.js + Express server
Tests.js executes some unit tests on that server
The problem is that the first instruction keeps listening for requests, so the second is never executed.
Is it possible to solve this behaviour?

I advise you to use the npm package start-server-and-test to be sure that your api server is ready to be tested
start-server-and-test 'node server.js' http://localhost:{API_PORT}/ 'node tests.js'

Related

What are the differences between the processes run by npm command:

Recently I made a simple API server using node.js+express. And the script below is a part of my package.json file I use to run with npm commands.
"scripts": {
...
"release": "cross-env NODE_ENV=production MODE=release node server/app.js",
}
After I starts the server with npm run release, I can see multiple processes such as below are running on my Linux server.
/bin/sh /api/node_modules/.bin/cross-env NODE_ENV=development MODE=test node server/app.js
node /api/node_modules/.bin/../cross-env/bin/cross-env.js NODE_ENV=development MODE=test node server/app.js
node server/app.js
I read a related documentation here, but I don't understand what actually happens in background.
What is the order of creating processes? npm => /bin/sh => node /api/.. => node server/app.js ?
What does each process do? All three processes are necessary to run my server?
If I wants to kill the server with pid, which process id should I use?
What is the order of creating processes? npm => /bin/sh => node /api/.. => node server/app.js ?
What does each process do? All three processes are necessary to run my server?
Well, the flow is like this:
NPM is spawned (you run it) inside your shell, npm itself runs with NPX in order to set the local path.
Your npm script spawns a process from a package called cross-env for cross-OS environment variable setting.
That process in turn spawns Node.js (after setting the environment variables)
That's why you see 3 processes. After your server itself run - only the actual server process is needed to run the server.
If I wants to kill the server with pid, which process id should I use?
This one: node server/app.js - since that's your actual server, the others are just "utility processes" (one for the npm script you ran and the other for the environment variables").
It's worth mentioning that in general - servers are run inside containers or other orchestrators/managers that have built-in logic for restarting/killing the process. Typically the orchestrator sends SIGTERM to the process.

child_process.fork not starting an express server inside of packaged electron app

I have an electron app where I need not only to run the interface to the user but also start an express server that will serve files for people connected through the network.
I have everything working if I start both electron and the express server normally, but I'm pretty confident that I will need the server running in a different thread to avoid slugish interface and even problems with the server.
For that matter I tried to run my express server using the child_process.fork and it worked when I use npm start, but when I use electron-builder to create an .exe, the installed program doesn't start the express server.
I tried to run my server right away using:
require('child_process').fork('app/server/mainServer.js')
I tried several changes, prefixing the file with __dirname, process.resourcesPath and even hard coding the generated file path; changing the fork options to pass cwd: __dirname, detached: true and stdio: 'ignore'; and even tried using spawn with process.execPath, which will also work with npm start but won't when packaged (it keeps opening new instances of my app, seems obvious after you do hehe)
Note: If I don't fork and require the server script right away, using require('server/mainServer.js') it works on the packaged app, so the problem most like isn't the express itself.
Note 2: I have asar: false to solve other problems, so this is not the problem solver here.
I put up a small git project to show my problem:
https://github.com/victorivens05/electron-fork-error
Any help will be highly appreciated.
With the great help from Samuel Attard (https://github.com/MarshallOfSound) I was able to solve the problem (he solved for me actually)
As he said:
the default electron app will launch the first file path provided to it
so `electron path/to/thing` will work
in a packaged state, that launch logic is not present
it will always run the app you have packaged regardless of the CLI args passed to it
you need to handle the argument manually yourself
and launch that JS file if it's passed in as the 1st argument
The first argument to fork simply calls `process.execPath` with the first
argument being the path provided afaik
The issue is that when packaged Electron apps don't automatically run the
path provided to them
they run the app that is packaged within them
In other words. fork is actually spawn being executed with process.execPath and passing the fork's first argument as the second for spawn.
What happens in a packaged app is that the process.execPath isn't electron but the packaged app itself. So if you try to spawn, the app will be open over and over again.
So, what Samuel suggest was implemented like this:
if (process.argv[1] === '--start-server') {
require('./server/mainServer.js')
return
}
require('./local/mainLocal.js')
require('child_process').spawn(process.execPath, ['--start-server'])
That way, the first time the packaged app will be executed, the process.argv[1] will be empty, so the server won't start. It will then execute the electron part (mainLocal in my case) and start the app over, but this time passing the argv. Next time the app starts, it will start the server and stop the execution, so the app won't open again because spawn is never reached.
Huge thanks to Samuel.

Need help getting simple node.js express to run

I'm trying a simple sample of node express that I copied from online. The script is below which I think is pretty standard.
var http = require('http');
http.createServer(function(request, response)){
response.writeHead(200);
response.write("hello");
response.end();
}).listen(8080);
console.log('listening on port 8080...');
I used the bash on ubuntu on windows command as follows:
npm init
node SampleServer.js (the name of my file)
When I do this, I expect some response from the command line. But when I enter the "node SamplerServer.js" command, nothing happens. When I direct the browser to port 8080, I get an error message as well.
I'm using nodeclipse and the installing that on my machine was pretty complicated. Prior to any of the steps above, I created an express project in eclipse ide. It seems to perform a lot of pre steps but in the end, I think I'm getting some of the error messages below. I'm mentioning this because I'm thinking perhaps I installed one of the modules wrong.
enter image description here
Start with simple stuff...
Use express-generator to create simple app by the following command
1-> npm install -g express-generator with root or Admin access
2-> Run express demoapp.
3-> Navigate to demoapp
4-> Do npm install
5-> Run from command with npm start: it run by default on http://localhost:3000
Hit that URL from Browser

node command vs app.listen()

I'm confused. So if I use gulp-develop-server, it's got a app.listen():
gulpfile.js
config.server.path is set to './app,js'
server = require('gulp-develop-server');
gulp.task('default', ['server:start'], function(){
});
gulp.task('server:start', function() {
server.listen({ path: config.server.path});
});
My app.js has this:
var koa = require('koa')();
koa.listen(config.server.port, function(){
console.log('Koa app is listening on port ' + config.server.port);
});
so I'm trying to understand better how node is being started. I see people mention doing it manually like "node app.js". So doesn't koa.listen() automatically do a "node" command to start the koa web server? If I use gulp-develop-server and specify server.listen, isn't that doing 2 server.listen() for node?
Just trying to understand the basics here and can't understand why anyone would manually type in 'node [file with .listen]' manually. I'm not doing that manually and server.listen() obviously uses the 'node' command on my app.js.
Your gulpfile is a Node script. So when you run gulp server:start you're executing a Node application, the gulp command is essentially node plus some extra functionality.
The way gulp-develop-server works is it runs an additional Node application as a child process. server.listen is basically just telling gulp-develop-server what script to run.
The naming is a little confusing, but essentially what's going on is: You have 2 Node applications running on your machine (one that you can see, and one in the background), but only 1 server.

How can I run grunt as a daemon?

I am running a packaged nodejs webserver that allows for reading of epub files (Readium-JS), and it is started with the grunt command.
However, if I run this on my VPS the server dies as soon as my terminal connection ends.
How can I run this task as a daemon?
I have looked at options like grunt-forever and grunt-daemon but the way the Gruntfile is written using load-grunt-config is messing with my mind and I can't piece together how to isolate the server code.
Here's the solution I found:
As was suggested above, using pm2
However, when I ran
pm2 start grunt
I got an error saying that the grunt module did not exist, which was weird.
So I ended up writing a script which worked:
-- start.js --
var pm2 = require('pm2');
pm2.connect(function() {
pm2.start({
script : '/usr/local/bin/grunt', // Script to be run
args: '--force',
}, function(err, apps) {
pm2.disconnect();
});
});
After running node start.js from the command line, everything sailed smoothly.

Resources