Opens in a new tab
Linux basics · Lesson 6 of 13

Linux processes: the prompt is back, but is the program finished?

In brief

Follow a sixty-second wait from launch to exit, then see how process IDs, signals, exit status and inherited settings describe different parts of its life.

5 min read

IntermediateLessonAbout reading levels
Is this the right starting point?
Before you read
The disposable Ubuntu VM, an ordinary account and basic command entry from previous lessons; use only the practice process you launch.
What you will take away
Follow a process from background launch through inspection and termination, distinguishing signals, exit status and inherited environment.
Sources
A yellow wind-up toy bird stands on a blue table beside a trail of footprints; a second toy bird sits on a shelf behind it.
On this page5 sections

The terminal prompt comes back, ready for another command. That can feel like a conclusion: whatever you started must be finished. But the shell can be ready while the program it launched is still working, or simply waiting.

A sixty-second wait makes the distinction easy to see. In this illustrative exercise, use your ordinary account in the disposable Ubuntu guest. You will start sleep, find that particular running instance, and ask it to finish. A running instance of a program is a process; the terminal can have more than one involved in the work you see.

sleep 60 &
lab_pid=$!
printf 'Started PID %s
' "$lab_pid"
ps -p "$lab_pid" -o pid,ppid,stat,etime,args

sleep waits for the specified time. The & at the end tells the shell, the program reading your commands, to accept more input while that wait continues in the background. The shell and sleep now have different jobs in the same terminal session.

A number for this run, not for every sleep

When the shell starts the background process, $! holds its number. The assignment immediately saves it as lab_pid, because another background launch would replace $!. This number is a process ID, usually shortened to PID. The ps command asks Linux about the specific instance with that ID.

In the row it returns, pid identifies the waiting process, ppid identifies its parent, and etime shows how long it has existed. The command column helps you confirm which program is there. Together, those details connect the waiting work to the shell that launched it.

Sixty seconds may already have passed while you read this. If sleep has finished, start sleep 60 & again and immediately save lab_pid=$!. Use that new number for the stopping exercise. A PID is not a permanent address for the sleep program: Linux may reuse it after the process ends. Check the current command in ps before sending a message to a number you saved earlier.

kill -TERM "$lab_pid"
wait "$lab_pid"
printf 'Wait status: %s
' "$?"

kill has an alarming name for a command whose job is to send a signal, a message to a process. TERM asks the process to terminate. The following wait collects the result from this child of your shell. In Bash, a process terminated by TERM commonly gives a wait status of 143: 128 plus signal number 15. Read the result you actually get; help wait describes your shell's behavior.

There are two separate events in those commands. A successful kill says the signal was sent. The later wait result tells you how the child finished. Sleep normally ends on TERM, while another program might first save its work, clean up or handle the message differently. Asking it to stop and learning how it stopped are different pieces of the story.

What a finished command tells the shell

These two tiny commands finish immediately, so there is no background wait to keep track of:

true
printf 'true status: %s
' "$?"
false
printf 'false status: %s
' "$?"

By convention, an exit status of zero reports success. Other numbers describe outcomes defined by the program. The shell keeps the most recent result in $?, which means you need to read or save it before another command runs. Even the printf that displays a result replaces that value with its own status.

The number needs the command's meaning beside it. In the file lesson, diff could complete a useful comparison and return a nonzero status because it found differences. Similarly, seeing a server process still running does not establish that it is delivering anyone's report. Process state and useful work answer different questions.

A child starts with information from its parent

Starting a program also gives it an environment: a set of named values available at launch. Here, one harmless practice value travels to a Python process:

LAB_NAME=dispatch python3 -c 'import os; print(os.environ["LAB_NAME"])'
printf 'Parent value: %s
' "${LAB_NAME-unset}"

The assignment before python3 supplies LAB_NAME to that one child. Python reads the value from its environment and should print dispatch. The following command asks the parent shell for its own value. It will usually print unset, because the temporary assignment did not change that shell's variable. If the shell already had a value for LAB_NAME, the earlier value remains.

The child received its starting information without reaching backward to rewrite the parent's variables. Exporting a shell variable makes it available to later children; an ordinary unexported variable stays in the shell. Use only the harmless practice value here. Depending on permissions and the tools involved, diagnostics or logs can expose process arguments and environment values.

This helps explain a familiar puzzle: the same program works in your terminal and behaves differently as a service. Compare the account, directory, environment and executable chosen by the service manager with the ones your shell uses. The program can be identical while the conditions at launch are not.

Finish the wait you started

Try the sleep sequence once more, inspecting the current command before sending TERM. Keep the target to the process you launched. Avoid killall, broad name matches and numbers copied from old screenshots. TERM gives a program a chance to clean up; forced termination can interrupt writes and needs a recovery plan.

Confirm that your practice sleep has ended, and keep its PID and observed wait result with your explanation of what happened. The prompt was ready before the wait was over. Now you have followed the work separately from the terminal: which instance started, what information it received, and how it finished.

Sources

The Bash manual covers job control, environments and wait. The Linux signals manual describes how signals are delivered and the default actions they can cause.

Sources & context

Sources linked in this article. Read alongside the author’s analysis; a citation does not independently verify a publisher’s claims.

Report an error or outdated detail

Keep reading

Where to go next