NodeJS returns ETIMEDOUT with snmpwalk calling - snmp

Hi I have a snmpwalk command that takes at least 50 seconds to complete.
I used childprocess to run and wait for its response but I always get this error:
Error: spawnSync /bin/sh ETIMEDOUT
Here is the code:
const command = `snmpwalk -v2c -On -c ABCDEF123 ${arg_ip} ${arg_oid}`;
let output = "";
try {
output = childProcess.execSync(command, {timeout: 25000, maxBuffer: 1024 * 1024 * 2});
} catch (e) {
console.log(command, e.toString());
throw new AppError({message: 'Error: Command failed'});
}
Is there any suggestion for handle such a long command?
I tried some 3rd lib but nothing helps.

From what I have understood, you are passing 25000ms that is equivalent to 25 seconds, setting it to 50000ms might work. Something like
const command = `snmpwalk -v2c -On -c ABCDEF123 ${arg_ip} ${arg_oid}`;
let output = "";
try {
output = childProcess.execSync(command, {timeout: 51000, maxBuffer: 1024 * 1024 * 2});
} catch (e) {
console.log(command, e.toString());
throw new AppError({message: 'Error: Command failed'});
}
(Extra 1 second margin)

Related

Running bash script from Deno

Let’s say I’ve got this super useful and advanced bash script:
#!/usr/bin/env bash
echo What is your name?
read name
echo What is your age?
read age
When I try to run it from Deno with a simple script like this:
const process = Deno.run({
cmd: [`./bash.sh`],
stdin: "piped",
stdout: "piped",
});
const decoder = new TextDecoder();
const output = await process.output()
const parsed = decoder.decode(output);
console.log(parsed);
It returns nothing, but if I simplify the Deno script to the first line of the bash script it returns the output just fine
const process = Deno.run({
cmd: [`echo`, `What is your name?`],
stdin: "piped",
stdout: "piped",
});
const decoder = new TextDecoder();
const output = await process.output()
const parsed = decoder.decode(output);
console.log(parsed);
Why is this? I’d assume since the start of the bash file and the single line command both start with echo it would return the same result twice
Version 1.5 of deno added the prompt function which allows you to completely remove the need for shelling out to a different program and handling inter-process communication via stdin/stdout.
let name: string | null = null;
let age: string | null = null;
while (name === null) {
name = prompt("What is your name?");
}
while (age === null) {
age = prompt("What is your age?");
}
console.log(`you are ${name}, ${age}yo`);
Your code is telling Deno to set up the subprocess to expect piped stdin -- but never providing it any content on stdin! Consequently, it hangs in the very first read.
If we take that out (letting stdin be passed through from the parent process), and do in fact answer the two prompts on the parent process's stdin, everything works perfectly:
deno run --allow-run run-bash.js <<'EOF'
A Nony Mouse
3
EOF
...with run-bash.js containing:
const process = Deno.run({
cmd: [`./bash.sh`],
stdout: "piped",
});
const decoder = new TextDecoder();
const output = await process.output()
const parsed = decoder.decode(output);
console.log(parsed);
...and your bash.sh unchanged. output thus captures the two prompts (What is your name? and What is your age?), and forwards them to the javascript interpreter's stdout as-requested.
You have to call bash to call your script
( of course with --allow-run option )
like :
const process = Deno.run({
cmd: ["bash","bash.sh"],
stdin: "piped",
stdout: "piped",
});
const decoder = new TextDecoder();
const output = await process.output()
const parsed = decoder.decode(output);
console.log(parsed);

How to receive messages via wifi while running main program in ESP32?

Ive incorporated multiple features i want in a microcontroller program (ESP32 Wroom32) and needed some advice on the best way to keep the program running and receive messages while it is running.
Current code:
//includes and declarations
setup()
{
//setup up wifi, server
}
main(){
WiFiClient client = server.available();
byte new_command[40];
if (client) // If client object is created, a connection is setup
{
Serial.println("New wifi Client.");
String currentLine = ""; //Used to print messages
while (client.connected())
{
recv_byte = client.read();
new_command = read_incoming(&recv_byte, client); //Returns received command and check for format. If invalid, returns a 0 array
if (new_command[0] != 0) //Checks if message is not zero, None of valid messages start with zero
{
execute_command(new_command);
//new_command is set to zero
}
}//end of while loop
}//end of if loop
}
The downside of this is that the ESP32 waits till the command is finished executing before it is ready to receive a new message. It is desired that the ESP32 receive commands and store them, and execute it at its own pace. I am planning to change the current code to receive a messages while the code is running as follows:
main()
{
WiFiClient client = server.available();
byte new_command[40];
int command_count = 0;
byte command_array[50][40];
if (command_count != 0)
{
execute_command(command_array[0]);
//Decrement command_count
//Shift all commands in command_array by 1 row above
//Set last executed command to zero
}
}//end of main loop
def message_interrupt(int recv_byte, WiFiClient& running_client)
{
If (running_client.connected())
{
recv_byte = running_client.read();
new_command = read_incoming(&recv_byte, running_client); //Returns received command and check for format. If invalid, returns a 0 array
//add new command to command_array after last command
//increment command_count
}
}
Which interrupt do I use to receive the message and update the command_array ? https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/wifi.html Doesnt mention any receive/transmit events. I couldnt find any receive/transmit interrupt either or maybe I searched for the wrong term.

std::process::Command cannot run hdiutil on macOS (mount failed - No such file or directory) but the command works fine when run in the terminal

hdiutils, when fed a correct path to a valid file, returns error 2, no such file or directory. When I join the indices of the command array with " ", print them, copy them and run the exact string in a terminal, it works fine.
This is the function edited to contain only the relevant bits. In order to reproduce my error, you will need a disk image located at ~/Downloads/StarUML.dmg.
use std::env;
use std::fs;
use std::process::Command;
fn setup_downloads(download_name: &str) {
let downloads_path: String = {
if cfg!(unix) {
//these both yield options to unwrap
let path = env::home_dir().unwrap();
let mut downloads_path = path.to_str().unwrap().to_owned();
downloads_path += "/Downloads/";
downloads_path
} else {
"we currently only support Mac OS".to_string()
}
};
let files_in_downloads =
fs::read_dir(&downloads_path).expect("the read_dir that sets files_in_downloads broke");
let mut file_path: String = "None".to_string();
for file_name in files_in_downloads {
let file_name: String = file_name
.expect("the pre string result which sets file_name has broken")
.file_name()
.into_string()
.expect("the post string result which sets file_name has broken")
.to_owned();
if file_name.contains(&download_name) {
file_path = format!("'{}{}'", &downloads_path, &file_name);
}
}
let len = file_path.len();
if file_path[len - 4..len - 1] == "dmg".to_string() {
let mount_command = ["hdiutil", "mount"];
let output = Command::new(&mount_command[0])
.arg(&mount_command[1])
.arg(&file_path)
.output()
.expect("failed to execute mount cmd");
if output.status.success() {
println!(
"command successful, returns: {}",
String::from_utf8_lossy(&output.stderr).into_owned()
);
} else {
println!(
"command failed, returns: {}",
String::from_utf8_lossy(&output.stderr).into_owned()
);
}
}
}
fn main() {
setup_downloads(&"StarUML".to_string());
}
Split your Command into a variable and print it using the debugging formatter after you have specified the arguments:
let mut c = Command::new(&mount_command[0]);
c
.arg(&mount_command[1])
.arg(&file_path);
println!("{:?}", c);
This outputs
"hdiutil" "mount" "\'/Users/shep/Downloads/StarUML.dmg\'"
Note that Command automatically provides quoting for each argument, but you have added your own set of single quotes:
format!("'{}{}'", &downloads_path, &file_name);
// ^ ^
Remove these single quotes.

Using ctypes function in firefox ChromeWorker

I am trying to use a ChromeWorker to launch a background process, like so:
var worker = new ChromeWorker(data.url("stun-manager.js"));
worker.addEventListener('message', function(e) {
console.log(e.data);
}, false);
worker.postMessage({'cmd': 'start', 'msg': 'Hi'});
But where exactly do I declare all my ctypes and such? Interestingly, in stun-manager.js, if I have the following:
dump ("Message 1");
var {Cu} = require("chrome");
dump ("Message 2");
/*import js-ctypes */
var {ctypes} = Cu.import("resource://gre/modules/ctypes.jsm")
var stun_driver = ctypes.open("C:\\Users\\derek_000\\Documents\\Visual Studio 2012\\Projects\\stunnel507\\stunnel507\\bin\\win32\\stun_driver.dll");
const launch_stun = stun_driver.declare("launch_stun", ctypes.default_abi, ctypes.int32_t, ctypes.int32_t, ctypes.char.ptr.ptr);
let argv_t = ctypes.ArrayType(ctypes.char.ptr);
let argc = 2;
let argv = new argv_t(argc);
var conf_path = "C:\\Users\\derek_000\\Documents\\Visual Studio 2012\\Projects\\stunnel507\\stunnel507\\stunnel.conf";
argv[0] = ctypes.char.array()(conf_path);
argv[1] = ctypes.char.array()(conf_path);
self.addEventListener('message', function (e) {
var data = e.data;
switch (data.cmd) {
case 'start':
self.postMessage("Value of launch_stun " + self.launch_stun);
self.postMessage('WORKER STARTED: ' + data.msg);
self.postMessage("debug" + self.argv_t);
self.postMessage("test: " + self.argv_t);
self.postMessage(self.argv[0].readString());
launch_stun(argc, argv );
break;
case 'stop':
self.postMessage('WORKER STOPPED: ' + data.msg +
'. (buttons will no longer work)');
self.close(); // Terminates the worker.
break;
default:
self.postMessage('Unknown command: ' + data.msg);
};
}, false);
"Message 2" is never printed to the screen, and "Message 1" is. It's almost like I am getting a silent fail from one of those other lines, but this is the exact code I have used to launch this from main.js, before I tried to use ChromeWorker.
Any ideas? I guess it seems like stun-manager.js is failing silently, and on a related note, I can't even find it in the Browser Toolbox to debug, but I do see my main.js file there.
Two simple examples of using ChromeWorker (and also an advancement of ChromeWorker, PromiseWorker, which rocks by the way):
GitHub :: Noitidart / ChromeWorker
GitHub :: Noitidart / PromiseWorker
You can't do var {ctypes} = Cu.import("resource://gre/modules/ctypes.jsm") in the worker (your worker is stun-manager.js). That's causing an error, remove that. You can just use ctypes without importing anything, ChromeWorker's autoamtically have it. That should fix it.
I'll look more over your code, but definitely check out the ChromeWorker repo it will help a lot, its a very basic messaging thing between worker and main.

Node.js Shell Script And Arguments

I need to execute a bash script in node.js. Basically, the script will create user account on the system. I came across this example which gives me an idea how to go about it. However, the script itself needs arguments like the username, the password and the real name of the user. I still can't figure out how to pass those arguments to the script doing something like this:
var commands = data.toString().split('\n').join(' && ');
Does anyone have an idea how I can pass those arguments and execute the bash script within node.js over an ssh connection.
thanks
See the documentation here. It is very specific on how to pass command line arguments. Note that you can use exec or spawn. spawn has a specific argument for command line arguments, while with exec you would just pass the arguments as part of the command string to execute.
Directly from the documentation, with explanation comments inline
var util = require('util'),
spawn = require('child_process').spawn,
ls = spawn('ls', ['-lh', '/usr']); // the second arg is the command
// options
ls.stdout.on('data', function (data) { // register one or more handlers
console.log('stdout: ' + data);
});
ls.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
ls.on('exit', function (code) {
console.log('child process exited with code ' + code);
});
Whereas with exec
var util = require('util'),
exec = require('child_process').exec,
child;
child = exec('cat *.js bad_file | wc -l', // command line argument directly in string
function (error, stdout, stderr) { // one easy function to capture data/errors
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if (error !== null) {
console.log('exec error: ' + error);
}
});
Finally, note that exec buffers the output. If you want to stream output back to a client, you should use spawn.
var exec = require('child_process').exec;
var child = exec('cat *.js | wc -l', function(error, stdout, stderr) {
if (error) console.log(error);
process.stdout.write(stdout);
process.stderr.write(stderr);
});
This way is nicer because console.log will print blank lines.
You can use process.argv. It's an array containing the command line arguments. The first element will be node the second element will be the name of the JavaScript file. All next elements will be any additional command line you given.
You can use it like:
var username = process.argv[2];
var password = process.argv[3];
var realname = process.argv[4];
Or iterate over the array. Look at the example: http://nodejs.org/docs/latest/api/all.html#process.argv

Resources