#1: Course overview + the shell + π
While the UoB version of this session will cover the same base material, please expect some differences during the live session.
Update 02/10/23: The contents below have been adjusted to reflect the Missing Semester content covered at UoB. Check our git history for a full list of changes.
Motivation
As computer scientists, we know that computers are great at aiding in repetitive tasks. However, far too often, we forget that this applies just as much to our use of the computer as it does to the computations we want our programs to perform. We have a vast range of tools available at our fingertips that enable us to be more productive and solve more complex problems when working on any computer-related problem. Yet many of us utilize only a small fraction of those tools; we only know enough magical incantations by rote to get by, and blindly copy-paste commands from the internet when we get stuck.
This class is an attempt to address this.
We want to teach you how to make the most of the tools you know, show you new tools to add to your toolbox, and hopefully instill in you some excitement for exploring (and perhaps building) more tools on your own. This is what we believe to be the missing semester from most Computer Science curricula.
Class structure
The class consists of multiple 1-hour lectures/hackβnβtell sessions running during the first and beginning of second term this year. For now, we have 14 exciting sessions lined up, introducing you the shell, editors, version control and more. In essence, we try to cover everything you need to get started as computer scientist frequently working on the command line!
The lectures itself are focused on a particular topic, and most of them are largely independent (with the exception of the different levels of working with the shell). Nonetheless, as the semester goes on we will presume that you are familiar with the content from the earlier lectures. We have lecture notes online, but there will be a lot of content covered in class (e.g. in the form of demos) that may not be in the notes.
The original MIT lectures recorded the lectures and posted the recording online; while our version will be different, they can still provide a good overview of covered topics.
While we cannot promise that all sessions are recorded, you may find information on selected recorded lectures on our discord server.
We are trying to cover a lot of ground over the course, so the lectures may be fairly dense. To allow you some time to get familiar with the content at your own pace, lectures may include a set of exercises that guide you through the lectureβs key points. If you have questions after the lecture, feel free to reach out to us on our Missing Semester Discord Server, or email us at missingsemesterbrum@gmail.com.
Due to the limited time we have, we wonβt be able to cover all the tools in the same level of detail a full-scale class might. Where possible, we will try to point you towards resources for digging further into a tool or topic, but if something particularly strikes your fancy, donβt hesitate to reach out to us and ask for pointers!
Last, we are always trying to extend and optimize our sessions based on your feedback, our interests, and suggestions from the School of Computer Science. If you would like to see anything covered we donβt already plan to cover, or want to provide us our suggestions for improvement, please make sure to fill our feedback form.
Topic 1: The Shell
What is the shell?
Computers these days have a variety of interfaces for giving them commands; fanciful graphical user interfaces, voice interfaces, and even AR/VR are everywhere. These are great for 80% of use-cases, but they are often fundamentally restricted in what they allow you to do β you cannot press a button that isnβt there or give a voice command that hasnβt been programmed. To take full advantage of the tools your computer provides, we have to go old-school and drop down to a textual interface: The Shell.
Nearly all platforms you can get your hand on has a shell in one form or another, and many of them have several shells for you to choose from. While they may vary in the details, at their core they are all roughly the same: they allow you to run programs, give them input, and inspect their output in a semi-structured way.
In this lecture, we will focus on the Bourne Again SHell, or βbashβ for short. This is one of the most widely used shells, and its syntax is similar to what you will see in many other shells. To open a shell prompt (where you can type commands), you first need a terminal. Your device probably shipped with one installed, or you can install one fairly easily.
Using the shell
When you launch your terminal, you will see a prompt that often looks a little like this:
missing:~$
This is the main textual interface to the shell. It tells you that you are on the machine missing
and that your βcurrent working directoryβ, or where you currently are, is ~
(short for βhomeβ). The $
tells you that you are not the root user (more on that later). At this prompt you can type a command, which will then be interpreted by the shell. The most basic command is to execute a program:
missing:~$ date
Sun Aug 6 16:55:00 BST 2024
missing:~$
Here, we executed the date
program, which (perhaps unsurprisingly) prints the current date and time. The shell then asks us for another command to execute. We can also execute a command with arguments:
missing:~$ echo hello
hello
In this case, we told the shell to execute the program echo
with the argument hello
. The echo
program simply prints out its arguments. The shell parses the command by splitting it by whitespace, and then runs the program indicated by the first word, supplying each subsequent word as an argument that the program can access. If you want to provide an argument that contains spaces or other special characters (e.g., a directory named βMy Photosβ), you can either quote the argument with '
or "
("My Photos"
), or escape just the relevant characters with \
(My\ Photos
).
But how does the shell know how to find the date
or echo
programs? Well, the shell is a programming environment, just like Python or Ruby, and so it has variables, conditionals, loops, and functions. When you run commands in your shell, you are really writing a small bit of code that your shell interprets. If the shell is asked to execute a command that doesnβt match one of its programming keywords, it consults an environment variable called $PATH
that lists which directories the shell should search for programs when it is given a command:
missing:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
missing:~$ which echo
/bin/echo
missing:~$ /bin/echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
When we run the echo
command, the shell sees that it should execute the program echo
, and then searches through the :
-separated list of directories in $PATH
for a file by that name. When it finds it, it runs it (assuming the file is executable; more on that later). We can find out which file is executed for a given program name using the which
program. We can also bypass $PATH
entirely by giving the path to the file we want to execute.
Note: You can use Ctrl+C
to terminate a running shell process.
Navigating in the shell
A path on the shell is a delimited list of directories; separated by /
on Linux and macOS and \
on Windows. On Linux and macOS, the path /
is the βrootβ of the file system, under which all directories and files lie, whereas on Windows there is one root for each disk partition (e.g., C:\
). We will generally assume that you are using a Linux filesystem in this class. A path that starts with /
is called an absolute path. Any other path is a relative path. Relative paths are relative to the current working directory, which we can see with the pwd
command and change with the cd
command. cd
can be run without any arguments to return to the home directory, and with an argument with the syntax cd [DIRECTORY]
to move to another directory. In a path, .
refers to the current directory, and ..
to its parent directory:
missing:~$ pwd
/home/missing
missing:~$ cd /home
missing:/home$ pwd
/home
missing:/home$ cd ..
missing:/$ pwd
/
missing:/$ cd ./home
missing:/home$ pwd
/home
missing:/home$ cd missing
missing:~$ pwd
/home/missing
missing:~$ ../../bin/echo hello
hello
Notice that our shell prompt kept us informed about what our current working directory was. You can configure your prompt to show you all sorts of useful information, which we will cover in a later lecture.
In general, when we run a program, it will operate in the current directory unless we tell it otherwise. For example, it will usually search for files there, and create new files there if it needs to.
To see what lives in a given directory, we use the ls
command:
missing:~$ ls
missing:~$ cd ..
missing:/home$ ls
missing
missing:/home$ cd ..
missing:/$ ls
bin
boot
dev
etc
home
...
Unless a directory is given as its first argument, ls
will print the contents of the current directory. Most commands accept flags and options (flags with values) that start with -
to modify their behavior. Usually, running a program with the -h
or --help
flag will print some help text that tells you what flags and options are available. For example, ls --help
tells us:
-l use a long listing format
missing:~$ ls -l /home
drwxr-xr-x 1 missing users 4096 Jun 15 2019 missing
This gives us a bunch more information about each file or directory present. First, the d
at the beginning of the line tells us that missing
is a directory. Then follow three groups of three characters (rwx
). These indicate what permissions the owner of the file (missing
), the owning group (users
), and everyone else respectively have on the relevant item. A -
indicates that the given principal does not have the given permission. Above, only the owner is allowed to modify (w
) the missing
directory (i.e., add/remove files in it). To enter a directory, a user must have βsearchβ (represented by βexecuteβ: x
) permissions on that directory (and its parents). To list its contents, a user must have read (r
) permissions on that directory. For files, the permissions are as you would expect. Notice that nearly all the files in /bin
have the x
permission set for the last group, βeveryone elseβ, so that anyone can execute those programs.
Some other handy programs to know about at this point are mv
(to rename/move a file), cp
(to copy a file), and mkdir
(to make a new directory).
If you ever want more information about a programβs arguments, inputs, outputs, or how it works in general, give the man
program a try. It takes as an argument the name of a program, and shows you its manual page. Press q
to exit.
missing:~$ man ls
Note: You can use clear
to clear the terminal window.
Cat
missing:~$ cat /etc/hostname
Demonstrated in the example above, cat
is a program that concat
enates files. When given file names as arguments, it prints the contents of each of the files in sequence to its output stream.
Regarding input/output streams, we will go into more detail on how to control and interact with these in later lectures on the linux shell.
SSH
Secure shell (SSH) is a protocol used to log in to another computer over a network. The ssh
tool is one of the most important utilities, as being able to use other computers without having to sit in front them is a key feature and something worth mastering. To log in to a remote machine with SSH, the command follows the format ssh <username>@<host>
. This should prompt you for a password, and following authentication, drop you into a shell on the remote machine.
ssh abc123@server.net
# abc123@server.net's password:
# [abc123@server.net ~]$
A versatile and powerful tool
On most Unix-like systems, one user is special: the βrootβ user. You may have seen it in the file listings above. The root user is above (almost) all access restrictions, and can create, read, update, and delete any file in the system. You will not usually log into your system as the root user though, since itβs too easy to accidentally break something. Instead, you will be using the sudo
command. As its name implies, it lets you βdoβ something βas suβ (short for βsuper userβ, or βrootβ). When you get permission denied errors, it is usually because you need to do something as root. Though make sure you first double-check that you really want to do it that way!
Note: Be careful when using sudo
, make sure what youβre running is safe, and you understand what is being done. If misused, root level privileges can damage and possibly even break your system.
One thing you need to be root in order to do is writing to the sysfs
file system mounted under /sys
. sysfs
exposes a number of kernel parameters as files, so that you can easily reconfigure the kernel on the fly without specialized tools. Note that sysfs does not exist on Windows or macOS.
For example, the brightness of your laptopβs screen is exposed through a file called brightness
under
/sys/class/backlight
By writing a value into that file, we can change the screen brightness. An experienced shell userβs first instinct might be to do something like:
$ sudo find -L /sys/class/backlight -maxdepth 2 -name '*brightness*'
/sys/class/backlight/intel_backlight/brightness
$ cd /sys/class/backlight/intel_backlight/
$ sudo echo 3 > brightness
An error occurred while redirecting file 'brightness'
open: Permission denied
This error may come as a surprise. After all, we ran the command with sudo
! This is an important thing to know about the shell. Operations like |
, >
, and <
are done by the shell, not by the individual program. echo
and friends do not βknowβ about |
. They just read from their input and write to their output, whatever it may be. In the case above, the shell (which is authenticated just as your user) tries to open the brightness file for writing, before setting that as sudo echo
βs output, but is prevented from doing so since the shell does not run as root. Using this knowledge, we can work around this:
$ echo 3 | sudo tee brightness
Since the tee
program is the one to open the /sys
file for writing, and it is running as root
, the permissions all work out. You can control all sorts of fun and useful things through /sys
, such as the state of various system LEDs (your path might be different):
$ echo 0 | sudo tee /sys/class/leds/tpacpi::lid_logo_dot/brightness
Next steps
At this point you know your way around a shell enough to accomplish basic tasks. You should be able to navigate around to find files of interest and use the basic functionality of most programs. In the next lecture, we will talk about how to perform and automate more complex tasks using the shell and the many handy command-line programs out there.
Exercises
Most classes in this course are accompanied by a series of exercises. Some give you a specific task to do, while others are open-ended, like βtry using X and Y programsβ. We highly encourage you to try them out.
We have not written solutions for the exercises. If you are stuck on anything in particular, feel free to send us an email describing what youβve tried so far, and we will try to help you out.
- For this course, you need to be using a Unix shell like Bash or ZSH. If you are on Linux or macOS, you donβt have to do anything special. If you are on Windows, you need to make sure you are not running cmd.exe or PowerShell; you can use Windows Subsystem for Linux or a Linux virtual machine to use Unix-style command-line tools. To make sure youβre running an appropriate shell, you can try the command
echo $SHELL
. If it says something like/bin/bash
or/usr/bin/zsh
, that means youβre running the right program. - Create a new directory called
missing
under/tmp
. - Look up the
touch
program. Theman
program is your friend. - Use
touch
to create a new file calledsemester
inmissing
. - Write the following into that file, one line at a time:
#!/bin/sh curl --head --silent https://missing.csail.mit.edu
The first line might be tricky to get working. Itβs helpful to know that
#
starts a comment in Bash, and!
has a special meaning even within double-quoted ("
) strings. Bash treats single-quoted strings ('
) differently: they will do the trick in this case. See the Bash quoting manual page for more information. - Try to execute the file, i.e. type the path to the script (
./semester
) into your shell and press enter. Understand why it doesnβt work by consulting the output ofls
(hint: look at the permission bits of the file). - Run the command by explicitly starting the
sh
interpreter, and giving it the filesemester
as the first argument, i.e.sh semester
. Why does this work, while./semester
didnβt? - Look up the
chmod
program (e.g. useman chmod
). - Use
chmod
to make it possible to run the command./semester
rather than having to typesh semester
. How does your shell know that the file is supposed to be interpreted usingsh
? See this page on the shebang line for more information. - Use
|
and>
to write the βlast modifiedβ date output bysemester
into a file calledlast-modified.txt
in your home directory. - Write a command that reads out your laptop batteryβs power level or your desktop machineβs CPU temperature from
/sys
. Note: if youβre a macOS user, your OS doesnβt have sysfs, so you can skip this exercise.
Feedback
As described before, feel free to fill our feedback feedback form. As bonus, we can also now generate a qr-code using the qrencode command line utility. While this utility is not installed by default (check our later sessions to learn how to install packets), you can give it a try and see if your distribution supports it:
$ echo "https://forms.gle/b25QBSdaZEYd6Cq18" | qrencode -t ansiutf8
βββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββ
ββββ βββββ βββ ββ β ββ β β βββββ ββββ
ββββ β β βββββ βββββββββ β β ββββ
ββββ βββββ ββ βββββ ββββ β βββββ ββββ
ββββββββββββββ βββ βββββ ββββββββββββ
ββββ β ββββ ββββββββββββββ βββββββββ
βββββββββββββββββ β βββββββ βββββββββ
βββββ ββββ ββββββββββββ βββββββββββ
ββββββ ββ ββ β βββ ββββββ ββββββββββ
βββββ ββββββ βββββ ββββββ ββ ββββββ
ββββ ββββββββββββ ββββ β ββ βββββββββ
ββββββββββββ β ββββ ββββ βββ β ββββ
ββββ βββββ ββ β ββββββββ βββ ββββββββ
ββββ β β β β βββββββββββββββ ββββββ
ββββ βββββ β ββββ β ββββββ ββ β βββββ
βββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββ
Licensed under CC BY-NC-SA.