Link to home
Start Free TrialLog in
Avatar of Shweta_Singh
Shweta_Singh

asked on

URGENT !! Debug this ksh script !

I have written a ksh script (options.ksh) that tells me the disk usage for every user in a specific directory that would be passed in as an argument.

printUsage()
{
        print "\nUsage: monitor disk usage for each user in a given directory\n"
        print "        [-h]  : Option. Display the help message. "
        print "        [-u]  : Option. COMING UP !!!!"
        print "        [-l]  : Option. COMING UP !!!!\n\n"

exit 1
}

getUsers()
{
        ls -lsR "${1}" 2>/dev/null | awk '{o[$4]+=$6;}END {for (i in o) print o[i]/1048576, i}'
        exit 1
}

showDiskUsage()
{
        getUsers | sort -rn |\

        awk '{ b=$1" MB" }
                ( $1>=1024 ) { b=$1/1024" GB" }
                ( $1<1 && $1>=.000976 ) { b=$1*1024" KB" }
                ( $1<.00976 ) { b=$1*1048576" bytes" }
                ( print  ": " b }' | awk '/^[a-zA-Z0-9]/ { printf "%-10s %s %s\n", $1, $2,$3 }'

        exit 1
}


showDiskUsageForUser()
{
        showDiskUsage | grep "${USER}" | awk '{print $0}'
        exit 1
}


longList()
{
        ls -lsR "${1}" 2>/dev/null | awk '{print $2, $4, $6, $10}' | grep "${2}" | awk '{print $0}' | awk '/^[l-]/ && NF -eq 10 {print $3, $1, $2, $4}' | sort -rn | more
        exit 1
}



while getopts u:l:h PARAM
do
case $PARAM in

  u) showDiskUsageForUser
       UFLAG=1
       USER=$OPTARG
       ;;

    l) longList
       LFLAG=1
       FEATURE_NAME=$OPTARG
       ;;

    h) printUsage
       ;;

      --) shift
       break
       ;;

    ?) printUsage
       exit -1
       ;;
    esac
done

shift $((OPTIND - 1))


Here is how I would want the output to look like:

./options.ksh /appl
uyg     : 68768GB
kulgui  : 876876MB
ihuih   : 869KB
iugui   : 876 bytes
tryt     : 0 bytes

./options.ksh -u kulgui /appl
 kulgui  : 876876MB

./options.ksh -l kulgui /appl
47035292 -rwxrwxrwx jhull itesisc2.rat.gz
10957732 -rw-rw-r-- kulgui namespace.ns
2744605 -rw-rw-r-- kulgui CS_QMGW_1.loging
2231248 -rwxrwxrwx kulgui itedbea2.rat.gz
2065266 -rw-rw-r-- kulgui ryjgv.outman
1407244 -rw-rw-r-- kulgui rty.datoplk.67576
1013 -rw-rw-r-- kulgui CS.log
305 -rw-rw-r-- kulgui CAP.log
0 -rw-rw-r-- kulgui EvtSrv.msg.7687

./options.ksh -h
        Usage: monitor disk usage for each user in a given directory
        [-h]  : Option. Display the help message.
        [-u]  : Option. COMING UP !!!!
        [-l]  : Option. COMING UP !!!!


THe question is: WHERE AM I WRONG ?
and how can I correct the code ?




Avatar of shmukler
shmukler
Flag of United States of America image

first you want to replace print on top with echo.
shell is not awk
Avatar of Shweta_Singh
Shweta_Singh

ASKER

these thing work on the command line. I made small scripts for every option and it was working fine. Im just wrong somewhere in the organisation somewhere. Never used case satements before.
ASKER CERTIFIED SOLUTION
Avatar of MikeOM_DBA
MikeOM_DBA
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial

PS: Also:
- you coded printUsage twice and forgot the showDiskUsage function.
- USER is a built-in environment variable set to current login user id.
-
can you pls explain me how does this conceptually work ?
I tried defining the functions below the case statements and it didn't recognize the function calls in the case statements.

Also, what is a better method of coding :
To make the function calls in the case satement or to sent variables equal to 1 in the case variables and then use if statement and check the variables. If it's 1, then call the function:  i.e

if [[ UFLAG = 1 ]]
then
  showDiskUsageForUser
fi



yea, I forgot to call the showDiskUsage function. I called it below the case statement and it worked. But it, by default, works on the current directory that i'm working on and not the directory that I pass in. Why ???
there was a syntax error in showDiskUsage


showDiskUsage()
{
        getUsers | sort -rn |\

        awk '{ b=$1" MB" }
                ( $1>=1024 ) { b=$1/1024" GB" }
                ( $1<1 && $1>=.000976 ) { b=$1*1024" KB" }
                ( $1<.00976 ) { b=$1*1048576" bytes" }
                { print  ": " b }' | awk '/^[a-zA-Z0-9]/ { printf "%-10s %s %s\n", $1, $2,$3 }'

        exit 1
}

I just changed { print  ": " b } from ( print  ": " b }

But again, it dosent' accept the directory argument I pass in
>         getUsers | sort -rn |\
>
>        awk '{ b=$1" MB" }

should be

        getUsers | sort -rn |\
        awk '{ b=$1" MB" }


You need to get the directory from the parameters as I suggested:

#...etc...
case $PARAM in

  u)  UFLAG=1
       USER=$OPTARG
       shift
       DIR=$2
      showDiskUsageForUser
       ;;
#...etc...
Notice the shift command.
MikeOM_DBA, either use:
  shift
   DIR=$1

or

  DIR=$2

but
  shift
   DIR=$2

needs 3 arguments to work

True, and the arguments are:

$ script.ksh -u user /path
+-----------------1-----2

$ cat script.ksh
#!/bin/ksh

printUsage() {
        print "\nUsage: monitor disk usage for each user in a given directory\n"
        print "        [-h]  : Option. Display the help message. "
        print "        [-u]  : Option. COMING UP !!!!"
        print "        [-l]  : Option. COMING UP !!!!\n\n"
}
while getopts u:l:h PARAM
do
case $PARAM in

  u) echo "showDiskUsageForUser"
       UFLAG=1
       USER=$OPTARG
       shift
       DIR=$2
       echo "USER=$USER"
       echo "PATH=$DIR"
       ;;

  l) echo "longList"
#... etc ...
#==== Execution:

$ script.ksh -u usrx /path
showDiskUsageForUser
USER=usrx
PATH=/path
$
This method wouldn't get the showDiskUsage function working correct if I call it after the case statement. ie if I want showDiskUsage to be working if no arguments are passed in. What bout this problem ??
This is how I want it to work :

./options.ksh /appl
uyg     : 68768GB
kulgui  : 876876MB
ihuih   : 869KB
iugui   : 876 bytes
tryt     : 0 bytes
if [ $# -le 0 ]; then
   showDiskUsageForUser
   exit
fi
There is one argument being passed: the directory name.

So, I guess the if condition wouldn't be satisfied. Besides what happens with getUsers function ?

getUsers()
{
        ls -lsR "${DIR}" 2>/dev/null | awk '{o[$4]+=$6;}END {for (i in o) print o[i]/1048576, i}'
        exit 1
}

showDiskUsage()
{
        getUsers | sort -rn |\
        awk '{ b=$1" MB" }
                ( $1>=1024 ) { b=$1/1024" GB" }
                ( $1<1 && $1>=.000976 ) { b=$1*1024" KB" }
                ( $1<.00976 ) { b=$1*1048576" bytes" }
                { print $2": "b }' | awk '/^[a-zA-Z0-9]/ { printf "%-10s %s %s\n", $1, $2,$3 }'

        exit 1
}


showDiskUsageForUser()
{
        showDiskUsage | grep "${USER}" | awk '{print $0}'
        exit 1
}


longList()
{
        ls -lsR "${DIR}" 2>/dev/null | awk '{print $2, $4, $6, $10}' | grep "${USER}" | awk '{print $0}' | awk '/^[l-]/ && NF -eq 10 {
print $3, $1, $2, $4}' | sort -rn | awk '{ printf "%-10s %s %s %s\n", $1, $2,$3,$4 }' | more
        exit 1

}



while getopts u:l:h PARAM
do
    case $PARAM in

    u) UFLAG=1
        USER=$OPTARG      
        shift
        DIR=$2
        showDiskUsageForUser
        ;;

    l) LFLAG=1
       USER=$OPTARG
       shift
       DIR=$2
       longList
       ;;

    h) printUsage
       ;;

   --) shift
       break
       ;;

    ?) printUsage
       exit -1
       ;;
    esac
done

shift $((OPTIND - 1))

if [ $# -le 0 ]; then
  showDiskUsage
   exit
fi
> .. if I call it after the case statement. ie if I want showDiskUsage to be working if no arguments are passed ..
and now
>  There is one argument being passed: the directory name.

do you realy know what you want to do? I insist on saying: you don't!

Please make a clear concept of what your script should do and how you want it to behave under different conditions, then you can start implementing the script.

I guess your initial question have been answerd several times in this thread. Please close it and open another one for new problems.
Avatar of Tintin
What Unix/Linux flavour are you running this on.  There are much easier ways to achieve your results depending on what tools you have.
ahoffmann,
I used the wrong terminology. Earlier I meant 'no options', but an argument, which was the directory name. How would showDiskUsage work if no arguments are passed ? It would show the disk usage of some DIRECTRY, right ??  
well, if you differ options and arguments (where options are arguments itself:)
But you see again, that it is very important that you describe your problem unambigious, best witth examples.
well, now do you have any idea of how can I get the following to work:

./options.ksh /appl
uyg     : 68768GB
kulgui  : 876876MB
ihuih   : 869KB
iugui   : 876 bytes
tryt     : 0 bytes

no options, only the directory name.
The above example could be trivally done as:

#!/bin/ksh
cd $1
for i in `du -sk|sort -rn|awk '{print $2}'`
do
  du -sh $i
done

Note that the above assumes your version of du supports the -h flag (that's why it's always important to state what Unix/Linux flavour you are using) and the above example has no error checking.
> no options, only the directory name.
after your done of the while loop over getopts you simply add something like:

  if [ $# -gt 0 ]; then
     DIRS="$1"
     getUsers();
  fi