NodeJS and Forever (monitoring and restarting app) - node.js

I'm trying to setup forever and NodeJS to monitor&restart my app and also keep it running when exits. Currently I have this:
var forever = require("forever-monitor");
var child = new(forever.Monitor)('main.js', {
'silent': false,
'pidFile': '../pids/app.pid',
'sourceDir': '.',
'watch': true,
'watchDirectory': '.',
'watchIgnoreDotFiles': null,
'watchIgnorePatterns': null,
'logFile': '../logs/forever.log',
'outFile': '../logs/forever.out',
'errFile': '../logs/forever.err'
});
child.start();
Which starts my app just fine but it doesn't restart it when I make changes in the file. Is there some option that I'm missing?
EDIT:
After digging into the problem I found that the file change is detected actually, it's just that the process isn't restarted.
I'm looking at line ~317 - Monitor.prototype.kill (in monitor.js) but everything looks like it should work.
EDIT:
I managed to fix the issue. It's a bug in the library's code. Check here: https://github.com/nodejitsu/forever-monitor/issues/27

nodemon and forever are a pain to get running consistently. I would try using a shell script first. If you are on linux, just place a monitornode file in /etc/cron.d
*/1 * * * * root /var/www/nodejs/monitornode.sh
and have a script somewhere on your machine
Try this if you are getting started, create a file /var/www/nodejs/monitornode.sh and chmod +x :
#!/bin/sh
TT_NODE="node /var/www/nodejs/node.js"
# NODEJS Watcher
if [ -z `pgrep -f -x "$TT_NODE"` ]
then
echo "Starting $TT_NODE."
cmdNODE="$TT_NODE >> /var/www/logs/node.log &"
eval $cmdNODE
fi

Check out the nodemon package to do the whole "reload on file change" thing.

Related

NodeJS child spawn exits without even waiting for process to finish

I'm trying to create an Angular11 application that connects to the NodeJS API that would run bash scripts when called and on exit it should either send an error or send a 200 status with a confirmation message.
here is one of the functions from that API. It runs a script called initialize_event.sh, gives it a few arguments when prompted and once the program finishes its course should display a success message (There is no error block for this function):
exports.create_event = function (req, res) {
var child = require("child_process").spawn;
var spawned = child("sh", ["/home/ubuntu/master/initialize_event.sh"]);
spawned.stdout.once("data", function (data) {
spawned.stdin.write(req.body.name + "\n");
});
spawned.stdout.once("data", function (data) {
spawned.stdin.write(req.body.domain_name + "\n");
});
spawned.on("exit", function (err) {
res.status(200).send(JSON.stringify("Event created successfully"));
});
};
The bash script is a long one, but what it basically does is take two variables (event name and domain name) and uses that to create a new event instance. Here are the first few lines of code for the program:
#!/bin/bash
#GET EVENT NAME
echo -n "Enter event name: "; read event;
echo -n "Enter event domain: "; read eventdomain;
#LOAD VARIABLES
export eventdomain;
export event;
export ename=$event-env;
export event_rds= someurl.com ;
export master_rds= otherurl.com;
export master_db=master;
# rest of code...
When called on its own directly from the terminal, the process takes around 30-40 seconds after taking input to create an event and then exits once completed. I can then check the list of events created using another script and the new event would show up in the list. However, when I call this script from the NodeJS function, it manages to take the inputs and the exit within 5 or 6 seconds, saying the event has been created successfully. When I check the list of events there is no event created. I wait to see if the process is still running and check back after a few minutes, still, no event created.
I suspect that the spawn exits before the script can be run completely. I thought that maybe the stdio streams are still open so I tried to use spawned.on.close instead of spawned.on.exit, but still the program exits before it even runs completely. I don't see any exceptions or errors appearing in the Node express console, so I can't really figure out why the program exits successfully without running all the way through.
I've used the same inputs when running from the terminal and on Postman, and have logged them as well to see if there are any empty variables being sent, but found nothing wrong with them either. I've double-checked the paths as well, literally copy-pasted from pwd to make sure I haven't been missing something, but still nothing.
What am I doing wrong here??
So here's the problem I found and solved:
The folder where the Node Express was being served from, and the folder where the bash scripts were saved were in different directories.
Problem:
So basically, whenever I created a child process, it was created with the following current directory:
var/www/html/node/
But the bash scripts were run from:
var/www/html/other/bash/scripts/
so any commands that were added to the bash script that involved directory change (like cd) were relative to the bash directory.
However, since the spawn's current directory was var/www/html/node the script being executed in the spawn also had the same current working directory as the node folder, and any directory changes within the script were now invalid since they didn't exist relative to node directory.
E.g.
When run from terminal:
test.sh -> cd /savedir/ -> /var/www/html/other/bash/scripts/savedir/ -> exists
When run from spawn:
test.sh -> cd /savedir/ -> /var/www/html/node/savedir/ -> Doesn't exist!
Solution:
The easiest way I was able to solve this was to modify the test.sh file. i.e during the start I added cd /var/www/html/other/bash/scripts/. This allowed the current directory of my spawn to change to the right directory that would make all the mv cd and other path relevant commands valid.

Automate Node.js CLI program from shell script

I and trying to execute a node.js CLI program which takes an input from user to decide the next step.
I am able to start the program by
node index.js
after this I want to send 1 as input. Is there a way I can give input to my node.js program.
My dumb brain came up with following script
--Script.sh--
node index.js
1
2
which obviously didn't work.
Maybe this would work?
Create an answers.txt file with each input on its own line:
first
second
then run the command like this:
node index.js < answers.txt
The < will redirect input to the specified file instead of stdin.
What about:
#!/bin/dash
echo "Type something or 'q' to quit and press Enter!"
while read user_input; do
if [ "$user_input" = 'q' ]; then
break
else
echo "You've typed: ""$user_input"
# do something
# node index.js "$user_input"
fi
done

Gearman: troubles with first use

I tried to start with Gearman. After downloading and setting it, gearman_version() works. But, when I start server and try to init worker like so:
php myFileName.php &
I see the code:
And when I init the client, I see code too. What am I doing wrong?
i don`t know why, but the examples from youtube was not correct in my case. The first scripts, which worked I get from http://php.net/manual/ru/gearman.examples-reverse-bg.php
You likely have short open tags disabled on your install. Notice, running a php file that doesn't actually contain any PHP will just echo the contents of the file.
>$ echo 'hello' > text.php
>$ php text.php
hello
>$
You can verify the setting for your install with the following
>$ php -i | grep "short_open_tag"
short_open_tag => On => On
If tags are On you're all set.

NodeJS passing command line arguments to forever

Im trying to pass command line arguments to forever, that I want to parse in my app.
Currently I'm starting my app like this:
forever start -c "node --max-old-space-size=8192 --nouse-idle-notification" /home/ubuntu/node/server.js
I want to be able to read some arguments in my server.js.
My code for reading:
var arguments = process.argv.slice(2);
console.log(arguments[0]);
if(!arguments[0]) {
console.log("Error: Missing port.");
process.exit(1);
}
But how to I tell forever to pass arguments that can be read inside server.js?
According to the forever docs, you should use this format where you append your script arguments to the very end:
forever [action] [options] SCRIPT [script-options]
So for your example, you should be able to do this (omitting the -c options to make this a little more readable):
forever start server.js 9000 anotherarg evenanother
You can add the -c and the full path to server.js back into your real call, based upon your situation.

symlink to executable doesn't launch application, error: <symlink> doesn't exist

I have a symlink to an executable, which I've created as follows:
$ ln -s /home/x/app/wps_office/wps
If on the commandline I type:
$ /home/x/app/wps_office/wps
Then my application launches correctly, but if I try to launch my application through the symlink, then I get the following error:
$ wps
wps does not exist!
Just to make sure if the symlink is correct;
$ readlink wps
/home/x/app/wps_office/wps
The folder /home/x/bin is where I've created the symlink, this folder is included in my $PATH variable.
I don't see what is going wrong here, why doesn't my application execute when I use the symlink?
Quick update;
I've just quickly looked trough the contents of the file where the symlink is pointing to, it looks like the message wps does not exist is actually coming from the application, meaning the symlink is actually correct. I don't know the exact reason why, as I find it strange that everything works correctly when I don't use the symlink. I need to look more thorougly to the code to find that out.
The code of the file where the symlink is pointing to:
#!/bin/bash
gOpt=
gTemplateExt=("wpt" "dot" "dotx")
gBinPath=$(dirname "$0")
if [ -d "${gBinPath}/office6" ]; then
gInstallPath=${gBinPath}
else
gInstallPath=/opt/kingsoft/wps-office
fi
gApp=wps
function parse_arg()
{
if [ $# -eq 1 ] ; then
ext="${1##*.}"
if [ "" = "${ext}" ] ; then
return 0
fi
for i in ${gTemplateExt}
do
if [ "${ext}" = "${i}" ] ; then
gOpt=-t
fi
done
fi
}
function run()
{
oldPwd="${PWD}"
if [ -e "${gInstallPath}/office6/${gApp}" ] ; then
if [ -d /usr/lib32/gtk-2.0 ]; then
export GTK_PATH=/usr/lib32/gtk-2.0
fi
${gInstallPath}/office6/${gApp} ${gOpt} "$#" || ${gBinPath}/wps_error_check.sh ${gInstallPath}/office6/${gApp}
else
echo "${gApp} does not exist!"
fi
}
function main()
{
parse_arg "$#"
run "$#"
}
main "$#"
Note the line where it says echo "${gApp} does not exist!", this is where my error is coming from.
Commands will only be executed without any path elements if they're part of the shell, or if they're in the PATH environment variable. Try
./wps
in the directory where the symlink is. Also confirm that the permissions are correct.
Change the line
gInstallPath=/opt/kingsoft/wps-office
in the script to
gInstallPath=/home/x/app/wps_office
The file where the symlink was pointing to, takes the current directory to launch a different file. This is the file actually being launched. The issue can be solved by simply creating a symlink to this file, which means a symlink to /home/x/app/wps_office/office6/wps
Another option is to edit the source file itself, as explained by #Pixelchemist. However as it concerns an application which I've downloaded and which I will probably update in the future, I think in this case that is not a preferred option.

Resources