Logo

Linux Commands, Part 2: Processes and DevOps

21 min read
Lesson slides
1 / 18

Operating Systems I - Lesson 10

Linux Commands, Part 2: Processes and DevOps

Inspect and control running processes, then use the core DevOps command set for privilege, text processing, and system and network information.

By the end of this lesson you will be able to inspect and control running processes on Linux, and use the core DevOps command set for privilege management, text processing, and system and network information.

Objectives

  • Define a process and its states, and read ps, ps -u, ps -A, ps aux, and top.
  • Send signals with kill, kill -9, kill -L, and pkill, and set process priority with nice and renice.
  • Explain what DevOps means and why it replaced the older, siloed development-and-operations model.
  • Use the core DevOps command set: sudo, chown, id, find, grep, tail, sort, cut, tr, sed, diff, dd, tar/gzip, df, du, free, ifconfig, ping, telnet, hostname, and history.

Prerequisites

  • A working Linux terminal (a native installation, a virtual machine, or WSL).
  • Comfort with basic navigation commands (pwd, cd, ls, mkdir, cp, mv, rm) and with cat and chmod.
  • A regular user account with sudo access, needed for a small number of steps.
  • An active network connection, needed for the ping and telnet steps.
  • telnet: which is not installed by default on some minimal Linux setups (including some WSL images); if the command is not found, install the client package your distribution provides for it.
  • ifconfig: which some newer or minimal Linux setups (including some WSL images) do not install by default; if the command is not found, install the package your distribution provides for it.

What Is a Process

A process is a program in execution. The moment you run a command, the operating system loads it into memory, assigns it a unique Process ID (PID), and starts tracking it. Every command you type starts at least one process.

Linux processes fall into two types:

  • Foreground processes, also called interactive, depend on the user for input; the terminal waits for them to finish before accepting a new command.
  • Background processes, also called non-interactive or automatic, run independently; the terminal is free to accept new commands while they run.

A process also moves through a small set of states between the moment it is created and the moment it terminates:

  • Running: executing, or ready to execute.
  • Sleeping: waiting for a resource (disk, network, user input). Split into interruptible sleep, which wakes to handle a signal, and uninterruptible sleep, which does not.
  • Stopped: paused after receiving a stop signal.
  • Zombie: finished executing, but its entry remains in the process table.
stateDiagram-v2
    [*] --> Running
    Running --> Sleeping: waiting for a resource
    Sleeping --> Running: resource becomes available
    Running --> Stopped: stop signal received
    Running --> Zombie: process finishes
    Zombie --> [*]

A process starts running, may repeatedly sleep while it waits on a resource, may be paused into the stopped state, and when it finishes, ends as a zombie with its entry remaining in the process table.

Viewing Processes with ps and top

ps (process status) prints a snapshot of processes at the moment it is run. Unlike top, its output does not refresh automatically.

ps

Plain ps lists only the processes attached to the current terminal, with four columns:

ColumnMeaning
PIDthe process ID
TTYthe terminal the process is attached to
TIMEtotal CPU time the process has used so far
CMDthe name of the command that started the process

To see more detail about each process, add the -u option:

ps -u

This adds %CPU, %MEM, and a STAT column showing the process state, using the same letters as top (explained below).

To list every process on the system instead of just the current terminal's, use:

ps -A

ps aux is another commonly used form of the command. It lists every process on the system in the same detailed %CPU/%MEM/STAT format that ps -u uses:

ps aux | grep firefox

The pipe (|) sends that full process table into grep firefox, which keeps only lines mentioning firefox, a quick way to find a specific program's PID without scrolling through the whole table.

top shows the same kind of information as ps aux, but live, refreshing every few seconds:

top

The columns in top are:

ColumnMeaning
PIDunique process ID
USERthe username that owns the process
PRthe scheduling priority given to the process
NIthe process's nice value (see priority, below)
VIRTamount of virtual memory used
RESamount of physical memory used
SHRamount of memory shared with other processes
Sprocess state: R running, S sleeping, D uninterruptible sleep, T traced or stopped, Z zombie
%CPUpercentage of CPU used
%MEMpercentage of RAM used
TIME+total CPU time consumed
COMMANDthe command that started the process

Inside top, the arrow keys move the selection, q quits, and k on a highlighted process kills it.

Signals and Killing Processes

Sending a signal to a process needs a process running long enough to receive it. Appending an ampersand (&) to a command starts it as a background process instead of a foreground one, so the shell returns a prompt immediately instead of waiting for it to finish:

sleep 300 &

The shell prints a line such as [1] 20458. The number after the PID, 20458, is what the kill examples below need; the bracketed number in front of it is a job number and is not needed here.

kill sends a signal to a process, most commonly to ask it to terminate. With no signal named, it sends the default, number 15, SIGTERM, which asks the process to shut down cleanly.

kill 20458

Some processes ignore SIGTERM. In that case, SIGKILL (signal 9) terminates the process unconditionally, without giving it a chance to clean up:

kill -9 20458

To see the full list of signal names and numbers kill can send, use:

kill -L

kill always needs a PID. pkill targets a process by name instead, useful when the PID is not known:

pkill sleep

pkill sleep asks every process named sleep to end, without needing its PID first.

Process Priority with nice and renice

Linux schedules CPU time between processes using a priority value called the niceness, ranging from -20 (highest priority) to 19 (lowest priority), with 0 as the default. It is visible in the NI column of top.

To start a new process with a chosen niceness, use nice:

nice -n 10 sleep 300

This starts sleep with a niceness of 10, so it yields CPU time to more important processes while it runs. To change the niceness of a process already running, use renice with its PID:

renice 10 -p 20458

-p marks the number that follows it, 20458, as a PID rather than some other kind of argument. This sets the niceness of PID 20458 to 10 without restarting it.

What DevOps Means

Software development traditionally split into two departments. The development team designed, planned, and built the system. The operations team tested and deployed whatever development produced, then reported back any bugs or rework needed. Because that feedback often arrived only after development had moved on to the next project, a single project could take weeks or months longer to close, with development sitting idle while it waited. This gap is often called the wall of confusion.

DevOps brings the two teams together to work in collaboration instead of in sequence. Its symbol is an infinity loop, representing a continuous process of building, testing, deploying, and improving. Adopters adapt faster to change and deliver more consistent, smoother deployments, even though closer collaboration brings its own communication challenges.

The DevOps lifecycle is carried out in phases, each commonly supported by its own tooling:

  1. Plan: the development team defines the objectives the application must deliver.
  2. Code: developers work on the same codebase, storing versions in a repository with a tool such as Git, which tracks every change made to a set of files over time and lets several people merge their changes back together, and merging changes as needed. This is version control.
  3. Build: the code is turned into an executable form with tools such as Maven and Gradle, which automate compiling source code and assembling it into a runnable package.
  4. Test: the build is checked for bugs; the most popular tool for this kind of automated testing is Selenium.
  5. Release and deploy: once testing passes, operations deploys it to the working environment; the most prominent tools used to automate this phase are Ansible, Docker, and Kubernetes.
  6. Monitor: the running product is continuously monitored; Nagios is one of the top tools used to automate this phase.
  7. Feedback: what monitoring discovers is fed back into planning, closing the loop.

The step tying build, test, and deployment together is continuous integration: a tool such as Jenkins, which automatically builds and tests newly committed code, sends it to be built and tested automatically, and on to deployment if it passes.

flowchart LR
    A["Plan"] --> B["Code (Git)"]
    B --> C["Build (Maven, Gradle)"]
    C --> D["Test (Selenium)"]
    D --> E["Release / Deploy (Ansible, Docker, Kubernetes)"]
    E --> F["Monitor (Nagios)"]
    F -.feedback.-> A
    B -. "sent for build + test, Jenkins" .-> D
    D -. "passes, Jenkins" .-> E

The solid arrows trace the loop: planning feeds coding, coding feeds building, building feeds testing, testing feeds deployment, deployment feeds monitoring, and monitoring feeds back into planning. The dotted arrows show Jenkins sending newly committed code straight into a combined build-and-test step, then on to deployment whenever it passes.

Large organizations such as Amazon, Netflix, Walmart, Facebook, and Adobe have adopted DevOps. Netflix is a well known example: after launching its streaming service in 2007, an estimated one hour of downtime by 2014 would have cost around $200,000. In response it built the Simian Army, a tool that continuously introduces failures into its own environment without affecting real users; this chaos motivated developers to build systems that keep working even when parts of the infrastructure fail.

Superuser Privileges and Ownership

sudo (superuser do) runs a single command with root privileges instead of the current user's. It is required for commands that manage users, groups, or system-wide settings.

sudo useradd student1
sudo passwd student1

The first line creates a user account named student1 with root privileges; the second sets its password. The same pattern covers sudo groupadd (create a group), sudo userdel (delete a user), sudo groupdel (delete a group), and sudo usermod -g (change a user's primary group).

chown (change owner) changes the owner, and optionally the group, of a file or directory.

sudo chown student1:students report.txt

student1:students sets the owner to student1 and the group to students; report.txt is the target file. sudo goes in front because changing a file's owner is a privileged operation.

id prints the identity behind a user account: their numeric user ID, their group ID, and every group they belong to.

id student1

Run with no argument, id reports this same information for the current user instead. id -u prints only the numeric user ID, and id -G prints only the group IDs, without the names:

id -u student1   # -> 1001
id -G student1   # -> 1001 1002 27

Searching and Viewing Files and Text

find walks a directory tree looking for files and directories that match a given condition, and can run a command against every match it finds.

find . -links 1 -exec ls -l {} \;

. is where the search starts, the current directory; -links 1 matches only files with exactly 1 link; -exec ls -l {} \; runs ls -l on every match, with {} standing in for the matched file's path and \; marking the end of the command being run. -inum 12345 matches by inode number instead of link count, and -ok behaves like -exec but asks for confirmation before running the command on each match.

grep searches inside files for lines that match a pattern.

grep -n "ERROR" server.log
grep -in "error" server.log

The first command searches server.log for ERROR; -n prints each matching line's number alongside the text. The second adds -i, so grep also matches error regardless of upper or lower case, while still printing line numbers because -n is combined with it. grep -c counts matching lines instead of printing them, and grep -v prints only the lines that do NOT match:

grep -c "ERROR" server.log   # -> 3, a count, not the matching lines themselves
grep -v "ERROR" server.log   # -> every line that does NOT contain ERROR

tail prints the last part of a file, useful for checking the newest lines of a log without opening the whole thing.

tail -n 5 server.log

-n 5 limits the output to the last 5 lines of server.log; without -n, tail defaults to the last 10 lines. tail +25 server.log is another form of the command, and tail -c 100 server.log prints only the last 100 bytes.

Sorting and Transforming Text

sort arranges the lines of a file either alphabetically or numerically.

sort -n scores.txt

-n tells sort to compare lines as numbers rather than text, so 9 sorts before 10. sort -r reverses the order, and sort -f ignores letter case:

sort -r scores.txt   # -> the same lines, largest first
sort -f names.txt    # -> alphabetical order, treating "ali" and "Ali" as equal

cut extracts a portion of each line of a file, based on character position.

cut -c1-5 codes.txt

-c1-5 selects characters 1 through 5 of every line, regardless of what those characters are. The result is a single column holding only that fixed slice of each line.

tr (translate) reads from standard input and replaces or deletes characters, one at a time.

cat greeting.txt | tr 'a-z' 'A-Z'

cat greeting.txt prints the file, the pipe sends that text into tr, and 'a-z' 'A-Z' maps every lowercase letter to its uppercase equivalent. tr -d deletes the listed characters instead of replacing them, and tr -s squeezes repeats down to one occurrence:

echo "aabbccdd" | tr -d 'ab'   # -> ccdd, every a and b removed
echo "aabbccdd" | tr -s 'a-z'  # -> abcd, each run of repeats squeezed to one

sed (stream editor) edits text non-interactively, most often used to find and replace a pattern.

sed 's/linux/Linux/' notes.txt

's/linux/Linux/' is a substitute instruction: s for substitute, linux the pattern to find, Linux the replacement. By default sed prints the edited text to the terminal without changing the file.

Comparing Files and Copying Raw Data

diff compares two files line by line and prints the lines that differ.

diff test.txt test1.txt

test.txt and test1.txt are the two files compared. Lines that exist only in one file, or differ between the two, are printed with markers showing which file each came from.

dd is a command-line utility that copies and converts data at the level of raw blocks rather than files, which is why device files (representing whole disks or partitions) can be read from or written to with it just like ordinary files. Because it operates directly on raw devices, its target always needs double-checking before running it; an incorrect one can overwrite data that was never meant to be touched.

dd if=/dev/zero of=testfile bs=1M count=10

if= names the input, here /dev/zero, a special device that produces an endless stream of zero bytes; of= names the output, an ordinary file in this case; bs=1M sets the block size to 1 megabyte; count=10 copies 10 of those blocks, so the result is a 10 MB file filled with zeros. Writing to an ordinary file like this is safe to practice with; the case that needs the double-checking is pointing of= at a device file such as /dev/sda instead, which would overwrite that device's raw data.

tar and gzip remain useful for packaging files before moving or backing them up: tar czf archive.tar.gz project/ bundles and compresses a project directory in one step, and tar xzf archive.tar.gz reverses it. c creates a new archive, z pipes it through gzip compression, and f names the archive file; x extracts instead of creating, reversing the operation.

System and Network Information

df (disk free) reports how much space is used and available on each mounted filesystem, and du (disk usage) reports how much space a specific directory occupies.

df -h
du -hs ~

-h prints sizes in human-readable units (KB, MB, GB) instead of raw bytes; -s on du prints one summary total for the target directory instead of a line per file inside it.

free reports how much RAM and swap space are in use.

free -h

The output has one row for physical memory (Mem) and one for swap (Swap), each broken into total, used, and free columns, again in human-readable units.

ifconfig (interface configuration) displays or sets up the machine's network interfaces.

ifconfig -a

-a shows every interface, including ones currently down.

ping sends packets to a host and reports whether, and how quickly, it responds, which makes it the standard first check for network connectivity.

ping -c 4 google.com

-c 4 limits ping to exactly 4 packets before it stops on its own; without -c it keeps sending until interrupted with Ctrl+C.

telnet connects to a remote Linux machine to run programs and perform remote administration on it. Naming a port after the host checks whether a specific service there is reachable.

telnet google.com 80

google.com is the host to connect to and 80 is the port, the one web servers listen on; a successful connection prints Connected to google.com. and Escape character is '^]'., confirming the service answered. telnet localhost instead targets the local machine on the default telnet port, but only succeeds if a telnet server is installed and running there; on a typical Linux, VM, or WSL setup nothing listens on that port, so the attempt fails immediately with Connection refused instead of opening a session. Interrupt an open session with Ctrl+C to return to the prompt.

hostname prints the name the machine is known by on the network.

hostname

Finally, history lists the commands previously typed in the current shell session, each one numbered.

history 10

history 10 limits the listing to the 10 most recent commands, useful for quickly recalling one typed earlier in the session.

Lab Tasks

Task 1: Exploring Running Processes

  1. Open a terminal and run ps. Expected output: a short table with PID, TTY, TIME, and CMD columns, limited to the shell itself and this command.

  2. Run ps -u. Expected output: the same kind of listing, now with %CPU, %MEM, and STAT columns.

  3. Run ps -A. Expected output: a much longer list, including system processes plain ps did not show.

  4. Run ps aux | grep bash. Expected output: one or more lines whose COMMAND column contains bash, each showing that process's PID, %CPU, and %MEM.

  5. Run top. Expected output: a continuously refreshing table sorted by CPU usage. Press q to leave top and return to the prompt.

Task 2: Signals, Killing, and Priority

  1. Run sleep 600 &. Expected output: a line such as [1] 20777, where 20777 is the PID to use in the following steps.

  2. Run kill -L. Expected output: a numbered list of signal names, including 9) SIGKILL and 15) SIGTERM.

  3. Run kill <its PID>. Expected output: no output from kill itself.

  4. Run ps aux | grep sleep. Expected output: the sleep 600 process from step 1 no longer appears; only the grep command itself shows up, matching its own search pattern.

  5. Run sleep 600 & again, then kill -9 <its PID>. Expected output: the process ends immediately, without the cleanup a plain kill would allow.

  6. Run sleep 500 & twice, then pkill sleep. Expected output: both background processes end; ps aux | grep sleep afterward no longer lists a sleep 500 process, only the grep command itself matching its own pattern.

  7. Run nice -n 10 sleep 400 &, then top. Expected output: the sleep 400 process appears with its NI column already set to 10 instead of the default 0.

  8. Run sleep 400 & with no nice prefix, then top to confirm its NI column reads 0, the default niceness. Note its PID, then in another terminal run renice 10 -p <PID>. Expected output: renice prints the old and new priority, 0 and 10, and NI in top updates to 10.

Task 3: Text-Processing DevOps Commands

  1. Create a small sample file:

    printf "3,Ali,90\n1,Sara,75\n2,Omar,60\n" > students.csv
  2. Run tail -n 2 students.csv. Expected output: the last two lines of the file, 1,Sara,75 then 2,Omar,60.

  3. Run sort -n students.csv. Expected output: the three lines reordered by the first field: 1,Sara,75, then 2,Omar,60, then 3,Ali,90.

  4. Create a fixed-width sample file and extract by character position:

    printf "12345ABCDE\n67890FGHIJ\n" > codes.txt
    cut -c1-5 codes.txt

    Expected output: 12345 then 67890, the first five characters of each line.

  5. Run grep -n "Omar" students.csv. Expected output: 3:2,Omar,60.

  6. Run grep -in "sara" students.csv. Expected output: 2:1,Sara,75, matched even though the search term was lowercase and the file has Sara capitalized.

  7. Run sed 's/Omar/Omar Khaled/' students.csv > students_updated.csv, then diff students.csv students_updated.csv. Expected output:

    3c3
    < 2,Omar,60
    ---
    > 2,Omar Khaled,60
  8. Run cat students.csv | tr 'a-z' 'A-Z'. Expected output:

    3,ALI,90
    1,SARA,75
    2,OMAR,60
  9. Run dd if=/dev/zero of=testfile bs=1M count=10, then ls -lh testfile. Expected output: dd prints a summary such as 10+0 records in, 10+0 records out, and 10485760 bytes (10 MB) copied, and ls -lh testfile shows a 10M file. Remove it afterward with rm testfile, since it was only created for practice.

Task 4: System, Ownership, and Network Information

  1. Run df -h then du -hs ~. Expected output: a filesystem table from df, and a single size such as 2.3G for your home directory from du.

  2. Run free -h. Expected output: two rows, Mem and Swap, each showing total, used, and free in human-readable units.

  3. Run hostname then ifconfig -a. Expected output: the machine's name, followed by a block per network interface showing its IP address and status.

  4. Run ping -c 4 google.com. Expected output: four reply lines each reporting a round-trip time, followed by a summary showing 0 percent packet loss (if connected).

  5. Run telnet google.com 80. Expected output: Trying <an IP address>... followed by Connected to google.com. and Escape character is '^]'., confirming the connection succeeded. Interrupt it with Ctrl+C to return to the prompt.

  6. Run sudo chown student1 students.csv (adjust the username to one that exists on your system), then ls -l students.csv, then id student1. Expected output: the owner column from ls -l now shows student1, and id student1 prints that account's numeric user ID, group ID, and group memberships.

  7. Run tar czf lab10_backup.tar.gz students.csv students_updated.csv codes.txt then history 10. Expected output: a new file lab10_backup.tar.gz in the current directory, and a numbered list of the last 10 commands; confirm the tar czf ... command you just ran appears as one of the 10 listed lines.

Summary

  • A process is a running instance of a program, identified by a PID, and it moves between the running, sleeping, stopped, and zombie states over its lifetime.
  • ps: ps -u, ps -A, and ps aux each show a different slice of the process table as a snapshot, while top shows the same kind of information live.
  • Appending & to a command runs it in the background instead of the foreground, freeing the terminal; kill then sends a signal to that process's PID, defaulting to SIGTERM, kill -9 forces termination with SIGKILL, kill -L lists every available signal, and pkill targets a process by name instead of PID.
  • nice starts a process with a chosen niceness from -20 to 19, and renice changes the niceness of a process that is already running.
  • DevOps grew out of the delay caused by separating development from operations; it unifies planning, coding, building, testing, deploying, and monitoring into one continuous loop, with tools such as Jenkins carrying code automatically from commit to deployment.
  • The DevOps command set covers privilege and identity (sudo, chown, id), search and viewing (find, grep -n, grep -i, tail), text transformation (sort, cut, tr, sed), comparison and raw copying (diff, dd), archiving (tar, gzip), and system/network status (df, du, free, ifconfig, ping, telnet, hostname, history).