It won't accept command line after first run - node.js

I ran my first server and seems fine except that it won't stop running. I cannot even type anything else in the command line. I will appreciate any help
Here is the code I ran
const http = require('http');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) =>
{
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('In the name of Allah, the Most Gracious, the Most Merciful.');
});
server.listen(port, hostname, () =>
{
console.log(`Server running at http://${hostname}:${port}/`);
});
But the problem is not the code, rather how to get back to this command line
$papus#QuantumOne MINGW64 /c/Projects/firstServer so that I can start retyping again on the command line without closing everything down and restart the whole process.
right now it gets stuck on Server running at http://127.0.0.1:3000 forever

Because it is a server and it is not supposed to stop after a time.
You can shut down by pressing ctrl + c
Or you can program a certain route that will kill it programatically (i did not say it should be done)
If you want to continue using the same terminal you can run the server in background (on unix systems it is done by adding & at the end of the start command)
You can also look at process manager for nodejs server like pm2

Related

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.

Im trying to test out node.js

so I just downloaded and installed node/npm and attempted to run a test with the following code.
const http = require(‘http’);
const hostname = ‘127.0.0.1’;
const port = 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader(‘Content-Type’, ‘text/plain’);
res.end(‘Hello from NodeJS\n’);
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
but the output gives me plenty of error messages (an identifier cant go after this identifier, this cant go here, unexpected, etc) I see a couple of things that could be wrong, but I'm new to this.
I would direct you to https://nodejs.dev/learn
You need to require the http module by doing const http = require('http');
Also your quotation marks are improper they must be single quotes, double quotes, or backticks. They cannot be whatever unicode character you have in there.
You are using some strange characters, this: ’
Try to use " or ' in module import, setHeader, ...

My express server is not exiting with both ctrl + c and process.exit(1)

I am getting an error message:
listen EADDRINUSE: address already in use :::3000.
When I tried after removing the server starting code(i.e app.listen part) nothing is happening
const path = require('path')
const express = require('express')
//var publicPathDirectory = path.join(__dirname,"../public")
const app = express()
app.listen(3000,()=>{
console.log('server started')
})
process.on('SIGINT', function() {
console.log( "\nGracefully shutting down from SIGINT (Ctrl-C)" );
// some other closing procedures go here
process.exit(1);
});
I've had this happen to me before, where even though I quit the node server with CTRL+C, it still is hogging port 3000. You can kill node with:
pkill -f node
Potentially related to Node.js Port 3000 already in use but it actually isn't?
Use number 1 inside exit only when you have an exit with failure. To force exit do not use number inside exit().
process.exit()
Please take a look at here. May be you can understand. link

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.

How to debug Node.JS child forked process?

I'm trying to debug the child Node.JS process created using:
var child = require('child_process');
child .fork(__dirname + '/task.js');
The problem is that when running in IntelliJ/WebStorm both parent and child process start on the same port.
debugger listening on port 40893
debugger listening on port 40893
So it only debugs the parent process.
Is there any way to set IntelliJ to debug the child process or force it to start on a different port so I can connect it in Remote debug?
Yes. You have to spawn your process in a new port. There is a workaround to debug with clusters, in the same way you can do:
Start your app with the --debug command and then:
var child = require('child_process');
var debug = typeof v8debug === 'object';
if (debug) {
//Set an unused port number.
process.execArgv.push('--debug=' + (40894));
}
child.fork(__dirname + '/task.js');
debugger listening on port 40894
It is a known bug in node.js that has been recently fixed (although not backported to v0.10).
See this issue for more details: https://github.com/joyent/node/issues/5318
There is a workaround where you alter the command-line for each worker process, although the API was not meant to be used this way (the workaround might stop working in the future). Here is the source code from the github issue:
var cluster = require('cluster');
var http = require('http');
if (cluster.isMaster) {
var debug = process.execArgv.indexOf('--debug') !== -1;
cluster.setupMaster({
execArgv: process.execArgv.filter(function(s) { return s !== '--debug' })
});
for (var i = 0; i < 2; ++i) {
if (debug) cluster.settings.execArgv.push('--debug=' + (5859 + i));
cluster.fork();
if (debug) cluster.settings.execArgv.pop();
}
}
else {
var server = http.createServer(function(req, res) {
res.end('OK');
});
server.listen(8000);
}
Quick simple fix ( where using chrome://inspect/#devices )
var child = require('child_process');
child.fork(__dirname + '/task.js',[],{execArgv:['--inspect-brk']});
Then run your app without any --inspect-brk and the main process won't debug but the forked process will and no conflicts.
To stop a fork conflicting when debugging the main process ;
child.fork(__dirname + '/task.js',[],{execArgv:['--inspect=xxxx']});
where xxxx is some port not being used for debugging the main process. Though I haven't managed to easily connect to both at the same time in the debugger even though it reports as listening.
I find that setting the 'execArgv' attribute in the fork func will work:
const child = fork('start.js', [], {
cwd: startPath,
silent: true,
execArgv: ['--inspect=10245'] });
if "process.execArgv" doenst work you have to try:
if (debug) {
process.argv.push('--debug=' + (40894));
}
this worked for me..
There are one more modern way to debug child (or any) process with Chrome DevTools.
Start your app with arg
--inspect
like below:
node --debug=9200 --inspect app/main.js
You will see the message with URL for each child process:
Debugger listening on port 9200.
Warning: This is an experimental feature and could change at any time.
To start debugging, open the following URL in Chrome:
chrome-devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:9200/207f2ab6-5700-4fc5-b6d3-c49a4b34a311
Debugger listening on port 9201.
Warning: This is an experimental feature and could change at any time.
To start debugging, open the following URL in Chrome:
chrome-devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:9201/97be3351-2ea1-4541-b744-e720188bacfa
Debugger listening on port 9202.
Warning: This is an experimental feature and could change at any time.
To start debugging, open the following URL in Chrome:
chrome-devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:9202/8eb8384a-7167-40e9-911a-5a8b902bb8c9
If you want to debug the remote processes, just change the address 127.0.0.1 to your own.

Resources