Table of Contents
Behind the scenes - How does it work?
Get eol data of a given product
- A request to
https://endoflife.date/api/v1/products/PRODUCT
is made - The response is saved to
/tmp/eol_<PRODUCT>.json
The local product specific JSON file is used as cache file and expires after 1 day. When checking the same product again the json data is taken from the cache file. This reduces the traffic to the endoflife.date server.
See details of the response in the documentation of the api: đ https://endoflife.date/docs/api/v1/#/Products/product
Find latest version
The block with information of the latest version we get from cat "$API_OUT" | jq ".result .releases.[0]"
. Inside this blockâŚ
- The current major version number is in the key
.name
. - The latest minor version is in
.latest .name
$ cat "$API_OUT" | jq ".result .releases.[0]"
{
"name": "8.4",
"codename": null,
"label": "8.4",
"releaseDate": "2024-11-21",
"isLts": false,
"ltsFrom": null,
"isEoas": false,
"eoasFrom": "2026-12-31",
"isEol": false,
"eolFrom": "2028-12-31",
"isMaintained": true,
"latest": {
"name": "8.4.8",
"date": "2025-06-05",
"link": "https://www.php.net/ChangeLog-8.php#8.4.8"
},
"custom": null
}
Find local version - Linux OS
When scanning EOL of a Linux OS using --os
it uses an internal algorithm by reading /etc/os-release
.
cat /etc/os-release | grep "^ID=" | cut -f 2 -d '"'
Hacks:
- Centos steam has the
ID="centos"
- the same key like Centos. If the string âCentOS Streamâ is found /etc/os-release then âcentos-steamâ will be set - Roky Linux has the
ID="rocky"
. In the endoflife.data API the products key was changed to ârocky-linuxâ in Sep 5th 2025. An os mapping was added on top of the script in the comment section.
Find local version - automatically
In result -> versionCommand is a command to get the version of a locally installed product.
$ cat "$API_OUT" | jq ".result .versionCommand"
"php --version"
The given command will be executed. Its output wonât be cached.
If the command containes line breaks with \n
(see response for âpythonâ). Those lines are commands or coments starting with #
. Then all lines will be executed until an output was found.
Hacks:
- Some commands in the âversionCommandâ field are unhandy. eg for PostgreSql you must establish a database connection or Docker needs to connect as well. In the comment section on top of the script is a mapping for product keys with another version cammand to execute
- If the version is not properly detected, eg. a client tool is not in $PATH and you want to scan some locations - then you can creare custom scripts. See next chapter
Find local version - by custom file
Some versions are difficult to fetch eg with a non privikledged user eg. for monitoring.
In the subdir ./eol_check-env/
are files per product to handle an override and detect a version in another way.
When using --verbose
you see if it was used:
$ ./eol_check.sh -v postgres
DEBUG: Params: PRODUCT = postgres, PRODUCT_VERSION =
DEBUG: Sourcing custom file for 'postgres' -> ./eol_check-env/postgres
...
Compare versions
The current version is compared with latest major and latest min or version.
Check support
We compare:
- Is the current version still supported? see
.isMaintained
in the current release - Detect date for end of support
- if
.eoesFrom
- end of extended security exists then this date will be used - otherwise of
.eolFrom
- end of life - will be used - If one of the date was found ist will be compared with the curent day to show how many days are left - or how long it is expired
- if
Lessons learnt
At the initial point it seemed to be an easy script to code. I can detect a product version with the value of versionCommand
. âJust execute thatâ and read STDOUT. Then comapre it somehow with data in a JSON.
The first check was up and running quite fast.
Then came the reality :-)
- Then I found âpythonâ - it has multiple commands. Cut by
\n
and take the first item worked for me. - ⌠bot my luck ended on another machine. Now I loop over all lines, exclude comments starting with
#
. The first successful command wins. - I found âjavaâ - its version data is written to STDERR. I added 2>&1 on each version command.
- Then there were tools where I âdidnât likeâ the version command. Docker and Postgres donât read the version of the client but initialize a connection to a service. Because one usage of my EOL check is with an unpriviledged user. It doesnât need access. Solution was: I created possibilities to override the version command. And yes, I know that this is a dirty hack.
We use the 1st line of the output from the version command. Sometimes it is just the version number. Sometimes there is the product in fron. Or text behind. I didnât count it but the regex to fetch the version number several times was changed.