grunt task: start mongod if not running - javascript

I want to write a grunt task to start the process mongod if the server is not already running. I need a mongod process running, but also need grunt-watch to work later in the task flow.
This question explains how to start mongod using grunt-shell ... the accepted answer is blocking, and the async version will spawn a new server even if one exists.
Is there a way (e.g. shell script) to start mongod only if it is not running, without blocking the rest of the grunt task flow?
Thanks

Here's a cleaner version
Store this as startMongoIfNotRunning.sh in same location as Gruntfile:
# this script checks if the mongod is running, starts it if not
if pgrep -q mongod; then
echo running;
else
mongod;
fi
exit 0;
And in your Gruntfile:
shell: {
mongo: {
command: "sh startMongoIfNotRunning.sh",
options: {
async: true
}
},
}
Edit - original version below
Ok - I think this is working properly...
create a shell script which will start mongod if it's not running... save it somewhere, probably in your project. I named it startMongoIfNotRunning.sh :
# this script checks if the mongod is running, starts it if not
`ps -A | grep -q '[m]ongod'`
if [ "$?" -eq "0" ]; then
echo "running"
else
mongod
fi
You may have to make it executable: chmod +x path/to/script/startMongoIfNotRunning.sh
Install grunt-shell-spawn : npm install grunt-shell-spawn --save-dev
Then in your Gruntfile add this:
shell: {
mongo: {
command: "exec path/to/script/startMongoIfNotRunning.sh",
options: {
async: true
}
},
}
(If you're using yeoman, using <%= yeoman.app %> didn't work because those paths are relative to the whole project, so you get something like 'app' instead of the whole path to the script. I'm sure you could get it working, I'm just not aware how to get the path to )
If you just execute the task grunt shell:mongo mongod will start but I wasn't able to close it using grunt shell:mongo:kill. However, assuming you're using a blocking task later (I'm using watch) then it should automatically be killed when you end that task.
Hope this helps someone!

I found your solution really helpful, but actually wanted to kill mongod when restarting grunt server. So I got this:
#!/bin/sh
# this script checks if the mongod is running, kills it and starts it
MNG_ID="`ps -ef | awk '/[m]ongod/{print $2}'`"
if [ -n "$MNG_ID" ]; then
kill $MNG_ID
fi
mongod
which works really nice on my mac. And my grunt file looks like this:
//used to load mongod via shell
shell: {
mongo: {
command: './mongo.sh',
options: {
async: true
}
}
}
So my mongo.sh is in the same location as my Grunfile.js
Cheers

The other two answers are correct. However for completeness here is the equivalent batch script on Windows. Save the following as startMongoIfNotRunning.bat:
tasklist /fi "imagename eq mongod.exe" |find "=" > nul
if errorlevel 1 mongod
If there is a task running called mongod.exe then the = character should appear in the output - hence if it is not running the = character will not be found and the errorlevel variable will be set to 1.
The rest is the same as #MaxBates answer.

Related

start node and pm2 application from bat file

I have a chat-bot application running on node and I keep it always active thanks to pm 2.
I would like to improve the way I launch the application. Instead of running the start command from the console, it would be nice to double click a .bat file.
I am trying to develop the bat file, but I lack knowledge.
I am grateful for any help.
#echo off
SET PM2_HOME=C:\Users\Usuario\.pm2
pm2 start C:\Users\Usuario\Desktop\ROBOTs\Chatbot SCTR\app.js
echo servicio ejecutado
This bat file that I developed does not work. I know that I am not calling the variables, because I don't know how to include it, since I always execute the pm2 start app.js command.
my application does not use ports like 8080 and others, because the same library allows me to establish a connection and with pm 2 I keep it always active.
add the start command to your package.json for launching your app with pm2, then with your bat file just direct it to run with npm or yarn, whatever your default package manager is
edit:
here is a sample of a script in bash, but the concept will be the same for batch
#!/bin/bash
## detect operating system machine so we can setup some environment variables
UNAME="$(uname -s)"
case "${UNAME}" in
Linux*) OS='linux';;
Darwin*) OS='mac';;
CYGWIN*) OS='cygwin';;
MINGW*) OS='mingw';;
*) OS="UNKNOWN:${UNAME}"
esac
## if OS is Ubuntu (IE Production Box) set the path of variables
if [ $OS == 'linux' ]
then
YARN=/usr/bin/yarn
PM2=/usr/bin/pm2
fi
## if OS is Mac (IE Development Box) set the path of variables
if [ $OS == 'mac' ]
then
YARN=/usr/local/bin/yarn
PM2=/usr/local/bin/pm2
fi
## run the app
cd /var/www/application || exit
$YARN run productionStart
$PM2 save
exit $?
here is the line of code for starting the app on mac/linux we use from our package.json
"productionStart": "pm2 start ecosystem.config.js --env=production",
for more information about starting your app with an ecosystem file with pm2, see the docs here

Node's spawn() silently failing when called from a forever script scheduled on boot

This is kind of a doozy. This issue is most likely server related and so my first recourse was AskUbuntu over here.
I'm trying to have crontab or rc.local or init.d to start a forever script on boot. It attaches a server to a port I can ping with some information and have it run a headless browser for me.
That said, it seems that I'm unable to get a response from Node.js's spawn():
var CASPER_PATH = '/home/ubuntu/dev/casperjs/bin/casperjs'; // actual binary location, not a symlink
var SCRIPTS_PATH = '/home/custom_user/endpoints/server.js';
var fileName = req.body.source + '_' + req.body.type + '.coffee'; // looks like: mysource_my_scrape_type.coffee
var scrapeId = 'test_scrape';
var user = 'user123';
var pass = 'pass123';
if (fs.existsSync(SCRIPTS_PATH + fileName)) {
// If file is in place, spawn casperjs
var sP = spawn(CASPER_PATH,
[SCRIPTS_PATH + fileName, '--ssl-protocol=any', '--user='+user, '--scrapeId='+scrapeId, '--pass='+pass],
{ detached: true },
function (err, stdout, stderr) {});
sP.stdout.on('data', function(data) { console.log('stdout', data.toString('utf8')); });
sP.stderr.on('data', function(data) { console.log('stderr', data.toString('utf8')); });
sP.stdout.on('close', function(code) { console.log('close', code); });
res.send({ scheduled: true, key: scrapeId });
} else {
res.send({ scheduled: false, error: 'Incorrect source, type or the script is missing.' });
}
Before I added the PHANTOMJS_EXECUTABLE env to crontab or rc.local (doesnt seem to matter no matter the user level), stdout was useful:
stdout Fatal: [Errno 2] No such file or directory; did you install
phantomjs?
close false
Now that the environment var is there, there is no output at all after spawn().
Mind you, Casper starts up just fine if a user (of any privilege level) runs node/forever from bash.
How can I see why spawn() is failing?
This actually looks like a combo-bug between forever, spawn and casperjs (maybe phantomjs).
I was able to reproduce your problem, here is the full code of my test application.
You didn't show the full code, so my guess is that you have an express application and there is a special URL to run the casperjs script.
I build a simple app like this and it behaved this way:
Just start app with node script.js (script.js is the express app which runs the casperjs script in server.js) - it works OK, renders response and writes output from the child process event handlers to console
Start app as root with init.d script - doesn't work, once the child is spawned, no event handlers are triggered
Start app as root with init.d script, replace casperjs with echo - the same, doesn't work (see, here we have this problem with just forever running as root, spawn and echo)
Start app as a regular user (not root) with init.d, replace casperjs with 'echo' - it works, event handlers are triggered, here I was almost sure the issue is solved, but ... :(
Start app as a regular user (not root) with init.d, put back casperjs - it doesn't work again, event handlers are not triggered
The practical solution to this it to use pm2, I did this:
# install pm2
sudo npm install -g pm2
# generate init.d scripts for pm2
# this command will fail, but hint about the correct format with sudo
pm2 startup ubuntu
# do this in the folder with your application
pm2 start script.js
# remember your application
pm2 save
# also useful
# sudo service stop/start/restart pm2
# pm2 stop/start/restart script
Now pm2 will start automatically with the system and it will launch your application. Everything works, child process event handlers are triggered.
I did not understand your requirement completely. But i do have a similar situation with Ubuntu headless server.
what i am trying to do here is what i did
First, How is my crontab ?
crontab -u USER -e
#reboot exec sudo -u USER /bin/bash /home/USER/SHELL_SCRIPT.sh
See, here i am actually starting a shell script, and not a node server
Now inside this shell script(SHELL_SCRIPT.sh)
#! /bin/bash
# SHELL_SCRIPT.sh
cd /home/USER/
/home/USER/.npm-packages/bin/forever start -p /home/USER -a -d --watch false --pidFile /home/USER/forever.pid -l /home/USER/forever.log -o /home/USER/forever.out -e /home/USER/forever.err /home/USER/MY_NODE.js
and even inside my MY_NODE.js i follow absolute path, i just ignore $PATH, and don't use that.
Inside this node server, I do 100's of spawn
Now, i did this around 2 years back, so if you ask me why do this way, which i cannot answer

how to determine if gulp watch is running

I run gulp on server in background running
gulp &
but sometimes it fail down. So mi question is: Is there some command for gulp to ask if is running. Something like
gulp status
Thanks
There is nothing special in gulp to limit running multiple processes or alert you to an already running gulp process.
Use regular Unix techniques to check if a process is running. Use a supervisor like supervisord or runit to automatically restart processes.
#the program pidof will set the variable $? to either
#1 or 0 in bash depending on if it finds a process
#with that name. It will also print out all the matching
#process IDs to the command line
pidof gulp
echo $? #1 if there is no process called gulp
#0 if there is a process called gulp
if pidof gulp; then
echo 'gulp is alive';
else
echo 'we need some support over here!'
./node_modules/.bin/gulp watch &
sleep 3
fi

How to access chromedriver logs for Protractor test

I have seen that chromedriver can output a logfile (https://sites.google.com/a/chromium.org/chromedriver/logging)
This page shows how to set this up when executing the exe directly:
chromedriver.exe --verbose --log-path=chromedriver.log
I cannot figure out how to set this up in Protractor however
My current protractor.conf.js
require('babel/register');
exports.config = {
framework: 'jasmine2',
seleniumServerJar: './node_modules/protractor/selenium/selenium-server-standalone-2.45.0.jar'
};
From #alecxe's answer below and protractor's browser setup docs I tried adding the following (with and without --s) but with no apparent effect:
capabilities: {
browserName: "chrome",
chromeOptions: {
args: [
"--verbose",
"--log-path=chromedriver.log"
]
}
}
I also tried specifying an absolute path (log-path=/chromedriver.log) which also didn't work.
You can always start up your own instance of chromedriver in a separate process and tell Protractor to connect to that. For example, if you start chromedriver with:
chromedriver --port=9515 --verbose --log-path=chromedriver.log
Then you could use a configuration file for Protractor like so:
exports.config = {
seleniumAddress: 'http://localhost:9515',
capabilities: {
'browserName': 'chrome'
},
specs: ['example_spec.js'],
};
We use a shell script to add chromedriver logging, among other checks. You can then point protractor at the shell script:
protractor config:
// When running chromedriver, use this script:
chromeDriver: path.resolve(topdir, 'bin/protractor-chromedriver.sh'),
bin/protractor-chromedriver.sh
TMPDIR="/tmp"
NODE_MODULES="$(dirname $0)/../node_modules"
CHROMEDRIVER="${NODE_MODULES}/protractor/selenium/chromedriver"
LOG="${TMPDIR}/chromedriver.$$.log"
fatal() {
# Dump to stderr because that seems reasonable
echo >&2 "$0: ERROR: $*"
# Dump to a logfile because webdriver redirects stderr to /dev/null (?!)
echo >"${LOG}" "$0: ERROR: $*"
exit 11
}
[ ! -x "$CHROMEDRIVER" ] && fatal "Cannot find chromedriver: $CHROMEDRIVER"
exec "${CHROMEDRIVER}" --verbose --log-path="${LOG}" "$#"
According to the protractor's source code, chromedriver service is started without any arguments and there is no direct way to configure the arguments. Even though the chromedriver's Service Builder that protractor uses actually has an ability to specify the verbosity and the log path:
var service = new chrome.ServiceBuilder()
.loggingTo('/my/log/file.txt')
.enableVerboseLogging()
.build();
Old (incorrect) answer:
You need to set the chrome arguments:
capabilities: {
browserName: "chrome",
chromeOptions: {
args: [
"verbose",
"log-path=chromedriver.log"
]
}
},
See also:
Viewing outstanding requests
Since, the previous answer by #P.T. didn't work for me on Windows 7, I started with his suggestions and got it working on Windows. Here is a working solution for Windows 7 users.
STEP 1: Install BASH and JQ and confirm they are working on your Windows box
Download bash (for Windows 10
https://itsfoss.com/install-bash-on-windows/ ; for Windows 7
download latest here:
https://sourceforge.net/projects/win-bash/files/shell-complete/latest/ ; for Windows Server 2012 or any Windows OS that already has Git installed on it, you already have a bash.exe and sh.exe installed at C:\Program Files\Git\usr\bin or C:\Program Files (x86)\Git\usr\bin already
)
Install bash - For Windows 7/ download it and extract the zip files to a directory.
Download jq (https://stedolan.github.io/jq/) and install it in the same directory location as bash
Make SURE that you add your above directory (for Windows 7- where you extracted the bash zip files to; for other applicable OSes that have git, the path it is installed at) to your PATH system environment variable.
Once the above is installed and added to your PATH, close ALL and reopen Webstorm and any CMD windows you wish to run your work in.
Test that bash is actually installed by simply typing it on a windows command prompt
C:\git\> bash .
Doing so should produce a bash cmd prompt like this
bash$
STEP 2: Add Custom Files for Redirecting Chromedriver to user Debug Logging
Add the following files to the top level of the project (wherever your protractor-conf.js is located). These files allow us to add custom debug switches to the chromedriver.exe execution.
Note that this is necessary because these switches are not exposed through protractor and cannot be done directly in the protractor.conf.js file via the chromeOptions/args flags as you would normally expect
chromedriver.cmd -- exact source shown below:
bash protractor-chromedriver.sh %*
protractor-chromedriver.sh -- exact source shown below:
TMPDIR="$(dirname $0)/tmp"
NODE_MODULES="$(dirname $0)/node_modules"
SELENIUM="${NODE_MODULES}/protractor/node_modules/webdriver-manager/selenium"
UPDATECONFIG="${SELENIUM}/update-config.json"
EXEFILENAME="$(cat ${UPDATECONFIG} | jq .chrome.last | tr -d '""')"
CHROMEDRIVER="${SELENIUM}/${EXEFILENAME##*'\\'}"
LOG="${TMPDIR}/chromedriver.$$.log"
fatal() {
# Dump to stderr because that seems reasonable
echo >&2 "$0: ERROR: $*"
# Dump to a logfile because webdriver redirects stderr to /dev/null (?!)
echo >"${LOG}" "$0: ERROR: $*"
exit 11
}
[ ! -x "$CHROMEDRIVER" ] && fatal "Cannot find chromedriver: $CHROMEDRIVER"
exec "${CHROMEDRIVER}" --verbose --log-path="${LOG}" "$#"
/tmp -- create this directory at the top level of your project (same as the location of the protractor.conf.js file.
STEP 3: Update protractor.conf.js file.
In the protractor.conf.js file, add the following line as a property in the exports.config object. As in:
exports.config = {
.. ..
chromeDriver: 'chromedriver.cmd',
.. ..
STEP 4: Launch your tests
your test should now run and if the chrome driver outputs any log information it will appear in a file called chromedriver.???.log in the tmp directory under your project.
Important caveats
This script set up assumes you install and run protractor (and the chrome driver under it) within the local node_modules directory inside your project. That is how I run my code, because I want it complete self-contained and re-generated in the build process/cycle. If you have protractor/chromedriver installed globally you should change the CHROMEDRIVER variable within the protractor-chromedriver.sh file to match your installation of protractor/chrome driver.
hope that helps.
If you're using the seleniumServerJar, in protractor.conf.js set the logfile path to wherever you want it to write the file:
seleniumArgs: [
'-Dwebdriver.chrome.logfile=/home/myUsername/tmp/chromedriver.log',
]
If you're using webdriver-manager start to run a local selenium server, you'll need to edit the webdriver-manager file:
// insert this line
args.push('-Dwebdriver.chrome.logfile=/home/myUsername/tmp/chromedriver.log');
// this line already exists in webdriver-manager, add the push to args before this line
var seleniumProcess = spawnCommand('java', args);
In case you use webdriver-manager: webdriver manager has the chrome_logs option (you can find it in its source code (in opts.ts or opts.js in the compiled code)), so you can use it something like:
webdriver-manager start --chrome_logs /path/to/logfile.txt
I'm using this as a global afterEach hook (mocha):
afterEach(() => {
browser.manage().logs().get('browser').then(function(browserLog) {
if(browserLog && browserLog.length) {
console.log('\nlog: ' + util.inspect(browserLog) + '\n');
}
});
});

Forever and node.js, stopping one forever process stops all processes [duplicate]

I am deploying two node.js apps on the aws, the two apps are in the paths shown as
/home/ubuntu/nodes/app1/app.js
/home/ubuntu/nodes/app2/app.js
respectively
to run the node.js apps in the background, I used forever to start two apps, so like
$ sudo forever start /home/ubuntu/nodes/app1/app.js
$ sudo forever start /home/ubuntu/nodes/app2/app.js
so forever works well by running the two node.js apps in the background process.
However, when I tried to stop one process with forever command like this.
$ sudo forever stop /home/ubuntu/nodes/app1/app.js
unexpectedly, both node.js process are closed with info like this
info: Forever stopped process:
data: uid command script forever pid logfile uptime
[0] r2pZ /usr/bin/nodejs app.js 24852 24854 /root/.forever/r2pZ.log 0:0:1:14.775
[1] 9f2h /usr/bin/nodejs app.js 24870 24872 /root/.forever/9f2h.log 0:0:0:58.733
I assume it is because two node.js process has the same name - app.js, how to avoid this by close only one process
You can use an uid (see here):
$ sudo forever --uid "app1" start app.js
$ sudo forever --uid "app2" start app.js
And to stop:
$ sudo forever stop app1
Update
The --uid option is deprecated.
Now you can use the --pidFile option. Example:
forever start --pidFile /some/path/app1.pid app.js
forever start --pidFile /some/path/app2.pid app.js
And to stop:
forever stop --pidFile /some/path/app1.pid
You can kill only one process using the index of the process shown in the forever list command. For example, if you type forever stop 1, only the process with the index 1 will be killed

Categories