0

I am trying to get the numerical and percentage outputs of free together in a table, which I send to myself per mail. I have tried to combine these into one table for quite a while, but nothing seems to work as I think it should.

#!/bin/bash
PATH=/opt/someApp/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
date="date +%Y%m%d"
file="/usr/local/bin/log/start-info_`$date`.txt"

touch $file
free | awk '/Mem/{printf("Mem: %.1f% "), $3/($2+.0000000001)*100} /Swap/{printf("Swap: %.1f%"), $3/($2+.0000000001)*100}' > /usr/local/bin/test-file.txt
percent=$(cat /usr/local/bin/test-file.txt)
percent="$(echo $percent)"

free -m | awk 'BEGIN{ print("<table border=1>")}
{
print "<tr>"
for ( i = 1; i<=NF ; i++ ) {
printf "<td> %s </td> ", $i
}
printf "<td> %s </td> ", $percent;
print "</tr>"
}
END{
print("</table>")
}' > $file

sed -i 's:<td> total:<td> </td> <td> total:' $file

(
 echo "To: myself@example.com"
 echo "From: server@example.com"
 echo "Subject: startinformation server"
 echo "MIME-Version: 1.0"
 echo "Content-Type: text/html charset=US-ASCII"
 cat $file
 echo
) | /usr/sbin/sendmail myself@example.com

The output of $percent isn't in the mail, it just repeats the previous data in a single cell.

enter image description here

If I put the output of $percent directly into the mail with "echo $percent >> $file", then it shows correctly as "Mem: 16.0% Swap: 0.0%", but I need it to be in the table.

EDIT: Here is an example of free -m:

$ free -m                                                                                                                 
              total        used        free      shared  buff/cache   available
Mem:           3873         616         898           0        2358        2990
Swap:          3872           0        3872

$ free                                                                                                                    
              total        used        free      shared  buff/cache   available
Mem:        3966276      630492     1045640         956     2290144     3062460
Swap:       3965948         780     3965168

In the first file (which I forgot to add at first) is the HTML code:

<table border=1>
<tr>
<td> </td> <td> total </td> <td> used </td> <td> free </td> <td> shared </td> <td> buff/cache </td> <td> available </td> <td>               total        used    >
<tr>
<td> Mem: </td> <td> 3873 </td> <td> 619 </td> <td> 597 </td> <td> 0 </td> <td> 2656 </td> <td> 2987 </td> <td> Mem:           3873         619         597      >
<tr>
<td> Swap: </td> <td> 3872 </td> <td> 0 </td> <td> 3872 </td> <td> Swap:          3872           0        3872 </td> </tr>
</table>

There is only the output of the first awk in the second file:

Mem: 16.0% Swap: 0.0%

What I'm trying to do, is get the output of the second file, so the 16.0% and 0.0%, into the table like this:

<table border=1>
<tr>
<td> </td> <td> total </td> <td> used </td> <td> free </td> <td> shared </td> <td> buff/cache </td> <td> available </td> <td> %used </td> </tr>
<tr>
<td> Mem: </td> <td> 3873 </td> <td> 619 </td> <td> 597 </td> <td> 0 </td> <td> 2656 </td> <td> 2987 </td> <td> 16.0% </td> </tr>
<tr>
<td> Swap: </td> <td> 3872 </td> <td> 0 </td> <td> 3872 </td> <td> 0.0% </td> </tr>
</table>
12
  • 2
    Please avoid using sudo unless it is actually needed, that can save you from a lot of pain. free doesn't require any special permissions so there is no reason to run it with sudo.
    – terdon
    Jun 22 at 11:08
  • 1
    Also, there are a lot of things in your script that just don't make sense. For example, you are getting a file's contents into a variable and then instead of just using the variable you are echoing it and saving in another. Please edit your question, show us the input you have (an example output of free -m on your system, and the contents of /usr/local/bin/test-file.txt—are you sure you want that in /usr/local/bin?) then show us the output you would like to get from that example so we can understand what you are trying to do.
    – terdon
    Jun 22 at 11:10
  • 1
    Thanks, but why would that be a requirement? Is this homework? Why would you even need a file at all? Why not just save the output into a variable directly. Also, please don't post images of text. Instead, copy/paste the text into your question and use the formatting tools to format it as code. We can't use the image to test our solutions.
    – terdon
    Jun 22 at 11:47
  • 1
    What is "it" in the sentence "...to have it inside of /usr/local/bin"? Surely it's the command you're creating, not any output or temp files produced by the command. bin directories are for executables, not log files or any other output.
    – Ed Morton
    Jun 22 at 11:58
  • 1
    It doesn't matter to us where the script is located, the point @terdon and I are making is that regardless of where the script lives it shouldn't be producing output files under a bin directory.
    – Ed Morton
    Jun 22 at 12:06

1 Answer 1

1

Best I can tell this is all you need, i.e. 1 call to free -m, 1 call to awk, and no call to sed:

free -m |
awk '
    BEGIN { print("<table border=1>") }
    {
        if ( NR == 1 ) {
            $0 = "_" FS $0 FS "%used"
            numCols = NF
            $1 = ""
        }
        else {
            $numCols = sprintf("%0.1f%%", ($2 ? ($3 / $2) * 100 : 0))
        }
        print "<tr>"
        for ( i=1; i<=NF; i++ ) {
            printf "<td>%s</td>%s", $i, (i<NF ? OFS : ORS)
        }
        print "</tr>"
    }
    END { print "</table>" }
'

Given the output of free -m you provided, the above will output:

<table border=1>
<tr>
<td></td> <td>total</td> <td>used</td> <td>free</td> <td>shared</td> <td>buff/cache</td> <td>available</td> <td>%used</td>
</tr>
<tr>
<td>Mem:</td> <td>3873</td> <td>616</td> <td>898</td> <td>0</td> <td>2358</td> <td>2990</td> <td>15.9%</td>
</tr>
<tr>
<td>Swap:</td> <td>3872</td> <td>0</td> <td>3872</td> <td></td> <td></td> <td></td> <td>0.0%</td>
</tr>
</table>
2
  • Thank you very much, that worked. Can you explain, why you used the questionmarks in the else statement?
    – user530909
    Jun 22 at 12:37
  • You're welcome. ($2 ? ($3 / $2) * 100 : 0) is just a ternary expression to ensure we don't divide by zero. It says IF $2 is not 0 THEN (?) evaluate ($3 / $2) * 100 ELSE (:) use 0
    – Ed Morton
    Jun 22 at 12:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.