I realize "Running PhantomJS on Heroku" is a related but slightly different question as I am trying to use a node app.
I'm having trouble deploying a casperJS (based on phantomJS) script for a node app. I've tried deploying to Heroku by placing the PhantomJS 64-bit binary in my app's /bin directory, but I get the following error when I try to run PhantomJS:
phantomjs: error while loading shared libraries: libQtWebKit.so.4: cannot open shared object file: No such file or directory
From what I've read this can be solved by installing the QtWebKit library, but Heroku does not have this installed. Is there another hosting provider I could use that will work or a way to install this package on Heroku?
Relevant code:
app.get('/', function(request, response) {
var sys = require('sys')
var exec = require('child_process').exec;
var child;
//works but gives error while loading shared library libqtwebkit.so.4
child = exec("phantomjs --version | tr -d '\n'", function(error, stdout, stderr) {
sys.print('stdout: ' + stdout);
sys.print('stderr: ' + stderr + '\n');
response.header('Content-Type', 'application/json');
response.send('_testcb(stdout:' + stdout + '\nstderr:' + stderr + ')', 200);
if(error !== null) {
console.log('exec error: ' + error);
}
});
});
I've signed up for beta-testing on Nodester but their documentation is still pretty limited at this point.
EDIT: I was able to get it working by simply copying the lib folder of PhantomJS to the root directory of my node app.
Copy the lib folder of phantomjs to the root directory of your node app
You could also try putting a sym link in bin or sbin
The key is that is has to run from terminal using the same account that node runs on.
Also, node-phantom is a good npm library to utilize phantomjs, once you get it working.
Related
I have a Node Express server that works on localhost. It uses child_process to run a C++ standalone executable.
The code that uses child_process is the following (the application creates output.txt):
app.post('/generate', async function(req, res)
{
var input1 = req.body.input1;
var input2 = req.body.input2;
var execFile = require('child_process').execFile;
var program = "path/to/executable";
var args = [input1, input2];
var child = execFile(program, args,
function (error, stdout, stderr){
console.log(error);
console.log(stdout);
console.log(stderr);
const file = __dirname + "/output.txt"
app.get('/output.txt', function (req, res) {
res.sendFile(path.join(__dirname + '/output.txt'));
});
res.send("/output.txt");
})
})
This works locally.
I'm now trying to deploy it on Google Cloud Platform with App Engine.
However, when I go the website that I host, and launch this POST /generate request, I don't get the expected output. In the Google Cloud Platform logs of my project I can see the following error:
textPayload: "{ Error: spawn cpp/web_cpp_app/x64/Debug/web_cpp_app ENOENT
at Process.ChildProcess._handle.onexit (internal/child_process.js:240:19)
at onErrorNT (internal/child_process.js:415:16)
at process._tickCallback (internal/process/next_tick.js:63:19)
"
At first I didn't understand the error, but now I can see that if I locally run the same project, but set the path of the standalone executable to an invalid path, I get the same error. I'm guessing that when I deploy, my executable is somehow not included?
Is there something specific I need to add in package.json or app.yaml files, to include the executable?
EDIT:
Could it be that the app engine runs on Linux, and my executable is for Windows?
ENOENT means "no such file or directory", so your path could be wrong, or the container doesn't recognize the program as executable.
But either way, you will need to build and include a linux-compatible binary of your child_process program in your project directory when you deploy. You could build this manually, or use something like Cloud Build to compile it in a container that's identical to that of App Engine.
You are right about the OS, per this Doc Appengine standard for NodeJS uses Ubuntu OS, and flexible uses Debian
About the executable compatibility I found this post
I have a experiment code like this just to test calling a child process from NativeScript app (myapp/app/views/login/login.js):
var exec = require('child_process').exec;
exec('ls', function (error, stdout, stderr) {
if(stdout){
console.log('stdout: ' + stdout);
}
if(stderr){
console.log('stderr: ' + stderr);
}
if (error !== null) {
console.log('Exec error: ' + error);
}
});
when I test this app with "tns run ios --emulator", it gives an error like this:
file:///app/views/login/login.js:1:89: JS ERROR Error: Could not find module 'child_process'. Computed path '/Volumes/xxxx/Users/xxxx/Library/Developer/CoreSimulator/Devices/392A8058-694B-4A5D-B194-DF935815ED21/data/Containers/Bundle/Application/2822CD65-4E4D-443C-8272-135DB09353FC/sampleGroceries.app/app/tns_modules/child_process'.
My question is: how can I resolve this? Should I do "npm install child_process" on the app's directory? But while I was searching for solutions on Google, I read that it should be naturally included from node_modules...
I find a child_process module in:
/usr/local/lib/node_modules/nativescript/lib/common
but as the error message says, it isn't included when I execute the app with tns command. Could someone tell me what I'm missing?
version info:
npm: 3.10.10
node: 7.2.1
tns: 2.4.2
The child_process that you are seeing is a wrapper in the NativeScript CLI for Node's child_process.
There is no child_process in NativeScript as the concept is not relevant in mobile environments (Android/iOS).
The reason Node JS works cross-platform for example, is because its engine has analogous feature implementation (file-system, http, child process) for each of the supported platforms.
Using node's child_process (installing it explicitly and requiring it) will likely not work, as there is no in-house implementation for mobile devices.
If you would like to perform something in the background, consider using NativeScript's Workers.
http://docs.nativescript.org/angular/core-concepts/multithreading-model.html
Edit:
If there isn't a plugin already that is readily available, you could use the underlying native API to call to the device's shell.
Android: execute shell command from android
iOS (Objective C): Cocoa Objective-C shell script from application?
Docs on the nativescript site are available that should help you in 'translating' objC/Java code to JavaScript, though it is pretty straightforward.
http://docs.nativescript.org/runtimes/android/marshalling/java-to-js
http://docs.nativescript.org/runtimes/ios/marshalling/Marshalling-Overview
I am running forllowing test.js file using
>node test.js
test.js is simple code
var fs = require("fs");
fs.readFile('2.rtf', function (err, data) {
if (err) return console.error(err);
console.log(data.toString());
});
console.log("Program Ended");
It shows error
so naturally I remove the extension and ran following command which worked fine.
node test
I am running windows 7 32 bit. How to stop WSH while using node commnad?
The problem seems to be that you have a file named node.js in the same directory and due to the way Windows resolves commands, it's trying to execute the file node.js (using the default handler for that file type, which is typically JScript) instead of node the node.js executable. Rename the node.js file to something else and it should work.
Here is a short overview to help you experts understand the situation I am in - sorry that its too verbose, but it might help resolving this issue:
So I have a Linux machine, and it runs Apache properly.
Under '/var/www/html', I put my project files which are HTML (index.html) , and a javaScript file with utility functions.
httpd runs and everyone can view the content when 'http:///index.html' from their PC's.
I want to run a bash script from my Linux machine by letting the users provide the parameters from the front end user interface.
Reading how to do that, I saw tons of examples of how node.js can do that, so I downloaded Node.JS to my Linux machine, and it can be run from:
"
~/Desktop/node-v4.2.1-linux-x64/bin/node --version
v4.2.1
~/Desktop/node-v4.2.1-linux-x64/bin/npm --version
2.14.7
"
So it seems like its properly installed...
Note: I did not put anything in my Linux path after extracting the node.js tar.gz file.
Now, from my Linux machine, under '/var/www/html' , I have an HTML file, and I created an 'onclick' event to invoke a javascript function, in which I wrote a call to run this bash script which is located in my Linux machine under "/" - here it is:
function start_run(pTopoFile, pEmailAddress) {
var childProcess = require('child_process');
var run_command;
run_command = childProcess.exec('/run.sh ' + pTopoFile + ' ' + pEmailAddress, function (error, stdout, stderr) {
if (error) {
console.log(error.stack);
console.log('Error code: '+error.code);
console.log('Signal received: '+error.signal);
}
console.log('Child Process STDOUT: '+stdout);
console.log('Child Process STDERR: '+stderr);
});
ls.on('exit', function (code) {
console.log('Child process exited with exit code '+code);
});
}
When I run the above I get this error:
"ReferenceError: require is not defined"
Which means that even though Node.js was installed properly (as I showed you above), I cannot access its methods from /var/www/html on my Linux machine ...
Can anyone let me know how to link between the great features that node.js has to my scripts?
I hope that I was clear enough with the info I provided...
Thanks,
Tom
I've successfully got Phantomjs to work on Heroku but now I'm hitting issues with the phantomjs-node interface for node.js (see https://github.com/sgentle/phantomjs-node).
When I'm attempting to initialize Phantom I'm seeing a 10-15 second delay and then:
> phantom stdout: ReferenceError: Can't find variable: socket
phantom stdout: phantomjs://webpage.evaluate():1
phantomjs://webpage.evaluate():1
phantomjs://webpage.evaluate():1
You can reproduce the problem with the following steps or by pulling down my test app at https://github.com/matellis/phantom-test
git init phantom-test
cd phantom-test
heroku apps:create
# create node app as per Heroku instructions here https://devcenter.heroku.com/articles/nodejs
# copy bin and lib folders from http://phantomjs.googlecode.com/files/phantomjs-1.6.1-linux-x86_64-dynamic.tar.bz2 into root of your new project
# if you don't do this step you'll get an error "phantom stderr: execvp(): No such file or directory"
git add .
git commit -m "init"
git push heroku
Test your app has come up, the third to last line will tell you the URL, it should read like:
http://fathomless-ravine-5563.herokuapp.com deployed to Heroku
If successful you should see Hello World! in your browser.
Now from the same folder as your Heroku application run:
heroku run node
At the node prompt try the following:
phantom = require('phantom');
x = phantom.create();
Wait 10-15 seconds and you should see the error. Nothing works from this point on.
This should output file foo.png:
x = phantom.create(function(ph){ph.createPage(function(page){ page.open('http://bbcnews.com', function(status){ page.render('foo.png', function(result) {ph.exit()}); }); }); });
To validate Phantomjs is working fine on Heroku, try the following using my test project:
>heroku run bash
Running `bash` attached to terminal... up, run.1
~ $ phantomjs test.js http://bbcnews.com foo.png
~ $ ls *.png
foo.png
I cannot reproduce any of these problems locally but there are other issues reported where folks may have hit this issue locally.
The problem seems to originate in shim.js line 1637:
s.on('request', function(req) {
var evil;
evil = "function(){socket.emit('message', " + (JSON.stringify(JSON.stringify(req))) + " + '\\n');}";
return controlPage.evaluate(evil);
});
I've tried variations of versions of node, phantom, etc. with no luck.
I've also tried a custom buildpack that sets the DYLD variable, see http://github.com/tecnh/heroku-buildpack-nodejs with no luck either.
Anyone who has got Phantom + Node playing together nicely on Heroku please let me know. There are several references to this on Stackoverflow but nobody is saying "I got it to work, here's how".
I've never used the phantomjs node module, but I do have an app running both node and phantomjs on Heroku.
You need to use custom buildpacks in order to get this to work. My .buildpacks file looks like
http://github.com/heroku/heroku-buildpack-nodejs.git
http://github.com/stomita/heroku-buildpack-phantomjs.git
You should then be able to run phantomjs scripts in a child process:
var script = app.get('root') + '/scripts/rasterize.js' //the phantomjs script to run
, bin = app.get('phantom') //normally this would just be the string "phantomjs"
, spawn = require('child_process').spawn;
// set up args to the phantom cli
// (run the phantomjs command in your terminal to see options/format)
var args = [];
// ...
var phntm = spawn(bin, args);
phntm.stdout.on('data', function (data) { /* do something */ });
phntm.stderr.on('data', function (data) { /* do something */ });
phntm.on('exit', function (code) { /* handle exit */ });
Heroku does not support WebSockets. With Socket.io it has a workaround. Not sure about dnode, which phantomjs-node uses.
I had a problem with WebSockets on Heroku too and I switched to Nodejitsu, which solved it for me.