Ram usage in %

Hello,
this is my first post here.

I'm currently trying to get the free RAM in %.
It is important to me to achieve this via a single shell command.

ChatGPT gave me things like

echo "scale=2; ($(sysctl -n vm.stats.vm.v_wire_count) + $(sysctl -n vm.stats.vm.v_free_count)) / ($(sysctl -n vm.stats.vm.v_page_count)) ) * 100" | BC

and similarly suggested, but that doesn't work.

I would like to query the value from another computer via ssh.

On Debian I use
free -m | awk 'NR==2 {printf "%d\n", $3/$2*100}'
 
These are all my tests.
Predominates with ChatGPT. The result should be around 50%.

root@truenas[~]# sysctl vm.stats.vm.v_inactive_count vm.stats.vm.v_cache_count vm.stats.vm.v_free_count | awk '{if (NR==1) inactive=$2; else if (NR==2) cache=$2; else if (NR==3) free=$2;} END {total=inactive+cache+free; used=inactive+cache; print (used/total)*100}'

24.8111

root@truenas[~]# sysctl vm.stats.vm.v_inactive_count vm.stats.vm.v_cache_count vm.stats.vm.v_free_count | awk '{if (NR==1) inactive=$2; else if (NR==2) cache=$2; else if (NR==3) free=$2;} END {total=inactive+cache+free; used=inactive+cache; print (used/total)*100}'

24.8112

root@truenas[~]# sysctl vm.stats.vm.v_inactive_count vm.stats.vm.v_cache_count vm.stats.vm.v_free_count | awk '{if (NR==1) inactive=$2; else if (NR==2) cache=$2; else if (NR==3) free=$2;} END {total=inactive+cache+free; used=inactive+cache; print (used/total)*100}'

24.8107

root@truenas[~]# sysctl vm.stats.vm.v_page_count vm.stats.vm.v_inactive_count vm.stats.vm.v_cache_count vm.stats.vm.v_free_count

vm.stats.vm.v_page_count: 2023683

vm.stats.vm.v_inactive_count: 343428

vm.stats.vm.v_cache_count: 0

vm.stats.vm.v_free_count: 1039802

root@truenas[~]# echo "scale=2; (( $(sysctl -n hw.physmem) - $(sysctl -n vm.stats.vm.v_free_count) ) / $(sysctl -n hw.physmem) ) * 100" | bc

99.00

root@truenas[~]# top -d1 | awk '/^Mem:/{print ($8/$4)*100}' 302.683

root@truenas[~]# echo "scale=2; ($(sysctl -n vm.stats.vm.v_wire_count) + $(sysctl -n vm.stats.vm.v_free_count)) / ($(sysctl -n vm.stats.vm.v_page_count)) * 100" | bc

80.00

root@truenas[~]# echo "scale=2; ($(sysctl -n vm.stats.vm.v_wire_count) + $(sysctl -n vm.stats.vm.v_free_count)) / ($(sysctl -n hw.physmem)) * 100" | bc

0

I know used Ram is good Ram.
 
I have it

echo "$(top | awk '/Mem:/ {total=$2 + $4 + $6 + $8; free=$8; printf "%.2f\n", (free / total) * 100}')"
 
A: Why? This is a classic XY problem. What are you trying to optimize? Is there a reason to care how much memory is free? Is the automatic memory management not sufficient for your requirements?

B: The need that it be in a single line is going to make it hard to read and debug. Not impossible, just hard. If it's really a requirement, I would try to solve it differently. For example by creating a little script that can be called in one line, or putting a shell function in your .shrc etc. file.

C: Your solutions, while theoretically workable, all seen brittle. The very first one (where you build a bc expression out of calling sysctl with the -n switch) is still the cleanest one. To make it easier to read and maintain and less error prone, I would turn it into a multi-line script:
Code:
used=$(sysctl -n vm.stats.vm.v_wire_count)
free=$(sysctl -n vm.stats.vm.v_free_count)
total=($(sysctl -n vm.stats.vm.v_page_count)
bc -e "100 * ( $used + $free ) / $total"
If you don't understand why (a) the 100 * comes first, (b) the bc expression is quoted then you need to learn about shells and bc.

Using awk is heavyweight; all you are doing is an addition and division, and awk forces you into parsing complex output (the various NR=... and $2... lines all seem like magic). Using top is even more heavyweight, as you are taking a big amount of information (dozens of lines, each with many fields) and doing extra effort to pick out just 3 numbers.
 
echo "$(top | awk '/Mem:/ {total=$2 + $4 + $6 + $8; free=$8; printf "%.2f\n", (free / total) * 100}')"

With sh(1), and htop 3.4.0-dev in the background:

1709498552468.png


8.92 ÷ 31.9 = ~0.29
 
Is there a reason to care how much memory is free?
Yes, it completely filled up a few times, including the swap, which I would like to follow up on.

For example by creating a little script that can be called in one line, or putting a shell function in your .shrc etc. file.
I'm not very good at that. I'm happy if I can keep my systems up to date via the shell and get the basics down.

Using awk is heavyweight;
It can be. But should it still be done in milliseconds? The command is executed every 300 seconds.

I used the data to build my own little dashboard.
1000035348.jpg
 
For x11/i3blocks I have a small script which is using sysutils/freecolor to print the total/used memory.
eg.
Code:
#!/bin/sh

total_mem="$(freecolor -m -o | head -n 2 | tail -n 1 | cut -c14-18)"
used_mem="$(freecolor -m -o | head -n 2 | tail -n 1 | cut -c24-29)"

if [ "${used_mem}" -lt "${total_mem}" ]; then
   echo "${used_mem}/${total_mem} MB"
   echo " "
fi
 
Back
Top