feat: Add initial chapters and revisions for Assignment 2

This commit is contained in:
Payton Bates committed 2026-09-26 19:10:32 -04:00
1 parent 05fff52f6f
commit 07f65b10e9
8 files changed
+410 -37

No files matched your search

+2 -2
View File
@@ -50,8 +50,8 @@ rules govern access to the Linux hosts once they are provisioned.
\item Interactive access is by \gls{ssh} public key only.
Password authentication is disabled in the server configuration.
The local account password recorded in \ChapterRef{Passwords} authenticates \texttt{sudo} only.
\item Inbound \gls{ssh} is restricted by source address to the workstation
listed above rather than opened to the public Internet.
\item Inbound \gls{ssh} is restricted by source address to the local workstation
rather than opened to the public Internet.
\item Day-to-day work is performed by an unprivileged account. Administrative
rights are granted per command rather than by general membership in the
\texttt{sudo} group.
+18 -21
View File
@@ -7,15 +7,10 @@
\section{Purpose}
This document records the configuration of the development environment used for
\CourseNumber\ and the working practices followed to produce it. For
Assignment~\AssignmentNumber\ it covers three subjects: the \gls{kanban} that
plans and tracks the assignment work, the hosts the environment will comprise,
and the passwords that will govern accounts on those hosts.
It is a working record rather than a one-time report. Each subsequent
assignment extends it, and the document history records what changed and when,
so that the state of the environment at any point in the term can be recovered
from this document alone.
\CourseNumber\ and the working practices followed to produce it.
Each chapter covers one subject, and each assignment adds or revises chapters
as recorded in the document history. The latest revision for Assignment~\AssignmentNumber\
adds \ChapterRef{LinuxCommands}.
\section{Scope and Constraints}
\index{scope!constraints}
@@ -23,15 +18,15 @@ The following constraints apply to this revision.
\begin{itemize}[leftmargin=*]
\item The environment is \emph{specified} here, not provisioned. The hosts
chapter names the machines to be configured and their intended roles; it
does not claim that any host exists, and it therefore presents no
execution \gls{evidence}.
chapter names the machines to be configured and their intended roles.
\item Command-line work was performed on a local workstation running
Ubuntu~24.04 under the \gls{wsl}, not on a course
host. Terminal listings are copied from actual executions.
\item No credential, access token, private key, or account secret appears in
this document. Password rules are documented by derivation hint only, as
described in \ChapterRef{Passwords}.
\item This is an individual submission. Teams have not yet been formalized, so
the board described in \ChapterRef{KanbanSetup} is operated by a single
person and every card is assigned to the author.
\item This is a group submission. Chapters written before teams were formed
were prepared individually and are identified as such in the document history.
\item The document is authored in \LaTeX\ and compiled with pdf\LaTeX\ on
Overleaf. The board is hosted in GitHub Projects. The planned environment
targets Amazon EC2.
@@ -42,18 +37,20 @@ The following constraints apply to this revision.
\toprule \textbf{Item} & \textbf{Expectation}\\ \midrule
Due date & \DueDate\\
Instructor & \Instructor\\
Team & \Author\\
Board & GitHub Projects, \texttt{SSW 590} (private; captured as figures in \ChapterRef{KanbanSetup})\\
Required deliverables & Compiled document; Kanban Setup, Passwords, and Hosts chapters; updated document history\\
Team policy & Individual submission pending team formalization\\ \bottomrule
Required deliverables & Compiled document; Linux Commands chapter; updated document history\\
Team policy & Group submission\\ \bottomrule
\end{tabularx}
\section{Document Organization}
\index{document organization}
\ChapterRef{KanbanSetup} describes the tool selected for the board, the steps
taken to configure it, the policy governing each column, and the inventory of
cards. \ChapterRef{Hosts} names the hosts to be configured and
their roles. \ChapterRef{Passwords} defines the account and password rules for those hosts. \ChapterRef{AIPromptLog} records AI assistance used in preparing
this document.
taken to configure it, the policy governing each column, and the inventory of cards.
\ChapterRef{Hosts} names the hosts to be configured and their roles.
\ChapterRef{Passwords} defines the account and password rules for those hosts.
\ChapterRef{LinuxCommands} records the Linux working-directory setup and the problem-set solutions.
\ChapterRef{AIPromptLog} records AI assistance used in preparing this document.
This document is derived from the \CourseNumber\ assignment template credited on
the Template Attribution page. The template's instructional example chapter and
+359
View File
@@ -0,0 +1,359 @@
\chapter{Linux Commands}
\ChapterLabel{LinuxCommands}
\index{Linux}
\index{Linux!command line}
\index{Linux!working directory}
\index{bash}
\index{symbolic link}
\index{file timestamps}
\section{Purpose}
This chapter records a set of Linux shell commands run in the authors' working
user directories, and the solutions to the accompanying problem set.
Terminal input and output are copied directly from the shell, so each listing is
a record of an actual execution and serves as \gls{evidence} for this chapter.
\section{Environment}
\index{Linux!environment}
The commands were run as the unprivileged user \texttt{payton} on Ubuntu~24.04
under the \gls{wsl} on the author's workstation, in a \texttt{bash} shell.
\section{Working Directory Setup}
\index{Linux!working directory setup}
Figure~\ref{Figure:LxTestSetup} shows the executed setup commands in the order given by
the assignment. Figure~{\ref{Figure:LxTestDirectories}} shows the resulting directory structure,
and Figure~{\ref{Figure:LxTestFiles}} shows the resulting file contents.
\subsection{What the Commands Do}
\index{Linux!command explanations}
\begin{sloppypar}
\begin{itemize}[leftmargin=*]
\item \texttt{mkdir -p \textasciitilde/lx-test \&\& cd \textasciitilde/lx-test}
creates the directory, along with any missing parent directories, and does
not fail if it already exists. The \texttt{\&\&} operator runs \texttt{cd}
only if \texttt{mkdir} succeeds.
\item \texttt{printf "\ldots" > \textit{file}} writes the string to a file,
turning each \texttt{\textbackslash n} into a newline. The \texttt{>}
redirection creates the file or overwrites it if it already exists.
\texttt{printf} is used instead of \texttt{echo} because it handles escape
sequences the same way in every shell.
\item \texttt{dd} with \texttt{if=/dev/zero}, \texttt{of=blob.bin},
\texttt{bs=1K}, and \texttt{count=48} copies $48$ blocks of
$1\,\mathrm{KiB}$ from \texttt{/dev/zero}, producing a file of
$48 \times 1024 = 49152$ zero bytes.
\item \texttt{mkdir -p src/lib tmp archive} creates three directories in one
command; \texttt{-p} creates \texttt{src} as the parent of \texttt{lib}.
\item \texttt{ln -s src/file1.txt link-to-file1} creates a symbolic link. The
stored target is the relative path \texttt{src/file1.txt}, which is
resolved relative to the directory that contains the link.
\item \texttt{touch -t 202401020304 old.txt} creates \texttt{old.txt} with a
modification time of 2024-01-02 03:04 in local time.
\item \texttt{ls -lA} lists each named directory in long format, including
hidden entries but omitting \texttt{.} and \texttt{..}.
\texttt{head} prints the first ten lines of each file under a
file name header; every file here is shorter than ten
lines, so each is shown in full.
\end{itemize}
\end{sloppypar}
\subsection{Interpretation of Results}
\index{Linux!result interpretation}
Figure~\ref{Figure:LxTestDirectories} confirms each step of the setup:
\begin{itemize}[leftmargin=*]
\item \textbf{File sizes:} \texttt{blob.bin} is $49152$ bytes, as computed
above. Each text file's size equals its characters plus one byte per newline.
\item \textbf{Symbolic link:} \texttt{link-to-file1} has type \texttt{l} and
points to \texttt{src/file1.txt}.
\item \textbf{Timestamp:} \texttt{old.txt} is empty and shows the modified timestamp (\texttt{Jan~2~2024}).
\item \textbf{Directories:} \texttt{archive}, \texttt{tmp}, and
\texttt{src/lib} report \texttt{total 0}, confirming they exist and are empty.
\item \textbf{Permissions:} New files are \texttt{rw-r--r--} ($644$) and new
directories are \texttt{rwxr-xr-x} ($755$).
\end{itemize}
\begin{figure}[htbp]
\begin{lstlisting}[numbers=none, columns=fullflexible, keepspaces=true]
payton@paytonpc:~$ mkdir -p ~/lx-test && cd ~/lx-test
payton@paytonpc:~/lx-test$ printf "alpha\nbeta\nGamma\ngamma\nbeta\n" > words.txt
payton@paytonpc:~/lx-test$ printf "id,name,dept\n1,Ada,EE\n2,Linus,CS\n3,Grace,EE\n4,Dennis,CS\n" > people.csv
payton@paytonpc:~/lx-test$ printf "INFO boot ok\nWARN disk low\nERROR fan fail\nINFO shutdown\n" > sys.log
payton@paytonpc:~/lx-test$ dd if=/dev/zero of=blob.bin bs=1K count=48 status=none
payton@paytonpc:~/lx-test$ mkdir -p src/lib tmp archive
payton@paytonpc:~/lx-test$ printf "one two three four\n" > src/file1.txt
payton@paytonpc:~/lx-test$ printf "two three four five\n" > src/file2.txt
payton@paytonpc:~/lx-test$ ln -s src/file1.txt link-to-file1
payton@paytonpc:~/lx-test$ touch -t 202401020304 old.txt
\end{lstlisting}
\caption{Terminal input for setting up the \texttt{lx-test} working directory.}
\label{Figure:LxTestSetup}
\end{figure}
\begin{figure}[htbp]
\begin{lstlisting}[numbers=none, columns=fullflexible, keepspaces=true]
payton@paytonpc:~/lx-test$ ls -lA . src src/lib archive tmp
.:
total 72
drwxr-xr-x 2 payton payton 4096 Sep 26 15:39 archive
-rw-r--r-- 1 payton payton 49152 Sep 26 15:39 blob.bin
lrwxrwxrwx 1 payton payton 13 Sep 26 15:39 link-to-file1 -> src/file1.txt
-rw-r--r-- 1 payton payton 0 Jan 2 2024 old.txt
-rw-r--r-- 1 payton payton 56 Sep 26 15:39 people.csv
drwxr-xr-x 3 payton payton 4096 Sep 26 15:39 src
-rw-r--r-- 1 payton payton 56 Sep 26 15:39 sys.log
drwxr-xr-x 2 payton payton 4096 Sep 26 15:39 tmp
-rw-r--r-- 1 payton payton 28 Sep 26 15:39 words.txt
archive:
total 0
src:
total 12
-rw-r--r-- 1 payton payton 19 Sep 26 15:39 file1.txt
-rw-r--r-- 1 payton payton 20 Sep 26 15:39 file2.txt
drwxr-xr-x 2 payton payton 4096 Sep 26 15:39 lib
src/lib:
total 0
tmp:
total 0
\end{lstlisting}
\caption{Terminal output showing the resulting directories after \texttt{lx-test} setup.}
\label{Figure:LxTestDirectories}
\end{figure}
\begin{figure}[htbp]
\begin{lstlisting}[numbers=none, columns=fullflexible, keepspaces=true]
payton@paytonpc:~/lx-test$ head words.txt people.csv sys.log src/file1.txt src/file2.txt
==> words.txt <==
alpha
beta
Gamma
gamma
beta
==> people.csv <==
id,name,dept
1,Ada,EE
2,Linus,CS
3,Grace,EE
4,Dennis,CS
==> sys.log <==
INFO boot ok
WARN disk low
ERROR fan fail
INFO shutdown
==> src/file1.txt <==
one two three four
==> src/file2.txt <==
two three four five
\end{lstlisting}
\caption{Terminal output showing the resulting file contents after \texttt{lx-test} setup.}
\label{Figure:LxTestFiles}
\end{figure}
\section{Problem Set Solutions}
\index{Linux!problem set}
\subsection{Navigation and File Operations}
\begin{enumerate}[label=\arabic*., leftmargin=*]
\item Show your present working directory path only.
\begin{lstlisting}[style=cmd]
$ pwd
\end{lstlisting}
\item List all entries in the current directory, one per line, including dotfiles.
\begin{lstlisting}[style=cmd]
$ ls -1a
\end{lstlisting}
\item Copy \texttt{src/file1.txt} to \texttt{tmp/} only if \texttt{tmp} exists; do it verbosely.
\begin{lstlisting}[style=cmd]
$ [ -d tmp ] && cp -v src/file1.txt tmp/
\end{lstlisting}
\item Move \texttt{old.txt} into \texttt{archive/} and keep its original timestamp.
\begin{lstlisting}[style=cmd]
$ mv old.txt archive/
\end{lstlisting}
\item Create a new empty file \texttt{notes.md} only if it doesn't already exist.
\begin{lstlisting}[style=cmd]
$ [ -e notes.md ] || touch notes.md
\end{lstlisting}
\item Show disk usage (human-readable) for the \texttt{src} directory only (not total FS).
\begin{lstlisting}[style=cmd]
$ du -sh src
\end{lstlisting}
\end{enumerate}
\subsection{Viewing and Searching}
\begin{enumerate}[label=\arabic*., leftmargin=*, resume]
\item Print line numbers while displaying \texttt{sys.log}.
\begin{lstlisting}[style=cmd]
$ cat -n sys.log
\end{lstlisting}
\item Show only the lines in \texttt{sys.log} that contain \texttt{ERROR} (case-sensitive).
\begin{lstlisting}[style=cmd]
$ grep 'ERROR' sys.log
\end{lstlisting}
\item Count how many distinct words appear in \texttt{words.txt} (case-insensitive).
\begin{lstlisting}[style=cmd]
$ tr '[:upper:]' '[:lower:]' < words.txt | sort -u | wc -l
\end{lstlisting}
\item From \texttt{words.txt}, show lines that start with \texttt{g} or \texttt{G}.
\begin{lstlisting}[style=cmd]
$ grep '^[gG]' words.txt
\end{lstlisting}
\item Display the first 2 lines of \texttt{people.csv} without using an editor.
\begin{lstlisting}[style=cmd]
$ head -n 2 people.csv
\end{lstlisting}
\item Show the last 3 lines of \texttt{sys.log} and keep following if the file grows.
\begin{lstlisting}[style=cmd]
$ tail -n 3 -f sys.log
\end{lstlisting}
\end{enumerate}
\subsection{Text Processing}
\begin{enumerate}[label=\arabic*., leftmargin=*, resume]
\item From \texttt{people.csv}, print only the name column (2nd), excluding the header.
\begin{lstlisting}[style=cmd]
$ tail -n +2 people.csv | cut -d, -f2
\end{lstlisting}
\item Sort \texttt{words.txt} case-insensitively and remove duplicates.
\begin{lstlisting}[style=cmd]
$ sort -fu words.txt
\end{lstlisting}
\item Replace every \texttt{three} with \texttt{3} in all files under \texttt{src/} in-place, creating \texttt{.bak} backups.
\begin{lstlisting}[style=cmd]
$ find src -type f -name '*.txt' -exec sed -i.bak 's/three/3/g' {} +
\end{lstlisting}
\item Print the number of lines, words, and bytes for every \texttt{*.txt} file in \texttt{src/}.
\begin{lstlisting}[style=cmd]
$ wc src/*.txt
\end{lstlisting}
\end{enumerate}
\subsection{Permissions and Ownership}
\begin{enumerate}[label=\arabic*., leftmargin=*, resume]
\item Make \texttt{tmp/} readable, writable, and searchable only by the owner.
\begin{lstlisting}[style=cmd]
$ chmod 700 tmp/
\end{lstlisting}
\item Give group execute permission to \texttt{src/lib} recursively without touching others/owner bits.
\begin{lstlisting}[style=cmd]
$ chmod -R g+x src/lib
\end{lstlisting}
\item Show the numeric (octal) permissions of \texttt{src/file2.txt}.
\begin{lstlisting}[style=cmd]
$ stat -c '%a' src/file2.txt
\end{lstlisting}
\item Make \texttt{notes.md} append-only for the owner via file attributes (if supported).
\begin{lstlisting}[style=cmd]
$ sudo chattr +a notes.md
\end{lstlisting}
\end{enumerate}
\subsection{Links and Find}
\begin{enumerate}[label=\arabic*., leftmargin=*, resume]
\item Verify whether \texttt{link-to-file1} is a symlink and show its target path.
\begin{lstlisting}[style=cmd]
$ [ -L link-to-file1 ] && readlink link-to-file1
\end{lstlisting}
\item Find all regular files under the current tree larger than 40~KiB.
\begin{lstlisting}[style=cmd]
$ find . -type f -size +40k
\end{lstlisting}
\item Find files modified in the last 10 minutes under \texttt{tmp/} and print their sizes.
\begin{lstlisting}[style=cmd]
$ find tmp/ -type f -mmin -10 -printf '%p %s\n'
\end{lstlisting}
\end{enumerate}
\subsection{Processes and Job Control}
\begin{enumerate}[label=\arabic*., leftmargin=*, resume]
\item Show your processes in a tree view.
\begin{lstlisting}[style=cmd]
$ pstree -p "$USER"
\end{lstlisting}
\item Start \texttt{sleep 120} in the background and show its PID.
\begin{lstlisting}[style=cmd]
$ sleep 120 & echo $!
\end{lstlisting}
\item Send a TERM signal to all \texttt{sleep} processes owned by you (don't use \texttt{kill -9}).
\begin{lstlisting}[style=cmd]
$ pkill -TERM -u "$USER" -x sleep
\end{lstlisting}
\item Show the top 5 processes by memory usage (one-shot, not interactive).
\begin{lstlisting}[style=cmd]
$ ps aux --sort=-%mem | head -n 6
\end{lstlisting}
\end{enumerate}
\subsection{Archiving and Compression}
\begin{enumerate}[label=\arabic*., leftmargin=*, resume]
\item Create a gzipped tar archive \texttt{src.tgz} from \texttt{src/} with relative paths.
\begin{lstlisting}[style=cmd]
$ tar -czf src.tgz src/
\end{lstlisting}
\item List the contents of \texttt{src.tgz} without extracting.
\begin{lstlisting}[style=cmd]
$ tar -tzf src.tgz
\end{lstlisting}
\item Extract only \texttt{file2.txt} from \texttt{src.tgz} into \texttt{tmp/}.
\begin{lstlisting}[style=cmd]
$ tar -xzvf src.tgz -C tmp/ --strip-components=1 src/file2.txt
\end{lstlisting}
\end{enumerate}
\subsection{Networking and System Information}
\begin{enumerate}[label=\arabic*., leftmargin=*, resume]
\item Show all listening TCP sockets with associated PIDs (no root assumptions).
\begin{lstlisting}[style=cmd]
$ ss -ltnp
\end{lstlisting}
\item Print your default route (gateway) in a concise form.
\begin{lstlisting}[style=cmd]
$ ip route show default
\end{lstlisting}
\item Display kernel name, release, and machine architecture.
\begin{lstlisting}[style=cmd]
$ uname -srm
\end{lstlisting}
\item Show the last 5 successful logins (or last sessions) on the system.
\begin{lstlisting}[style=cmd]
$ last -n 5
\end{lstlisting}
\end{enumerate}
\subsection{Packages and Services (Debian/Ubuntu)}
\begin{enumerate}[label=\arabic*., leftmargin=*, resume]
\item Show the installed version of package \texttt{coreutils}.
\begin{lstlisting}[style=cmd]
$ dpkg-query -W -f='${Version}\n' coreutils
\end{lstlisting}
\item Search available packages whose names contain \texttt{ripgrep}.
\begin{lstlisting}[style=cmd]
$ apt-cache search --names-only ripgrep
\end{lstlisting}
\item Check whether service \texttt{cron} is active and print its status line only.
\begin{lstlisting}[style=cmd]
$ systemctl status cron | grep 'Active:'
\end{lstlisting}
\end{enumerate}
\subsection{Bash and Scripting}
\begin{enumerate}[label=\arabic*., leftmargin=*, resume]
\item Write a one-liner that loops over \texttt{*.txt} in \texttt{src/} and prints each file's name and line count.
\begin{lstlisting}[style=cmd]
$ for f in src/*.txt; do echo "$f: $(wc -l < "$f")"; done
\end{lstlisting}
\item Write a command that exports CSV rows where \texttt{dept == "CS"} to \texttt{cs.txt} (exclude header).
\begin{lstlisting}[style=cmd]
$ awk -F, 'NR>1 && $3=="CS"' people.csv > cs.txt
\end{lstlisting}
\item Create a variable \texttt{X} with value 42, print it, then remove it from the environment.
\begin{lstlisting}[style=cmd]
$ export X=42; echo "$X"; unset X
\end{lstlisting}
\end{enumerate}