Exercise: Stop the Runaway
Find and stop three misbehaving programs with ps, pgrep, kill and pkill, then write two small tools, one that stops any process the polite way before it uses force and one that starts a long export so it survives the terminal closing, and let a check script tell you what's done.
Journeyman · Unix · Linux · Updated
It's the night before a deadline, and your laptop's fan is roaring. Three programs were left running in the background: a thumbnail maker stuck in a loop, an alarm that beeps every second, and a sync program that won't stop when it's asked nicely. Meanwhile, the video export you actually need has to keep going, even after you close the terminal. You'll find the three programs and stop each one the right way, then write two small tools so you never have to do it by hand again: stop-politely.sh, which stops any process the polite way before it uses force, and start-export.sh, which starts the export so it survives the terminal closing. A check script tells you what's done.
Before you start
You need a terminal: the Terminal app on a Mac, or Ubuntu on Linux or in WSL on Windows. The check runs with bats, a small program that runs checks written for bash. If bats --version doesn't print a version number yet, install it:
sudo apt install bats # Ubuntu, and Ubuntu in WSL
brew install bats-core # a Mac, with Homebrew
sudo asks for your password, the one you use to sign in; nothing shows on the screen while you type it.
Get the exercise code
Open this lesson's GitHub repository, github.com/ask-codey/exercise-bash-stop-the-runaway, also linked from the Exercise box beside the lesson. Click Code, then Download ZIP, and unzip it into your terminal-practice folder. Or clone it with Git. On Windows, put it inside Ubuntu, in your Linux home folder, not in a Windows folder under /mnt/c, so chmod works on the scripts.
The folder holds:
answers.txt: five questions, each with a numbered line for your answer.stop-politely.shandstart-export.sh: the two tools. Each starts with a comment that says exactly what it must do and print. These, andanswers.txt, are the files you write.start-the-mess.sh: starts the three misbehaving programs inmess/in the background. Each one stops by itself after 30 minutes, in case you forget it.clean-up.sh: stops whatever the mess left running, if you get stuck.export-video.sh: the pretend export, one line a second for ten minutes.check.bats: the check. You don't need to change it.
Every program here is a practice program from this folder. Stop only these, and leave the rest of your computer's processes alone.
What to do
Open a terminal in the exercise folder, make the scripts runnable, and start the mess:
chmod +x *.sh
./start-the-mess.sh
- Find the runaway. Look at what's running with
ps aux --sort=-%cpu | head -n 5,pgrep -af mess/ortop, and answer questions 1 to 5 inanswers.txtas you go. Write each answer after its), like the example:0) ps aux. - Stop the mess. Stop the alarm with one
pkillcommand, and the other two withkilland their PIDs. One of them won't stop the polite way. When they're all gone,pgrep -af mess/prints nothing. - Write
stop-politely.sh PID. It sends TERM, checks once a second for up to five seconds, and sends KILL only if the process is still there. Try it on a fresh mess: run./start-the-mess.shagain, then./stop-politely.shwith each PID. - Write
start-export.sh. It starts./export-video.shin the background withnohup, sends its output intoexport.log, and saves its PID inexport.pid. Run it, close the terminal, open a new one, and check withpgrep -af export-videothat it's still going. Stop it withpkill -f export-videowhen you're done.
Check your work
From the exercise folder:
bats check.bats
At first almost every check fails. That's expected: each question you answer and each job you finish turns its check into a ✓. The check tries your scripts on small practice processes of its own, in a throwaway folder, and stops only the processes it started. It takes about 20 seconds, because it waits the way your script does. A failing check says what to look at, for example This practice process ignores TERM, and it's still running. After 5 seconds, send it KILL.
Hints
- A script runs as
bash, sopgrepandpkillneed-fto match the script's name in the whole command line (Stopping Things: kill and Signals). - Is it still running?
ps -p "$1" > /dev/nullsucceeds only while that process is running, so it fits anifor awhile(Did It Work? Exit Codes, && and ||). - Waiting five seconds: a loop that runs
sleep 1and then checks, five times at most, stopping as soon as the process is gone. - The PID of the export:
$!is the PID of the job you started last with&(Background Jobs: &, jobs, fg and bg). - Surviving the terminal closing:
nohupgoes in front of the command, and> export.log 2>&1sends its output and its errors into the log.
When you're done
Every check passes:
check.bats
✓ the scripts and the mess are here
✓ 1) the program using the most CPU
✓ 2) the polite way to stop process 4242
✓ 3) one command for every alarm.sh
✓ 4) the signal for a program that ignores TERM
✓ 5) the signal Ctrl+C sends
✓ 6) stop-politely.sh with no PID shows how to use it
✓ 7) stop-politely.sh says when there's no such process
✓ 8) stop-politely.sh stops a process with TERM
✓ 9) stop-politely.sh sends KILL only after TERM and a wait
✓ 10) start-export.sh returns at once and saves the PID
✓ 11) the export keeps running after a hang-up
✓ 12) the export's output goes to export.log
13 tests, 0 failures
Now look back at stop-politely.sh. Your export saves its PID in export.pid; which one line would stop the export politely, using that file and your new tool?
Submit your exercise
The exercise is how you finish this lesson. When your work is done, put it on GitHub in a repo of your own, then submit that repo's address here.
On GitHub, click +, then New repository. Name it (for example
exercise-bash-stop-the-runaway), choose Public, and click Create repository. Leave out the README: your folder already has one.In a terminal in your exercise folder (Ubuntu in WSL on Windows), send your work to your new repo. If you downloaded the ZIP:
git init -b main git add . git commit -m "My solution" git remote add origin https://github.com/your-name/exercise-bash-stop-the-runaway.git git push -u origin mainIf you cloned the starter instead, point your copy at your own repo, then commit and push:
git remote set-url origin https://github.com/your-name/exercise-bash-stop-the-runaway.git git add . git commit -m "My solution" git push -u origin mainPaste your repo's address, such as
https://github.com/your-name/exercise-bash-stop-the-runaway, into Submit your exercise on this page. The site checks that the repo is public and holds your commits, and then the lesson is complete.
Changed something after you submitted? Push it, and submit again: your latest submission is the one that counts.
So what
Finding what's running, stopping it politely before you use force, and starting a long job so it outlives your terminal is the everyday care of any computer, from your laptop to a server you'll never see.