Open localhost:3000 in kiosk mode after the Node.js server has finished spinning up - node.js

I'm working on a raspberry pi project that involves running a node server in kiosk mode.
I'm using BROWSER=none to suppress the default opening of the localhost upon the server being run.
I'm thinking I should be able to use wait-on to force the bash script that runs the kiosk mode to wait until the server is fully up. Would I use something like this?
"scripts": {
...
"kiosk": "concurrently -n \"npm start\" \"wait-on http://localhost:3000 & /home/pi/kiosk.sh\""
},
It gives me the following error(s) which I'm not quite able to decipher:
[npm start] server does not have extension for -dpms option
[npm start] libEGL warning: DRI2: failed to authenticate
[npm start] [1498:1498:1125/180040.467781:ERROR:gpu_init.cc(441)] Passthrough is not supported, GL is egl
[npm start] [1498:1498:1125/180040.786918:ERROR:viz_main_impl.cc(162)] Exiting GPU process due to errors during initialization
[npm start] [1558:1558:1125/180041.392714:ERROR:gpu_init.cc(441)] Passthrough is not supported, GL is swiftshader
[npm start] [1443:1590:1125/180042.359030:ERROR:object_proxy.cc(622)] Failed to call method: org.freedesktop.DBus.Properties.Get: object_path= /org/freedesktop/UPower: org.freedesktop.DBus.Error.ServiceUnknown: The name org.freedesktop.UPower was not provided by any .service files
[npm start] [1443:1590:1125/180042.364570:ERROR:object_proxy.cc(622)] Failed to call method: org.freedesktop.UPower.GetDisplayDevice: object_path= /org/freedesktop/UPower: org.freedesktop.DBus.Error.ServiceUnknown: The name org.freedesktop.UPower was not provided by any .service files
[npm start] [1443:1590:1125/180042.367155:ERROR:object_proxy.cc(622)] Failed to call method: org.freedesktop.UPower.EnumerateDevices: object_path= /org/freedesktop/UPower: org.freedesktop.DBus.Error.ServiceUnknown: The name org.freedesktop.UPower was not provided by any .service files
[npm start] Fontconfig error: Cannot load default config file: No such file: (null)
I'm now realizing the error in my code has more to do with kiosk.sh than it does with the npm commands. Here's the code to kiosk.sh:
#!/bin/bash
xset s noblank
xset s off
xset -dpms
unclutter -root &
sed -i 's/"exited_cleanly":false/"exited_cleanly":true/' /home/pi/.config/chromium/Default/Preferences
sed -i 's/"exit_type":"Crashed"/"exit_type":"Normal"/' /home/pi/.config/chromium/Default/Preferences
/usr/bin/chromium-browser --noerrdialogs --disable-infobars --kiosk http://localhost:3000/ &

& and && mean different things, && means AND, & means background process, run that service in the background and continue with the next.
I think what you're trying to do is wait-on service && example, not wait-on service & example.
What will happen with what you've done is it will run the wait-on, then immediately background process it, then immediately run the shell script without waiting for anything. Your script will run before the server is up.
That's not really your issue though, I believe your issue is with chromium itself. There's an open issue for it here: https://bugs.chromium.org/p/chromium/issues/detail?id=1221905&q=Passthrough%20is%20not%20supported%2C%20GL%20is%20swiftshader&can=1. That issue was last updated earlier this year and seems to still be unresolved.
There was also another answer for it here: Passthrough is not supported, GL is disabled.
I've seen quite a few people suggest that you use --headless and --disable-gpu and --disable-software-rasterizer. People have mentioned that some of those options are only required on windows and some have already been fixed, I don't know which of those are actually required.
This answer here: Force headless chromium/chrome to use actual gpu instead of Google SwiftShader, mentioned that you can force webgl using --enable-webgl to prevent it from loading swiftshader and use the gpu. You can do this if you need to force it in headless mode.
It seems to have something to do with webgl or hardware acceleration. Apparently it happens if you've disabled gpu acceleration and then it's forced to fallback on swiftloader.
I don't know which one of those is actually going to help you, you'll have to play around with it. However I have seen over 10 different chromium and other related issues all made during 2021 because of this bug in chromium.
What's more is that I'm not sure it's actually a critical error, some people mention it's just showing the error but can be just ignored. I don't know if that's the case.

I assume that you are using the package "wait-on" (https://www.npmjs.com/package/wait-on). The wait-on command is used without npm in front of it.
Try to use
wait-on http://localhost:3000 && /home/pi/kiosk.sh

You could use the "child_process" npm package to execute your bash script once the server is ready. Assuming you use Express.js in your backend, this should work with little modification
const exec = require('child_process');
//all your other codes and whatevers
app.listen(3000, () => {
var kiosk = exec('sh kiosk.sh',
(error, stdout, stderr) => {
if (error) {
console.log(`exec error: ${error}`);
}
});
});

wait-on waits until the process is closed. You are not closing chromium so it never continues. If you want to wait until the server is running. You can log the server's status to a text file and have your bash script read it in a loop until it contains the ready text you specify.
If you want to confirm beyond a reasonable doubt that the server is running as needed.
You can install the npm package puppetter. Then use the create and run a node script from bash using page.goto command to load the web page in an instance of chromium and use waitForSelector to check if the DOM element of your web page exists.
Then you use call process.exit() with whatever error codes you want to use to confirm that the page is live and running.

Related

How to enable xvfb for an express server running inside a docker container?

I have a express server running inside a docker container. Once a user makes a REST call to an endpoint, it should make multiple in-memory screenshots of a randomly generated mesh from different angles using Babylon.js, do some image processing on it, create a PDF out of it and return the generated PDF file to the user.
To do so, I am trying to use headless-gl to provide virtual frame buffer for Babylon.js engine.
As far as I understood, I first need to get the gl context and then pass it to babylon engine:
var gl = require(‘gl’)(1024, 768, { preserveDrawingBuffer: true });
var engine = new BABYLON.Engine(gl, true, { disableWebGL2Support: true });
My issue is that I am not able to init the gl and it returns null.
Inside my Dockerfile, I use the following to install the dependencies for xvfb:
RUN apt-get update && apt-get install -y
libgl1-mesa-dri
libglapi-mesa
libosmesa6
mesa-utils
xvfb
&& apt-get clean
My server depends on mongo DB as well so inside my docker-compose.yml file, I wait for the DB container to get initialized before I load my express container:
command: wait-for.sh mongodb:27017 – …/node_modules/.bin/nodemon --inspect=0.0.0.0:9229 ./server.js
I think I need to updated my Dockerfile and docker-compose files with proper commands to load xvfb before running the node application but I am not sure how to do that.
I tried the following along with some other combinations but no luck so far:
command: wait-for.sh mongodb:27017 – xvfb-run -s “-ac -screen 0 1280x1024x24” node ./server.js
I appreciate if someone can help me resolve the issue.
I think you are missing the server number as an argument. I am using xvfb-run --auto-servernum <command> to automatically get a free one. The default is number 99.
You can also use Xvfb manually with the DISPLAY environment variable set to :99 (default server number), but xvfb-run makes live a lot easier. I think you already read this, but for future users I will quote the stackgl/headless-gl README:
Interacting with Xvfb requires you to start it on the background and to execute your node program with the DISPLAY environment variable set to whatever was configured when running Xvfb (the default being :99). If you want to do that reliably you'll have to start Xvfb from an init.d script at boot time, which is extra configuration burden. Fortunately there is a wrapper script shipped with Xvfb known as xvfb-run which can start Xvfb on the fly, execute your Node.js program and finally shut Xvfb down.

Error: Status Code is 403 (MongoDB's 404) This means that the requested version-platform combination dosnt exist

beforeAll(async () => {
mongo = new MongoMemoryServer();
const mongoURI = await mongo.getConnectionString();
await mongoose.connect(mongoURI, {
useNewUrlParser: true,
useUnifiedTopology: true
});
});
For some reason mongodb-memory-server, doesn't work and it seems that it's because it's downloading mongodb for some reason? Wasn't mongodb supposed to be included with the package, what is the package downloading? How do we prevent mongodb-memory-server from downloading everytime I use it? Is there a way to make it work as it's intended?
$ npm run test
> auth#1.0.0 test C:\Users\admin\Desktop\projects\react-node-docker-kubernetes-app-two\auth
> jest --watchAll --no-cache
2020-06-06T03:12:45.207Z MongoMS:MongoMemoryServer Called MongoMemoryServer.ensureInstance() method:
2020-06-06T03:12:45.207Z MongoMS:MongoMemoryServer - no running instance, call `start()` command
2020-06-06T03:12:45.207Z MongoMS:MongoMemoryServer Called MongoMemoryServer.start() method
2020-06-06T03:12:45.214Z MongoMS:MongoMemoryServer Starting MongoDB instance with following options: {"port":51830,"dbName":"b67a9bfd-d8af-4d7f-85c7-c2fd37832f59","ip":"127.0.0.1","storageEngine":"ephemeralForTest","dbPath":"C:\\Users\\admin\\AppData\\Local\\Temp\\mongo-mem-205304KB93HW36L9ZD","tmpDir":{"name":"C:\\Users\\admin\\AppData\\Local\\Temp\\mongo-mem-205304KB93HW36L9ZD"},"uri":"mongodb://127.0.0.1:51830/b67a9bfd-d8af-4d7f-85c7-c2fd37832f59?"}
2020-06-06T03:12:45.217Z MongoMS:MongoBinary MongoBinary options: {"downloadDir":"C:\\Users\\admin\\Desktop\\projects\\react-node-docker-kubernetes-app-two\\auth\\node_modules\\.cache\\mongodb-memory-server\\mongodb-binaries","platform":"win32","arch":"ia32","version":"4.0.14"}
2020-06-06T03:12:45.233Z MongoMS:MongoBinaryDownloadUrl Using "mongodb-win32-i386-2008plus-ssl-4.0.14.zip" as the Archive String
2020-06-06T03:12:45.233Z MongoMS:MongoBinaryDownloadUrl Using "https://fastdl.mongodb.org" as the mirror
2020-06-06T03:12:45.235Z MongoMS:MongoBinaryDownload Downloading: "https://fastdl.mongodb.org/win32/mongodb-win32-i386-2008plus-ssl-4.0.14.zip"
2020-06-06T03:14:45.508Z MongoMS:MongoMemoryServer Called MongoMemoryServer.stop() method
2020-06-06T03:14:45.508Z MongoMS:MongoMemoryServer Called MongoMemoryServer.ensureInstance() method:
FAIL src/test/__test___/Routes.test.ts
● Test suite failed to run
Error: Status Code is 403 (MongoDB's 404)
This means that the requested version-platform combination dosnt exist
at ClientRequest.<anonymous> (node_modules/mongodb-memory-server-core/src/util/MongoBinaryDownload.ts:321:17)
Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 127.136s
Ran all test suites.
Seems you have the same issue like I have had.
https://github.com/nodkz/mongodb-memory-server/issues/316
Specify binary version in package.json
E.g:
"config": {
"mongodbMemoryServer": {
"version": "latest"
}
},
I hope it helps.
For me, "latest" (as in accepted answer) did not work, the latest current version "4.4.1" worked:
"config": {
"mongodbMemoryServer": {
"version": "4.4.1"
}
}
For anyone getting the dreaded
''
Error: Status Code is 403 (MongoDB's 404)
This means that the requested version-platform combination doesn't exist
''
I found an easy fix.
in the package.json file we need to add an "arch" for the mongo memory server config
  "config": {
"mongodbMemoryServer": {
"debug": "1",
"arch": "x64"
}
},
the error is occurring because the URL link that mongo memory server is creating to download a binary version of mongo is wrong or inaccessible.
By adding debug we now are able to get a console log of the mongo memory server process and it should correctly download because we changed the arch variable to a one that worked for me. **You might need to change the arch depending on you system.
Without adding the arch I was able to see why it was crashing in the console log here:
MongoMS:MongoBinaryDownloadUrl Using "mongodb-win32-i386-2008plus-ssl-latest.zip" as the Archive String +0ms
MongoMS:MongoBinaryDownloadUrl Using "https://fastdl.mongodb.org" as the mirror +1ms
MongoMS:MongoBinaryDownload Downloading: "https://fastdl.mongodb.org/win32/mongodb-win32-i386-2008plus-ssl-latest.zip" +0ms
MongoMS:MongoMemoryServer Called MongoMemoryServer.stop() method +2s
MongoMS:MongoMemoryServer Called MongoMemoryServer.ensureInstance() method: +0ms
If you notice it is trying to download "https://fastdl.mongodb.org/win32/mongodb-win32-i386-2008plus-ssl-latest.zip" - if you visit the link you will notice it is a BROKEN LINK and that is the reason mongo memory server is failing to download.
For some reason mongo memory server was defaulting to the i386 arch, which didn't work in my case because the link was broken / inaccessible when I visited it. *normally a download should start right away when visiting a link like that.
I was able to configure the to the correct arch manually in the package.json file. Once I did that, it started to download mongo binary and ran all my tests no problem. You will even notice a console log of the download and displaying the correct download link.
You can find your system arch by going to the command prompt and typing
WINDOWS
SET Processor
MAC
uname -a
** EDIT **
The reason I was running into this was because I was running a 32 bit version of Node.js and my Windows machine was a 64 bit system. After installing to a 64 bit version of Node.js I no longer have to specify the arch type in Package.json file.
you can find what architecture type your Node.js is by typing in your terminal:
node -p "process.arch"
Status 403 usually means that your ip is restricted from server(for example maybe your country is in sanction list like iran,syria,...).
The best solution for this challenge is to change dns to dns of vpns.
In linux just type:
sudo nano /etc/resolv.conf
And then type your dns in nameserver place.
Try this version mongodb-memory-server#6.5.1
I found a solution for this problem that worked for me.
I just set writing permissions to the binary file of mongod that is used for mongo-memory and is saved in the .cache path of your computer or in the node_modules folder.
just locale the mongod file and set writing permission to the file with chmod +x mongod

How to run two shell scripts at startup?

I am working with Ubuntu 16.04 and I have two shell scripts:
run_roscore.sh : This one fires up a roscore in one terminal.
run_detection_node.sh : This one starts an object detection node in another terminal and should start up once run_roscore.sh has initialized the roscore.
I need both the scripts to execute as soon as the system boots up.
I made both scripts executable and then added the following command to cron:
#reboot /path/to/run_roscore.sh; /path/to/run_detection_node.sh, but it is not running.
I have also tried adding both scripts to the Startup Applications using this command for roscore: sh /path/to/run_roscore.sh and following command for detection node: sh /path/to/run_detection_node.sh. And it still does not work.
How do I get these scripts to run?
EDIT: I used the following command to see the system log for the CRON process: grep CRON /var/log/syslog and got the following output:
CRON[570]: (CRON) info (No MTA installed, discarding output).
So I installed MTA and then systemlog shows:
CRON[597]: (nvidia) CMD (/path/to/run_roscore.sh; /path/to/run_detection_node.sh)
I am still not able to see the output (which is supposed to be a camera stream with detections, as I see it when I run the scripts directly in a terminal). How should I proceed?
Since I got this working eventually, I am gonna answer my own question here.
I did the following steps to get the script running from startup:
Changed the type of the script from shell to bash (extension .bash).
Changed the shebang statement to be #!/bin/bash.
In Startup Applications, give the command bash path/to/script to run the script.
Basically when I changed the shell type from sh to bash, the script starts running as soon as the system boots up.
Note, in case this helps someone: My intention to have run_roscore.bash as a separate script was to run roscore as a background process. One can run it directly from a single script (which is also running the detection node) by having roscore& as a command before the rosnode starts. This command will fire up the master as a background process and leave the same terminal open for following commands to be executed.
If you could install immortal you could use the require option to start in sequence your services, for example, this is could be the run config for /etc/immortal/script1.yml:
cmd: /path/to/script1
log:
file: /var/log/script1.log
wait: 1
require:
- script2
And for /etc/immortal/script2.yml
cmd: /path/to/script2
log:
file: /var/log/script2.log
What this will do it will try to start both scripts on boot time, the first one script1 will wait 1 second before starting and also wait for script2 to be up and running, see more about the wait and require option here: https://immortal.run/post/immortal/
Based on your operating system you will need to configure/setup immortaldir, her is how to do it for Linux: https://immortal.run/post/how-to-install/
Going more deep in the topic of supervisors there are more alternatives here you could find some: https://en.wikipedia.org/wiki/Process_supervision
If you want to make sure that "Roscore" (whatever it is) gets started when your Ubuntu starts up then you should start it as a service (not via cron).
See this question/answer.

how to run windows service automatically using nodejs application? [duplicate]

Can any node.js experts tell me how I might configure node JS to autostart a server when my machine boots?
I'm on Windows
This isn't something to configure in node.js at all, this is purely OS responsibility (Windows in your case). The most reliable way to achieve this is through a Windows Service.
There's this super easy module that installs a node script as a windows service, it's called node-windows (npm, github, documentation). I've used before and worked like a charm.
var Service = require('node-windows').Service;
// Create a new service object
var svc = new Service({
name:'Hello World',
description: 'The nodejs.org example web server.',
script: 'C:\\path\\to\\helloworld.js'
});
// Listen for the "install" event, which indicates the
// process is available as a service.
svc.on('install',function(){
svc.start();
});
svc.install();
p.s.
I found the thing so useful that I built an even easier to use wrapper around it (npm, github).
Installing it:
npm install -g qckwinsvc
Installing your service:
> qckwinsvc
prompt: Service name: [name for your service]
prompt: Service description: [description for it]
prompt: Node script path: [path of your node script]
Service installed
Uninstalling your service:
> qckwinsvc --uninstall
prompt: Service name: [name of your service]
prompt: Node script path: [path of your node script]
Service stopped
Service uninstalled
If you are using Linux, macOS or Windows pm2 is your friend. It's a process manager that handle clusters very well.
You install it:
npm install -g pm2
Start a cluster of, for example, 3 processes:
pm2 start app.js -i 3
And make pm2 starts them at boot:
pm2 startup
It has an API, an even a monitor interface:
Go to github and read the instructions. It's easy to use and very handy. Best thing ever since forever.
If I'm not wrong, you can start your application using command line and thus also using a batch file. In that case it is not a very hard task to start it with Windows login.
You just create a batch file with the following content:
node C:\myapp.js
and save it with .bat extention. Here myapp.js is your app, which in this example is located in C: drive (spcify the path).
Now you can just throw the batch file in your startup folder which is located at C:\Users\%username%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
Just open it using %appdata% in run dailog box and locate to >Roaming>Microsoft>Windows>Start Menu>Programs>Startup
The batch file will be executed at login time and start your node application from cmd.
This can easily be done manually with the Windows Task Scheduler.
First, install forever.
Then, create a batch file that contains the following:
cd C:\path\to\project\root
call C:\Users\Username\AppData\Roaming\npm\forever.cmd start server.js
exit 0
Lastly, create a scheduled task that runs when you log on. This task should call the batch file.
I would recommend installing your node.js app as a Windows service, and then set the service to run at startup. That should make it a bit easier to control the startup action by using the Windows Services snapin rather than having to add or remove batch files in the Startup folder.
Another service-related question in Stackoverflow provided a couple of (apprently) really good options. Check out How to install node.js as a Windows Service. node-windows looks really promising to me. As an aside, I used similar tools for Java apps that needed to run as services. It made my life a whole lot easier. Hope this helps.
you should try this
npm forever
https://www.npmjs.com/package/forever
Use pm2 to start and run your nodejs processes on windows.
Be sure to read this github discussion of how to set up task scheduler to start pm2: https://github.com/Unitech/pm2/issues/1079
Here is another solution I wrote in C# to auto startup native node server or pm2 server on Windows.
I know there are multiple ways to achieve this as per solutions shared above. I haven't tried all of them but some third party services lack clarity around what are all tasks being run in the background. I have achieved this through a powershell script similar to the one mentioned as windows batch file. I have scheduled it using Windows Tasks Scheduler to run every minute. This has been quite efficient and transparent so far. The advantage I have here is that I am checking the process explicitly before starting it again. This wouldn't cause much overhead to the CPU on the server. Also you don't have to explicitly place the file into the startup folders.
function CheckNodeService ()
{
$node = Get-Process node -ErrorAction SilentlyContinue
if($node)
{
echo 'Node Running'
}
else
{
echo 'Node not Running'
Start-Process "C:\Program Files\nodejs\node.exe" -ArgumentList "app.js" -WorkingDirectory "E:\MyApplication"
echo 'Node started'
}
}
CheckNodeService
Simply use this, install, run and save current process list
https://www.npmjs.com/package/pm2-windows-startup
By my exp., after restart server, need to logon, in order to trigger the auto startup.
Need to create a batch file inside project folder.
Write this code in batch file
#echo off
start npm start
save batch file with myprojectname.bat
Go to run command and press window + R
Enter this command :- shell:common startup
Press ok then folder will be open.
Folder path like as C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp
You will be paste your myprojectname.bat file.
You can check also. Need to system restart.
Copied directly from this answer:
You could write a script in any language you want to automate this (even using nodejs) and then just install a shortcut to that script in the user's %appdata%\Microsoft\Windows\Start Menu\Programs\Startup folder

mocha-phantomjs-core - slimerjs hangs without any error

Using mocha-phantomjs-core with slimerjs
I manage to run my tests successfully from CMD:
slimerjs mocha-phantomjs-core.js tests.html tap
Slimerjs window opens, I see the a browser window and all seems good, but the CMD doesn't finish (seems to wait for something). nothing is happening until I close the slimerjs window. I want to output the test result (using TAP reporter) as a file.
is that possible?
https://github.com/nathanboktae/mocha-phantomjs-core/issues/25
system.stderr.writeLine doesn't work on CMD or GIT bash... I've changed mocha-phantomjs-core.js fail function stderr to do stdout instead. now I get the error:
Likely due to external resource loading and timing, your tests require
calling window.initMochaPhantomJS() before calling any mocha setup
functions. See #12
So I had to add window.initMochaPhantomJS() before the setup function.. how silly! all this because I couldn't see any error due to the stderr issue not printed

Resources