Labs: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14.

Before class reading

There is nothing new for before class reading for this class.

Instead, review what we have done so far. The related quiz also touches mostly known topics with a bit of manpage reading mixed in.

Before class quiz

The quiz file is available in the 06 folder of this GitLab project.

Copy the right language mutation into your project as 06/before.md (i.e., you will need to rename the file).

The questions and answers are part of that file, fill in the answers in between the **[A1]** and **[/A1]** markers.

The before-06 pipeline on GitLab will test that your answers are in the correct format. It does not check for actual correctness (for obvious reasons).

Submit your before-class quiz before start of lab 06.

Learning outcomes are covered in the previous lab.

Graded tasks (deadline: Apr 3)

These tasks are shared by 05 and 06.

06/dir.sh (30 points)

Create a script for listing file sizes.

The script would partially mimic behaviour of ls: without arguments it lists information about files in the current directory, when some arguments are provided, they are treated as list of files to print details about.

Example run can look like this:

./06/dir.sh /dev/random 06/dir.sh 06
/dev/random  <special>
06/dir.sh          312
06               <dir>

The second column will display file size for normal files, <dir> for directories and <special> for any other file. File size can be read through the stat(1) utility.

Nonexistent files should be announced as FILENAME: no such file or directory. to stderr.

You can safely assume that you will have access to all files provided on the command-line.

You will probably find the column utility useful, especially the following invocation:

column --table --table-noheadings --table-columns FILENAME,SIZE --table-right SIZE

You can assume that there filenames will be reasonable (e.g. without spaces). To simplify things, we will not check exit code to be different when some of the files were not found.

06/scoring.sh (50 points)

Write a shell script that sums points in a tournament.

The scripts reads a simple text format from stdin, where each line consists of two fields (separated by whitespace): team id and number of points.

After reading the data, the script prints sum of points for each team in passwd-style format (fields separated by a colon).

Example run can look like this:

alpha    5
charlie  8
bravo   10
alpha    7
bravo    2
bravo    3

Output:

alpha:12
bravo:15
charlie:8

We expect you would use temporary files to store the points for each team. Use mktemp and clean-up your files afterwards properly.

You can safely assume that the team ids are sane and can be used to create a filename (i.e., no spaces, slashes, colons etc.).

06/sysinfo.sh (50 points)

Write a shell script that is able to print the following information:

  • current system load (see /proc/loadavg)
  • current system (kernel) version (uname -r)
  • number of processors (nproc)

Note that the tests expects that you will use the above commands/files inside your script. Other commands are not mocked and the tests will not work.

When the program is executed without any arguments, it prints the information in the following format.

load=0.05 kernel=5.15.fc34.x86_64 cpus=12

If the program is launched with any of the following options, only the relevant part of the output is displayed:

  • -l or --load for current system load
  • -k or --kernel for kernel version
  • -c or --cpus for number of processors

Running the program with -h or --help should print a short help (see tests for the exact format).

Adding -s or --script will print the individual values each on a separate line.

Examples

$ 05/sysinfo.sh
load=0.05 kernel=5.15.fc34.x86_64 cpus=12
$ 05/sysinfo.sh -k --load
load=0.06 kernel=5.15.fc34.x86_64
$ 05/sysinfo.sh --script
load=0.12
kernel=5.15.fc34.x86_64
cpus=12
$ 05/sysinfo.sh -s -c
cpus=12

06/plot.sh (70 points)

Write a shell script for drawing a labeled barplot. The user would provide data in the following format:

12  First label
120 Second label
1 Third label

The script will print graph like this:

First label (12)   | #
Second label (120) | #######
Third label (1)    |

The script will accept input filename as the first argument and will adjust the width of the output to the current screen width. It will also align the labels as can be seen in the plot above.

You can safely assume that the input file will always exist and that it will be possible to read it multiple times. No other arguments need to be recognized.

Hints

Screen width is stored in the variable $COLUMNS. Default to 80 if the variable is not set. (You can assume it will be either empty (not set) or contain a valid number).

The plot should be scaled to fill the whole width of the screen (i.e. scaled up or down).

You can squeze all consecutive spaces to one (even for labels), the first and second column are separated by space(s).

See what wc -L does.

Note that the first tests use labels of the same length to simplify writing the first versions of the script.

Consider using printf for printing the aligned lables.

The following ensures that bc computes with fractional numbers but the result is displayed as an integer (which is useful for further shell computations).

echo 'scale=0; (5 * 2.45) / 1' | bc -l

Examples

2 Alpha
4 Bravo
# COLUMNS=20
Alpha (2) | ####
Bravo (4) | ########
2 Alpha
4 Bravo
16 Delta
# COLUMNS=37
Alpha (2)  | ###
Bravo (4)  | ######
Delta (16) | ########################