node-phantom createPage() never calls callback - javascript

I used nodejs with node-phantom module for some time. It worked fine.
Now I try it on another machine and same code example don't work:
var Scan=function(request,response)
{
var parsedURL=url.parse(request.url,true);
if(parsedURL.query.site)
{
console.log("scanning "+parsedURL.query.site);
phantom.create(function(err,ph) {
console.log(err);
return ph.createPage(function(err,page) {
console.log(err);
return page.open(parsedURL.query.site, function(err,status) {
console.log("opened site? ", status);
if (status=="fail") {
response.writeHead(404, {'Content-Type': 'text/plain'});
response.end('URL not found');
return;
}
var filename="temp.jpg';
console.log(filename);
page.render(filename,function(err){
if (err) {
console.log(err);
return;
}
page.close(function(){
response.writeHead(404, {'Content-Type': 'text/plain'});
response.end('URL not found');
});
});
console.log("opened site? ", status);
if (status=="fail") {
response.writeHead(404, {'Content-Type': 'text/plain'});
response.end('URL not found');
return;
}
var filename="temp.jpg';
console.log(filename);
page.render(filename,function(err){
if (err) {
console.log(err);
return;
}
page.close(function(){
response.writeHead(404, {'Content-Type': 'text/plain'});
response.end('URL not found');
});
});
});
});
});
}
}
It never gets inside createPage() callback and it looks like lack of communication between nodejs and phantomjs.
nodejs version: 0.10.10
phantomjs version: 1.9.1
How can I check what wrong with it?
UPD: Installed new Debian distro and now it throws folowing warning in the console sometimes.
warn - client not handshaken client should reconnect
It looks like socket.io problem.

Well hard to diagnose exactly but I tried your code with the following fixes for the mismatched quotations and it seems to work fine on v0.10.6. These 2 lines that look like:
var filename="temp.jpg';
need fixing first.
My best guess is that you have a 32 bit versus 64 bit problem... seeing as you switch machines and it fails or works. So I simulated that by installing 32 bit node on a 64 bit system to show the troubleshooting procedure for that sort of thing:
First check the exit code:
[node#hip1 blah]$ phantomjs
[node#hip1 blah]$ $?
-bash: 127: command not found
follow all the symlinks and run the executable directly, for example on my system:
[node#hip1 blah]$ which phantomjs
~/node/bin/phantomjs
[node#hip1 blah]$ ls -l ~/node/bin/phantomjs
lrwxrwxrwx. 1 node node 43 Jun 16 20:06 /node/node/bin/phantomjs -> ../lib/node_modules/phantomjs/bin/phantomjs
[node#hip1 blah]$ ls -l /node/node/lib/node_modules/phantomjs/bin/phantomjs
-rwxr-xr-x. 1 node node 540 Jun 16 20:14 /node/node/lib/node_modules/phantomjs/bin/phantomjs
execute that...
[node#hip1 blah]$ /node/node/lib/node_modules/phantomjs/bin/phantomjs
/node/libs/node-v0.10.6-linux-x86/lib/node_modules/phantomjs/lib/phantom/bin/phantomjs: error while loading shared libraries: libfreetype.so.6: cannot open shared object file: No such file or directory
Ah, notice the .6 on the end of that library, it's that this is a 64 bit system but we have installed 32 bit node to avoid memory issues and have also noticed better performance with it. So an npm install phantomjs goes and gets the 32 bit version of that. So now I'd need the devel i686 versions of those libraries, which won't be installed if I don't specify - instead I'll get the x86_64 versions. So do a few of these:
yum install freetype-devel.i686 or on debian use apt-get install. You might also need libfontconfig.so.1, which is in fontconfig-devel.i686.
And finally!
phantomjs>
After that things should probably work.

Related

I am trying to execute a file in sh with nodejs but the console tells me that the file cannot be found

This is the code that i found on the internet:
const { exec } = require('child_process');
var yourscript = exec('sh launch.sh', (error, stdout, stderr) => {
console.log(stdout);
console.log(stderr);
if (error !== null) {
console.log(`exec error: ${error}`);
}
});
and here is my sh file which is in the same file as my previous code:
echo "Hi There!"
but each time I run the program the console shows me:
exec error: Error: Command failed: sh launch.sh
sh: 0: Can't open launch.sh
Can somebody help me with my code please?
First, you seem to have a file permissions issue, so to fix that, start by setting the file permissions for the user as the user needs execution permissions:
chmod 755 launch.sh
Second, the code you found online is using "exec" that is now deprecated in favour of builtin child_process.execFile. So, for your needs the code would look a bit like:
var child_process = require('child_process');
child_process.exec('sh launch.sh', function(error, stdout, stderr){
console.log(stdout);
});
This should help to get started! The inner command sh launch.sh should be executable in the command line, directly, so tested without running the main host or nodejs script! Type the command in your CLI and press enter! Alternatively to calling sh launch.sh do /bin/sh launch.sh
Of course, you might want to look at docs to improve the implementation and fully understand file permissions under your OS, what sh means and finally child_process.exec.
https://www.linux.com/tutorials/understanding-linux-file-permissions
https://en.wikipedia.org/wiki/Bourne_shell
https://nodejs.org/api/child_process.html

Node.js - execFile throws spawn UNKNOWN

I am trying to spawn a service created with pyInstaller from an electron application. I am using the following code for that:
return new Promise((reject, resolve)=>{
var exec = require('child_process').execFile;
exec(path.join(install_path, 'myService.exe'), ['--startup=auto', 'install'], function(err, data) {
if(err) {
reject(err);
return;
}
console.log(data.toString());
exec(path.join(install_path, 'myService.exe'), ['start'], function(err, data){
if(err) {
reject(err);
return;
}
resolve(data.toString());
})
});
}
Unfortunately, this throws an
Uncaught Error: spawn UNKNOWN
on a testing system, which does not have node installed and is running Windows 10 x64. On my machine it is working fine.
Does anyone have tips how I could investigate this further? I am especially curious how this error is uncaught, because the callback functions obviously contain simple error handling.
Okay, after I built in better error handling thanks to Keiths help and rebuilt the project, the testers could not reproduce the issue anymore. I am still not sure if that actually fixed the problem or if the testers pulled an old version the last time.
Anyway, this is solved.

Node.js callback not executed when using VSCode debugger

I have an issue with the VSCode Node.js debugger.
I have the following code (it downloads an image an calculates its hash):
var request = require('request');
var crypto = require('crypto');
request({ uri : 'http://static.wixstatic.com/media/28f6fa_1519eb247c97446098566248a9f86441.jpg',
encoding: null,
timeout: 10000
}, function (err, res, body) {
if (err) {
return res.status(500).send(err);
}
if (res.statusCode !== 200) {
return res.status(500).send(buildResponse(500, "Image download returned status code " + res.statusCode));
}
console.log(crypto.createHmac('sha256', body).digest('hex'));
});
If I run node test.js, it prints the hash of the file perfectly.
If I run it using VSCode debug mode, it does not.
If I set a break point at line 4 (request({...), the debugger hits the break point.
If I set a break point at line 8 (if (err) { ...), the debugger does not hit the break point.
Am I doing something wrong or is this a bug?
$ node -v
v4.6.0
VSCode version: 1.6.1 Recovery Build
Just use the node-inspector it is for me the better way to debug code of backend
here is the link and there are complete guides to start witht that
https://www.npmjs.com/package/node-inspector
By the way is you want to debug some specific file use the node-debug
node-debug my_file_to_debug.js
I hope it help you.

Node.js: Error trying to use shell command that interacts with files

I am trying to use pngquant after I have uploaded images to my Node.js application.
I am running the following code after upload:
if (pngFiles.length) {
console.log('PNG Files Ready for Processing: ', pngFiles);
pngFiles.forEach(function(file) {
console.log(file);
exec('pngquant --force ' + file, function(error, stdout, stderr) {
console.log(error, stdout, stderr);
});
});
}
But end up with the following error:
{ [Error: Command failed: error: cannot open /Users/nfento/Projects/jamdeo/public/uploads/mytestcontrollers/92614D43-A55A-4456-9663- ABF90A23D9F5/92614D43-A55A-4456-9663-ABF90A23D9F5_7_tablet.png for reading
] killed: false, code: 2, signal: null } '' ' error: cannot open /Users/nfento/Projects/jamdeo/public/uploads/mytestcontrollers/92614D43-A55A-4456-9663-ABF90A23D9F5/92614D43-A55A-4456-9663-ABF90A23D9F5_7_tablet.png for reading\n'
For every file, if I go into the shell and run
`pngquant /Users/nfento/Projects/jamdeo/public/uploads/mytestcontrollers/92614D43-A55A-4456-9663-ABF90A23D9F5/92614D43-A55A-4456-9663-ABF90A23D9F5_7_tablet.png`
I get a success message, what am I doing wrong here? Does my application need additional access?
Well, the first thing to check when you get the error cannot open <PATH> for reading is check the filesystem permissions including owner, group, mode, and all parent directories. Is your node code running as the same user as when you run the command manually in the shell?
Other note probably not your issue, but in general, be really careful when building up a string to be passed to exec as it is extremely easy to allow bugs and big security vulnerabilities via this type of code. So first, try quoting your file path so if you had a path with a space in it, for example, your code would still work correctly.
exec("pngquant --force '" + file + "'", function(error, stdout, stderr) {

How to execute shell command in Javascript

I want to write a JavaScript function which will execute the system shell commands (ls for example) and return the value.
How do I achieve this?
I'll answer assuming that when the asker said "Shell Script" he meant a Node.js backend JavaScript. Possibly using commander.js to use frame your code :)
You could use the child_process module from node's API. I pasted the example code below.
var exec = require('child_process').exec;
exec('cat *.js bad_file | wc -l',
function (error, stdout, stderr) {
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if (error !== null) {
console.log('exec error: ' + error);
}
});
I don't know why the previous answers gave all sorts of complicated solutions. If you just want to execute a quick command like ls, you don't need async/await or callbacks or anything. Here's all you need - execSync:
const execSync = require('child_process').execSync;
// import { execSync } from 'child_process'; // replace ^ if using ES modules
const output = execSync('ls', { encoding: 'utf-8' }); // the default is 'buffer'
console.log('Output was:\n', output);
For error handling, add a try/catch block around the statement.
If you're running a command that takes a long time to complete, then yes, look at the asynchronous exec function.
...few year later...
ES6 has been accepted as a standard and ES7 is around the corner so it deserves updated answer. We'll use ES6+async/await with nodejs+babel as an example, prerequisites are:
nodejs with npm
babel
Your example foo.js file may look like:
import { exec } from 'child_process';
/**
* Execute simple shell command (async wrapper).
* #param {String} cmd
* #return {Object} { stdout: String, stderr: String }
*/
async function sh(cmd) {
return new Promise(function (resolve, reject) {
exec(cmd, (err, stdout, stderr) => {
if (err) {
reject(err);
} else {
resolve({ stdout, stderr });
}
});
});
}
async function main() {
let { stdout } = await sh('ls');
for (let line of stdout.split('\n')) {
console.log(`ls: ${line}`);
}
}
main();
Make sure you have babel:
npm i babel-cli -g
Install latest preset:
npm i babel-preset-latest
Run it via:
babel-node --presets latest foo.js
This depends entirely on the JavaScript environment. Please elaborate.
For example, in Windows Scripting, you do things like:
var shell = WScript.CreateObject("WScript.Shell");
shell.Run("command here");
In a nutshell:
// Instantiate the Shell object and invoke its execute method.
var oShell = new ActiveXObject("Shell.Application");
var commandtoRun = "C:\\Winnt\\Notepad.exe";
if (inputparms != "") {
var commandParms = document.Form1.filename.value;
}
// Invoke the execute method.
oShell.ShellExecute(commandtoRun, commandParms, "", "open", "1");
Note: These answers are from a browser based client to a Unix based web server.
Run command on client
You essentially can't. Security says only run within a browser and its access to commands and filesystem is limited.
Run ls on server
You can use an AJAX call to retrieve a dynamic page passing in your parameters via a GET.
Be aware that this also opens up a security risk as you would have to do something to ensure that mrs rouge hacker does not get your application to say run: /dev/null && rm -rf / ......
So in a nutshel, running from JS is just a bad, bad idea.... YMMV
With NodeJS is simple like that!
And if you want to run this script at each boot of your server, you can have a look on the forever-service application!
var exec = require('child_process').exec;
exec('php main.php', function (error, stdOut, stdErr) {
// do what you want!
});
function exec(cmd, handler = function(error, stdout, stderr){console.log(stdout);if(error !== null){console.log(stderr)}})
{
const childfork = require('child_process');
return childfork.exec(cmd, handler);
}
This function can be easily used like:
exec('echo test');
//output:
//test
exec('echo test', function(err, stdout){console.log(stdout+stdout+stdout)});
//output:
//testtesttest
Here is simple command that executes ifconfig shell command of Linux
var process = require('child_process');
process.exec('ifconfig',function (err,stdout,stderr) {
if (err) {
console.log("\n"+stderr);
} else {
console.log(stdout);
}
});
If you are using npm you can use the shelljs package
To install: npm install [-g] shelljs
var shell = require('shelljs');
shell.ls('*.js').forEach(function (file) {
// do something
});
See more: https://www.npmjs.com/package/shelljs
Another post on this topic with a nice jQuery/Ajax/PHP solution:
shell scripting and jQuery
In IE, you can do this :
var shell = new ActiveXObject("WScript.Shell");
shell.run("cmd /c dir & pause");
With nashorn you can write a script like this:
$EXEC('find -type f');
var files = $OUT.split('\n');
files.forEach(...
...
and run it:
jjs -scripting each_file.js
As far as I can tell, there is no built-in function, method or otherwise, in the official ECMAScript specification to run an external process. That said, extensions are allowed, see this note from the spec, for example:
NOTE Examples of built-in functions include parseInt and Math.exp. A
host or implementation may provide additional built-in functions that
are not described in this specification.
One such "host" is Node.js which has the child_process module. Let's try this code to execute the Linux shell command ps -aux, saved in runps.js, based on the child_process documentation:
const { spawn } = require('child_process');
const ps = spawn('ps', ['-aux']);
ps.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
ps.stderr.on('data', (data) => {
console.error(`stderr: ${data}`);
});
ps.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});
Which produces the following example output, running it in docker:
$ docker run --rm -v "$PWD":/usr/src/app -w /usr/src/app node:17-bullseye node ./runps.js
stdout: USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.8 319312 33888 ? Ssl 11:08 0:00 node ./runps.js
root 13 0.0 0.0 6700 2844 ? R 11:08 0:00 ps -aux
child process exited with code 0
The thing I like about this module, is that it's included with the Node.js distribution, no npm install ... needed.
If you search the Node.js code in github for spawn you will find references to the implementation in C or C++ in the engine. Modern browsers like Firefox and Chrome would be reluctant to extend JavaScript with such features, for obvious security reasons, even if the underlying engine such as V8 supports it.
On that note, it's better not to run our container as root, let's try the above example again, adding a random user this time.
$ docker run --rm -u 7000 -v "$PWD":/usr/src/app -w /usr/src/app node:17-bullseye node ./runps.js
stdout: USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
7000 1 5.0 0.8 319312 33812 ? Ssl 11:19 0:00 node ./runps.js
7000 13 0.0 0.0 6700 2832 ? R 11:19 0:00 ps -aux
child process exited with code 0
Of course that's better but not enough. If this approach is used at all, more precautions must be taken, such as ensuring that no arbitrary user commands can be executed.
Windows 10
My version of Windows 10 still has Windows Script Host which can run JScript on the console with the wscript.exe or cscript.exe programs, i.e. no browser needed. To try it out you can open a PowerShell Windows Terminal. Save the following code into a file which you can call shell.js:
WScript.StdOut.WriteLine("Hallo, ECMAScript on Windows!");
WScript.CreateObject("WScript.Shell").run("C://Windows//system32//mspaint.exe");
And on the command line, run:
cscript .\shell.js
Which shows the following and opens Paint:
Microsoft (R) Windows Script Host Version 5.812
Copyright (C) Microsoft Corporation. All rights reserved.
Hallo, ECMAScript on Windows!
Other variations exist. Find the documentation applicable to your preferred JavaScript runtime environment.
const fs = require('fs');
function ls(startPath) {
fs.readdir(startPath, (err, entries) => {
console.log(entries);
})
}
ls('/home/<profile_name>/<folder_name>')
The startPath used here is in reference with debian distro
Js file
var oShell = new ActiveXObject("Shell.Application");
oShell.ShellExecute("E:/F/Name.bat","","","Open","");
Bat file
powershell -Command "& {ls | Out-File -FilePath `E:F/Name.txt}"`
Js file run with node namefile.js
const fs = require('fs')
fs.readFile('E:F/Name.txt', (err, data) => {
if (err) throw err;
console.log(data.toString());
})
You can also do everything in one solution with an asynchronous function.
Directly there could be security problems.

Categories