Skip to content

Instantly share code, notes, and snippets.

@zerobias
Created March 6, 2019 14:44
Show Gist options
  • Save zerobias/45c0e17ac24687ba981bebea5090fe07 to your computer and use it in GitHub Desktop.
Save zerobias/45c0e17ac24687ba981bebea5090fe07 to your computer and use it in GitHub Desktop.
//@flow
import _os from 'os'
export function platform() {
return process.platform
}
export function cpuCount() {
return _os.cpus().length
}
export function sysUptime() {
return (
//seconds
_os.uptime()
)
}
export function processUptime() {
return (
//seconds
process.uptime()
)
}
// Memory
export function freemem() {
return _os.freemem() / (1024 * 1024)
}
export function totalmem() {
return _os.totalmem() / (1024 * 1024)
}
export function freememPercentage() {
return _os.freemem() / _os.totalmem()
}
export function freeCommand(callback: (n: number) => any) {
// Only Linux
require('child_process').exec('free -m', (error, stdout, stderr) => {
const lines = stdout.split('\n')
const str_mem_info = lines[1].replace(/[\s\n\r]+/g, ' ')
const mem_info = str_mem_info.split(' ')
const total_mem = parseFloat(mem_info[1])
const free_mem = parseFloat(mem_info[3])
const buffers_mem = parseFloat(mem_info[5])
const cached_mem = parseFloat(mem_info[6])
const used_mem = total_mem - (free_mem + buffers_mem + cached_mem)
callback(used_mem - 2)
})
}
// Hard Disk Drive
export function harddrive(
callback: (total: number, free: number, used: number) => any,
) {
require('child_process').exec('df -k', (error, stdout, stderr) => {
let total = 0
let used = 0
let free = 0
const lines = stdout.split('\n')
const str_disk_info = lines[1].replace(/[\s\n\r]+/g, ' ')
const disk_info = str_disk_info.split(' ')
total = Math.ceil((disk_info[1] * 1024) / 1024 ** 2)
used = Math.ceil((disk_info[2] * 1024) / 1024 ** 2)
free = Math.ceil((disk_info[3] * 1024) / 1024 ** 2)
callback(total, free, used)
})
}
// Return process running current
export function getProcesses(
nProcess: Function | number,
callback: (n: string) => any,
) {
// if nprocess is undefined then is function
if (typeof nProcess === 'function') {
callback = nProcess
nProcess = 0
}
let command = `ps -eo pcpu,pmem,time,args | sort -k 1 -r | head -n${10}`
//command = 'ps aux | head -n '+ 11
//command = 'ps aux | head -n '+ (nProcess + 1)
if (nProcess > 0)
command = `ps -eo pcpu,pmem,time,args | sort -k 1 -r | head -n${nProcess +
1}`
require('child_process').exec(command, function(error, stdout, stderr) {
const that = this
const lines = stdout.split('\n')
lines.shift()
lines.pop()
let result = ''
lines.forEach((_item, _i) => {
let _str = _item.replace(/[\s\n\r]+/g, ' ')
_str = _str.split(' ')
// result += _str[10]+" "+_str[9]+" "+_str[2]+" "+_str[3]+"\n";
// process
result += `${_str[1]} ${_str[2]} ${_str[3]} ${_str[4].substring(
_str[4].length - 25,
)}\n` // process
})
callback(result)
})
}
/*
* Returns All the load average usage for 1, 5 or 15 minutes.
*/
export function allLoadavg() {
const loads = _os.loadavg()
return `${loads[0].toFixed(4)},${loads[1].toFixed(4)},${loads[2].toFixed(4)}`
}
/*
* Returns the load average usage for 1, 5 or 15 minutes.
*/
export function loadavg(_time?: 1 | 5 | 15) {
if (_time === undefined || (_time !== 5 && _time !== 15)) _time = 1
const loads = _os.loadavg()
let v = 0
if (_time == 1) v = loads[0]
if (_time == 5) v = loads[1]
if (_time == 15) v = loads[2]
return v
}
export function cpuFree(callback: (n: number) => any) {
getCPUUsage(callback, true)
}
export function cpuUsage(callback: (n: number) => any) {
getCPUUsage(callback, false)
}
function getCPUUsage(callback: (n: number) => any, free) {
const stats1 = getCPUInfo()
const startIdle = stats1.idle
const startTotal = stats1.total
setTimeout(() => {
const stats2 = getCPUInfo()
const endIdle = stats2.idle
const endTotal = stats2.total
const idle = endIdle - startIdle
const total = endTotal - startTotal
const perc = idle / total
if (free === true) callback(perc)
else callback(1 - perc)
}, 1000)
}
function getCPUInfo(callback) {
const cpus = _os.cpus()
let user = 0
let nice = 0
let sys = 0
let idle = 0
let irq = 0
let total = 0
//$todo
for (const cpu in cpus) {
if (!cpus.hasOwnProperty(cpu)) continue
user += cpus[cpu].times.user
nice += cpus[cpu].times.nice
sys += cpus[cpu].times.sys
irq += cpus[cpu].times.irq
idle += cpus[cpu].times.idle
}
total = user + nice + sys + idle + irq
return {
idle,
total,
}
}
//@flow
import tty from 'tty'
import {Stream} from 'stream'
export default function createCharm(...args: $ReadOnlyArray<*>) {
let input = null
function setInput(s) {
if (input) throw new Error('multiple inputs specified')
else input = s
}
let output = null
function setOutput(s) {
if (output) throw new Error('multiple outputs specified')
else output = s
}
for (const arg of args) {
if (!arg) continue
if (arg.readable) setInput(arg)
else if (arg.stdin || arg.input) setInput(arg.stdin || arg.input)
if (arg.writable) setOutput(arg)
else if (arg.stdout || arg.output) setOutput(arg.stdout || arg.output)
}
if (input && typeof input.fd === 'number' && tty.isatty(input.fd)) {
if (process.stdin.setRawMode) {
//$off
process.stdin.setRawMode(true)
} else tty.setRawMode(true)
}
const charm = new Charm()
if (input) {
input.pipe(charm)
}
if (output) {
//$off
charm.pipe(output)
}
charm.once('^C', process.exit)
charm.once('end', () => {
if (input) {
if (typeof input.fd === 'number' && tty.isatty(input.fd)) {
if (process.stdin.setRawMode) {
//$off
process.stdin.setRawMode(false)
} else tty.setRawMode(false)
}
input.destroy()
}
})
return charm
}
export class Charm extends Stream {
writable = true
readable = true
pending: Array<(buf: Buffer | string) => void | boolean> = []
write(buf: Buffer | string) {
if (this.pending.length) {
const codes = extractCodes(buf)
let matched = false
for (let i = 0; i < codes.length; i++) {
for (let j = 0; j < this.pending.length; j++) {
const cb = this.pending[j]
if (cb(codes[i])) {
matched = true
this.pending.splice(j, 1)
break
}
}
}
if (matched) return
}
if (buf.length === 1) {
if (buf[0] === 3) this.emit('^C')
if (buf[0] === 4) this.emit('^D')
}
this.emit('data', buf)
return this
}
destroy() {
this.end()
}
end(buf?: Buffer | string) {
if (buf) this.write(buf)
this.emit('end')
}
reset(cb: void) {
// resets the screen on iTerm, which appears
// to lack support for the reset character.
this.write(encode('[0m'))
this.write(encode('[2J'))
this.write(encode('c'))
return this
}
position(...args: [number, number] | [(x: number, y: number) => any]) {
if (args.length === 1) {
const [x] = args
// get/set absolute coordinates
if (typeof x === 'function') {
const cb = x
this.pending.push((buf: Buffer | string) => {
if (
buf[0] === 27
&& buf[1] === encode.ord('[')
&& buf[buf.length - 1] === encode.ord('R')
) {
const pos = buf
.toString()
.slice(2, -1)
.split(';')
.map(Number)
cb(pos[1], pos[0])
return true
}
})
this.write(encode('[6n'))
}
} else if (args.length === 2) {
const x = args[0]
//$off
const y = args[1]
//$todo
this.write(encode(`[${Math.floor(y)};${Math.floor(x)}f`))
}
return this
}
move(x: number, y: number) {
// set relative coordinates
const bufs = []
if (y < 0) this.up(-y)
else if (y > 0) this.down(y)
if (x > 0) this.right(x)
else if (x < 0) this.left(-x)
return this
}
up(y: number = 1) {
this.write(encode(`[${Math.floor(y)}A`))
return this
}
down(y: number = 1) {
this.write(encode(`[${Math.floor(y)}B`))
return this
}
right(x: number = 1) {
this.write(encode(`[${Math.floor(x)}C`))
return this
}
left(x: number = 1) {
this.write(encode(`[${Math.floor(x)}D`))
return this
}
column(x: number) {
this.write(encode(`[${Math.floor(x)}G`))
return this
}
push(withAttributes: boolean) {
this.write(encode(withAttributes ? '7' : '[s'))
return this
}
pop(withAttributes: boolean) {
this.write(encode(withAttributes ? '8' : '[u'))
return this
}
erase(s: 'end' | '$' | 'start' | '^' | 'line' | 'down' | 'up' | 'screen') {
if (s === 'end' || s === '$') {
this.write(encode('[K'))
} else if (s === 'start' || s === '^') {
this.write(encode('[1K'))
} else if (s === 'line') {
this.write(encode('[2K'))
} else if (s === 'down') {
this.write(encode('[J'))
} else if (s === 'up') {
this.write(encode('[1J'))
} else if (s === 'screen') {
this.write(encode('[1J'))
} else {
this.emit('error', new Error(`Unknown erase type: ${s}`))
}
return this
}
delete(s: 'line' | 'char', n: number = 1) {
if (s === 'line') {
this.write(encode(`[${n}M`))
} else if (s === 'char') {
this.write(encode(`[${n}M`))
} else {
this.emit('error', new Error(`Unknown delete type: ${s}`))
}
return this
}
insert(mode: boolean | 'line' | 'char', n: number = 1) {
if (mode === true) {
this.write(encode('[4h'))
} else if (mode === false) {
this.write(encode('[l'))
} else if (mode === 'line') {
this.write(encode(`[${n}L`))
} else if (mode === 'char') {
this.write(encode(`[${n}@`))
} else {
this.emit('error', new Error(`Unknown delete type: ${mode}`))
}
return this
}
display(
attr:
| 'reset'
| 'bright'
| 'dim'
| 'underscore'
| 'blink'
| 'reverse'
| 'hidden',
) {
const c = {
reset: 0,
bright: 1,
dim: 2,
underscore: 4,
blink: 5,
reverse: 7,
hidden: 8,
}[attr]
if (c === undefined) {
this.emit('error', new Error(`Unknown attribute: ${attr}`))
}
this.write(encode(`[${c}m`))
return this
}
foreground(
color:
| number
| 'black'
| 'red'
| 'green'
| 'yellow'
| 'blue'
| 'magenta'
| 'cyan'
| 'white',
) {
if (typeof color === 'number') {
if (color < 0 || color >= 256) {
this.emit('error', new Error(`Color out of range: ${color}`))
}
this.write(encode(`[38;5;${color}m`))
} else {
const c = {
black: 30,
red: 31,
green: 32,
yellow: 33,
blue: 34,
magenta: 35,
cyan: 36,
white: 37,
}[color.toLowerCase()]
if (!c) this.emit('error', new Error(`Unknown color: ${color}`))
this.write(encode(`[${c}m`))
}
return this
}
background(
color:
| number
| 'black'
| 'red'
| 'green'
| 'yellow'
| 'blue'
| 'magenta'
| 'cyan'
| 'white',
) {
if (typeof color === 'number') {
if (color < 0 || color >= 256) {
this.emit('error', new Error(`Color out of range: ${color}`))
}
this.write(encode(`[48;5;${color}m`))
} else {
const c = {
black: 40,
red: 41,
green: 42,
yellow: 43,
blue: 44,
magenta: 45,
cyan: 46,
white: 47,
}[color.toLowerCase()]
if (!c) this.emit('error', new Error(`Unknown color: ${color}`))
this.write(encode(`[${c}m`))
}
return this
}
cursor(visible: boolean) {
this.write(encode(visible ? '[?25h' : '[?25l'))
return this
}
}
export function encode(xs: string | Array<number>) {
function bytes(s) {
if (typeof s === 'string') {
return s.split('').map(ord)
} else if (Array.isArray(s)) {
return s.reduce((acc, c) => acc.concat(bytes(c)), [])
}
return []
}
return Buffer.from([0x1b].concat(bytes(xs)))
}
encode.ord = ord
function ord(c) {
return c.charCodeAt(0)
}
export function extractCodes(buf: Buffer | string) {
const codes = []
let start = -1
for (let i = 0; i < buf.length; i++) {
if (buf[i] === 27) {
if (start >= 0) codes.push(buf.slice(start, i))
start = i
} else if (start >= 0 && i === buf.length - 1) {
codes.push(buf.slice(start))
}
}
return codes
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment