How to save in XML/JSON format all information from “free” command and “vmstat” command including time?

I need it every 2 minutes:

command

I am using Debian (text mode only).


Solution 1:

How can I (simply) wrap this output up on XML/JSON ?

Assuming you don't want individual tags for total, used, free shared etc, you can wrap the whole output in enclosing tags, as appropriate:

XML

The following script could be saved as (eg) memoryinfo-xml.sh:

#!/bin/bash
# memoryinfo-xml.sh - wrap output of free + vmstat in XML tags
echo "<output>"
  echo -e "\t<date>$(date)</date>"
  echo -e "\t<free>$(free)</free>"
  echo -e "\t<vmstat>$(vmstat)</vmstat>"
echo "</output>" 

example output:

<output>                                                                                                          
    <date>Thu 30 Mar 16:21:18 BST 2017</date>
    <free>             total       used       free     shared      buffers     cached
Mem:       3853532    3721596     131936     100868     227652    3024584
-/+ buffers/cache:     469360    3384172
Swap:      1182716       2512    1180204</free>
    <vmstat>procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
1  0   2512 132084 227652 3024584    0    0     3     2    4    4  1  0 99  0  0</vmstat>
</output>

As you can see, it isn't exactly pretty!

JSON

Very similar to before, save as (eg) memoryinfo-json.sh:

#!/bin/bash
# memoryinfo-json.sh - wrap output of free + vmstat in json
# thanks to https://stackoverflow.com/a/1252191 for \n replacement
echo "{ \"output\":"
  echo -e "\t { \"date\":  \"$(date)\", "
  echo -e "\t  \"free\":   \"$(free | sed ':a;N;$!ba;s/\n/||/g')\", "
  echo -e "\t  \"vmstat\": \"$(vmstat| sed ':a;N;$!ba;s/\n/||/g')\" "
echo "}"

example output:

{
    "output": {
        "date": "Thu 30 Mar 16: 48: 51 BST 2017",
        "free": "total used free shared buffers cached || Mem: 3853532 3722428 131104 100868 227888 3024844 || -/+ buffers/cache: 469696 3383836 || Swap: 1182716 2512 1180204",
        "vmstat": "procs-- -- -- -- -- - memory-- -- -- -- -- -- - swap-- -- -- - io-- -- - system-- -- -- --cpu-- -- - || r b swpd free buff cache si so bi bo in cs us sy id wa st || 1 0 2512 131096 227888 3024844 0 0 3 2 4 4 1 0 99 0 0"
    }
}

Note that to get valid JSON, the newlines have been replaced by a double pipe character (||), via sed replacement.

Solution 2:

I created a tool called jc that converts the output of many commands, including free and vmstat to JSON:

$ jc free | jq
[
  {
    "type": "Mem",
    "total": 3993360,
    "used": 293248,
    "free": 3185992,
    "shared": 1196,
    "buff_cache": 514120,
    "available": 3465280
  },
  {
    "type": "Swap",
    "total": 2097148,
    "used": 0,
    "free": 2097148
  }
]
$ vmstat | jc --vmstat | jq
[
  {
    "runnable_procs": 2,
    "uninterruptible_sleeping_procs": 0,
    "virtual_mem_used": 0,
    "free_mem": 2794468,
    "buffer_mem": 2108,
    "cache_mem": 741208,
    "inactive_mem": null,
    "active_mem": null,
    "swap_in": 0,
    "swap_out": 0,
    "blocks_in": 1,
    "blocks_out": 3,
    "interrupts": 29,
    "context_switches": 57,
    "user_time": 0,
    "system_time": 0,
    "idle_time": 99,
    "io_wait_time": 0,
    "stolen_time": 0,
    "timestamp": null,
    "timezone": null
  }
]

The vmstat parser also supports streaming, where it outputs JSON Lines:

$ vmstat 1 | jc --vmstat-s -u | jq -c
{"runnable_procs":2,"uninterruptible_sleeping_procs":0,"virtual_mem_used":0,"free_mem":2794468,"buffer_mem":2108,"cache_mem":741208,"inactive_mem":null,"active_mem":null,"swap_in":0,"swap_out":0,"blocks_in":1,"blocks_out":3,"interrupts":29,"context_switches":57,"user_time":0,"system_time":0,"idle_time":99,"io_wait_time":0,"stolen_time":0,"timestamp":null,"timezone":null}
...

https://github.com/kellyjonbrazil/jc