How to get the total physical memory in Bash to assign it to a variable? - linux

How can I get the total physical memory in bytes of my Linux PC?
I need to assign it to a bash script variable.

grep MemTotal /proc/meminfo | awk '{print $2}'
The returned number is in KB

phymem=$(awk -F":" '$1~/MemTotal/{print $2}' /proc/meminfo )
or using free
phymem=$(LANG=C free|awk '/^Mem:/{print $2}')
or using shell
#!/bin/bash
while IFS=":" read -r a b
do
case "$a" in
MemTotal*) phymem="$b"
esac
done <"/proc/meminfo"
echo $phymem

I came up with this one under the assumption, that the physical memory will be the first number in free's output:
free -m | grep -oP '\d+' | head -n 1
This allows you to configure free to output the unit you want (-m, -g, ...) and it is independent of the system language (other answers depend on the "Mem:" string in free's output which may change based on the language).

How about
var=$(free | awk '/^Mem:/{print $2}')

I'll try to make this answer self explanatory, just keep up with me.
To get the description of memory, you can use the free utility :
free -t
Output (in KB):
total used free shared buff/cache available
Mem: 8035900 3785568 324984 643936 3925348 3301908
Swap: 3906556 271872 3634684
Total: 11942456 4057440 3959668
To extract all of these values from this output in a single column :
free -t | grep -oP '\d+'
Output (in KB):
8035900
3866244
266928
650348
3902728
3214792
3906556
292608
3613948
11942456
4158852
3880876
Note : Minute difference can be there in values, which doesn't matter most of the times.
If you just want to get the total physical memory (mem+swap), it is the 10th value in above output :
free -t | grep -oP '\d+' | sed '10!d'
Output (on my PC):
11942456
Note: All the above outputs are in Kilo Bytes. If you want in Mega Bytes or Giga Bytes just append -m or -g after -t in
above free commands respectively.
For Example :
free -t -g | grep -oP '\d+' | sed '10!d'
Output (in Giga Bytes on my PC) :
11

Silly inline python version, which looks overly complicated, but is actually kind of useful.
freemem=$(echo -e 'import re\nmatched=re.search(r"^MemTotal:\s+(\d+)",open("/proc/meminfo").read())\nprint(int(matched.groups()[0])/(1024.**2))' | python)
It returns the memory in GB.

If someone need a human readable:
var=$(free -h | awk '/^Mem:/{print $2}')
result:
1.9G

Related

How to get Network Traffic as one number on Linux

currently I am using this script to get CPU Load, Memory Load and used Diskspace. Now I want to expand it to also give me Network traffic.
top -bn1 | grep "Cpu(s)" | \
sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | \
awk '{print "CPU Load> " 100 - $1"%"}'
free | grep Mem | awk '{print "Memory Usage> "$3/$2 * 100.0"%"}'
used=$(df / | awk 'END{print $5}')
echo "Storage Used> "$used
The result should look something like this:
CPU Load> 82.8%
Memory Usage> 98.7924%
Storage Used> 23%
Network Traffic> 281 byte/s
Is there some way to go about that?
Sorry, I missed the bottom of your comment where you are looking for throughput. in this case, I'd use ifstat
apt-get install ifstat.
And in your script.
ifstat 1 1 | tail -1 | awk '{ print $1,$2}'.
this will give you Kb in and out. you can add them together.

Bash: Show info after grep search term

I'm trying to output information about a machine's system hardware in a bash script. What I'm using is grep to get information about total memory and free memory.
echo -n -e "RAM:\t"
cat /proc/meminfo | grep "MemTotal"
My output shows "MemTotal: 3994850 MB". What I want is just the memory information itself. Is there a way to do this?
Just one awk would be enough instead of multiple piped command here:
awk '/MemTotal/{print $2}' /proc/meminfo
15404808
If you want unit also then use:
awk '/MemTotal/{print $2, $3}' /proc/meminfo
15404808 kB

Using LINUX top command to compute used memory percentage

I am writing the top command output to a text file.
I am trying to write a simple bash script to calculate the percentage of used memory and send an
email if the memory used percentage exceeds, say 90%.
Here is the bash script I have thus far.
#!/bin/bash
top -n 1 -b | grep "Mem" > /home/modadm/top-output.txt
MAXMEM=/home/modadm/top-output.txt | grep "Mem" | cut -c 7-14
USEDMEM=/home/modadm/top-output.txt | grep "Mem" | cut -c 25-31
$USEDPCT='echo $USEDMEM / $MAXMEM * 100 | bc'
$USEDPCT | mail -s "Test Email from MOD Server" test#test.com
When I save and execute the script, I get the error "No such file or directory":
-bash-3.2$ ./memcheck.sh
./memcheck.sh: line 4: =echo $USEDMEM / $MAXMEM * 100 | bc: No such file or directory
Null message body; hope that's ok
-bash-3.2$
Can someone assist? I am a newbie to bash scripting and this is my first script.
Thank you
I will not repeat the content of the other answers; instead I will question the wisdom of parsing the output of top, when all you need is information on the system memory usage.
The output of top is intended for humans and also contains a lot of per-process information that is both unneeded and expensive to produce. The output of free is far more suitable for this particular use.
Secondly, judging by the calculations in your script, you do not seem to understand the way system memory usage is measured on Linux and other Unix-like systems. Contrary to the other OS, the used memory size contains the memory used for disk caches and other buffers. On any system that has been up for some time the free memory tends towards zero - unused memory is wasted memory.
A first step towards finding out the amount of memory used by processes would be to subtract the amount of memory used for buffers from the used memory size. But even that would not be enough on a modern system - even free and top get it wrong to a degree, as mentioned in this older answer of mine.
You have a few problems here.
First, this doesn't do what you want it to do.
USEDMEM=/home/modadm/top-output.txt | grep "Mem" | cut -c 25-31
You can't pipe a filename into a command. You actually want to pipe the contents of the file into the command. You can do that with 'cat'. However, grep is actually designed to search within a file so you can do
USEDMEM=$(grep "Mem" /home/modadm/top-output.txt | cut -c 25-31)
Note that $(cmd) is how you execute a command in a subshell. i.e., you can run some commands to compute the value of a variable in your script. You can also use `cmd` (backticks; usually on the tilde key) but that syntax is less clear.
Again, you probably want to calculate this result in a subshell. Also, don't use $ when assigning to variables.
$USEDPCT='echo $USEDMEM / $MAXMEM * 100 | bc'
This can be rewritten as
USEDPCT=$(echo "scale=3; $USEDMEM / $MAXMEM * 100" | bc)
Finally, you want to pipe the contents of the variable into the mail program. The pipe is expecting a program to be on the left hand side. You do this by echo'ing the value of the variable into the pipe.
echo "$USEDPCT" | mail -s "Test Email from MOD Server" test#test.com
To put everything back together:
#!/bin/bash
top -n 1 -b | grep "Mem" > /home/modadm/top-output.txt
MAXMEM=$(grep "Mem" /home/modadm/top-output.txt | cut -c 7-14)
USEDMEM=$(grep "Mem" /home/modadm/top-output.txt | cut -c 25-31)
USEDPCT=$(echo "$USEDMEM / $MAXMEM * 100" | bc -l)
echo "$USEDPCT" | mail -s "Test Email from MOD Server" test#test.com
Others have pointed out problems with your code, but there are much easier options for this, namely not parsing top output at all. Use /proc/meminfo, and awk - you won't need a temporary file.
$ awk '/MemTotal:/{total=$2} \
/MemFree:/{free=$2} \
END{ \
print "Free mem percent: "(free*100/total); \
print "Used mem percent: "((total-free)*100/total) \
}' /proc/meminfo
Free mem percent: 87.7348
Used mem percent: 12.2652
Pipe that to mail or whatever you want.
Try the following script.
#! /bin/bash
memusage=`top -n 1 -b | grep "Mem"`
MAXMEM=`echo $memusage | cut -d" " -f2 | awk '{print substr($0,1,length($0)-1)}'`
USEDMEM=`echo $memusage | cut -d" " -f4 | awk '{print substr($0,1,length($0)-1)}'`
USEDMEM1=`expr $USEDMEM \* 100`
PERCENTAGE=`expr $USEDMEM1 / $MAXMEM`%
echo $PERCENTAGE | mail -s "Test Email" test#test.com
I have corrected your syntax errors. Pl. note the use of command substitution,
like you have written
MAXMEM=/home/modadm/top-output.txt | grep "Mem" | cut -c 7-14.
This is wrong, you need to write
grep "Mem" /home/modadm/top-output.txt | cut -c 7-14
and then enclose it within backquotes(the key at the lefthand side over tab key) to assign final value to a variable.
Also you have written,
$USEDPCT='echo $USEDMEM / $MAXMEM * 100 | bc'
The dollar sign is used wrongly. $ should be used when you are using the value of
a variable.The quotes should be ` (back quote) and not '(single quote). Backquote means the command will be substituted with the output of the command.
Also for floating point bc needs a scale to be set.
Pl. see the modified code. Hope this helps. Pl. note I have not checked the functionality of the mail command that if it is sending mail or not.
top -n 1 -b | grep "Mem" > /home/modadm/top-output.txt
MAXMEM=`grep "Mem" /home/modadm/top-output.txt | cut -c 7-14`
USEDMEM=`grep "Mem" /home/modadm/top-output.txt | cut -c 25-31`
USEDPCT=`echo "scale=2; $USEDMEM / $MAXMEM * 100" | bc `
echo $USEDPCT | mail -s "Test Email from MOD Server" test#test.com

Simpler way of extracting text from file

I've put together a batch script to generate panoramas using the command line tools used by Hugin. One interesting thing about several of those tools is they allow multi-core usage, but this option has to be flagged within the command.
What I've come up with so far:
#get the last fields of each line in the file, initialize the line counter
results=$(more /proc/cpuinfo | awk '{print ($NF)}')
count=0
#loop through the results till the 12th line for cpu core count
for result in $results; do
if [ $count == 12 ]; then
echo "Core Count: $result"
fi
count=$((count+1))
done
Is there a simpler way to do this?
result=$(awk 'NR==12{print $NF}' /proc/cpuinfo)
To answer your question about getting the first/last so many lines, you could use head and tail,e.g. :
cat /proc/cpuinfo | awk '{print ($NF)}' | head -12 | tail -1
But instead of searching for the 12th line, how about searching semantically for any line containing cores. For example, some machines may have multiple cores, so you may want to sum the results:
cat /proc/cpuinfo | grep "cores" | awk '{s+=$NF} END {print s}'
count=$(getconf _NPROCESSORS_ONLN)
see getconf(1) and sysconf(3) constants.
According to the Linux manpage, _SC_NPROCESSORS_ONLN "may not be standard". My guess is this requires glibc or even a Linux system specifically. If that doesn't work, I'd probably take looking at /sys/class/cpuid (perhaps there's something better?) over parsing /proc/cpuinfo. None of the above are completely portable.
There are many ways:
head -n 12 /proc/cpuinfo | tail -1 | awk -F: '{print $2}'
grep 'cpu cores' /proc/cpuinfo | head -1 | awk -F: '{print $2}'
and so on.
But I must note that you take only the information from the first section of /proc/cpuinfo and I am not sure that that is what you need.
And if the cpuinfo changes its format ;) ? Maybe something like this will be better:
cat /proc/cpuinfo|sed -n 's/cpu cores\s\+:\s\+\(.*\)/\1/p'|tail -n 1
And make sure to sum the cores. Mine has got like 12 or 16 of them ;)
unsure what you are trying to do and why what ormaaj said above wouldn't wouldn't work either. my instinct based on your description would have been much simpler along the lines of.
grep processor /proc/cpuinfo | wc -l

How to print out size of physical memory in linux

If I use this grep MemTotal /proc/meminfo in linux terminal, I get MemTotal: 2059908 kB.
Does anybody know how to get numbers only? which will be 2059908?
One way is to filter the output with something like:
grep MemTotal /proc/meminfo | sed 's/[^0-9]//g'
This will remove all characters that aren't digits, as per the following transcript:
pax:~$ grep MemTotal /proc/meminfo
MemTotal: 4122788 kB
pax:~$ grep MemTotal /proc/meminfo | sed 's/[^0-9]//g'
4122788
Try adding this: |awk '{print $2}'
besides looking at /proc/meminfo, any of the following commands on LINUX will help: free, top

Resources