I am running ubuntu in vmware. I am trying to get the baseboard serial number.
var si = require("systeminformation");
console.log(si.baseboard().serial);
It return undefined. Is the problem in my code? Or the problem is ubuntu is running in vmware?
You can see here in the systeminformation source that it's reading the file /sys/devices/virtual/dmi/id/board_serial (if running dmidecode -t 2 2>/dev/null fails).
If you cat /sys/devices/virtual/dmi/id/board_serial in your shell (if it even exists), what do you get?
If it's empty or non-existent, then the data isn't provided by your environment.
To complete AKX answer, si.baseboard() returns a Promise (since v3), so you have to do something like this:
si.baseboard().then(el => console.log(el.serial))
or, if you want to stick with callback syntax
si.baseboard(el => { console.log(el.serial) })
Note for me, it returns an empty string if I launch the script as a regular user. I can display the serial number only if I launch it as root.
I find that I can use serial-number to get an unique number even on virtual machine.
var serialNumber = require('serial-number');
serialNumber(function (err, value) {
console.log(value);
});
Related
In electron, I am registering a shortcut to open a terminal:
globalShortcut.register('CommandOrControl+Alt+Shift+P', () => {
spawn(os.platform() === 'linux' ? 'xterm' : 'cmd');
});
I noticed that xterm don't have the same "style" of the terminal opened from OS menu and I found that the latter is customized by the Desktop Environment (I have an Ubuntu Mate where its terminal is mate-terminal and a RedHat 7.5 with konsole).
I read here that nodejs don't have an API to detect the distribution, so it seems not feasible to know which terminal to run depending on distribution.
Is there any way to open the correct terminal or to style xterm as the OS one?
TL;DR: There's no standardised API for that and you cannot be sure that a distribution indicates the terminal application.
First of all, XTerm, Mate's Terminal, Konsole, etc. are all different applications. And because Ubuntu Mate under the hood reports as Ubuntu, AFAIK, you cannot even be certain that this is the application registered as "the" terminal app. Also, nearly every desktop environment brings its own terminal application, and since you can install multiple terminal applications side by side, it is at most an educated guess to automatically select an "appropriate" terminal application.
However, there are multiple approaches which can be considered to solve this (aesthetic) problem:
Let the user decide what terminal application they want. If your application has a configuration file, you could use that to write a value specified by the user and take that as the terminal app. In theory, they could specify a path to an application which is not a terminal app, but then it's their fault.
Compile a list of known terminal applications and check if they're installed. For example, you could make an (ordered) list of the apps your application should search for and if none of them is found, fall back to XTerm (because that is installed on most if not all desktop systems running Linux). To see if an application is installed and runnable on Linux, you can use the which command. Example:
const { spawnSync } = require ("child_process");
const terms = [ "konsole", "mate-terminal", "gnome-terminal" /* ... */ ];
var terminal = null;
// In your startup method (e.g. before opening a BrowserWindow)
if (os.platform () === "linux") {
for (term in terms) {
which = spawnSync ("which", [term]);
if (which.status !== null && which.status === 0) { // Command found
terminal = term;
break;
}
}
if (terminal === null) terminal = "xterm";
} else {
terminal = "cmd";
}
Of course you could also use spawn in favour of spawnSync but this will get more complex. Also, this only provides you with the first application found to be installed, it does not select the one "appropriate" for the desktop environment. But I believe it is a good step in the right direction if you want your application the be (somewhat) seemlessly integrated into the DE.
As a side note, your code does not take MacOS into account, but it is also possible to open a terminal on MacOS, it's simply called "Terminal" there.
Node.js doesn't provide a method to detect the name of the distribution natively, because there is no standard way to get that information from different Linux distributions.
But you can do it with a library sush as getos:
const getos = require('getos');
getos((err, os) => {
if (err) return console.log(err);
console.log(os.dist, os.codename)
})
There is a package called OpenTerm, it has configurable function which automatically determines terminal to use, and it currently supports windows and linux, but not MacOs.
const { VTexec } = require('open-term')
VTexec('help') // Runs "help" command in determined terminal.
"help" command would work both on bash and cmd. So i use it here as example.
I am working on a project where I want to access and display the temperature of my CPU. I found a tutorial where I via the "systeminformation" package can gain access to mutliple CPU stats. But when I use the cpuTemperature function it does not return the temperature, instead it returns "-1" and empty list and "-1".
si.cpuTemperature(function(data) {
console.log('CPU-Temperature:');
console.log(data);
});
=> { main: -1, cores: [], max: -1 }
Am I doing something wrong or is my CPU not supporting this type of event?
Tutorial I have used: https://github.com/sebhildebrandt/systeminformation
I presume you are trying that on windows. Accoording to docs you need to run wmic with admin privileges, if you don't get any data. For OSX and Linux you also need some extra packages installed like osx-temperature-sensor Node module for OSX, and the sensors package (lm-sensors for Debian based) Linux machines. You can try to run node from an Administrator terminal to check out the privilege issue on Windows.
I have been following a series of tutorials on Node.js. To demonstrate child processes using exec, I have been given the code below under the file of exec.js When I go to the command line for node, I type in
node exec.js
then nothing happens. Why would this be?
var exec = require("child_process").exec;
exec("open http://www.linkedin.com");
Your code works for me.
To diagnose and fix this, I would try:
In your terminal (not using Node), verify that open http://www.linkedin.com works at all. You should see your default web browser open to the appropriate URL. If that doesn't happen, then Node can't magically fix it. Most likely, you'll need to set the default browser.
Wrap the URL in single quotes just for good measure. This protects you in some cases where the URL contains certain reserved characters.
exec("open 'http://www.linkedin.com'");
Add a callback so you can see the command's output and verify it completed successfully.
exec("open 'http://www.linkedin.com'", function (err, stdout, stderr) {
console.log('err:', err);
console.log('stdout:', stdout);
console.log('stderr:', stderr);
});
The ideal solution is to use opn, a high-quality module that already exists for this exact purpose.
For Windows, use the start command instead of open (which is for Mac) as below:
exec("start http://www.linkedin.com");
How might I set up node.js as a shell replacement for bash? For example I should be able to run vi('file') to open a file and cd('location') to change between directories.
Is this even possible?
Sure you can! It will become much less straightforward to use your computer, though.
First off, you will need to know how to set this up. While you could likely set your user shell in Linux to usr/bin/node, this will leave you with only a Node.js REPL with no additional programs set up. What you're going to want to do is write a setup script that can do all of the below setup/convenience steps for you, essentially something that ends with repl.start() to produce a REPL after setting everything up. Of course, since UNIX shell settings can't specify arguments, you will need to write a small C program that executes your shell with those arguments (essentially, exec("/usr/bin/node", "path/to/setup/script.js");) and set that as your UNIX shell.
The main idea here is that any commands that you use beyond the very basics must be require()d into your shell - e.g. to do anything with your filesystem, execute
var fs = require("fs")
and do all of your filesystem calls from the fs object. This is analogous to adding things to your PATH. You can get basic shell commands by using shelljs or similar, and to get at actual executable programs, use Node's built-in child_process.spawnSync for a foreground task or child_process.spawn for a background task.
Since part of your requirement is that you want to call each of your programs like a function, you will need to produce these functions yourself, getting something like:
function ls(path) {
child_process.spawnSync('/bin/ls', [path], { stdio: 'inherit' });
}
for everything you want to run. You can probably do this programmatically by iterating through all the entries in your PATH and using something involving eval() or new Function() to generate execute functions for each, assigning them to the global object so that you don't have to enter any prefixes.
Again, it will become much less straightforward to use your computer, despite having these named functions. Lots of programs that cheat and use bash commands in the background will likely no longer work. But I can certainly see the appeal of being able to leverage JavaScript in your command-line environment.
ADDENDUM: For writing this setup script, the REPLServer object returned by repl.start() has a context object that is the same as the global object accessible to the REPL session it creates. When you write your setup script, you will need to assign everything to the context object:
const context = repl.start('> ').context;
context.ls = function ls(path) { /* . . . */ }
context.cd = function cd(path) { /* . . . */ }
I think it would be an intersting proposition. Create a test account and tell it to use node as it's shell. See 'man useradd' for all options
$ useradd -s /usr/bin/node test
$ su - test
This works on mac and linux.
require('child_process').spawnSync('vi', ['file.txt'], { stdio: 'inherit' })
You could bootstrap a repl session with your own commands, then run the script
#!/bin/bash
node --experimental-repl-await -i -e "$(< scripts/noderc.js)"`
This allows for things like:
> ls()
> run('vi','file.txt')
> await myAsyncFunc()
I think you're looking for something like this https://youtu.be/rcwcigtOwQ0 !
If so.... YES you can!
If you like I can share my code. But I need to fix some bugs first!
tell me if you like.
my .sh function:
const hey = Object.create(null),
sh = Object.create(null);;
hey.shell = Object.create(null);
hey.shell.run = require('child_process').exec;
sh.help = 'Execute an OS command';
sh.action = (...args) => {
// repl_ is the replServer
// the runningExternalProgram property is one way to know if I should
// render the prompt and is not needed. I will create a better
// way to do this (action without if/decision)!
repl_.runningExternalProgram = true;
hey.shell.run(args.join(' '),
(...args) => {
['error', 'log'].forEach((command, idx) => {
if (args[idx]) {
console[command](args[idx]);
}
});
repl_.runningExternalProgram = false;
});
};
PS: to 'cd' into some directory you just need to change the process.cwd (current working directory)
PS2: to avoid need to write .sh for every OS program/command you can use Proxy on the global object.
I like to get an unique reusable identifier of the terminal window my node app (a CLI) is running in. The reason I like to know this is the common use of the app by the same user within multiple terminals at the same time.
It is necessary to get back selected data for each terminal and also getting to know what is selected on different terminal windows the CLI-App is running in.
The best way to save this would be in a hidden log file basically named by a unique terminal identifier.
[x] Working on process.platform === 'win32' each cmd.exe has its own PID.
[ ] Working on process.platform === 'darwin' (Mac OS X) the PPID is the same on all terminal windows.
[ ] Working on process.platform === 'freebsd' || 'linux' || 'sunos' I assume it is the same problem also depending on the GUI you are running.
Executing tty on the terminal gives me different identifiers like /dev/ttys003 what would be useful.
But trying to get this out of the app is not possible because executing this within a child_process ends up in a not a tty!
The PID of the app itself is changing every time it is executed. Thats not helpful in this case. The parent PID is the same (but also in different terminals).
Setting env will not be bound to the terminal but only to the apps runtime.
Is there any idea to get this done ?
I got it myself:
SpoTTY is the solution for posix based systems.
The example on the page has a misleading bug - use this example to get it done:
// A clone of the `tty` command
var spotty = require('spotty');
var tty = spotty.tty(function(err, res) {
if (err) {
console.error("Error found: " + err.toString())
} else {
return res;
}
})
hope this helps someone.