Skip to main content

5. Shell functions

Functions can be declared in one of these two forms, which are equivalent:

function name {
commands
return
}
name () {
commands
return
}
  1. A simple example of a function is in the script fun.sh:

    fun.sh
    #!/bin/bash

    # Shell function demo

    function step2() {
    echo "Step 2"
    return
    }

    # Main program starts here

    echo "Step 1"
    step2
    echo "Step 3"
    vim fun.sh
    :q!
    ./fun.sh
  2. Inside a function we can use local variables:

    local-vars.sh
    #!/bin/bash

    # Script to demonstrate local variables

    foo=0 # global variable foo

    funct_1 () {
    local foo # variable foo local to func_1

    foo=1
    echo "funct_1: foo = $foo"
    }

    funct_2 () {
    local foo # variable foo local to func_2

    foo=2
    echo "funct_2: foo = $foo"
    }


    echo "global: foo = $foo"
    funct_1
    echo "global: foo = $foo"
    funct_2
    echo "global: foo = $foo"
    vim local-vars.sh
    :q!
    ./local-vars.sh
  3. Let's display some additional info on the report page, using functions. We would like to display info about:

    • System uptime and load.
    • Disk space.
    • Home space.

    Let's define a function for each of these:

    vim sys_info.sh
    /cat

    Press capital O and input:

    report_uptime () {
    return
    }

    report_disk_space () {
    return
    }

    report_home_space () {
    return
    }

    Press ESC and :w

    Let's call these functions inside the html body:

    /TIMESTAMP

    Press lowercase o and type:

    $(report_uptime)
    $(report_disk_space)
    $(report_home_space)

    Press ESC and :wq

    The script should look like this:
    !/bin/bash

    # Program to output a system information page.

    declare -r TITLE="System Information Report for $HOSTNAME"
    CURRENT_TIME=$(date +"%x %r %Z")
    TIMESTAMP="Generated on $CURRENT_TIME, by $USER"

    report_uptime() {
    return
    }

    report_disk_space() {
    return
    }

    report_home_space() {
    return
    }

    cat << _EOF_
    <html>
    <head>
    <title>$TITLE</title>
    </head>
    <body>
    <h1>$TITLE</h1>
    <p>$TIMESTAMP</p>
    $(report_uptime)
    $(report_disk_space)
    $(report_home_space)
    </body>
    </html>
    _EOF_
    ./sys_info.sh
    The output should look like this:
    <html>
    <head>
    <title>System Information Report for linuxmint</title>
    </head>
    <body>
    <h1>System Information Report for linuxmint</h1>
    <p>Generated on 09/28/23 03:01:28 PM UTC, by dashamir</p>



    </body>
    </html>
  4. We see that each function is replaced by an empty line and we don't know what is going on. Let's display some feedback from each function:

    vim sys_info.sh
    /^report_uptime

    Press o and insert this line:

    echo "Function report_uptime executed."

    Press ESC and then search:

    /^report_disk_space

    Press o and insert this line:

    echo "Function report_disk_space executed."

    Press ESC and then search:

    /^report_home_space

    Press o and insert this line:

    echo "Function report_home_space executed."

    Press ESC and :wq

    The functions should look like this:
    report_uptime() {
    echo "Function report_uptime executed."
    return
    }

    report_disk_space() {
    echo "Function report_disk_space executed."
    return
    }

    report_home_space() {
    echo "Function report_home_space executed."
    return
    }
    ./sys_info.sh
    The output should look like this:
    <html>
    <head>
    <title>System Information Report for linuxmint</title>
    </head>
    <body>
    <h1>System Information Report for linuxmint</h1>
    <p>Generated on 09/28/23 03:13:29 PM UTC, by dashamir</p>
    Function report_uptime executed.
    Function report_disk_space executed.
    Function report_home_space executed.
    </body>
    </html>
  5. Now let's provide the real data:

    uptime
    df -h .
    du -hs $HOME
    vim sys_info.sh
    /^report_uptime

    Type: j dd O.

    cat <<- _EOF_
    <h2>System Uptime</h2>
    <pre>$(uptime)</pre>
    _EOF_
    caution

    Use TAB to indent the lines below cat.

    Press ESC.

    /^report_disk_space

    Type: j dd O.

    cat <<- _EOF_
    <h2>Disk Space Utilization</h2>
    <pre>$(df -h .)</pre>
    _EOF_

    Press ESC.

    /^report_home_space

    Type: j dd O.

    cat <<- _EOF_
    <h2>Home Space Utilization</h2>
    <pre>$(du -hs $HOME)</pre>
    _EOF_

    Press ESC and :wq

    The functions should look like this:
    report_uptime() {
    cat <<- _EOF_
    <h2>System Uptime</h2>
    <pre>$(uptime)</pre>
    _EOF_
    return
    }

    report_disk_space() {
    cat <<- _EOF_
    <h2>Disk Space Utilization</h2>
    <pre>$(df -h .)</pre>
    _EOF_
    return
    }

    report_home_space() {
    cat <<- _EOF_
    <h2>Home Space Utilization</h2>
    <pre>$(du -hs $HOME)</pre>
    _EOF_
    return
    }
    ./sys_info.sh
  6. Check it in browser:

    ./sys_info.sh > sys_info.html
    lynx sys_info.html

    Quit with qy.

Loading asciinema cast...