Use localtunnel and pass generated url to node command - node.js

Im looking to use ngrok on port 4000 and which is a command that will export a Forwarding URL. Every time this runs theres a new randomly generated URL.
I would like to pass that url http://2e1v870f.ngrok.io to a node process.env variable, rather then hard-coding it evey time.
For example in bash:
ngrok http 4000 | <process/define_something> | FORWARDING={something} node index.js
Plus these are in two running processes I've used npm-run-all to do something like this. https://www.npmjs.com/package/npm-run-all
ngrok by #inconshreveable (Ctrl+C to quit)
Session Status online
Version 2.2.8
Region United States (us)
Web Interface http://127.0.0.1:4041
Forwarding http://2e1v870f.ngrok.io -> localhost:4000
Forwarding https://2e1v870f.ngrok.io -> localhost:4000
Connections ttl opn rt1 rt5 p50 p90
0 0 0.00 0.00 0.00 0.00

I've turned to using the node wrapper for ngrok as I couldn't access the output from bash. Here's an example start.js:
if (!process.env.ROOT_URL) {
var ngrok = require('ngrok');
var shell = require('shelljs');
ngrok.connect(3000, function(err, url) {
shell.exec('ROOT_URL=' + url + ' meteor --settings settings.json', function(code, stdout, stderr) {
console.log('Exit code:', code);
console.log('Program output:', stdout);
console.log('Program stderr:', stderr);
});
});
}

Related

curl more than 300 times slower than node-fetch?

I'm writing a script to scan the /config route on some ports on a host.
I have first written the script in node.js and am now porting it to bash to achieve less dependencies.
Why is the bash script more than 300 times slower when scanning localhost. What am I missing?
I guess there are some optimizations built in node-fetch. How can I achieve the same in bash?
node.js: 10 Ports -> 79ms
bash(0.0.0.0): 10 Ports -> 2149ms
bash(localhost): 10 Ports -> 25156ms
I found out that in bash when using 0.0.0.0 instead of localhost, it is only 27 times slower, but still... (In node.js, using 0.0.0.0 does not make a significant difference.)
node.js (IFFE omitted for readability)
import fetch from 'node-fetch';
for (let port = portFrom; port <= portTo; port++) {
try {
const res = await fetch("http://localhost" + port + '/config');
const json = await res.json();
console.log(json);
} catch {/*no-op*/}
}
bash
for ((port=$port_from; port<=$port_to; port++))
do
json="$(curl -s http://localhost:$port/config)"
echo "$json"
done

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.

Open up terminal/shell on remote server via tcp request

I have this:
const http = require('http');
const cp = require('child_process');
const server = http.createServer((req,res) => {
const bash = cp.spawn('bash');
req.pipe(bash.stdin, {end:false);
bash.stdout.pipe(res);
bash.stderr.pipe(res);
});
server.listen('4004');
when I hit the server with:
curl localhost:4004
and I type bash commands, nothing gets outputed to my console, anybody know why?
Note: To address security I plan to run this in a docker container, use https/ssl, and implement authentication (any recommendations on auth schemes lmk).
More importantly, I am looking for shell prompts to appear ... apparently bash by itself doesn't open up a shell/prompt?
It is possible to do this "over the web" so to speak. However, your approach will not work, because you are mixing paradigms (batch vs. interactive), and you are missing large chunks of setup that's needed to run terminal applications.
Normally I would show you how to program this, however, that's really involved. Have a look at:
https://github.com/chjj/tty.js
and,
https://github.com/xtermjs/xterm.js
as starting points to create your solution.
Both are usable directly from node.js to serve up terminal applications over HTTP.
This is a partial answer, but I started a bounty because I am looking for something better. I was able to create something rudimentary with TCP like so:
const net = require('net'); // !use net package not http
const cp = require('child_process');
const server = net.createServer(s => {
const bash = cp.spawn('bash');
s.pipe(bash.stdin, {end:false});
bash.stdout.pipe(s);
bash.stderr.pipe(s);
});
server.listen('4004');
not sure why it won't work with HTTP though. I connect to it using netcat:
nc localhost 4004
but this isn't opening a terminal, just a bash process. the experience is not ideal, as described here:
https://unix.stackexchange.com/questions/519364/bash-shell-modes-how-to-pipe-request-to-shell-on-remote-server
however I am looking to replicate the shell experience you have when you do something like:
docker exec -ti <container> /bin/bash
when I run my script it "works", but I don't get any shell prompts or anything like that. (One way to solve this might be with ssh, but I am trying to figure out a different way).
You can connect to an http server with telnet. It depends on how you're starting the http server. Here's an example
Start an http server with the npm package http-server
npm install -g http-server
cd ~/ <Any directory>
http-server
Now seperately start a telnet session
telnet localhost 8080
OR
nc localhost 8080
And then type something like GET /
Use the telnet client instead of nc
Check this: https://www.the-art-of-web.com/system/telnet-http11/
Update: Running an ssh server over nodejs. It allows you to run an ssh server
I found this at https://github.com/mscdex/ssh2
var fs = require('fs');
var crypto = require('crypto');
var inspect = require('util').inspect;
var ssh2 = require('ssh2');
var utils = ssh2.utils;
var allowedUser = Buffer.from('foo');
var allowedPassword = Buffer.from('bar');
var allowedPubKey = utils.parseKey(fs.readFileSync('foo.pub'));
new ssh2.Server({
hostKeys: [fs.readFileSync('host.key')]
}, function(client) {
console.log('Client connected!');
client.on('authentication', function(ctx) {
var user = Buffer.from(ctx.username);
if (user.length !== allowedUser.length
|| !crypto.timingSafeEqual(user, allowedUser)) {
return ctx.reject();
}
switch (ctx.method) {
case 'password':
var password = Buffer.from(ctx.password);
if (password.length !== allowedPassword.length
|| !crypto.timingSafeEqual(password, allowedPassword)) {
return ctx.reject();
}
break;
case 'publickey':
var allowedPubSSHKey = allowedPubKey.getPublicSSH();
if (ctx.key.algo !== allowedPubKey.type
|| ctx.key.data.length !== allowedPubSSHKey.length
|| !crypto.timingSafeEqual(ctx.key.data, allowedPubSSHKey)
|| (ctx.signature && !allowedPubKey.verify(ctx.blob, ctx.signature))) {
return ctx.reject();
}
break;
default:
return ctx.reject();
}
ctx.accept();
}).on('ready', function() {
console.log('Client authenticated!');
client.on('session', function(accept, reject) {
var session = accept();
session.once('exec', function(accept, reject, info) {
console.log('Client wants to execute: ' + inspect(info.command));
var stream = accept();
stream.stderr.write('Oh no, the dreaded errors!\n');
stream.write('Just kidding about the errors!\n');
stream.exit(0);
stream.end();
});
});
}).on('end', function() {
console.log('Client disconnected');
});
}).listen(0, '127.0.0.1', function() {
console.log('Listening on port ' + this.address().port);
});
Your approaches are quite mixed, nonetheless, when ever you finally connect to the remote server do not use 'bash' as a method to start the connection, BASH is just born again shell with other commands & stuff in it,
Rather use some of the following program, command-line names: i.e :
~ $ 'gnome-terminal'
~ $ 'xterm'
there you will now be referencing a true program in the system, even kernel level C code has its own recognition of these, if not changed.

Bluemix Node js app push Start unsuccessful

I am using watson conversation service on node js application.
while trying to push application to bluemix. (through command prompt)
After uploading all the files..
0 of 1 instance running, 1 starting
0 of 1 instance running, 1 starting
0 of 1 instance running, 1 starting
0 of 1 instance running, 1 starting
0 of 1 instance running, 1 crashed
FAILED
Start unsuccessful
Kindly help what's the issue..
command prompt
'My coding
var watson=require('watson-developer-cloud');
var conversation =watson.conversation({
url: 'https://gateway.watsonplatform.net/conversation/api',
username:' ',
password:' ',
version:'v1',
version_date:'2017-06-20'
});
var context={};
context.hour=-1;
function prompt(question,callback){
var stdin=process.stdin,
stdout=process.stdout;
stdin.resume();
stdout.write(question);
stdin.once('data',function(data){
callback(data.toString().trim());
});
}
function tConvert(time){
time=time.toString().match(/^([01]\d2[0-3])(:)([0-5]\d)(:[0-5]\d)?$/)||[time];
if(time.length>1){
time=time.slice(1);
time[5]=+time[0]<12?'AM':'PM';
time[0]=+time[0]%12||12;
}
return time.join('');
}
function convMessage(message){
var d=new Date();
var n=tConvert(d.getHours() + ':' + d.getMinutes() + ':00');
context.hour=(n.split(':'))[0];
context.minute=(n.split(':'))[1];
conversation.message({
workspace_id:'09ee7558-0d3e-4af3-8429-14e60be348d7',
input:{'text':message},
context:context
},function(err,response){
if(err){
console.log('error:',err);
}else {
console.log('Watson: ' + response.output.text[0])
prompt('You: ', function(input){
convMessage(input);
});
context=response.context;
}
});
}
convMessage('Hi.');
Your program might run locally. However, to run as Bluemix Node.js app on Cloud Foundry it needs to meet certain requirement. A web app is expected and the health manager checks on the expected port whether your app is alive. If the app cannot be detected it is considered "dead" and the logs will show it as "crashed".
Take a look at the sample app "Conversation Simple" and the main file "server.js" for how the port info is handled.
As an alternative for your code, you could consider setting a health check type of process. It would indicate Bluemix / Cloud Foundry that you don't deploy a regular (Web) app, but something running in the background or executed once.

My node.js doesn't respond without reporting any errors

I wrote http server in node.js, which is a like reverse-proxy for Amazon S3, and deployed it in production environment with Node's Cluster module, nodejitsu/forever and Nginx.
It worked very good but one day (today) it stopped responding. I checked node's console.log() outputs and processes but I found nothing strange.
Gist of my code is like:
http.createServer(function(webReq, webRes) {
http.get(s3Options, function(s3Res) {
if (s3Res.statusCode == 200) {
s3Res.on('end', function() {
webRes.end('Found data on S3');
});
} else {
webRes.end('No data on S3');
}
}).on('error', function(e) {
console.log('problem with s3Req: ' + e.message);
});
}).listen(1337);
Node processes are all alive (2 child workers) without forever's restarting:
# ps x | grep node
31436 ? Ss 3:43 node /usr/bin/forever -l LOG -o OUT -e ERR -a start server.js
31437 ? Sl 0:10 node /root/server.js
31440 ? Sl 1:17 /usr/bin/nodejs /root/server.js
31441 ? Sl 1:17 /usr/bin/nodejs /root/server.js
Then I doubted too-many-connection stuffs and did "lsof -p PID | wc -l" but the counts were all in good conditions - only dozens.
My node.js experience is only a week or so. Did I miss something important?

Resources