node.js & rabbitmq - publish a message using cli - node.js

So I'm trying to do the following from the command line:
> somecommand "Hello world"
will cause my listening node.js application (RabbitMQ) to receive "hello world" and print it to stdout...
Here's my node.js application (app.js) that's listening for "newTrend" events:
var context = require('rabbit.js').createContext();
var sub=null;
context.on('ready', function() {
sub = context.socket('SUB');
sub.setEncoding('utf8');
console.log("Connected to rabbitmq");
sub.on('newTrend',function(data){
console.log(data);
});
});
Start using:
nodejs app.js
But how to send it "newTrend" events via RabbitMQ using just the command line? I have rabbitmqadmin installed.

Is there something stopping you from writing a Node.JS program to act as the client?
#!/usr/bin/env node
var context = require('rabbit.js').createContext();
...
Either that or see if rmqcat will do what you need: https://github.com/squaremo/rmqcat

Related

Using node.js, I cannot get the stdout from a macos app until the process finishes

I've created a helper app with Xcode. It's a command line app that keeps running using RunLoop (because it will do Bluetooth things in the background).
I want to spawn this app using node.js and read its output. I've sucessufully done this with other applications using the spawn method. However, with this MacOS app nothing is visible until the app finishes.
My node.js code:
const { spawn } = require('node:child_process')
const child = spawn(PROCESS)
child.stdout.on('data', data => {
console.log(data.toString());
})
My Swift code (helper app):
import Foundation
var shouldKeepRunning = true
print("app started")
let controller = Controller()
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + .seconds(10)) {
shouldKeepRunning = false
}
while shouldKeepRunning == true && RunLoop.current.run(mode: RunLoop.Mode.default, before: Date.distantFuture) {
}
In node.js app started is only printed after 10 seconds, when the app finishes. When running the app using Terminal, I see app started immediately.
Does anyone know why this happens and how it can be solved?
Thanks!
This question is actually the same: swift "print" doesn't appear in STDOut but 3rd party c library logs do when running in docker on ECS but instead of node.js Docker is not logging the output.
I fixed it by adding the following to the top of my code:
setbuf(stdout, nil)
This will make print() write to stdout directly without waiting for some buffer to be full first.

Bash: No such file or directory when running shell comands with node.js spawn on linux

I wrote the following web server in node.js using express and hbs that can run shell files, but I keep getting the following error when I type this url into a web browser
linux username here is replaced with my linux username
http://127.0.0.1:3000/run?file="/home/linux username here/nasServer/GameServers/minecraft/1.16.2 server/run.sh"
stderr: bash: <path to .sh file here>: No such file or directory.
child process exited with code 127.
Contents of nodejs file:
const express = require('express')
const hbs = require('hbs')
const app = express()
const port = 3000
// Set up handlebars engine
app.set('view engine', 'hbs')
app.get('/run', (req, res) => {
const { spawn } = require('child_process');
let callback = ""
ls = spawn("bash", [req.query.file])
ls.stdout.on('data', function (data) {
console.log('stdout: ' + data.toString());
});
ls.stderr.on('data', function (data) {
console.log('stderr: ' + data.toString());
});
ls.on('close', function (code) {
console.log('child process exited with code ' + code.toString());
});
res.send({
out: callback
})
})
app.listen(port, () => {
console.log(`App listening on port ${port}`)
})
This is the contents of run.sh:
#!/bin/bash
java -Xmx5G -jar /home/linux username here/nasServer/GameServers/minecraft/1.16.2\ server/spigot-1.16.2.jar nogui
Hello, I don't know why I decided to try to fix this since I know just a little bit about coding (only scripting actually lol) and nothing about nodeJs but I got fun testing your app with the help of my friend google !
First of all, since i dont have your minecraft files (jar etc.), I just writed a little script "test.sh", that will just echo your command:
❯ cat test.sh
#!/bin/bash
echo "java -Xmx5G -jar /home/linux username here/nasServer/GameServers/minecraft/1.16.2\ server/spigot-1.16.2.jar nogui"
second of all after like 2hours of training, modifying, testing by adding/deleting stuff into your app to understand how it works, I finally came back to your original app when i find that it works with this:
http://localhost:3000/run?file=test.sh
here is the browser output (as expected):
{"out":""}
here is the console output:
❯ node 71963151.js
App listening on port 3000
stdout: java -Xmx5G -jar /home/linux username here/nasServer/GameServers/minecraft/1.16.2\ server/spigot-1.16.2.jar nogui
child process exited with code 0
The fact is that when we remove the double quotes from the query it works fine, but when I add back the double quotes like you are trying to do:
http://localhost:3000/run?file="test.sh"
here is the browser output (as expected):
{"out":""}
but here is the consol output:
❯ node 71963151.js
App listening on port 3000
stderr: bash: "test.sh": No such file or directory
child process exited with code 127
So, to conclude, instead of trying to run this on your browser:
http://127.0.0.1:3000/run?file="/home/<linux username here>/nasServer/GameServers/minecraft/<1.16.2 server>/run.sh"
try this:
http://127.0.0.1:3000/run?file=/home/<linux username here>/nasServer/GameServers/minecraft/<1.16.2 server>/run.sh
A lot of documentation helped me out to understand the way nodejs works, I loved doing this :p thank you, You made me want to code!
bguess.
I fixed the problem by replacing all the windows line endings with Unix line endings, then bash found the .sh file.

How to interact with multiple console windows?

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.

Dynamic arguments for ZINTERSTORE with node_redis

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) {
...
});

Automate Jasmine-Node and express.js

I created a simple Webapp using express.js and want to test it with jasmine-node. Works fine so far but my problem is that I have to start the server manually every time before I can run my tests.
Could you help me on how to write a spec-helper that runs the server (with another port then my development one) just for the tests and then kills it afterwards?
This is what I do:
I have a server.js file inside the root of my node project that sets up the node application server (with express) and exports 2 methods:
exports.start = function( config, readyCallback ) {
if(!this.server) {
this.server = app.listen( config.port, function() {
console.log('Server running on port %d in %s mode', config.port, app.settings.env);
// callback to call when the server is ready
if(readyCallback) {
readyCallback();
}
});
}
};
exports.close = function() {
this.server.close();
};
The app.js file will be simple at this point:
var server = require('./server');
server.start( { port: 8000 } );
So the files/folder basic structure would be the following:
src
app.js
server.js
Having this separation will allow you to run the server normally:
node src/app.js
..and/or require it from a custom node script, which could be a node script (or a jake/grunt/whatever task) that executes your tests like this:
/** my-test-task.js */
// util that spawns a child process
var spawn = require('child_process').spawn;
// reference to our node application server
var server = require('./path/to/server.js');
// starts the server
server.start( { port: 8000 }, function() {
// on server ready launch the jasmine-node process with your test file
var jasmineNode = spawn('jasmine-node', [ '.path/to/test/file.js' ]);
// logs process stdout/stderr to the console
function logToConsole(data) {
console.log(String(data));
}
jasmineNode.stdout.on('data', logToConsole);
jasmineNode.stderr.on('data', logToConsole);
jasmineNode.on('exit', function(exitCode) {
// when jasmine-node is done, shuts down the application server
server.close();
}
});
I use Mocha - which is damn similar - but the same principle should apply: you could try requireing your app.js file in a 'beforeEach' hook inside the main describe. That should fire it up for you.
Assuming you use some code that invokes app.listen() in server.js, don't require the file on each run but only once and then have two functions like
startServer = -> app.listen(3000)
stopServer = -> app.close()
Then you can use these in beforeEach and afterEach
If you want then to go one step further in automating your testing while you develop, you can go to your terminal line and execute
jasmine-node . --autotest
Jasmine then will stay listening to every file inside your project and whenever you make changes to one it will tell if that piece of your code breaks any of your tests ;)

Resources