MoreBash:Exercises - Output and return

From Juneday education
Jump to: navigation, search

stdout

These exercises are about the output from a script and also the "exit status" of a script (which affects the $? variable) which tells you whether a script (or command) was successful or not.

As with all scripts, in order to run the script, e.g. my_script.sh, you need to change the permissions of the file to also include "execute permission" for your user. You can do this by issuing the following command:

$ chmod u+x my_script
$

In the example above, your script is in a file called my_script.sh.

And in order to run the script, just as with any new executable command, there is a great chance that your script isn't in a directory contained in the PATH environment variable. So, if you have created a script, and it is in a directory not in your PATH, you will need to run it by providing the full path to the script. In these exercises, you are typically in the same directory as your newly created script, so if you script is called my_script.sh, you will need to run it like this:

$ ./my_script.sh

Why?

Well, if your script is in a directory not in your PATH variable, and you would just type my_script.sh as if it were just any typical command or program, how would Bash know what you mean? Bash shouldn't look in the current directory (that would be unsafe). So, should Bash look in every directory in your whole file system, until it finds a file called my_script.sh?

No. To keep things reasonable, Bash only looks for scripts in directories included in the PATH variable, unless you provide a relative or absolute path to the script, like ./my_script.sh if you are in the same directory as the script.

This is no different from running any other command. If the directory where ls is wasn't in your PATH variable's list of directories, how would Bash know what you mean by "ls"? It looks for ls in every directory listed in the PATH variable until it finds the file ls. If it wasn't in any of the directories in the PATH variable, it would complain "command not found" (or similar). So, since your scripts typically are not in a directory included in the PATH variable, you need to qualify the relative path to the script, even if you are in the same directory as the script, hence: ./my_script.sh (where "./" means "in current directory").

Output extended information about files

Write a script that loops through the shell scripts (.sh) in the current directory and:

  • prints the file name
  • list long information (ls -al)
  • list the attributes of the file (lsattr)
  • outputs a blank line

Example output:

list-sh.sh
-rwxrwxr-x. 1 hesa hesa 349 Jan 15 14:41 list-sh.sh
--------------e---- list-sh.sh

script-info.sh
-rwxrwxr-x. 1 hesa hesa 104 Jan 15 19:48 script-info.sh
--------------e---- script-info.sh

Expand using link to the right to see a solution.

Create a (text) file, typically called script-info.sh with the following content.

#!/bin/bash

for file in $(ls *.sh)
do
    echo "$file"
    ls -al $file
    lsattr $file
    echo
done

Return values

Output if a file is readable or not

Write a script that loops through the shell files and directories in the current directory and:

  • output "Can read: " followed by the filename if the file is readable by the user
  • output "Can't read: " followed by the filename if the file is readable by the user

Example output:

Can't read: example-file-2.txt
Can't read: example-file-3.txt
Can't read: example-file-4.txt
Can't read: example-file-5.txt
Can read:   example-file-6.txt
Can read:   example-file-7.txt

Expand using link to the right to see a hint.

You can check if you can read a file in several ways. One rather cumbersome way would be to check the output of ls -al. Instead we will recommend to use the program/tool test. You can use it likes this:

test -r example-file-10.txt

and then check the return value. We can do this in the following way:

    test -r $file
    if [ $? -eq 0 ]
    .... etc etc etc

But bash comes with a nice way to do this a bit cleaner:

    if [ -r $file ]

[ actually invokes the tool test :)

To have some files to play around with we recommend you enter the directory bash-output-and-return/example-files that comes with the Juneday Education material for this book. In this directory you will find a script create-files.sh which you can excute to create some files that are readable and some that are not. Execute your script in this directory to checkc if it is working.

Expand using link to the right to see a solution.

Create a (text) file, typically called readable.sh with the following content.

#!/bin/sh                                                                       

for file in $(ls)
do
    # One way of doing the test                                                 
    #    test -r $file                                                          
    #    if [ $? -eq 0 ]                                                        
    # ... and a nicer one                                                       
    if [ -r $file ]
    then
        echo "Can read:   $file"
    else
        echo "Can't read: $file"
    fi
done

Check for shell script

Write a script that checks if there is at least one shell script (.sh) in the current directory. The script shall return:

  • 0 - if there is at least one shell script in the current directory
  • 1 - if there is no shell script in the current directory

Note: this is a rather useless script.

Expand using link to the right to see a solution.

Create a (text) file, typically called atleastone.sh with the following content.

#!/bin/bash

ls *.sh &> /dev/null

if [[ $? != 0 ]]
then
    exit 1
else
    exit 0
fi

Check server

Write a script that

  • checks if a server is up
  • the script shall be given as argument to the script
  • output servername followed by "is up" if the server is up
  • output servername followed by "is down" if the server is down (or does not exist)

The server shall return:

  • 0 - if the server is up
  • 1 - if the server is down
  • 2 - if the user did not provide a server name


To check if a server is up you can use the following command:

ping -W 1 -c 1 192.168.1.114

Expand using link to the right to see a solution.

Create a (text) file, typically called serverup.sh with the following content.

#!/bin/bash

if [ "$1" = "" ]
then
    echo "Missing server name"
    exit 2
fi
SERVER=$1

ping -W 1 -c 1 $SERVER
PING_RET=$?

if [ $PING_RET -ne 0 ]
then
    echo "$SERVER is down"
    exit 1
fi
echo "$SERVER is up"
exit 0

Check server silently

Make the diagnostic output from ping disappear.

Expand using link to the right to see a hint.

You can do redirect stderr and stodut to /dev/null like this:

ping server 2>/dev/null  >/dev/null

Expand using link to the right to see a solution.

Create a (text) file, typically called serverupsilent.sh with the following content.

#!/bin/bash

if [ "$1" = "" ]
then
    echo "Missing server name"
    exit 2
fi
SERVER=$1

ping -W 1 -c 1 $SERVER  2>/dev/null  >/dev/null
PING_RET=$?

if [ $PING_RET -ne 0 ]
then
    echo "$SERVER is down"
    exit 1
fi
echo "$SERVER is up"
exit 0

Get data from server

Write a script that fetches a web page from a server. You shall use the script above to check if the server is up before you request the web page.

You can fecth a web page using several tools. We suggest you use curl. To get the page http://xkcd.com/ you simply type:

curl http://xkcd.com/

The script shall return the following exit codes:

  • 0 - if the server is up
  • 1 - if the server is down
  • 2 - if the user did not provide a server name
  • 3 - if curl failed

Expand using link to the right to see a solution.

Create a (text) file, typically called getserverpage.sh with the following content.

#!/bin/bash

./serverupsilent.sh $1
SERVER_UP=$?

if [ $SERVER_UP -ne 0 ]
then
    # same return values as the script above, so let's reuse them
    exit $SERVER_UP
fi

curl $1
CURL_RET=$?
if [ $CURL_RET -ne 0 ]
then
    exit 3
fi

Links

Source code

Chapter links

previous | next (Control flow)