How to run a CMD on web assembly without a server - javascript

I wanted to create a web assembly program that would enable me to execute bash commands and get output without contacting a server.
I created some rust code and did a wasm-pack compiling but it gives this error
RuntimeError: unreachable executed
My code
use std::process::Output;
use wasm_bindgen::prelude::*;
use std::process::Command;
#[wasm_bindgen]
pub fn exec(code:&str)->Vec<u8>{
let output = if cfg!(target_os = "windows") {
Command::new("cmd")
.args(["/C", code])
.output()
.expect("failed to execute process")
} else {
Command::new("sh")
.arg("-c")
.arg(code)
.output()
.expect("failed to execute process")
};
output.stdout
}
^^lib.rs (used wasm-pack)
RuntimeError: unreachable executed

Related

How to save and execute script as function in MongoDB?

In each deploy of our system, we have some mongodb scripts that we run in NoSQL Manager via Shell.
By running the scripts remotely, they have performance issues when we need to use cursors.
Is it possible to save a script as a function in mongo and run it calling via shell?
I managed to save it as a function, but when I run it, an error similar to the following error occurs:
// Command #1 1:1 0,007 s
uncaught exception: SyntaxError: unexpected token: identifier :
DB.prototype.loadServerScripts/<#src/mongo/shell/db.js:1310:29
DBQuery.prototype.forEach#src/mongo/shell/query.js:512:9
DB.prototype.loadServerScripts#src/mongo/shell/db.js:1308:5
#(shell):1:1
// Command #2 2:1 0,003 s
uncaught exception: ReferenceError: findProductFunctionTest is not defined :
#(shell):1:1
enter image description here
Performed step by step:
Save the script as a function:
db.system.js.insertOne(
{
_id: "findProductFunctionTest",
value : function()
{
try
{
var produto = db.Produto.findOne({Nome: /como treinar/i});
if (produto == null)
throw new Error("Produto não encontrado!");
return produto.Nome;
}
catch (ex)
{
printjson("Erro ao processar! Exceção: " + ex.message);
}
}
}
);
Load script from local server, via shell command:
db.loadServerScripts();
Call function, via shell command:
findProductFunctionTest();

Running stateful commands in PowerShell through Node.js

Context: I have a javascript file that activates PowerShell's native SpeechSynthesizer module. The script receives a message and passes that through to PowerShell, where it is rendered as speech.
Problem: there is horrible latency (~5sec) between execution and response. This is because the script creates an entirely new PowerShell session and SpeechSynthesizer object with every execution.
Objective: I want to change the script so that a single PowerShell session and SpeechSynthesizer object is persisted and used across multiple sessions. I believe this will eradicate the latency completely.
Limiting Factor: this modification requires making the PowerShell execution stateful. Currently, I don't know how to incorporate stateful commands for the PowerShell in a javascript file.
Code:
const path = require('path');
const Max = require('max-api');
const { exec } = require('child_process');
// This will be printed directly to the Max console
Max.post(`Loaded the ${path.basename(__filename)} script`);
const execCommand = command => {
// Max.post(`Running command: ${command}`);
exec(command, {'shell':'powershell.exe'}, (err, stdout, stderr) => {
if (err) {
// node couldn't execute the command
Max.error(stderr);
Max.error(err);
return;
}
// the *entire* stdout and stderr (buffered)
Max.outletBang()
});
}
// Use the 'outlet' function to send messages out of node.script's outlet
Max.addHandler("speak", (msg) => {
let add = 'Add-Type -AssemblyName System.speech'
let create = '\$speak = New-Object System.Speech.Synthesis.SpeechSynthesizer'
let speak = `\$speak.Speak(\'${msg}\')`
let command = ([add,create,speak]).join('; ')
execCommand(command)
});
Objective, Re-stated: I want to move the add and create commands to a 'create' handler which will only be ran once. The speak command will be run an arbitrary amount of times afterward.
Attempted Solution: I've found one package (https://github.com/bitsofinfo/powershell-command-executor) that supposedly supports stateful PowerShell commands, but it's very complicated. Also, the author mentions a risk of command injection and other insecurities, of which I have no knowledge of.
Any and all suggestions are welcome. Thanks!

Nodejs subprocess not waiting on finish while logging output

Well I'm trying to get a nodejs process to launch a python script. - And this python script logs while it is busy - as it logs I wish to display this in the console window used by the nodejs process.
The python script is really trivial
from time import sleep
if __name__ == '__main__':
print('small text testing')
sleep(10)
raise Exception('test')
prints 'small text testing', sleeps for 10 seconds(!) and then raises an exception which is uncaught and thus finishes the script.
In node I tried to get this to work with:
const { exec } = require('child_process');
const exec_str = '. BackgroundServer/BackgroundServer/bin/activate && python BackgroundServer/main.py 1';
const child = exec(exec_str,
{
// detachment and ignored stdin are the key here:
detached: true,
stdio: [ 'ignore', 1, 2 ]
});
child.unref();
child.stdout.on('data', function(data) {
console.log(data.toString());
});
child.stderr.on('data', function(data) {
console.error(data.toString());
});
However this "fails" in the sense that it will only print after the python process has finished running.
Now I know it is possible to run a script through spawn but that would require me to create a temporary script, give that script permissions and then execute that script. Not optimal either.
Not knowing much about javascript or node.js I am pretty sure your problem is due to the fact that Python buffers its output if it is run as subprocess.
To fix this issue, you can do either manually ensure that Python flushes the buffer by adding calls to sys.stdout.flush() as
import sys
from time import sleep
if __name__ == '__main__':
print('small text testing')
sys.stdout.flush()
sleep(10)
raise Exception('test')
or you can force Python to not be buffered also when used as a subprocess by calling the intrepreter with the -u argument, thus modifying exec_str to
const exec_str = '. BackgroundServer/BackgroundServer/bin/activate && \
python -u BackgroundServer/main.py 1';
The first solution will always flush the output, if that is desirable and you use it in another place, without you having to think about the -u option. However, I would still recommend the second approach as it still allows the code to run buffered (which sometimes can be what you want) and also when working with longer scripts you may have to insert quite a number of manual sys.stdout.flush() calls otherwise.
Also, as a sidenote, there is no need for raising an exception in the Python script. It will end anyway, when it reaches its last line.

How to make nodejs to talk with golang

I am creating a web app in node.js and golang. I need to connect nodejs with golang code which talks to mongodb and returns data to node program. is there any way to connect so? I tried to use gonode API.This is my code using gonode API.
my node.js file contains below code:
var Go = require('gonode').Go;
var options = {
path : 'gofile.go',
initAtOnce : true,
}
var go = new Go(options,function(err){
if(err) throw err;
go.execute({commandText: 'Hello world from gonode!'}, function(result, response) {
if(result.ok) {
console.log('Go responded: ' + response.responseText);
}
});
go.close();
}); `
And this is the code in my gofile.go file:
package main
import(
gonode "github.com/jgranstrom/gonodepkg"
json "github.com/jgranstrom/go-simplejson"
)
func main(){
gonode.Start(process)
}
func process(cmd *json.Json) (response *json.Json) {
response, m := json.MakeMap()
if(cmd.Get("commandText").MustString() == "Hello") {
m["responseText"] = "Well hello there!"
} else {
m["responseText"] = "What?"
}
return
}
This is the error am getting while running as node node.js in terminal
events.js:72
throw er; // Unhandled 'error' event
^
Error: write EPIPE
at errnoException (net.js:905:11)
at Object.afterWrite (net.js:721:19)
Golang from 1.5, you can build go to shared object binary file (*.so). This allows you to connect your go compiled library to be called by nodejs, python, ruby, java etc.
Here is a guide you could refer to: https://medium.com/learning-the-go-programming-language/calling-go-functions-from-other-languages-4c7d8bcc69bf
thanks for the response. I got a solution for this. I made 2 different servers. One for NodeJS and another for Golang. I am calling golang uri in Node server and getting data from golang server.
Based on a very cursive check of the gonode source code, the module seems to spawn go code as a child process and communicate through stdin/-out. EPIPE error means that the other end closed the stream. Based on this it might be that your go process exits prematurely.
You could try to debug the problem by modifying Command.prototype.execute in gonode/lib/command.js to print out the JSON that's sent to the go process. Then you can debug the go program by running it directly and giving it the same input via stdin.

Listening for outside events. Bash to NodeJS bridge

Being inside of a NodeJS process, how can I listen for events from bash?
For example
NodeJS side
obj.on("something", function (data) {
console.log(data);
});
Bash side
$ do-something 'Hello World'
Then in the NodeJS stdout will appear "Hello World" message.
How can I do this?
I guess it's related to signal events.
The problem with using signals is that you can't pass arguments and most of them are reserved for system use already (I think SIGUSR2 is really the only safe one for node since SIGUSR1 starts the debugger and those are the only two that are supposed to be for user-defined conditions).
Instead, the best way that I've found to do this is by using UNIX sockets; they're designed for inter process communication.
The easiest way to setup a UNIX socket in node is by setting up a standard net server with net.createServer() and then simply passing a file path to server.listen() to create the socket at the path you specified. Note: It's important that a file at that path doesn't exist, otherwise you'll get a EADDRINUSE error.
Something like this:
var net = require('net');
var server = net.createServer(function(connection) {
connection.on('data', function(data) {
// data is a Buffer, so we'll .toString() it for this example
console.log(data.toString());
});
});
// This creates a UNIX socket in the current directory named "nodejs_bridge.sock"
server.listen('nodejs_bridge.sock');
// Make sure we close the server when the process exits so the file it created is removed
process.on('exit', function() {
server.close();
});
// Call process.exit() explicitly on ctl-c so that we actually get that event
process.on('SIGINT', function() {
process.exit();
});
// Resume stdin so that we don't just exit immediately
process.stdin.resume();
Then, to actually send something to that socket in bash, you can pipe to nc like this:
echo "Hello World" | nc -U nodejs_bridge.sock
What about using FIFOs?
NodeJS code:
process.stdin.on('readable', function() {
var chunk = process.stdin.read();
if (chunk !== null) {
process.stdout.write('data: ' + chunk);
}
});
NodeJS startup (the 3>/tmp/... is a trick to keep FIFO open):
mkfifo /tmp/nodeJsProcess.fifo
node myProgram.js </tmp/nodeJsProcess.fifo 3>/tmp/nodeJsProcess.fifo
Bash linkage:
echo Hello >/tmp/nodeJsProcess.fifo
The signals described in the page that you've linked are used to send some specific "command" to processes. This is called "Inter Process Communication". You can see here a first definition of IPC.
You can instruct you node.js code to react to a specific signal, as in this example:
// Start reading from stdin so we don't exit.
process.stdin.resume();
process.on('SIGUSR1', function() {
console.log('Got SIGUSR1. Here you can do something.');
});
Please note that the signal is sent to the process, and not to a specific object in the code.
If you need to communicate in a more specific way to the node.js daemon you can listen on another port too, and use it to receive (and eventually send) control commands.

Categories