Přeložit do češtiny pomocí Google Translate ...
Labs: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14.
Table of contents
-
Users and
root
- Package management
- File management
- Storage management
- Process management and signals
- Graded tasks
- Changelog
This lab is devoted to a mixture of maintenance tasks. It contains the bare minimum needed for management of your Linux machine. And it also contains few extras that might be useful for your shells scripts.
Users and root
Although we touched this topic already few times, it is probably better to state it explicitly at this point.
Among user accounts on a Linux system, one user has special privileges.
The user is called root
(or superuser), has numerical id of 0 and has
virtually unlimited power over the running machine.
For example, access rights
are actually ignored for root
user (i.e., process running under root
ignores
any of the rw
privileges and can read/write any file).
Unlike on other systems, Linux is designed in such way that end-user
programs are always executed under normal users and never require root privileges.
As a matter of fact, some programs (historically, this was a very common behaviour
for IRC chat programs) would not even start under root
.
root
is needed for actions that modify the whole system. This includes system
upgrade, formatting of a hard-drive or modification of system-wide configuration files.
The strict separation of normal (work) accounts and a superuser comes from
the fact that Linux was designed as a multi-user system.
The philosophy dates back 50+ years where system was shared by many users and only one
of them – root
– was the administrator of the machine.
Today, when typical notebook installations contain only one account, the separation
is often more artificial but still exists.
The truth is that user today is threatened more by a malicious webpage rather than an unauthorized system software update and superuser account was designed to prevent the latter rather than the former. However, the idea of separate user accounts can be still valid today and a careful user may use different accounts for different activities (e.g. browsing social media vs working with your bank account).
sudo
Some programs need privilege escalation, i.e., run with higher privileges and wider permissions than other programs. Some need this by design and we already mentioned the sticky bit on executables that is used when the application always needs the elevated rights (and for any user actually launching the program). But the sticky bit is usable when we want to allow only certain group of users to run a particular command with elevated privileges. Furthermore, some commands require higher privileges only once in a while. Then there is no need to broaden the possible attack vectors.
For these situations, one option is sudo
(homepage).
As the name suggests, it executes (does) one command with superuser privileges.
The advantage of sudo
is that system admin can specify who can run which command
with elevated permissions.
Thus it does not give the allowed user unlimited power over the machine but only
over a selected subset of commands.
For example, it is possible to give a user option to restart a specific service
(e.g. we want to allow a tester to restart a web server) without giving him
control over the whole machine.
Note that the granularity of sudo
stops at the level of programs.
It does not restrict what sudo
does inside the program.
For example, it is possible to impose a restriction, that alice
can
execute dangerous_command
only with --safe-option
.
However, if dangerous_command
reads options also from a ~/.dangerousrc
,
alice
can provide --unsafe-option
there and sudo
cannot
prevent that.
In other words, once the initial check is completed, the program
runs as if it was launched under root
.
That is extremely important for shared machines where the administrator
typically wants to restrict all users as much as possible.
On the other hand, for desktop installations, the typical default is
that the first user created (usually during installation) can sudo
anything.
The reasoning is that it is the only (physical) user and knows the
root
password anyway.
That is why most tutorials on web usually provide the commands for
system maintenance including the sudo
prefix.
However, you should always understand why you need to run sudo
.
Never get into the habit if it does not work, let’s try prepending sudo
.
Also note that there are
multiple options for gaining a root shell
(i.e., sudo bash
).
Note that sudo
is not the only security mechanism present.
We will not discuss other mechanisms in great detail but just to give you
pointer to documentation, there is also
SELinux
or AppArmor
and high-level overview is on
this Wikipedia page.
To try sudo
, you can try running fdisk -l
.
With -l
, it reads information about all disks on your system and displays
information about individual partitions.
Without sudo
, it will display probably only the following message.
fdisk: cannot open /dev/sda: Permission denied
Running it with sudo
displays the actual information.
sudo fdisk -l
Disk /dev/sda: 480 GiB, 515396075520 bytes, 1006632960 sectors
Disk model: QEMU HARDDISK
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xdc505942
Device Boot Start End Sectors Size Id Type
/dev/sda1 * 2048 2099199 2097152 1G 83 Linux
/dev/sda2 2099200 18620415 16521216 7.9G 82 Linux swap / Solaris
/dev/sda3 18620416 1006632959 988012544 471.1G 83 Linux
Note that sudo
typically asks for a password
(though that can be configured).
It is password of the current user, not root’s
(obviously, otherwise you could do su
without needing sudo
at all).
Package management
Software in Linux is usually installed through the means of package manager. The package manager is a special program that takes care of installation, upgrading and removing packages. A package can be anything that could be installed; this includes
- a program (for example, package
ranger
installs the programranger
), - a data file or a configuration (e.g.
libreoffice-langpack-cs
for Czech support inside LibreOffice), - a library (e.g.
gmp
orgmp-devel
providing the GNU arbitrary precision library), - or a meta package (e.g.
xfce
that coversxfce4-terminal
,xfwm4-themes
etc.).
In this sense, Linux is very similar to what you know from the shopping-center-style management of applications on your smartphones. It is very irregular to install software on Linux using a graphical install wizard.
The advantage of using centralized package manager is the ability to upgrade the whole system at once without the need to check updates of individual applications.
Individual packages often have dependencies
– installing one package results in transitive installation of other
packages the first one depends on
(for example, a web browser will require basic graphical support etc.).
It makes the upgrading process a bit more complicated
(for the package manager, not for the user, though).
But it can save some disk space.
And the most important advantage is that different application share
the same libraries (on Linux, they have .so
extension and are somewhat
similar to DLLs on Windows) and it is possible to upgrade a library
even for an otherwise abandoned application.
That is essential when patching security vulnerabilities.
Note that it is possible to install software manually too. From the file-system point of view, there is no difference – the package manager also just copies files to the right directories. However, manually installed software has to be upgraded manually too and generally complicates the setup. So avoid it when possible.
A typical package manager works with several software repositories. You can think about it as if your cell-phone has multiple marketplaces where to choose applications from. It is up to the user to decide which repositories he wants to use. Typically, you will encounter following types of repositories. It is up to each user (administrator) to decide which to use.
- Stable and testing, where the latter provides newer versions of a software with slight possibility of bugs (usually, there is a third repository, often called unstable for the bleeding-edge).
- Free and non-free where the former contains only software without any patent or royalty issues (usually based on US law).
It is also possible to setup your own repository that can be useful if you want to distribute your software to multiple machines (and you cannot publish the packages in the normal repositories because it is, for example, proprietary).
Most distributions also offer some kind of user-repositories support where virtually anyone can publish their software. For Fedora, this is done via Copr.
Note that both official and unofficial repositories offer no guarantees in the legal sense. However, using the official repositories of a given distribution is considered safe, the amount of attacks on software repositories is low and – unlike with many commercial organizations – distribution maintainers are very open in informing about the incidents. It is probably much easier to encounter a malicious application in your smartphone marketplace than to encounter it in an official distribution repository.
dnf
(a.k.a. package manager in Fedora)
Note: Fedora used to have yum
as the package manager and it can be found
in many tutorials on the Internet (even in quite recent ones).
It is considered obsoleted and you shall not use it.
If you are used to yum
from older versions of Fedora or from other RPM-based
distributions, you will find dnf
very similar and in many situations faster
than yum
.
The package manager for Fedora is called DNF.
You can use the search
command to get a list of packages that matches the
given name.
Note that searching is not a privileged operation hence it does not require sudo
.
dnf search arduino
dnf search atool
Note that searching for a very generic term can yield hundreds of results.
Note that the output is in the following format.
atool.noarch : A perl script for managing file archives of various types
ratools.x86_64
The .noarch
and .x86_64
strings describe the nature of the package.
noarch
usually refers to a data package or package using interpreted languages,
while .x86_64
denotes a package with binaries for x86-64 architecture
(e.g., originally written in C or Rust).
To install a software, run dnf
with install
subcommand, giving it the
package name to install.
Here, sudo
is needed as we are modifying the system.
sudo dnf install atool
Some applications are not part of any software repository but you can still download them in a format understandable by your package manager. That is a better situation than installing the files manually because your package manager knows about the files (although it cannot upgrade it automatically). One such example is the Zoom client that has to be installed like this.
sudo dnf install "https://zoom.us/client/latest/zoom_x86_64.rpm"
To upgrade the whole system, simply run sudo dnf upgrade
.
DNF will ask for confirmation and then upgrade all available packages.
Note that unlike on other systems, you can always choose when to upgrade. The system will never reboot the machine for you or display a message about needed restart unless you explicitly ask for it.
If you want to install the whole group of packages, you can use dnf grouplist
to view their list and sudo dnf install @GROUP_NAME
to install it.
The commands above contain the basics for maintaining your Fedora installation with respect to package management. Following links provide more information. The official Wiki page is a good source of information if you already know the system a bit.
For beginners, this guide about DNF and this tutorial are probably a better starting point.
Alternatives to classic package managers
The existence of various package managers has its disadvantages – when using multiple distributions, the user has to know how to operate different package managers. Furthermore, different distributions need to create different packages (compatible with their package managers), which results in more work.
Therefore, an effort has been made to unite the package managers. Snap was created in order to install packages among distributions uniformly. While for some users it is a way to get the software they want as quickly as possible, for some the proprietary nature of Snap and a need for an account at the package store presents potential dangers and shift in Linux open-source ideology.
To demonstrate a problematic example, let’s attempt to install PyCharm. PyCharm is an IDE for Python, which is (unfortunately) mostly directed at Windows users and also offers a charged professional version. No PyCharm package is offered in Fedora.
This is rather an exception – you won’t encounter problems with most open-source software. Actually, even companies that were traditionally oriented towards different OSes offer DNF-based repositories for their products these days. Note that in this case, providing a full repository is the ideal choice. Users can choose whether to enable this repository or not, distribution maintainers can focus on other tools and the company keeps full control over the release cycle and the distribution process.
There are these two options to install PyCharm:
- Use Snap
- Use the ad-hoc installation script. It is downloaded with the PyCharm installation.
Note that the second option is usually frowned-at in general. It requires running a shell script that the user downloads which is generally considered dangerous – you should always examine such scripts. (Obviously, using a package manager also involves downloading and running scripts but the attack surface is a bit smaller. The chances of following a wrong or malicious link are much lower compared to copying them manually from a chat, for example.)
Another issue is that any application downloaded in this way will not be automatically updated.
Which one to use
Snap is not the only alternative to the classic package managers.
Among others, there is Flatpak or AppImage. They can co-exist and it is up to the user to decide which one to choose.
The decision which one to use is influenced by many factors. Generally, using pre-packaged software distributed with your system (distribution) should be preferred.
As a last note – even if the software you want to install does not provide packages for your distribution, you can always create them yourself. The process is out-of-scope for this course but it is actually not very difficult.
File management
Because you already know ranger
and mc
and ls
/cd
and plenty of file-modification utilities, this section will be extremely short.
It will only strengthen your knowledge about file archiving as other
utilities were already covered in previous labs.
Archiving and compression
Archiving on Linux systems typically refers to merging multiple files into one (for easier transfer) and compression of this file (to save space). Sometimes, only the first step (i.e., merging) is considered archiving.
While these two actions are usually performed together, Linux keeps the distinction as it allows combination of the right tools and formats for each part of the job. Note that on other systems where ZIP-file is the preferred format, these actions are blended into one.
The most widely used program for archiving is tar
.
By default, it tries to access your tape archiving device (hence the name).
Because you probably do not have one, you need to execute it with -f
to specify tape-archive filename.
Option -x
is used when extracting files from the archive, option -c
is used to create a new archive from existing files.
tar
itself recognizes -z
or -j
(and few others) to automatically run
a compression program on top of the archive.
However, the general process for creating a compressed file is following.
tar -cf archive.tar dir_to_archive/
gzip archive.tar
tar
creates archive.tar
but gzip
by default compresses archive.tar
into archive.tar.gz
and removes the original file (one could use -k
of gzip
to prevent that).
The same effect can be obtained by using the following shortcut.
tar -czf archive.tar.gz dir_to_archive/
Often gzip
is used alone if you need to compress single file.
Some tools or APIs can even except gzip-compressed file transparently.
Unpacking can be again done in two steps or in a single one with the following command.
tar -xzf archive.tar.gz
Note that like many other file-system related programs, tar
will
overwrite existing files without any warning.
We recommend to install atool
as a generic wrapper around tar
, gzip
,
unzip
and plenty of other utilities to simplify working with archives.
apack archive.tar.gz dir_to_archive/
aunpack archive.tar.gz
Note that atool
will not overwrite existing files by default
(which is another very good reason why to use it).
Note that it is a good practice to always archive a single directory. That way, user that unpacks your archive will not have your files scattered in the current directory but neatly prepared in a single new directory.
To view list of files inside an archive, you can execute als
or
tar -tf archive.tar.gz
(execution with -tvf
instead of -tf
prints also permission bits and other details).
Storage management
Files resides on file systems that are the structures on the actual block devices (typically, disks). Working with file systems and block devices is necessary when installing new system, rescuing from a broken device or simply checking available free space.
Mounts and mount-points
Recall that each file system (that we want to access) is accessible as
a directory somewhere (compared to a letter drive in other systems, for example).
When we can access /dev/sda3
under /home
we say that /dev/sda3
is mounted under /home
, /home
is then called the mount point,
/dev/sda3
is often called a volume.
Most devices are mounted automatically during boot.
This includes /
(root) where the system is as well as /home
where your
data resides.
Note that /dev
, /proc
(among others) are special file systems that are
mounted to these locations.
Hence, the file /proc/uptime
does not physically exist (i.e., there is no
disk block with its content anywhere on your hard-drive) at all.
The file systems that are mounted during boot are listed in /etc/fstab
.
You will rarely need to change this file on your laptop and this file was
created for you during installation.
Note that it contains volume identification (such as path to the partition),
the mount point and some extra options.
When you plug-in a removable USB drive, your desktop environment will typically
mount it automatically.
Mounting it manually is also possible using the mount
utility.
However, mount
has to be run under root
to work
(this thread explains several aspects
why mounting a volume could be a security risk).
Therefore, you need to play with this on your installations where you can become
root
.
It will not work on any of the shared machines.
Technical note: the above text may seem contradictory, as mount
requires root
password yet your desktop environment (DE) may mount the drive automatically without
asking for any password.
Internally, your DE does not call mount
but uses a different program
(today, often based on Udisks and Polkit) that together verify that the mounted device is
actually a removable one and that the user is a local one (i.e., it will not work
over SSH). This program has sticky bit set and thus runs with root
privileges
automatically (the concrete implementation may slightly differ).
To test the manual mounting, plug-in your USB device and unmount it in your GUI
if it was mounted automatically
(note that the usual path the device is mounted is somewhere under /media
).
If you have rotational disk, your USB will probably be available as /dev/sdb1
,
if you have SSD, your USB drive will become /dev/sda1
(consult the following
section about lsblk
to view list of drives).
sudo mkdir /mnt/flash
sudo mount /dev/sdb1 /mnt/flash
Your data shall be visible under /mnt/flash
.
To unmount, run the following command.
sudo umount /mnt/flash
Note that running mount
without any arguments (and even without sudo
–
recall text above) prints list of currently active mounts.
Working with disk images
Linux has a built-in support for working with disk images. That is, with files with content mirroring a real disk drive. As a matter of fact, you probably already worked with them when you setup Linux in a virtual machine or when you downloaded the USB disk image at the beginning of the semester.
Linux allows you to mount such image as if it was a real physical drive and modify the files on it. That is essential for the following areas.
- Developing and debugging file systems (rare)
- Extracting files from virtual machine hard-drives
- Recovering data from damaged drives (rare, but priceless)
Note that for recovering data from damaged drives, the typical approach is to try to copy the data from the file as-is on the lowest level possible (typically, copying the raw bytes without interpreting them as a file system or actual file). Only after you recover the disk (mirror) image, you run the actual recovery tools on the image. That prevents further damage to the hard-drive and gives you plenty of time for the actual recovery.
In all cases, to mount the disk image we need to tell the system to
access the file in the same way as it accesses other block devices
(recall /dev/sda1
from the example above).
There are, as usual, several options.
We can run mount
with -o loop
to do it in one step or run
udisksctl loop-setup
to add the disk image as a removable drive that could
be automatically mounted in your desktop.
Recall that mount
requires sudo
privileges hence you need to execute
the following example on your own machine, not on any of the shared ones.
To try that, you can download this FAT image and mount it.
# Using mount
sudo mkdir /mnt/photos-fat
sudo mount -o loop photos.fat.img /mnt/photos-fat
... (work with files in /mnt/photos-fat)
sudo umount /mnt/photos-fat
# Using udisksctl and auto-mounting in GUI
udisksctl loop-setup -f fat.img
# This will probably print /dev/loop0 but it can have a different number
# Now mount it in GUI (might happen completely automatically)
... (work with files in /run/media/$(whoami)/07C5-2DF8/)
udisksctl loop-delete -b /dev/loop0
Disk space usage utilities
The basic utility for checking available disk space is df
.
Filesystem 1K-blocks Used Available Use% Mounted on
devtmpfs 8174828 0 8174828 0% /dev
tmpfs 8193016 0 8193016 0% /dev/shm
tmpfs 3277208 1060 3276148 1% /run
/dev/sda3 494006272 7202800 484986880 2% /
tmpfs 8193020 4 8193016 1% /tmp
/dev/sda1 1038336 243188 795148 24% /boot
In the default execution (above), it uses bytes.
For a more readable output, run it with -BM
or -BG
(megas and gigas)
or with -h
to let it select the most suitable unit.
Do not confuse df
with du
that can be used to estimate file space usage.
Typically, you would run du
as du -sh DIR
to print total space occupied
by all files in DIR
.
You could use du -sh ~/*
to print summaries for top-level directories in your
$HOME
.
But be careful as it can take quite some time to sum everything and may render
the machine less responsive (it depends on many factors but do not be surprised).
To see how volumes (partitions) are nested and which block devices your kernel
knows about, you may use lsblk
.
On the shared machine, following will appear.
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 480G 0 disk
├─sda1 8:1 0 1G 0 part /boot
├─sda2 8:2 0 7.9G 0 part [SWAP]
└─sda3 8:3 0 471.1G 0 part /
This shows that the machine has 480G disk divided into three partitions.
Tiny /boot
for boostrapping the system, swap partition of 8G and about
470G are left for system and user data.
Using lsblk -o FMT
allows you to customize the output format.
Inspecting and modifying volumes (partitions)
We will leave this topic to a more advanced course. If you wish to learn by yourself, you can start with the following utilities.
fdisk(8)
btrfs(8)
lvs(8)
,pvs(8)
and related ones
Process management and signals
When you start a program (i.e., an executable file), it becomes a process. The executable file and a running process share the code - it is the same in both. However, process also contains the stack (e.g., for local variables), heap, list of opened files etc. etc. – all this is usually considered a context of the process. Often, words running program and process are used interchangeably.
To view list of running processes on your machine, you can execute ps -e
.
However, for interactive inspection, htop is a much nicer
alternative.
We can use htop
to view basic properties that a Linux system binds with each
process.
First of all, each process has a process ID, often just PID
(but not this one).
PID is a number assigned by kernel and used by many utilities for process management.
PID 1 is used by the first process in the system
(0 is reserved as a special value – see fork(2)
if you are interested in details),
when this process terminates, the system shuts down.
Other processes are assigned PIDs incrementally (more or less) and PIDs are eventually
reused.
Note that all this information mentioned below is also available under /proc/PID/
.
Each process has its user that executes it.
It is used to determine access to files, so practically to every resource (recall that
everything is eventually represented as a file).
Note that this information is also visible from the ownership of /proc/PID/
.
htop
then shows memory occupied by the process and CPU utilization.
Interpreting these values it not always straightforward as many applications seem to occupy
hundreds of megabytes of virtual memory but practically need only few kilobytes of physical
memory to work.
But using these columns to check that some program is not using disproportionally
too much memory or CPU is certainly fine.
Machine-readable interface is available under /proc/PID/status
.
The TIME
column shows how long a process is running.
Available under /proc/PID/stat
as well (though the format is a bit daunting at first).
Finally, the last column shows the command-line that was used to execute the program.
Mirror of /proc/PID/cmdline
.
Signals
Linux systems use the concept of signals to communicate asynchronously with a running program (process). The word asynchronously means that the signal can be sent (and delivered) to the process regardless of its state. Compared to communication via standard input (for example), where the program controls when it will read from it.
However, signals do not provide a very rich communication channel. As a matter of fact, kernel defines which signals (i.e., signal numbers) exist and handles some of them by itself (which usually means that the process in question is forcefully terminated). Other signals can be intercepted by the application and acted upon. If the signal is not intercepted by the application, the kernel terminates the application by default.
This is actually expressed in the fact that the utility used to send signals
is called kill
(because usually the target process terminates).
By default, the kill
utility sends signal 15 (also called TERM
) that
instructs the application to terminate.
An application may decide to catch this signal, close its opened files etc.
and then terminate.
Apart from TERM
, we can instruct kill
to send KILL
signal (number 9)
that is handled by kernel only and immediately and forcefully terminates
the application (signal 9 is non-maskable as it cannot be intercepted from
within the application).
Most of the signals are sent to the process in reaction to a specific event.
For example, signal PIPE
is sent when a process is part of a pipe and some
of the other processes in the pipe terminate prematurely (i.e., when they
close their input and the application has nowhere to write their data).
Typically, applications do not react to majority of the signals and kernel
terminates them. (Remember the issue from lab
04.)
For example, when the system is shutting down, it sends TERM
to all of its
processes.
This gives them the option to terminate cleanly.
Processes that are still alive after some time are killed forcefully with KILL
.
Your program would typically react to TERM
(the default “soft” termination),
INT
(Ctrl-C from the keyboard) and perhaps to USR1
or USR2
(the only
user-defined signals).
Note that traditionally, reaction to USR1
is reloading program configuration.
Following Python program reacts to Ctrl-C
by terminating (imports omitted).
# Actual signal callback
def on_signal(signal_number, frame_info):
print("")
print("Caught signal {} ({})".format(signal_number, frame_info))
sys.exit()
def main():
# Setting signal callback
signal.signal(signal.SIGINT, on_signal)
while True:
time.sleep(0.5)
print("Hit Ctrl-C...")
if __name__ == '__main__':
main()
Exercise: write a program that tries to find highest prime number. When terminating, it stores the highest number found so far and on next invocation it continues from there. Solution.
Reacting to a signal in a shell script is also possible using the trap
command.
Note that a typical action for a signal handler in shell is clean-up of
temporary files.
#!/bin/bash
set -ueo pipefail
on_exit() {
echo "Cleaning up..."
rm -f "$MY_TEMP"
trap - EXIT
exit 0
}
MY_TEMP="$( mktemp )"
trap "on_exit" INT QUIT TERM EXIT
echo "Running as $$"
counter=1
while [ "$counter" -lt 30 ]; do
date "+%Y-%m-%d %H:%M:%S | Waiting for Ctrl-C (loop $counter) ..."
echo "$counter" >"$MY_TEMP"
sleep 1
counter=$(( counter + 1 ))
done
The command trap
receives as the first argument the command to execute on
the signal.
Following arguments are signals to react to.
Note that a special signal EXIT
means normal script termination.
Hence, we do not need to call on_exit
after the loop terminates.
Using -
instead of the handler causes the respective handler to be set to
default.
Without this reset in on_exit
, the handler would be called twice after the
user would hit Ctrl-C
(first for INT
caused by Ctrl-C
itself and second by the explicit call to exit
).
From now on, your shell scripts shall always include a signal handler for clean-up of temporary files.
Note the use of $$
which prints current PID.
Alternatively, you can use pgrep <program_name>
to find a PIDs for running programs.
Similarly, you can use killall
to kill processes by name (but be careful as with great power comes great responsibility).
Consult these with manual pages for more details.
Run the above script, note its PID and run the following in a new terminal.
kill THE_PID_PRINTED_BY_THE_ABOVE_SCRIPT
The script was terminated and the clean-up routine was called.
Compare with situation when you comment-out the trap
command.
Run the script again but pass -9
to kill
to specify that you want to
send signal nine (i.e., KILL
).
What happened? Answer.
While signals do not offer a rich communication
(richer communication channel is offered, for example, by D-Bus)
they are at the core of rudimentary process control.
Reasonable reaction to basic signals is a must for server-style applications
(e.g., a web server upon receiving TERM
should complete outstanding requests
but do not accept new ones and terminate afterwards) and a good style for
larger shell scripts (at least, to clean-up temporary files).
Graded tasks
Note that all tasks are supposed to be submitted to GitLab as usual, some of them require to be prepared on the remote machine (but we will check only files in your submission repository).
08/lorem.tar.gz
(15 points)
Archive the directory linux.ms.mff.cuni.cz:/srv/nswi177/lorem
into 08/lorem.tar.gz
.
Ensure that unpacking your archive will result in creation of the lorem
directory
(i.e., only the last one, not full /srv/nswi177/lorem
).
It is necessary to prepare the compressed archive at the remote machine in order to get points
for this task (i.e., do not copy the files from /srv/nswi177/lorem
to your
machine first).
After the archiving and compression is done, upload the file to GitLab as usual.
08/fat.txt
(15 points)
File linux.ms.mff.cuni.cz:~/lab08.fat.img
is a disk image with a single file.
Paste its (decompressed) content into 08/fat.txt
(to GitLab).
Note that we can create the source file ~/lab08.fat.img
only after you login to
the remote machine for the first time.
If the file is not there, wait for the next work day for the file to appear.
Do not leave this task for the last minute and contact us if the file has not appeared as explained in the previous paragraph.
08/proc_read_stats.sh
(15 points)
One of the files under /proc/[pid]
contains (approximate) information about
number of bytes read and written by a process (i.e., the rchar
and wchar
statistics).
Write a shell script that produces output in the following format for all
processes on the machine.
Lines starting with #
are comments and does not have to be in the real output.
# PID : read bytes : written bytes : command-line (cmdline)
# If the information is not available, dash is inserted
1:-:-:/sbin/init
171:40619189:12923788:bash
56824:-:-:-
You do not have to deal with a situation when a process disappears in the middle of the query but your output has to be well formatted at all times.
To allow testing, your script must support reading alternate /proc
location
from the variable PROCFS_BASE
.
In other words, look into ${PROCFS_BASE:-/proc}
.
Sort the output by PID (i.e., run the final output through sort -n
).
Do not print any errors when the process suddenly disappears or when some files are missing (i.e. due to the fact that your list of process from the time you start the script can be different from the list at the end of your script execution).
Update: although it would make sense (because of the focus of the whole lab)
to use pgrep
or ps
, please, scan the file-system.
Otherwise, we will not be able to test your solution
(see also this discussion).
08/quiz.md
(40 points)
Fill-in the quiz from linux.ms.mff.cuni.cz:/srv/nswi177/lab08-quiz.md
and upload it to GitLab (as usual).
Ensure that you place your answer in the **[A1]**
-style markers so that
we can find it easily.
The point of the quiz is not to check that you can copy a text from the Internet but to ensure you understand the principles. Explain things in your own words, feel free to use bullet lists.
Please, try to make your answers concise where possible (obviously, correctness is preferred over brevity but text several pages long is not something we expect for these answers). Thank you!
Update: we managed to upload an older version of the file that stated a total sum of 45 points. Fix was already uploaded, the correct sum is 40 points (the last set of questions is for lower amount of points because they are really easy). Sorry.
08/countdown.sh
(15 points)
Write a script which gets one parameter: number of seconds (nonnegative integer) to count down, and each second it prints time left.
If user hits Ctrl-C
during execution (or sends the TERM
signal), the
script aborts by printing the word Aborted
and exits with the status of 17.
Example:
$ ./countdown.sh 10
10
9
8
7
6
5
4
3
2
1
Each line will appear a second after the previous one. Use sleep 1
to wait between
printing the lines and before exiting.
Therefore, the first number is printed immediately, whereas after the final
line with 1
you still have to wait before your script terminates.
Note that the script will be a little bit slower than the requested time in seconds
(because of the overhead of calling the sleep
command itself) but that is fine.
Example execution when user hits Ctrl-C
is as follows (^C
denotes the place
where the user hit Ctrl-C
and is not an output from your program).
Note that the FAILED
message comes from the echo
and serves only to emphasize
the non-zero exit code.
$ ./countdown.sh 5 || echo "FAILED"
5
4
^C
Aborted
FAILED
Deadline: May 10, AoE
Solutions submitted after the deadline will not be accepted.
Note that at the time of the deadline we will download the contents of your project and start the evaluation. Anything uploaded/modified later on will not be taken into account!
Note that we will be looking only at your master branch (unless explicitly specified otherwise), do not forget to merge from other branches if you are using them.
Changelog
2021-05-10: Add information about als
and tar -tf
.