I'm trying to use the ZINTERSTORE command of redis from node.js using node_redis:
//node.js server code
var redis = require("redis");
var client = redis.createClient();
// ... omitted code ...
exports.searchImages = function(tags, page, callback){
//tags = ["red", "round"]
client.ZINTERSTORE("tmp", tags.length, tags.join(' '), function(err, replies){
//do something
});
}
But the call client.ZINTERSTORE throws the error: [Error: ERR syntax error]. Passing in tags as an array (instead of using tags.join(' ')) throws the same error.
Where can I find the correct syntax for this command? The source code for node_redis has it buried in the javascript parser, but it's tricky to see what's going on without 'stepping through' the code. Is there a good way to do step through debugging with node.js?
There are multiple ways to debug a Redis client with node.js.
First you can rely on the Redis monitor feature to log every commands received by the Redis server:
> src/redis-cli monitor
OK
1371134499.182304 [0 172.16.222.72:51510] "info"
1371134499.185190 [0 172.16.222.72:51510] "zinterstore" "tmp" "2" "red,round"
You can see the zinterstore command received by Redis is ill-formed.
Then, you can activate the debugging mode of node_redis by adding the following line in your script:
redis.debug_mode = true;
It will output the Redis protocol at runtime:
Sending offline command: zinterstore
send ncegcolnx243:6379 id 1: *4
$11
zinterstore
$3
tmp
$1
2
$9
red,round
send_command buffered_writes: 0 should_buffer: false
net read ncegcolnx243:6379 id 1: -ERR syntax error
Then, you can use node.js debugger. Put a debugger breakpoint in the code in the following way:
function search(tags, page, callback) {
debugger; // breakpoint is here
client.ZINTERSTORE("tmp", tags.length, tags, function(err, replies){
console.log(err);
console.log(replies);
callback('ok')
});
}
You can then launch the script with node in debug mode:
$ node debug test.js
< debugger listening on port 5858
connecting... ok
break in D:\Data\NodeTest\test.js:1
1 var redis = require("redis");
2 var client = redis.createClient( 6379, "ncegcolnx243" );
3
debug> help
Commands: run (r), cont (c), next (n), step (s), out (o), backtrace (bt), setBreakpoint (sb), clearBreakpoint (cb),
watch, unwatch, watchers, repl, restart, kill, list, scripts, breakOnException, breakpoints, version
debug> cont
break in D:\Data\NodeTest\test.js:8
6 function search(tags, page, callback) {
7
8 debugger;
9 client.ZINTERSTORE("tmp", tags.length, tags, function(err, replies){
10 console.log(err);
... use n(ext) and s(tep) commands ...
By stepping through the code, you will realize that the command array is not correct because the tags are serialized and processed as a unique parameter.
Changing the code as follows will fix the problem:
var cmd = [ "tmp", tags.length ];
client.zinterstore( cmd.concat(tags), function(err, replies) {
...
});
Related
Hi I have a standalone script which should be run on commandline (not trigger by API request)
I can run this script this way node db.js
However, could I be able to put any breakpoint on this kind of script.
And stop at the breakpoint when debugging?
I can not imagine we can only use console.log to debug.
var mongoose = require('./db');
fs= require('fs');
var AppCtrl = require('../handlers/handlerModule.js');
AppCtrl.joinJSONFiles("DeltaAirlines",function (err, data) {
data.forEach()
....
})
Reference: Debugger | Node.js v6.4.0 Documentation
Inserting the statement debugger; into the source code of a script will enable a breakpoint at that position in the code:
// myscript.js
x = 5;
setTimeout(() => {
debugger;
console.log('world');
}, 1000);
console.log('hello');
To use the debugger, run your program with node debug db.js. When a breakpoint is reached, the debugger prompt (debug>) appears. Some sample commands:
cont, c – continue execution
next, n – step next
backtrace, bt – print backtrace of current execution frame
exec expression – execute an expression in the debugging script's context
repl – open debugger's repl for evaluation in the debugging script's context
For a full list, see the Command reference section of the above link.
How can I run a command line and get the outputs as soon as available to show them somewhere.
For example if a run ping command on a linux system, it will never stop, now is it possible to get the responses while the command is still processing ?
Or let's take apt-get install command, what if i want to show the progress of the installation as it is running ?
Actually i'm using this function to execute command line and get outputs, but the function will not return until the command line ends, so if i run a ping command it will never return!
var sys = require('sys'),
exec = require('child_process').exec;
function getOutput(command,callback){
exec(
command,
(
function(){
return function(err,data,stderr){
callback(data);
}
}
)(callback)
);
}
Try using spawn instead of exec, then you can tap into the stream and listen to the data and end events.
var process = require('child_process');
var cmd = process.spawn(command);
cmd.stdout.on('data', function(output){
console.log(output.toString()):
});
cmd.on('close', function(){
console.log('Finished');
});
//Error handling
cmd.stderr.on('data', function(err){
console.log(err);
});
See the Node.js documentation for spawn here: https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options
how can interact with multiple console windows, from one node.js script?
so far i have researched a bit, and not have found anything that covers my case.
What i want to accomplish is to have one main console window, which it reads my input,
1. action#1
2. action#2
> do 1 // select action
and it would redirect its output to another console window named as Logger which shows the stdout of the action that the user selected, but keeps the main "select action" console window clean.
well i manage to find a way around it, since i wanted to stay with node.js all the way.
start.js
var cp = require("child_process");
cp.exec('start "Logger" cmd /K node logger.js',[],{});
cp.exec("start cmd /K node startAdminInterface.js",[],{});
setTimeout(function(){process.exit(0);},2000);
logger.js
var net = require('net');
net.createServer(function (socket) {
socket.on('data',function(d){
console.log(": "+d.toString("utf8"));
});
socket.on('error',function(err){
console.log("- An error occured : "+err.message);
});
}).listen(9999);
startAdminInterface.js
var net = require("net");
var logger = net.connect(9999);
var readline = require('readline'),
rl = readline.createInterface(process.stdin,process.stdout);
rl.setPrompt('> ');
rl.prompt();
rl.on('line', function(line) {
logger.write(line);
rl.prompt();
}).on('close', function() {
process.exit(0);
});
bottom, line its a workaround not exactly what i was after, put i saw potential, on logger.js it could listen from multiple sources, which is an enormous plus in the application that i'm building.
Im using mocha framework in my node application.If i run my test file using mocha means i'm getting error reports in terminal but i want to store the reports in local file.How can i do that.Is there any builtin method for this in mocha.
describe('Test with mocha', function(){
it ('result should be true',function(done){
var finalResult=false;
expect(finalResult).to.be(true);
done();
});
});
no there no built-in feature for mocha to do this, but you can do some other stuff by working with pipes which are standard in OSes.
open up a terminal, and give the command
mocha TEST.js > report.txt
the command above simply pipes all output to report.txt file.
You can also try working with child_process module from node, where you pretty much do the same thing as the command line, but in pure js.
*code is from node.js docs
var fs = require('fs'),
spawn = require('child_process').spawn,
out = fs.openSync('./out.log', 'a'),
err = fs.openSync('./out.log', 'a');
var child = spawn('prg', [], {
stdio: [ 'ignore', out, err ]
});
child.unref();
Ideally you can use mocha-junit-reporter and write output to XML file.
mocha tests --recursive --reporter mocha-junit-reporter --reporter-options mochaFile=./myJUnitfile.xml
If by local file you mean simple txt file then I have a sample code for you on which you can extend your own implementation. Please note that following code is only for knowledge sake. It doesn't handle many of the reporter events such as test suite start, and end etc., and exceptions that may be thrown by file operations.
For complete list of reporter events refer to https://github.com/mochajs/mocha/wiki/Third-party-reporters.
Also the following code is extended from the sample code present in above link.
// This code is extended on the orginal source present
// at https://github.com/mochajs/mocha/wiki/Third-party-reporters
// my-file-reporter.js
const mocha = require('mocha');
const fs = require('fs');
const os = require("os");
module.exports = MyFileReporter;
function MyFileReporter(runner, options) {
this._mochaFile = options.reporterOptions.mochaFile || process.env.MOCHA_FILE || 'test-results.txt';
mocha.reporters.Base.call(this, runner);
var passes = 0;
var failures = 0;
runner.on('start', function() {
if (fs.existsSync(this._mochaFile)) {
console.log('Removing existing test result file!');
fs.unlinkSync(this._mochaFile);
}
}.bind(this));
runner.on('pass', function(test){
passes++;
console.log('Pass: %s', test.fullTitle()); // Remove console.log statements if you dont need it (also below in code)
fs.appendFileSync(this._mochaFile, 'Pass: ' + test.fullTitle() + os.EOL); // Note: Exception not handled
}.bind(this));
runner.on('fail', function(test, err){
failures++;
console.log('Fail: %s -- error: %s', test.fullTitle(), err.message);
fs.appendFileSync(this._mochaFile, 'Fail: ' + test.fullTitle() + 'Error: ' + err.message + os.EOL); // Note: Exception not handled
}.bind(this));
runner.on('end', function(){
console.log('Test Summary: %d/%d', passes, passes + failures);
fs.appendFileSync(this._mochaFile, os.EOL + 'Test Summary: ' + passes + '/' + (passes + failures) + os.EOL); // Note: Exception not handled
}.bind(this));
}
Use the following command line (it assumes that my-file-reporter.js is present in the same folder where this command is executed)
mocha tests --recursive --reporter my-file-reporter --reporter-options mochaFile=./myfile.txt
I have an endless command line stream - namely logs from my heroku app - and want to parse it by line into node.js.
I have tried various approaches, like with the readline interface (does nothing):
var command = 'heroku logs --app myapp --tail';
var heroku = Npm.require('child_process').exec(command);
var readline = Npm.require('readline');
var rl = readline.createInterface({
input: heroku.stdin,
output: process.stdout
});
rl.on('line', function(log) {
console.log(log);
});
Or with just raw exec, that does return an initial buffer, but does not read continously from the process:
var command = 'heroku logs --app myapp --tail';
var heroku = Npm.require('child_process').exec(command);
heroku.stdout.setEncoding('utf8');
heroku.stdout.on('data', function (data) {
console.log('stdout: ' + data);
});
I did not get it to work with spawn - even though I think it may be correct.
What would be a better approach (I'm using meteor, hence the added Npm).