Disk Capacity Shell Script

Use and complete the template provided. The entire template must be completed. If you don't, your post may be deleted!
I am pretty close I think, but stuck. I don't know how to send an email to the user specified on the command line, and I receive an error stating -ge expecting a unary value(lines 13 and 17), and ']' missing. The class is not on shell scripting, and I managed all of this from scratch myself so any help would be appreciated. I don't know why the variable and comparison isn't working.

  1. The problem statement, all variables and given/known data:
    Create a script sends an email message to the user specified on the command line if any of the filesystems at more than 70% of capacity. The script should not process special filesystems as /proc on the ce.uml.edu. It should only process filesystems which are either locally mounted or are mounted via NFS.
    An individual email should be sent for each filesystem which is at the warning level. There should be a subject on the email with a message "Warning: Filesystem <put filesystem the>here is at <X>% of capacity" If the filesystem is at greater than 90% of capacity, the "Warning" should be changed to "Critical Warning".
    You may use any scripting language including /bin/sh, ksh, bash, awk or perl. Work done in the C-Shell (csh) will not be accepted. This assignment may be done either on ce.uml.edu or on your own Linux/UNIX system.

  2. Relevant commands, code, scripts, algorithms:

  3. The attempts at a solution (include all code and scripts):

#!/bin/sh
# set -x # Uncomment to debug this script
# set -n # Uncomment to check syntax without any execution
# Shell script to monitor or watch the disk space
####Main Script####

df -H | grep -vE '^Filesystem | none' | awk '{ print $1 " " $5 }' | while read
do
 echo $output
 perc=$(echo $output | awk '{ print $1 }' | cut -d'%' �f1)
 part=$(echo $output | awk '{ print $2 }' )

 if [ $perc -ge 90 ]; then
 echo "Critical Warning: Filesystem \"$part\" at �$perc�% of capacity | 
 mail -s "Critical Warning: Filesystem \�$part\� at �$perc�% of capacity�

 elif [ $perc -ge 70 && $perc -lt 90 ]; then
 echo "Warning: Filesystem \"$part\" at �$perc�% of capacity | 
 mail -s "Warning: Filesystem \�$part\� at �$perc�% of capacity�

 fi
done
  1. Complete Name of School (University), City (State), Country, Name of Professor, and Course Number (Link to Course):
    University of Mass, Lowell, Unix/Linux System Admin 90.321-061, Professor Michael Richards, Michael_Richards@uml.edu

Note: Without school/professor/course information, you will be banned if you post here! You must complete the entire template (not just parts of it).

A few things I noticed:

1) you need to read into a variable (I assume output). The syntax would be something like command | while read output . Possibly this is a cut/past error when sharing your code.

2) You are missing ending double quotes in your echo statements that are being used to fill the body of the mail.

3) Your mail commands need to be on the same line as your echo (this might have been a copy/past problem and not something wrong in your code)

4) You are assigning the percentage and partition backwards. The output from the df command is partition ($1) then percentage ($2), but you are assigning percentage from $1 and partition from $2.

5) The reason you are getting 'missing ]' errors is because you cannot use && as a part of a single bracketed expression. The easy fix is to make this two expressions:

if [ $a = "foo" ] && [ $b = "bar" ]
then

I'm not sure that old Bourne shell (sh) supports this, so you might consider using ksh or bash instead.

Hope these suggestions get you going again.

---------- Post updated at 19:59 ---------- Previous update was at 19:52 ----------

Also thought I'd toss in a quick trick. You could make things a bit more efficient by reading directly into your percentage and partition variables. Consider this small script:

ls -al | awk '{printf( "%d %s\n", $5, $NF}' | while read size name
do
    echo "name=$name size=$size bytes"
done

Using printf with %d will also remove your trailing percent sign without the need for invoking a cut process.

1 Like

Reference agama's point 3.

You can use a single backslash at the end of the line to make the two lines be read as one line by the Shell.
Don't forget the email address on the "mail" line. If you are using Linux then "mail" is usually the right command. If you are using unix then "mailx" is the right command.

echo "Critical Warning: Filesystem \"$part\" at �$perc�% of capacity" | \
mail -s "Critical Warning: Filesystem \�$part\� at �$perc�% of capacity� mailaccount@domain.com

1 Like

I made the suggested corrections, but am still receiving the following error messages...

 cut: you must specify a list of bytes, characters, or fields
Try `cut --help' for more information.
diskcapacity.sh: line 13: [: -ge: unary operator expected
diskcapacity.sh: line 17: [: -ge: unary operator expected

I am assuming that something is wrong with the cut syntax, and is causing the errors on 13 and 17. Data isn't getting passed to the variable correctly, but I can't seem to figure it out. The corrected script follows...

#!/bin/bash
# set -x # Uncomment to debug this script
# set -n # Uncomment to check syntax without any execution
# Shell script to monitor or watch the disk space
####Main Script####

df -H | grep -vE '^Filesystem | none' | awk '{ print $1 " " $5 }' | while read $output
do
 echo $output
 perc=$(echo $output | awk '{ print $2 }' | cut -d'%' �f2 )
 part=$(echo $output | awk '{ print $1 }' )

 if [ $perc -ge 90 ]; then
 echo "Critical Warning: Filesystem \"$part\" at �$perc�% of capacity� | \
 mail -s "Critical Warning: Filesystem \�$part\� at �$perc�% of capacity� clay@clay-ubuntu.com

 elif [ $perc -ge 70 ] && [ $perc -lt 90 ]; then
 echo "Warning: Filesystem \"$part\" at �$perc�% of capacity� | \
 mail -s "Warning: Filesystem \�$part\� at �$perc�% of capacity� clay@clay-ubuntu.com

 fi
done

A few minor corrections.
1) Lose the $ from $output on the "while read" line. We only have the $ when referring to the value of a variable.
2) Put double quotes round your string variable $output. It contains two values separated with a space character.
3) The percentage field is like 90% . Therefore the number bit is -f1 not -f2 in the cut statement.

df -H | grep -vE '^Filesystem | none' | awk '{ print $1 " " $5 }' | while read output
do
 echo "$output"
 perc=$(echo "$output" | awk '{ print $2 }' | cut -d'%' �f1 )
 part=$(echo "$output" | awk '{ print $1 }' )
1 Like

Thanks for the help. I made the suggested corrections, but still receive the error message about cut, -ge and an expected unary operator in lines 13 and 17 when I run the script.

Hi, try flipping "-f1" and "-d%" around

$ cut
usage: cut -b list [-n] [file ...]
       cut -c list [file ...]
       cut -f list [-s] [-d delim] [file ...]
1 Like

Please post the current version of the script and any error messages verbatim.

Please post the O/S version, blotting anything confidential with X's,

uname -a

Well spotted Scrutinizer. My cut doesn't misbehave if the parameters are in the wrong order and an example in man cut has the -d before the -f .

Perhaps this is Linux not unix?

1 Like

Interestingly, the POSIX specification also says this:

SYNOPSIS

    cut -b list [-n] [file...]

    cut -c list [file...]

    cut -f list [-d delim] [-s] [file...]

cut

Since the order is explicit in the synopsis, I suspect there must have been some historical implementations that were picky about the order. I don't recall coming across one, but since the error message explicitly says:

cut: you must specify a list of bytes, characters, or fields

I am guessing this is what this particular implementation wants to see first..

1 Like

I cut-and-pasted some of the code and to my surprise the Unix "cut"-command was giving me a similar error. Things looked kinda spooky for a moment:

$ echo hello:boss | cut -d: -f2
boss
$ echo hello:boss | cut -d: �f2
usage: cut -b list [-n] [file ...]
       cut -c list [file ...]
       cut -f list [-s] [-d delim] [file ...]

Then this is what set -x showed:

$ echo hello:boss | cut -d: -f2
+ echo hello:boss
+ cut -d: -f2
boss

$ echo hello:boss | cut -d: �f2
+ echo hello:boss
+ cut -d: $'?\200\223f2'

And this is what od -c showed:

-   d   '   %   '       �  **  **   f   1

So my guess is the OP has not been using a regular ASCII editor to produce his code...

1 Like

@Scrutinizer
I can't reproduce that effect. Perhaps your own computer or the O/P's is using Unicode not ASCII and my cut/paste is correcting the character? Or, as you suggest the O/P has used a non-unix editor.
The O/P could try editing the script with unix vi (or vim ) and retyping the whole line.

The cut with Berkeley unix was a but sensitive to syntax, and we don't know what O/S we have here.
Might be worth trying space characters in the command line as well as following the strict field order:

cut -f 1 -d '%'
1 Like

Right now, if I cut and paste this:

echo hello:boss | cut -d: -f2

I do not get the error.

If I cut-and-paste this:

echo hello:boss | cut -d: -f2

I do get the error.

I have tried this on both OSX and Linux, using a Linux computer, a Mac and a Windows computer as intermediary. If I cut and paste the OP's original post into a here document that I run through od -c , I get the same thing...

1 Like

fwiw, I get the same results as Scrutinzer on Windows 7 to RHEL or Solaris (putty).

1 Like

Brilliant deduction gentlemen.

1) I originally did the cut/paste with IE8 into Reflections 14 telnet which somehow sorted the mess and gave me the correct character.

2) Now if I use IE8 and Microsoft telnet on XP and cut/paste into vi all the funny characters are stripped. I then ran diff to see how different they were.

3) If I use IE8 and cut/paste into Windows Notepad on XP all the funny characters become visible. It's not just the hyphen in the first cut , there are some sloping quotes too. If I then transfer the Notepad version to unix with text file FTP the bad characters are still there.

The script is riddled with them.

sed -n l scriptname

#!/bin/sh$
# set -x # Uncomment to debug this script$
# set -n # Uncomment to check syntax without any execution$
# Shell script to monitor or watch the disk space$
####Main Script####$
$
df -H | grep -vE '^Filesystem | none' | awk '{ print $1 " " $5 }' | whi\
le read$
do$
 echo $output$
 perc=$(echo $output | awk '{ print $1 }' | cut -d'%' \226f1)$
 part=$(echo $output | awk '{ print $2 }' )$
$
 if [ $perc -ge 90 ]; then$
 echo "Critical Warning: Filesystem \\"$part\\" at \223$perc\224% of capacity\
 | $
 mail -s "Critical Warning: Filesystem \\\224$part\\\224 at \223$perc\224% of\
 capacity\224$
$
 elif [ $perc -ge 70 && $perc -lt 90 ]; then$
 echo "Warning: Filesystem \\"$part\\" at \223$perc\224% of capacity | $
 mail -s "Warning: Filesystem \\\224$part\\\224 at \223$perc\224% of capacity\
\224$
$
 fi$

Advice to O/P is to edit the script with vi or vim and correct all the strange characters. The script has almost certainly been edited with a Microsoft Windows editor not a unix editor and it contains characters from a different character set which are causing the script to fail. If the script was not transferred to the unix server with text file ftp, it will probably also have a spurious ^M (carriage return) character at the end of each line which must be removed.

1 Like

Guys. You finally got it. Not sure how that happened, as I was using nano and vi exclusively to create and edit. Starting over and recreating from scratch seemed to have alleviated the issues.

1 Like