Hi I'm new to using Code Deploy. I am trying to launch a node application. I have setup.sh, start.sh and app.js in my root directory.
This is my appspec.yml file
version: 0.0
os: linux
files:
- source: /
destination: /
hooks:
Install:
- location: setup.sh
timeout: 3600
ApplicationStart:
- location: start.sh
timeout: 3600
setup.sh
yum -y install nodejs npm --enablerepo=epel
npm install
start.sh
node /app.js
app.js (just a basic dummy server)
var express = require("express");
var app = express();
app.get("/",function(req,res) {
res.send("Hello world")
})
var server = app.listen(8080,function() {
console.log("Listening at " + server.address().address + ": " + server.address().port);
});
The Install step successfully completes, but Code Deploy gets stuck on pending when it does the ApplicationStart step.
I'm pretty sure it's because the app.js program runs continously, so how is CodeDeploy supposed to know that it's working and move on?
The CodeDeploy agent is waiting for the script it launched to return an exit code and to close stdout and stderr. To start a process in the background and detach it from the host agent so it can run as a daemon, try:
node /app.js > /dev/null 2> /dev/null < /dev/null &
Note: you'll want to modify your program to write to a log file instead of the console, since daemons usually don't have a console to write to (as it is in this version).
See the official docs here: http://docs.aws.amazon.com/codedeploy/latest/userguide/troubleshooting.html#troubleshooting-long-running-processes
The command node /app.js does not run in background but in foreground, therefor the start.sh script is never finished.
See this thread for more info about running node in background Node.js as a background service
Related
I have a simple node-cron schedule that calls a function:
cron.schedule('00 00 00 * * *', () => {
console.log('update movies', new Date().toISOString());
updateMovies();
});
When I log in to my server using PuTTy or use the droplet console in Digital Ocean and then run the updateMovies.mjs file node server/updateMovies.mjs and wait for the time that the cron-job should run, everything works as expected.
But when I close PuTTy or the droplet console in Digital Ocean, then nothing happens when the cron-job should run. So the server seems to lose the cron-job when I close the session.
Short answer
You need to run the app in the background
nohup node server/updateMovies.mjs >/dev/null 2>&1
Long answer
Run your app directly in the shell is just for demos or academic purposes. On an enterprise environment you should a live process like a server which runs independently of the shell user.
Foreground and background processes
Processes that require a user to start them or to interact with them are called foreground processes
Processes that are run independently of a user are referred to as background processes.
How run background process (Linux)
No body uses windows for an modern deployments, so in Linux the usual strategy is to use nohup
server.js
var express = require('express');
var app = express();
app.get('/', function(req, res) {
res.type('text/plain');
res.send('Hell , its about time!!');
});
app.listen(process.env.PORT || 8080);
nohup node server.js >/dev/null 2>&1
If you login to the server using some shell client, and run only node server.js it will start but if you close the shell window, the process will ends.
How run background process with nodejs and PM2
pm2 server.js
More details here:
https://pm2.keymetrics.io/docs/usage/quick-start/
Best way : Docker
You need to dockerize your app and it will run everywhere with this command:
docker run -d my_app_nodejs ....
My docker file is super simple:
FROM node:4-onbuild
RUN npm install gulp -g;
EXPOSE 8888
This image will automatically run the start script in package.json which I have set simply as gulp.
If I run gulp on my host machine, and make a change to node file, it automatically restarts server:
var gulp = require('gulp');
var nodemon = require('gulp-nodemon');
gulp.task('default', function() {
nodemon({
script: 'server.js', // starts up server on port 4000
env: { 'NODE_ENV': 'development' }
})
});
Figuring everything is okay I run this: docker run -d -p 1234:4000 -v $(pwd):/usr/src/app my-image
Going to http://192.168.99.100:1234/ shows 'Hello World!' from my server.js file. Updating the file does NOT update what I see by hitting that URL again. If I exec into the container, I see the file is updated. Since the container started node via the same gulp command, I don't understand why the node server wouldn't have restarted and shown the update.
The TL;DR of this is that you need to set nodemon to poll the filesystem for changes as follows: https://github.com/remy/nodemon#application-isnt-restarting
In some networked environments (such as a container running nodemon reading across a mounted drive), you will need to use the legacyWatch: true which enabled Chokidar's polling.
Via the CLI, use either --legacy-watch or -L
The longer version is this (with one key assumption - you're using docker on Mac or similar):
On Mac or similar, docker doesn't run natively and instead runs inside of a virtual machine (generally virtual box via docker-machine). Virtual machines generally don't propagate filesystem inotify events, which is what most watchers rely on to restart or perform an action when a file changes. As the virtual machine doesn't propagate the events from the host, Docker never receives the events. Your original docker file would probably work on a native linux machine.
There's an open issue and much more detailed discussion of this here.
I am trying to have a nodejs application start automatically on system boot. Basically all I need is to run the command node /dir/app.
I am using openwrt on an Arduino Yun. And have tried a couple things.
On the openwrt website it said I can do this. https://wiki.openwrt.org/inbox/procd-init-scripts :
#!/bin/sh /etc/rc.common
USE_PROCD=1
start_service() {
procd_open_instance
procd_set_param command node ///www/www-blink.js
procd_close_instance
}
I have also tried changing the dir to /www/www-blink.js not ///
However i'm not sure what i'm doing wrong as nothing comes up when I try run it with /etc/init.d/node-app start I am obviously writing the code wrong but i'm not sure what it should exactly look like.
The other thing I have tried is the node modules forever and forever-service.
I downloaded them on my computer using npm install -g forever and forever-service aswell. I transfered them to usr/lib/node_modules on my arduino yun. However when I try to use and forever(-service) commands it says
-ash: forever: not found
I have tried a couple other things, however nothing has worked. Any help would be greatly appreciated.
-- I also need to be able to start my express script with npm start not node app but I guess the first thing is getting it to work at all.
you can put the starting command (node /dir/app &)in the /etc/rc.local script. This will start your nodejs application automatically on system boot.
OpenWRT procd has a "respawn" parameter, which will restart a service that exits or crashes.
# respawn automatically if something died, be careful if you have an
# alternative process supervisor if process dies sooner than respawn_threshold,
# it is considered crashed and after 5 retries the service is stopped
procd_set_param respawn ${respawn_threshold:-3600} ${respawn_timeout:-5} ${respawn_retry:-5}
So, you cold just add:
procd_set_param respawn 60 5 5
or something like that to your OpenWRT procd initscript. This 60 5 5 means it will wait 5s between respawns (middle parameter), and if it respanws more than 5 times (last parameter) in 60s (first parameter), it will disable the service ("restart loop" detected).
Refer to this page for more information:
https://openwrt.org/docs/guide-developer/procd-init-scripts
You need to execute your node application like a Linux Service.
Upstart is perfect for this task
Upstart is an event-based replacement for the /sbin/init daemon which handles starting of tasks and services during boot, stopping them during shutdown and supervising them while the system is running.
If you have an app like this (for example):
// app.js
var express = require('express')
var app = express()
var port = process.env.PORT
app.get('/', function(req, res) {
res.send('Hello world!')
})
app.listen(port)
With a package.json like this:
{
"name": "my-awesome-app",
"version": "1.0.0",
"dependencies": {
"express": "^4.13.3"
},
"scripts": {
"start": "node app.js"
}
}
We create a upstart configuration file called myAwesomeApp.conf with the following code:
start on runlevel [2345]
stop on runlevel [!2345]
respawn
respawn limit 10 5
setuid ubuntu
chdir /opt/myAwesomeApp.conf
env PORT=3000
exec npm start
To finish, put your application (app.js and package.json) in the /opt/myAwesomeApp.conf and copy the configuration file myAwesomeApp.conf in /etc/init/
This is all, now you just need to run service myAwesomeApp start to run your node application as a service
I've never used procd before, but it likely needs the full path to node (e.g., /usr/bin/node). You'd need to make the line something like procd_set_param command /usr/bin/node /www/www-blink.js, assuming the file you want to run is /www/www-blink.js. You can locate node by running which node or type -a node.
I am new to docker, I have successfully installed docker on ubuntu,
I am testing a node app, at folder: /home/samir/Documents/docker-centos:
$ ls
Dockerfile Dockerfile~ index.js index.js~ package.json package.json~
I don't know what are those duplicates ending with ~ as I didn't add them.
index.js:
var express = require('express');
// Constants
var PORT = 8080;
// App
var app = express();
app.get('/', function (req, res) {
// even if I change the output here, I still get Hello world only
res.send('Hello world, This was added\n');
});
app.listen(PORT);
console.log('Running on http://localhost:' + PORT);
Although I have started the container using a data volume that points to the same app dir like this:
docker run -p 49160:8080 -v /home/samir/Documents/docker-centos -d samir/centos-node-hello
but when I view the output like:
curl -i localhost:49160
I get Hello world even if I changed the file..
Do I miss something?
How would I run the container, and edit files at host? why it didn't work?
EDIT
Dockerfile
FROM centos:centos6
# Enable Extra Packages for Enterprise Linux (EPEL) for CentOS
RUN yum install -y epel-release
# Install Node.js and npm
RUN yum install -y nodejs npm
# Install app dependencies
COPY package.json /src/package.json
RUN cd /src; npm install
# Bundle app source
COPY . /src
EXPOSE 8080
CMD ["node", "/src/index.js"]
You need to build the Docker image again using the docker build command
If you're planning on using this setup not only for one-off testing of your app, but for development as well, you'd be better off mounting your application code as a volume.
I am using Ionic framework and nodejs for one app. All nodejs files are in linux server. I am starting the nodejs server using 'npm start &' command through putty. But the problem is if I close putty the server is getting stopped after sometime. I tried 'nohup npm start &'. But still I am facing the same issue. How to start this as a daemon process..?
You can use pm2 for production.
To install pm2 :
npm install pm2 -g
To start an application simply just run :
pm2 start app.js
You can check logs via:
pm2 logs
For more options just checkout their readme files on github repo.
This is adaptation of daemon module:
const child_process = require('child_process')
function child(exe, args, env) {
const child = child_process.spawn(exe, args, {
detached: true,
stdio: ['ignore', 'ignore', 'ignore'],
env: env
})
child.unref()
return child
}
module.exports = function(nodeBin) {
console.log('Daemonize process')
if (process.env.__daemon) {
return process.pid
}
process.env.__daemon = true
var args = [].concat(process.argv)
var node = args.shift()
var env = process.env
child(node, args, env)
return process.exit()
}
Usage:
const daemon = require('daemon')
daemon()
app.listen(...)
https://wiki.unix7.org/node/daemon-sample
For creating true daemons (a process not attached to any tty) you can use one of the several daemon modules available on npm.
A quick search gave me this: https://www.npmjs.com/package/daemon
Interestingly, the module above works using pure javascript and node.js built-in modules without requiring any C extensions. It works by exploiting how child_process works in newer versions of node (> 0.9).
either use PM2/forever & nginx for managing the services well. [RECOMMENDED]
or you can run by the default OS services. I'm using ubuntu 20.04 amd64 on ec2-t2.micro and everything is preinstall with image.
# TO Run the service on port 80 as deamon thread
sudo PORT=80 nohup node server.js &
#To run the service on 3000 port and point to 80.
PORT=3000 nohup node server.js &
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3000
# to kill the process run
ps -ef | grep "node"
kill -9 <pid>