360 lines
14 KiB
TeX
360 lines
14 KiB
TeX
\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}
|