• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1295
  • Last Modified:

Shell scripts and shell function

Please, give me a few example when might it be necessary or advisable to write a shell script instead of a shell function?

cheers,
P.
0
pizdzielec
Asked:
pizdzielec
  • 2
  • 2
1 Solution
 
AnacreoCommented:
Here is an example of a script I wrote in bourne shell  a while ago.  I think it offers a good use pattern for shell scripting with function calls.  Generally you want to use a function call anytime you see repeating patterns in your code, or if you can define that functionality as a discrete component of some procedural call.

Function calls will let you define locally scoped variables, which are variables that are protected from outside influence, or from affecting other areas of your same code.  Support for this is very varied among shell scripting languages, and most do not use scoped variables in function calls.

Function calls also let you pass parameters and return a response allowing you to move whole pieces of logic from one script to another.  This also has the advantage of making the code a lot easier to troubleshoot because you don't have to look at the entire script, just the function that has failed, generally.

So IMHO the number one reason to start using functions is if you see any kind of code or pattern of coed that is repeated in your procedural code.  Once you start identifying these after the fact you'll identify them before you start writing code and produce better code because of it.  All the other benefits will come naturally and you'll start writing procedural code with function calls to make your life easier.  Then you'll realize that your procedural code should probably be written as object oriented code, and go back and want to re-write anything you ever wrote.

Good luck, hope the pattern I set below helps you...


 
#!/bin/sh

###
# checkinterfaces
# 
# Written by Alec Effrat, aeffrat@tribune.com, this script
#   is designed to display the plumbed interfaces and show
#   the speed, and duplex currently configured.  Please
#   e-mail me to add any interface support or if you
#   encounter any bugs.
###

# Only the root user can run the ndd commands
root_check ()
{
  if [ "`/usr/bin/id | /usr/bin/cut -c1-5`" != "uid=0" ] ; then
     echo "Interface $INTERFACE requires root user priveledges."
     ROOT=1
  fi
}

# speed lookup
speed_lookup ()
{
      case $1 in
         0) SPEED="10 Mbit/s" ;;
         1) SPEED="100 Mbit/s" ;;
         10) SPEED="10 Mbit/s" ;;
         100) SPEED="100 Mbit/s" ;;
         1000) SPEED="1 Gbit/s" ;;
         10000000) SPEED="10 Mbit/s" ;;
         100000000) SPEED="100 Mbit/s" ;;
         1000000000) SPEED="1 Gbit/s" ;;
      esac
}

duplex_lookup ()
{
      case $1 in
         0) DUPLEX="link down" ;;
         1) DUPLEX="half" ;;
         2) DUPLEX="full" ;;
         half) DUPLEX="half" ;;
         full) DUPLEX="full" ;;
         ndd_0) DUPLEX="half" ;;
         ndd_1) DUPLEX="full" ;;
      esac
}

# ndd routine
ndd_set ()
{
  RESULT=`ndd -set /dev/$DEVICE $1`
}

ndd_get ()
{
  VALUE=`ndd -get /dev/$DEVICE $1`
}

# kstat routine
kstat_get ()
{
  set - `kstat -p "$DEVICE:$INSTANCE:$INTERFACE:$1"`
  VALUE=$2
}

# Interface Routines
ce_get ()
{
  kstat_get "link_speed"
  speed_lookup $VALUE
  kstat_get "link_duplex"
  duplex_lookup $VALUE
}

qfe_get ()
{
  kstat_get "ifspeed"
  speed_lookup $VALUE
  if [ `uname -r` = "5.8" ]; then
    root_check
    if [ ! $ROOT ]; then
      ndd_set "instance $INSTANCE"
      ndd_get "link_mode"
      duplex_lookup "ndd_$VALUE"
    fi
  else
    kstat_get "link_duplex"
    duplex_lookup $VALUE
  fi
}

nge_get ()
{
  kstat_get "ifspeed"
  speed_lookup $VALUE
  kstat_get "duplex"
  duplex_lookup $VALUE
}

ge_get ()
{
  root_check
  if [ ! $ROOT ]; then
    ndd_set "instance $INSTANCE"
    ndd_get "link_speed"
    speed_lookup $VALUE
    ndd_get "link_mode"
    duplex_lookup "ndd_$VALUE"
  fi
}

dman_get ()
{
  SPEED=internal
  DUPLEX=n/a
}

interface ()
{
  # Break down the interface into device and instance
  # call a function for each interface to set the 
  # SPEED and DUPLEX variables appropriately

  INTERFACE=$1
  set - `echo "$1" | sed -e 's/[0-9]\{1,\}/ &/g;'`
  DEVICE=$1
  INSTANCE=$2 

  case $DEVICE in
    ce) ce_get;; 
    nge|bge) nge_get;; 
    dman) dman_get;;
    ge) ge_get;;
    qfe|hme|eri) qfe_get;;
    *) echo "Unknown interface $INTERFACE";;
  esac
} 

# Print column header information
/usr/bin/echo "Interface\tSpeed\t\tDuplex"
/usr/bin/echo "---------\t-----\t\t------"

# Determine the speed and duplex for each live NIC on the system
for INTERFACE in `/usr/bin/netstat -i | /usr/bin/egrep -v "^Name|^lo0" \
   | /usr/bin/awk '{print $1}' | /usr/bin/sort | /usr/bin/uniq`
do
   unset SPEED; unset DUPLEX; unset DEVICE; unset INSTANCE
   interface $INTERFACE
   /usr/bin/echo "$INTERFACE\t\t$SPEED\t$DUPLEX"
done

Open in new window

0
 
pizdzielecAuthor Commented:
Hi,
Thank you for answer, perhaps it is my fault, but it is not exactly what I'm asking for.
In this case, I'm asking about advantages of standalone shell script over shell function declared, for example, in .bash_profile (the shell does not retain shell functions after I log out).

Cheers,
P.
0
 
AnacreoCommented:
Oh in that case... Is it just for you or for more than just you?

If it's just for you put it in your .bash_profile and be happy.  If it's for any serious functionality or for multiple users, you're better off putting it in a separate script.

Do you really want to lose your cool function because you've now switched to a different user and don't want to have to run bash each time and setup their profile our source yours?

What if you write a script, and accidently write a definition that your new script or other location, say an Xwindow menu definition, it is now dependent on that bash_profile being around.  As soon as you move that shell script to another machine, or run it as another account, or run it in a non login environment, your shell script will mysteriously break.

I'd limit yourself to just interactive command line doodads with a bash_profile definition, anything non-interactive, dependent upon by other scripts/processes, or expected to be used by multiple-users should definitely not be in a .bash_profile.

Hope that is more in line with your question, sorry for the misfire on understanding the original question.
0
 
pizdzielecAuthor Commented:
HI,

Thank you, now I understand.

Cheers,
P.
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now