140 lines
10 KiB
Plaintext
140 lines
10 KiB
Plaintext
Episode: 4627
|
|||
|
|
Title: UNIX Curio #5 - Faster, Pussycat! Kill! Kill!
|
||
|
|
Source: https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr4627/hpr4627.mp3
|
||
|
|
Transcribed: 2026-07-31 16:15:24 (official HPR transcript)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
This is Hacker Public Radio Episode 4627, for 2026-04-28
|
||
|
|
Today's show is entitled, "UNIX Curio #5 - Faster, Pussycat! Kill! Kill!"
|
||
|
|
The host is Vance and the duration is 00:14:35
|
||
|
|
The flag is Clean, and the license is CC-BY-SA
|
||
|
|
The summary is "Sending signals to processes, or just checking if they exist"
|
||
|
|
Hi there, I'm Vance and welcome to Unix Curio number 5.
|
||
|
|
This series is dedicated to exploring little known and occasionally useful,
|
||
|
|
trinkets lurking in the dusty corners of Unix-like operating systems.
|
||
|
|
Let me start by admitting that I've never actually seen the film referenced in the episode title,
|
||
|
|
but I couldn't resist using it anyway.
|
||
|
|
If you've used the Unix command line to any extent, chances are good that you are familiar with the
|
||
|
|
kill command. A common use is to terminate a misbehaving program.
|
||
|
|
But there is more behind how kill works, including a curio you might not know about.
|
||
|
|
The kill utility works by sending a signal to the targeted process.
|
||
|
|
This signal is selected from a predefined list and triggers the process to interrupt its normal
|
||
|
|
flow and handle the signal before potentially returning back to its work.
|
||
|
|
This signal handler can do whatever activities are written in its code, but typically it will take
|
||
|
|
actions connected to the purpose of the specific signal received.
|
||
|
|
One option is for the process to not have a signal handler at all.
|
||
|
|
In that case, there is a default action that the operating system will take
|
||
|
|
on behalf of the process, depending on what the signal is.
|
||
|
|
The possible default actions are to terminate the process,
|
||
|
|
take some implementation defined action, usually rating a core file to disk,
|
||
|
|
and then terminate the process, stop that is to say pause execution of the process,
|
||
|
|
continue execution of a stopped process, or just ignore the signal.
|
||
|
|
By default, kill sends the term signal to the process and indicate that it should terminate.
|
||
|
|
Each signal has a name and a number assigned to it.
|
||
|
|
Sig term is the name of the terminate signal.
|
||
|
|
You can use the hyphen S option with the name to choose which signal to send.
|
||
|
|
The kill command is specified to take these names without the Sig prefix,
|
||
|
|
though some implementations will accept them either way.
|
||
|
|
Also, kill is supposed to be case insensitive when it comes to these names,
|
||
|
|
but the convention is to write them in all upper case.
|
||
|
|
The assigned numbers for signals can vary depending on the operating system,
|
||
|
|
and on Linux, depending on what process our architecture you're on.
|
||
|
|
However, there is a short list of signals that have a stable number assigned to them.
|
||
|
|
A link to this is provided in the shown notes.
|
||
|
|
Despite this, I recommend using the signal name, not the number in your scripts,
|
||
|
|
both to make them clear and to ensure maximum portability to different systems.
|
||
|
|
Well-behaved programs will have a signal handler that responds to the term signal
|
||
|
|
by stopping what they are doing, cleaning up any open resources like temporary files and promptly exiting.
|
||
|
|
However, not every program behaves well, so sometimes it becomes necessary to send them the kill signal.
|
||
|
|
This one is special and cannot be handled or ignored by the program.
|
||
|
|
The operating system will immediately terminate the program,
|
||
|
|
possibly leaving a mess behind.
|
||
|
|
Two other signals that can come in handy sometimes are stop and count,
|
||
|
|
spelled CONT.
|
||
|
|
As you might expect, stop forces a process to pause in the middle of whatever it was doing.
|
||
|
|
Its counterpart, CONT, that's short for, continue, causes it to resume execution.
|
||
|
|
This can be useful if a program consumes CPU time when not actually doing anything worthwhile.
|
||
|
|
Sending it the stop signal will end that, and when you're ready to use it again, CONT will
|
||
|
|
cause it to pick up right where it left off.
|
||
|
|
Like the kill signal, stop cannot be handled or ignored by the program.
|
||
|
|
I have used this to pause the game free-sive when I wanted to break away to do something else,
|
||
|
|
but didn't one have to deal with exiting my current game and having to reload it later.
|
||
|
|
Take note, though, that the program might get confused if it expects the system clock not to suddenly
|
||
|
|
jump forward as that is exactly how the situation will appear to it.
|
||
|
|
Network connections or other resources the process is using, that change while it is stopped,
|
||
|
|
our other potential trouble spots.
|
||
|
|
Also be aware that a stopped graphical program will not update its window.
|
||
|
|
So I find it best to minimize the window before stopping it and then continuing the process
|
||
|
|
before trying to raise the window again.
|
||
|
|
Programs are not necessarily required to interpret signals in the way they are described.
|
||
|
|
For example, the HUP signal was originally intended to be sent when a modem or serial connection
|
||
|
|
hang up occurred. Today, some demons use it for other purposes and take a specific action in response.
|
||
|
|
For example, the Apache web server will restart and network manager will reload its configuration.
|
||
|
|
These uses of signals are usually described in the demons manual page,
|
||
|
|
often in a separate section dedicated to signals.
|
||
|
|
While all this background might be interesting or maybe not,
|
||
|
|
it's pretty commonly known. So it isn't really a curio.
|
||
|
|
Our Unix curio for today is the zero signal.
|
||
|
|
This is not actually a signal at all. Instead, it tells the kill utility
|
||
|
|
to just check for the existence of a process.
|
||
|
|
If the process exists, kill will exit with a status of zero.
|
||
|
|
If it doesn't exist, the exit status will be greater than zero.
|
||
|
|
This provides a handy way to check whether a particular process is still around.
|
||
|
|
A shell command can use this exit status with its control structures like if
|
||
|
|
to take a particular action depending on whether a process exists.
|
||
|
|
Somewhat oddly, the numerals zero is both the number and the name of this pseudo signal.
|
||
|
|
Why would you want to do this? I've used it for a script to analyze log files that runs
|
||
|
|
daily on a web server. Depending on how much traffic the site is getting,
|
||
|
|
the log files can grow to the point where it takes longer than a day for the script to get through them.
|
||
|
|
If a second instance of the script is started, while one is still running, it will slow down both.
|
||
|
|
And if more keep being added, eventually the machine will run out of memory.
|
||
|
|
My solution was to create a PID file containing the process ID number of the running script.
|
||
|
|
You might see examples of these if you look in the slash run or slash var slash run
|
||
|
|
directories on your system. The script creates a file named something like
|
||
|
|
my script dot PID in this directory containing its own process ID, which can be accessed in the
|
||
|
|
shell with the variable dollar sign dollar sign.
|
||
|
|
When my script starts, it checks to see whether this file exists.
|
||
|
|
If so, it loads the process ID from the file and runs kill, hyphen s, space 0 with it,
|
||
|
|
to see if the previous process still exists. If the process is no longer around,
|
||
|
|
that's a sign that it exited abnormally before it had the chance to delete the PID file.
|
||
|
|
So the script removes the abandoned PID file, replaces it with a new one containing the current
|
||
|
|
process ID, and continues with its work. If the previous process is still around, my script just
|
||
|
|
exists with a message to that effect. This way, I can be sure that only one instance of the script will
|
||
|
|
ever be running at one time. Be aware that the kill utility might also return a non-zero exit
|
||
|
|
status, if the user running it does not have privileges to send a signal to the process with the
|
||
|
|
specified ID. This is not a concern if you are running a script as the root user, but could be if you
|
||
|
|
are not. This can occur even if you aren't actually sending a signal just using the 0 pseudo-signal
|
||
|
|
to check if a process exists. There is a weakness in this method. Unix lake systems generally
|
||
|
|
have a limit to the quantity of process ID numbers that can be issued, so they get reused over time.
|
||
|
|
However, there will never be two processes with the same ID number running at the same time.
|
||
|
|
Typically, the first process that is run on startup will be given the ID number one,
|
||
|
|
and each subsequent process will get the next higher number.
|
||
|
|
Once the maximum is reached, the system starts again at the beginning with the lowest number not in use.
|
||
|
|
It is possible for the script to crash and leave behind the PID file,
|
||
|
|
and then the same process ID could be recycled and actively used for another program,
|
||
|
|
causing a new instance of the script to give up. The chances of this are small enough that for my
|
||
|
|
purposes it's not worth worrying about, but you should be aware that it could happen.
|
||
|
|
I should also note that it's not strictly necessary to use kill for the purpose I described.
|
||
|
|
The PS utility can also be given a process ID with the hyphen P option.
|
||
|
|
If the process exists, the exit status will be 0, otherwise it will be greater than 0.
|
||
|
|
In this case, you could also use the output of the PS command to check that the name of the script matches what you expect,
|
||
|
|
helping avoid the problem of a recycled process ID.
|
||
|
|
In addition, PS doesn't concern itself with permissions for sending signals,
|
||
|
|
so it will report on the existence of a process no matter what user you are running it as.
|
||
|
|
From an efficiency standpoint, kill generally requires fewer resources to run.
|
||
|
|
In fact, it is built into some shells, but functionally, PS can also do the job.
|
||
|
|
You can find example scripts in the show notes for this episode,
|
||
|
|
showing how to use both the kill and PS commands to tell if a process exists and take action depending on the result.
|
||
|
|
So keep in mind that kill is capable of doing more than just killing off programs.
|
||
|
|
Maybe you can put it to one of these uses for your needs.
|
||
|
|
Thanks for listening and keep an eye out for our next Unix Curio,
|
||
|
|
which will be about the at and bad utilities here on Hacker Public Radio.
|
||
|
|
If you have a question or a suggestion for a future topic,
|
||
|
|
please comment on this episode on the HPR website.
|
||
|
|
You have been listening to the Hacker Public Radio podcast, at hackerpublicradio.org.
|
||
|
|
Today's show was contributed by a HPR listener like yourself.
|
||
|
|
If you ever thought of recording a podcast, then visit the HPR site to find out how easy it really is.
|
||
|
|
Hosting for HPR has been kindly provided by anhonesthost.com, the Internet Archive, rsync.net, and the HPR Community Content Delivery Network.
|
||
|
|
Unless otherwise stated, today's show is released under a Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.
|