Node.JS windows service cannot start - node.js

I'm using windows-service package to run my script as a windows service.
if (process.argv[2] == "--add") {
logger.info('Starting to add service', global.appRoot + "\\app.js")
ws.add (config.service_name, {programPath: global.appRoot + "\\app.js"});
logger.info('Service added', config.service_name, global.appRoot + "\\app.js")
} else if (process.argv[2] == "--remove") {
logger.info('Removing service', config.service_name)
ws.remove (config.service_name);
logger.info('Service removed', config.service_name)
} else if (process.argv[2] == "--run") {
logger.info('Starting service', config.service_name);
ws.run (logger, function() {
logger.info('Stopping service', config.service_name);
ws.stop()
logger.info('Service stopped')
});
} else if (process.argv[2] == "--stop") {
logger.info('Stopping service', config.service_name);
ws.stop()
logger.info('Service stopped')
}
After running "node service.js --add", I have verified that my windows service is installed correctly with command like below
"C:\Program Files\nodejs\node.exe" "E:\Utils\app.js"
I pasted the command into node.js command prompt and it launched the script correctly.
However, when I tried to start the windows service from the service console, it always complains
Error 1053: The service did not respond to the start or control request in a timely fashiion.
I tried "node service.js --run", it simply prints out the "Starting service" message and hangs there. The underlying script isn't kicked off either.
Verified service log, no error. No script-specific log is generated.
All my script objects are using global.appPath for absolute path reference.
I run out of ideas. Any advice on this matter?

Related

App launched from npm works perfectly, but complied x64 app works incorrect

I use the Electron-forge framework and try to make an audio player. When I launch my app from npm start it works perfectly. But when I compile app using npm run package to x64 app and launch from its .exe file, the app works incorrectly. Window creates, but audio doesn't play.
Error in console.log:"Uncaught (in promise) DOMException: Failed to load because no supported source was found."
Paths to audio files are definitely correct, I wrote them to console too.
Edit: I found it is better to use Promise for tag audio, but the problem still persists. Code:
$(document).ready(function () {
prepare_song('D:' + '\\' + 'Downloads' + '\\' + 'audio_1.mp3');
$("#button_play_pause").click(function () {
console.log("click play");
var playPromise = document.querySelector('audio').play();
if (playPromise !== undefined) {
playPromise.then(function () {
console.log("play !");
// triggered from npm start and music is playing
}).catch(function (error) {
console.log("play error:" + error);
// triggered from npm run package (x64 .exe app) Error: NotSupportedError: The element has no supported sources.
});
}
});
});
function prepare_song(filepath) {
console.log(" prepare: " + filepath);
$("#audio").attr("src", filepath);
let audio = document.getElementById('audio');
audio.load();
}

Different browser behavior when pass .env variables in command for run tests

It's not actually a problem, but I do not fully understand, what happened and why.
I have this runner for my test. I test a React app.
let testcafe = null
const isCiEnv = process.env.CI === 'true'
const exit = async err => {
console.log('Exiting...')
if (testcafe) {
console.log('Closing TestCafe...')
testcafe.close()
}
console.log('Exiting process...')
process.exit(err ? 1 : 0)
}
console.log('Is CI ENV: ', isCiEnv)
console.log('Creating TestCafe...')
createTestCafe('localhost', 1337, 1338)
.then(tc => {
testcafe = tc
})
.then(() => {
console.log('Starting server...')
return startServer()
})
.then(() => {
console.log('Starting client...')
return startClient()
})
.then(() => {
console.log('Creating TestCafe Runner...')
return testcafe.createRunner()
})
.then(runner => {
console.log('About to start TestCafe Runner...')
return runner
.src([
'test/e2e/fixtures/auth.js'
])
.browsers({
path: isCiEnv
? '/usr/bin/chromium-browser'
: 'Chrome',
cmd: isCiEnv
? '--no-sandbox --disable-gpu'
: undefined
})
.screenshots('screenshots', true)
.run({
skipJsErrors: true,
selectorTimeout: 25000,
assertionTimeout: 25000
})
})
.then(failedCount => {
console.log('failed count:', failedCount)
return exit(failedCount)
})
.catch(err => {
console.error('ERR', err)
return exit(err)
})
In package.json i have this command for run test
"test:e2e": "HOST=0.0.0.0 NODE_ENV=test NODE_PATH=server babel-node test/e2e/index.js --presets stage-2"
But in the local environment, I run a test with this command
sudo REDIS_HOST=127.0.0.1 PORT=80 yarn test:e2e
That because on my local machine I have different config and I don't want to change it for everyone else.
Usually, test runs in a different, clear version of the browser, without any account data, plugins and etc. But in this case, tests run in a new browser window, but with all plugins and my account name. But, it's doesn't have cookie and session auth data from the browser window, in which I usually work (because I authorized on-site in the working browser and doesn't auth in test browser).
And if I change "Chrome" to "chrome" it stops run completely. Same behavior for Firefox and Safari.
Earlier, without passing REDIS_HOST and HOST, it works as usual and runs in a clean new browser window.
It's not a big problem, for now at least, but it's unexpected behavior and I don't understand, why it works this way.
I'm not very familiar with Node and React, and maybe this related to them.
Spec: macOS 10.12.5, Testcafe 0.20.3, Chrome 67
Specifying browsers using { path, cmd } is a legacy low-level option, you shouldn't use it. When a browser is specified in this way, TestCafe doesn't try to guess browser's type (Chrome, Firefox) and doesn't perform advanced initialization steps like creating a clean profile (because profile structure depends on browser's type). So it's better to use the following runner code:
.browsers(isCiEnv ? 'chromium --no-sandbox --disable-gpu' : 'chrome')

Node js app running inside container opens user's web browser

I need an option to open user's default web browser from node js app which is running inside docker container. I need to know that to implement OAuth flow.
I know that I can do it by opening new tab on the client side, but I don't have this option for other reasons.
I'm not familiar with docker container, but for just straight nodejs, this works for me:
// start browser
if (opSys == "Win64")
command = ("start http://localhost:8000/init"); // Win64
else if (opSys == "MacOS")
command = ("open http://localhost:8000/init"); // MacOS
else
command = ("xdg-open http://localhost:8000/init"); // Linux
exec (command, function (error, stdout, stderr)
{
if (error)
{
console.log ("command: ", command);
console.log ("error: ", stderr);
}
});

How do I ensure a local directory with fs.readdir()

So I have an express server that upon a GET request, returns a json file.
app.get('/server-generated/pages.json',function(req, res) {
fs.readdir('public/pages',function(err,data){
res.json(data || err);//temp error checking
});
});
it works just fine when I run node app or forever app in its directory but when I run it as a forever service from Ubuntu upstart on startup
exec forever start /home/*****/transfer/app.js
I get this in response
{
"errno": 34,
"code": "ENOENT",
"path": "public/pages"
}
which is directory error if I'm right? the full folder hierarchy goes like this /home/****/transfer/public/pages
How would I write a directory that would work on any computer (windows/ubuntu) running the app locally or from upstart?
you should use the path relative to the directory where the module is:
var path = require('path');
fs.readdir(path.join(__dirname, 'public/pages'), function(err, data) {
res.json(data || err);
});

Using grunt to run a node server and do cleanup after

So basically this is what I want to do. Have a grunt script that compiles my coffee files to JS. Then run the node server and then, either after the server closes or while it's still running, delete the JS files that were the result of the compilation and only keep the .coffee ones.
I'm having a couple of issues getting it to work. Most importantly, the way I'm currently doing it is this:
grunt.loadNpmTasks("grunt-contrib-coffee");
grunt.registerTask("node", "Starting node server", function () {
var done = this.async();
console.log("test");
var sp = grunt.util.spawn({
cmd: "node",
args: ["index"]
}, function (err, res, code) {
console.log(err, res, code);
done();
});
});
grunt.registerTask("default", ["coffee", "node"]);
The problem here is that the node serer isn't run in the same process as grunt. This matters because I can't just CTRL-C once to terminate JUST the node server.
Ideally, I'd like to have it run in the same process and have the grunt script pause while it's waiting for me to CTRL-C the server. Then, after it's finished, I want grunt to remove the said files.
How can I achieve this?
Edit: Note that the snippet doesn't have the actual removal implemented since I can't get this to work.
If you keep the variable sp in a more global scope, you can define a task node:kill that simply checks whether sp === null (or similar), and if not, does sp.kill(). Then you can simply run the node:kill task after your testing task. You could additionally invoke a separate task that just deletes the generated JS files.
For something similar I used grunt-shell-spawn in conjunction with a shutdown listener.
In your grunt initConfig:
shell: {
runSuperCoolJavaServer:{
command:'java -jar mysupercoolserver.jar',
options: {
async:true //spawn it instead!
}
}
},
Then outside of initConfig, you can set up a listener for when the user ctrl+c's out of your grunt task:
grunt.registerTask("superCoolServerShutdownListener",function(step){
var name = this.name;
if (step === 'exit') process.exit();
else {
process.on("SIGINT",function(){
grunt.log.writeln("").writeln("Shutting down super cool server...");
grunt.task.run(["shell:runSuperCoolJavaServer:kill"]); //the key!
grunt.task.current.async()();
});
}
});
Finally, register the tasks
grunt.registerTask('serverWithKill', [
'runSuperCoolJavaServer',
'superCoolServerShutdownListener']
);

Resources