eping.py 3.65
Continuous ICMP reachability monitor built on fping. Scans a host list in a loop,
reports each host UP/DOWN/NO-DNS, counts state changes. CLI (curses) or web GUI.
Written by Ewald Jeitler — https://www.jeitler.cc
Requirements
- Python 3.6+ (eping.py and epinga.py)
fpingin$PATH- A terminal supporting
curs_set()for CLI mode --check-sourceused automatically if fping supports it (5.0+)- Non-UTF-8 terminal locale (e.g.
LANG=C): works, but box-drawing characters are shown as ASCII/?;LC_ALL=C.UTF-8gives the full look
Installation / Update
Via pip (installs eping and epinga as commands, fping still required separately):
pip install eping
Standalone scripts (installs/updates eping.py, epinga.py, esplit.py):
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/ewaldj/eping/refs/heads/main/e-install.sh)"
esplit.py isn't part of the pip package - use the standalone install for it.
Quick start
pip install: use eping/epinga instead of ./eping.py/./epinga.py below.
./eping.py # CLI, uses/creates eping-hosts.txt
./eping.py -n 172.17.16.0/20 # scan a network
./eping.py -web # web GUI on http://<host>:8080
./eping.py -web -port 9000 -bind 127.0.0.1
./eping.py -wv # CLI + read-only web view
./eping.py -wvc # CLI + controllable web view
No args: creates a sample eping-hosts.txt. -df: start with no hosts, add at runtime.
Running unattended (screen / tmux)
CLI mode needs a live terminal — run inside screen/tmux and detach:
https://github.com/ewaldj/microups/blob/main/SCREEN_AND_TMUX-QUICK_GUIDE.md
Host sources
Combinable:
| Source | Option |
|---|---|
| Host file | -f FILE[,FILE...], comma/space separated, disable with -df; .txt host list or inventory .csv (see Inventory CSV import) |
| CIDR network | -n (mask /13 … /32), comma separated |
| IP range | -r, start-end, comma separated |
-n 172.17.17.0/24,10.0.0.0/30 · -r 10.0.0.0-10.0.0.10,172.19.0.0-1.13,172.20.2.0-15
(range end may shorten to its last 1-3 octets: 172.19.0.0-1.13 = 172.19.0.0-172.19.1.13).
Limits: 512000 hosts total, 524288 addresses per range. Duplicates removed. CIDR
expansion includes network/broadcast. Several -f files are combined before dedup.
Host file format
Same parser for -f, F/ADD FILE (CLI), and web GUI ADD FILE:
# comment to end of line
127.0.0.1 # IPv4
192.168.99.0/29 # CIDR - expanded
10.131.0.0/19 # 8192 addresses
www.google.com # hostname/FQDN
8.8.8.8, 9.9.9.9; 1.1.1.1 # comma/semicolon = blank
2606:4700:4700::1111 # IPv6
2606:4700:4700::1111/128 # IPv6 with /128 - single host
Network mask range /13…/32 everywhere (host file, ADD FILE, web upload, ADD/DELETE
host input); out of range is rejected (message names the allowed range; -f warns and
ignores). IPv6: only /128 accepted, any other mask rejected. Anything else is ignored.
opt: / OPT: lines
A line starting with opt:/OPT: carries CLI options instead of a host:
opt: -ph -du -w 2
opt: -web -port 9000
1.1.1.1
8.8.8.8
Multiple opt: lines join in file order. # comments out the rest of the line (or
the whole line at the start). Quote values with spaces: opt: -f "my hosts.txt". A
flag typed on the command line wins over the same flag from a file. Only applies to
the initial -f read at startup — F/ADD FILE (CLI or web, FROM CLIENT/FROM SERVER)
never parse opt: lines, they're just text.
The default eping-hosts.txt: sample hosts, this section, then every CLI option as a
commented-out opt: line with its default (remove # to activate).
Inventory CSV import
A .csv inventory export (one device per row) can be used as host file: -f FILE.csv,
F/ADD FILE (CLI), web GUI ADD FILE (FROM CLIENT, FROM SERVER, drag and drop). Files
named *.txt are never treated as CSV - they keep the plain host file format above.
- Detection: first non-empty line is a header with the columns
IP AddressandHostname(case-insensitive); the delimiter (;,,or tab) is detected. - Columns used:
IP Address,Hostname,Serial Number,Model,Location,sysLocation,Type,Comment. All other columns are ignored. - Host entry: the IP address; rows without a valid IP are ignored. With PREFER
HOSTNAME (
-ph, or that address mode active when the file is added) the entry is theHostnameinstead - rows without an IP are then pinged by name too (NO-DNS if it does not resolve); a name that is not a valid hostname falls back to the IP. Rows without a usable entry are ignored. - Duplicates: one host per entry, the first row wins. The count of ignored and duplicate rows is reported when the file is added (startup message / web footer).
- Log: the six inventory values and the CSV hostname are written with every row
of that host, see Logging. A
Hostnamethat is not the host entry (IP mode) is only kept there as information. - Plain
.txthosts andSAVE HOSTS FILEcarry no inventory values: a saved hosts file lists only the host entries.
Example (; delimited, extra columns are ignored):
Hostname;IP Address;Serial Number;Model;Location;sysLocation;Type;Comment
sw-core-01;10.0.0.1;FOC1234A1BC;C9300-48P;Vienna DC1;Rack A3;Switch;spare PSU missing
sw-core-02;10.0.0.2;FOC1234A1BD;C9300-48P;Vienna DC1;Rack A4;Switch;
ap-lobby-01;;FCW2528P5PSV;C9120AXI-E;Graz HQ;Lobby;AP;
rtr-edge-01;192.0.2.10;FTX9876B2CD;ISR4331;Linz POP;Rack B1;Router;uplink to ISP
sw-access-01;10.0.1.1;FOC5678C3DE;C9200L-24P;Vienna DC1;Rack C1;Switch;
fw-edge-01;192.0.2.1;JMX2345F6GH;ASA5516;Linz POP;Rack B2;Firewall;ASA 5516 - EoL 2027
Without -ph this gives 5 hosts (the IP addresses); ap-lobby-01 has no IP and is
ignored. With -ph it gives 6 hosts, named by Hostname.
CLI mode
Sorted table (IPv4 numerically, then hostnames), 64-column blocks. Green = UP, red = DOWN. Columns: hostname/IP, state, RTT (ms), last-change timestamp, change count.
| Key | Action |
|---|---|
U |
view picker — all 9 views (see Views and sort orders) |
M |
match filter — regex on hostname/IP and inventory fields, display only (see Match filter) |
A |
add host — IP, hostname, CIDR (/13…/32), or ip1-ip2 (max 524288) |
D |
delete host — same formats/limits as add |
F |
add hosts from a file |
O |
sort order picker — 5 orders (see Views and sort orders) |
T |
add comment — timestamped CSV row (logging on only) |
S |
set reference — shown list becomes new base list |
Z |
zero changes — reset CH-TIME/CH NO, states kept |
C |
clear all hosts and state |
P |
address mode picker — 4 modes (see Address modes) |
X |
ADV OPTIONS — live option editing (see ADV OPTIONS) |
N |
ANALYSE NOW — run epinga.py against the active logfile in the background (see GENERATE REPORT) |
G |
GET NAMES — reverse-DNS raw IPs, one-shot, background |
R |
redraw screen |
L |
reset logging (logging on) / START LOG (logging off) |
E |
exit — os._exit() immediately |
U, O and P open a picker dialog (↑/↓ select, ENTER confirms, ESC cancels) -
same option set as the matching web GUI dropdown.
Dialogs: ENTER confirms, ESC/empty cancels. Key bar shortens on narrow terminals.
PLEASE WAIT box with elapsed counter shown until the first round has results.
Ping checks keep running while a dialog (A/D/F/M/T) is open — same
retry/state/logging logic as the main loop; screen repaints once the dialog closes.
Screen repaints ~7×/s independent of fping. UP, SET REFERENCE, DEL HOST, ZERO CHANGES apply immediately without waiting for the round. A list-changing key cuts the
round short (~0.15s reaction). Aborting is safe — no-output host keeps its prior state.
Read-only web view (-wv)
--web_view: CLI drives, browser mirrors over HTTP (--port/--bind). No controls —
POST /api/command and POST /api/upload answer 403. Client-side column sort still
works locally.
Controllable web view (-wvc)
--web_view_control: like -wv, but the browser can drive too (POST endpoints not
403). Same buttons/keys as Web GUI below, curses stays usable simultaneously. A CLI
keypress result (e.g. S, Z, O, U, A/D/F) also shows in the browser.
Web GUI (-web)
Single self-contained page, no external resources.
- Table: CLI-style columns, filled top-down then next column right. Horizontal scroll if needed ("SCROLL RIGHT FOR MORE" hint in the stats bar).
- Footer stats: RUNTIME, HOST UP/DOWN/FLAPPING, for the whole current view regardless
of the match filter. RUNTIME shows
n/abriefly during a background round. - Adding many hosts (
ADD,ADD FILE, upload) shows "added N host(s) - please wait, pinging ..." until they appear with a state, thendone. - Font size 6–28px (slider,
A−/A+,+/−keys), stored inlocalStorage. - Column headers sort the list (IPv4-aware).
- Toolbar, two rows (wraps if narrow):
- Row 1: view select (9 views), sort order select, SET REFERENCE, ZERO CHANGES, CLEAR ALL, address mode select, GET NAMES, ADV OPTIONS, RESET LOG, FILE OPERATIONS select, EXIT, font size.
- Row 2: match filter (SET/CLEAR), host field (ADD/DELETE), comment field (COMMENT), ADD FILE select, GENERATE REPORT select.
- View select, sort order select, address mode select and ADV OPTIONS all match the
CLI's
U/O/P/Xpickers exactly. FILE OPERATIONS and ADD FILE > FROM CLIENT/ FROM SERVER are web-gui-only (no CLI key - CLI already runs on the server's own filesystem).
- FILE OPERATIONS dropdown, in this order:
Entry Does SAVE HOSTS FILE ON SERVER confirmation, then saves the currently displayed hosts; blank name overwrites the active -fhostfile (first one, if eping.py was started with one) or, with none active, the defaulteping-hosts.txt; a typed name always saves as that new file instead,.txtappended once, active hostfile left untouchedUPLOAD FILE TO SERVER picks a local .txt/.csv, saves as-is server-side, no host parsing; never overwrites, appends-1/-2/...DOWNLOAD ALL HOSTS full reference list, plain text DOWNLOAD ACTIVE HOSTS currently displayed hosts (view/address mode/filter applied), plain text DOWNLOAD ACTIVE LOGFILE active CSV log, zipped; disabled while logging off DOWNLOAD SELECTED FILES picker: every .csv/.txt/.htmlin the working dir, table (name/size/date), extension filter, "select all", "no compression" checkbox (single-file selection only); multi-select bundles into one ZIPDELETE FILES FROM SERVER same picker as DOWNLOAD SELECTED FILES, red DELETE button, confirms with file count; active logfile can't be deleted VIEW FILE FROM SERVER picker: every .csv/.txtin the working dir, table (name/size/date), "select all"; opens each picked file read-only, raw content, COPY/DOWNLOAD buttons - see VIEW FILE FROM SERVER below - ADD FILE dropdown:
FROM CLIENT(local file picker) /FROM SERVER(picks one or more.txtfiles or inventory.csvfiles already on the server, adds their hosts; a.csvwithout the inventory header, e.g. an eping log, is refused). - Keyboard shortcuts (no modifier, only while no text field has focus; own quick
variants, not the CLI's picker keys of the same letter):
Ucycles the original 3 views (ALL HOSTS → CURRENTLY-UP → UP+FLAPPING → ALL HOSTS), the other 6 need the dropdown;Ocycles all 5 sort orders one at a time;P/Itoggle PREFER HOSTNAME / SWITCH TO IP ONLY directly, the address mode select reaches all 4 modes;G/S/Z/C/L/Eclick the matching button (E/C/Lconfirm);A/Dfocus host field;M/Tfocus their field;Fopens the file picker;Rforces a status refresh;+/−font size (works while typing). No keyboard shortcut forX/ADV OPTIONS or GENERATE REPORT - click required. - Host field feeds both ADD/DELETE; ENTER triggers the button used last, ESC clears.
- Files can also be dropped anywhere on the page (max 16MB, see Host file format).
- Commands acknowledge immediately; a click aborts the running round.
Views and sort orders
Flapping: last state change within -fw minutes (default 72000 = 50 days, off
unless lowered). CH NO counts changes; Z resets it.
CLI U and web GUI's view select/U picker (see CLI mode) reach the same 9 views.
The web GUI's own U keyboard shortcut only cycles ALL HOSTS → CURRENTLY-UP →
UP+FLAPPING → ALL HOSTS (see Web GUI keyboard shortcuts). A view also limits what's
probed — filtered hosts aren't probed until back to ALL HOSTS. Host list snapshotted at
switch time. A view with no matches is rejected, previous view stays active.
ALWAYS-UP/ALWAYS-DOWN: never changed state this run (CH NO = 0). NO-DNS counts
as DOWN for CURRENTLY-DOWN/ALWAYS-DOWN/DOWN+FLAPPING.
Picker/dropdown order: ALL HOSTS, CURRENTLY-UP, ALWAYS-UP, UP+FLAPPING, FLAPPING-ONLY, ALWAYS-DOWN, CURRENTLY-DOWN, DOWN+FLAPPING, NO-DNS.
| View | Contains |
|---|---|
| ALL HOSTS | everything |
| CURRENTLY-UP | UP now |
| ALWAYS-UP | UP, never changed this run |
| UP+FLAPPING | UP now + flapping |
| FLAPPING-ONLY | flapping, regardless of state |
| ALWAYS-DOWN | DOWN/NO-DNS, never changed this run |
| CURRENTLY-DOWN | DOWN or NO-DNS now |
| DOWN+FLAPPING | DOWN/NO-DNS now + flapping |
| NO-DNS | unresolvable now |
CLI O and web GUI's sort select/O picker reach the same 5 sort orders directly; the
web GUI's own O keyboard shortcut cycles them one at a time. ADDRESS (default),
UP/FLAP/DOWN, DOWN/FLAP/UP, FLAP/UP/DOWN, FLAP/DOWN/UP. FLAP group contains both
UP and DOWN flapping hosts; NO-DNS counts as DOWN. Inside FLAP: state first (direction
per mode), then change count (highest first), then address. Both view and order apply
immediately, order re-evaluated every round.
ADV OPTIONS
Web GUI (button) and CLI (X key). Web: modal, every option as slider + text field,
applied live; RESET TO DEFAULT restores startup values, APPLY re-sends every field. CLI:
same 16 options/ranges in a dialog - ↑/↓ select, +/- step, ENTER to type a value
directly, D resets the selected option to its default, R resets all, ESC/X closes.
| Option | Range | 0/-1 means |
|---|---|---|
| BACKOFF | 1 – 2 | — |
| TIMEOUT | 10 – 5000 ms | — |
| RETRIES | 0 – 5 | — |
| DOWN RETRIES | 0 – 5 | 0 = disabled, full RETRIES |
| INTERVAL | -1 – 250 ms | -1 = auto (use RATE), 0 = no pacing |
| THREADS | 0 – 32 | 0 = auto |
| WAIT TIME | 0 – 600 s | — |
| CONFIRM | 1 – 10 | — |
| RATE | 10 – 25000 pps | — |
| FLAP WINDOW | 1 – 72000 min | — |
| DOWN SLICES | 1 – 20 | — |
| FULL SWEEP | 0 – 50 | 0 = disabled |
| DNS TTL | 0 – 3600 s | — |
| TIMEZONE | -24 – +24 h | — |
| MAX LOG SIZE | 0, 10 – 2500 MB | 0 = no rotation |
| MAX LOG FILES | 0 – 500 | 0 = unlimited |
Same bounds as the matching CLI flags (-lms/-lmf for the last two - see Output).
HTTP API
| Method | Path | Body | Purpose |
|---|---|---|---|
| GET | / |
— | the page |
| GET | /api/status |
— | JSON: rows, counters, scan/phase info |
| GET | /api/logfiles |
— | JSON list of .csv/.txt/.html files (FILE OPERATIONS, ADD FILE > FROM SERVER) |
| GET | /api/download/hosts_all |
— | full reference list, .txt |
| GET | /api/download/hosts_shown |
— | shown hosts, .txt |
| GET | /api/download/logfile |
— | active CSV log, zipped; 404 if logging off |
| GET | /api/download/choose_logfile?name=...&nozip=1 |
— | one or more files, ZIP (or raw for a single file with nozip=1) |
| GET | /api/view_file?name=...&queue=... |
— | server-rendered VIEW FILE viewer page for one .csv/.txt file; repeatable queue= params carry the rest of the selection for the page's own "OPEN NEXT FILE" link |
| POST | /api/delete_logfile |
{"names":[...]} |
delete files; active logfile refused |
| POST | /api/upload_server_file?name=... |
raw file content | save .txt/.csv as-is; never overwrites |
| POST | /api/add_from_server |
{"names":[...]} |
add hosts from listed .txt files |
| GET | /api/report |
— | last GENERATE REPORT HTML; 404 until done |
| POST | /api/command |
{"cmd":"...","value":"..."} |
control (see cmd list below) |
| POST | /api/upload |
host list, text | add hosts |
cmd values: up_only, set_filter, addr_mode, get_names, match_filter,
sort, add, del, set_ref, zero, add_comment, reset_log, clear,
set_option, reset_options, run_report, save_hosts_file, exit. set_option
value: key=value. reset_log value: logging off - optional custom file name (blank =
auto-generated); logging on - y (clear) or new/new=<name> (new file, optional
custom name). run_report: value = empty (active logfile) or one .csv filename; or
JSON body field values: [...] to merge and analyse multiple .csv files as one
(max 25). save_hosts_file value: optional target file name (blank
= active -f hostfile, or eping-hosts.txt if none).
-wv answers 403 to POST /api/command//api/upload; -wvc/-web allow both. No
authentication. Default bind 0.0.0.0 — use -bind 127.0.0.1 outside trusted networks.
How a scan round works
- Hostnames resolved once (32 parallel), cached around
-dnsseconds (randomized a bit so a large batch resolved together doesn't all expire - and need re-resolving - in the same round later). Same-address names share one probe. Unresolvable → NO-DNS, no fping call.-dns 0= fping-side resolve. - UP/new hosts get full
-reretries; confirmed-DOWN hosts get-drretries. Every-fs-th round probes everything with full retries. - Only 1/
-dsof DOWN hosts probed per round, strided. - Both classes run concurrently, one fping process each, sharing
--rate;-iderived from that share. - With
-cf> 1, a host leaves UP only after that many consecutive non-UP results; suppressed count written to the log's TBD column.
One fping process per group (-p still accepts up to 32 for diagnostics): measured on
a /20 with 4109 hosts, 9 processes reported 244 UP, one process reported 866.
-i floor is 1ms (~1000 pps nominal); measured ~1.8ms (~550 pps) on a real /20. -i 0
removes pacing (needs fping's install privileges), one hard burst.
Options
Host selection
-f hostfile(s) (comma/space separated) · -df disable hostfile · -n CIDR (comma
separated) · -r IP range (comma separated, shortened end)
Probing
| Option | Range | Default | Meaning |
|---|---|---|---|
-B |
1 – 2 | 1.5 | backoff factor per retry |
-t |
10 – 5000 | 250 | initial timeout (ms) |
-re |
0 – 5 | 3 | retries, UP/unknown hosts |
-dr |
0 – 5 | 1 | retries, confirmed DOWN (0 = same as others) |
-i |
-1 – 250 | auto | send interval (ms), overrides -ra; -1 auto, 0 unpaced |
-p |
0 – 32 | auto | fping processes per group |
-w |
0 – 600 | 0.5 | pause between rounds (s) |
-cf |
1 – 10 | 2 | consecutive DOWN before leaving UP (1 = off) |
-ra |
10 – 25000 | 1000 | ICMP packets/s |
-fw |
1 – 72000 | 72000 | minutes to count as flapping |
-ds |
1 – 20 | 4 | spread DOWN hosts over N rounds |
-fs |
0 – 50 | 10 | every Nth round: full sweep (0 = never) |
-dns |
0 – 3600 | 300 | hostname cache TTL (s, 0 off) |
-4 / -6 |
— | auto | prefer IPv4/IPv6, mutually exclusive |
-ph |
— | off | start with PREFER HOSTNAMES |
-ipo |
— | off | start with IP ONLY |
-gn |
— | off | GET NAMES once at startup |
-ncs |
— | off | skip --check-source |
-up |
— | 0 | learning phase: after N rounds keep only hosts seen UP |
-setref |
— | off | with -up: hosts seen UP become new reference list |
Hard-enforced at startup and live via ADV OPTIONS (-web only), same bounds.
Output
| Option | Range | Default | Meaning |
|---|---|---|---|
-o |
— | auto | CSV log file name |
-dl |
— | — | disable logging |
-cl |
— | — | delete all eping-* files and exit |
-tz |
-24 – +24 | 0 | timezone offset (h) |
-dg |
— | off | cycle time breakdown |
-du |
— | — | disable online version check |
-lms |
0, 10 – 2500 | 0 | max CSV log size (MB) before rotating; 0 = no rotation |
-lmf |
0 – 500 | 0 | max eping-log_*.csv files kept, oldest deleted first; 0 = unlimited |
-web |
— | off | web GUI instead of CLI |
-wv |
— | off | CLI + read-only web view |
-port |
— | 8080 | http port |
-bind |
— | 0.0.0.0 | bind address |
Logging
Unless -dl, every round appends to eping-log_YYYY-MM-DD_HH:MM:SS.csv (or -o FILE):
TIMESTAMP,HOSTNAME,PREVIOUS_STATE,CURRENT_STATE,RTT,NO_OF_CHANGES,CHANGE_TIMESTAMP,TBD,IP,INV_HOSTNAME,SERIAL_NUMBER,MODEL,LOCATION,SYSLOCATION,TYPE,INV_COMMENT
INV_HOSTNAME … INV_COMMENT: the inventory values of a host added from an inventory CSV (see
Inventory CSV import), empty for all other hosts. Logs without these columns (older
versions) stay readable by epinga.py.
TBD: suppressed DOWN observations (-cf). IP: address actually pinged (empty for
NO-DNS). Log rotates to a new file once it reaches -lms MB; a single round's data is
always written in full to one file, rotation only starts the next round in a new file.
-lmf prunes the oldest files once exceeded. A size-rotated file reuses the chain's
original timestamp with an incrementing -1/-2/... suffix
(eping-log_<original-timestamp>-N.csv); starting a new file manually (RESET LOGGING/L) always gets the current time instead and begins a fresh chain.
ZERO CHANGES/Z: resets NO_OF_CHANGES/CHANGE_TIMESTAMP for the running instance;
log file keeps everything already written.
ADD COMMENT/T: appends a timestamped row while logging is on, #COMMENT# sentinel
in HOSTNAME, text in IP. No-op with a notice if logging is off. epinga.py detects
these rows automatically.
RESET LOGGING/L:
- Logging on: confirmation first (CLI keypress / web modal).
Yclears all entries, restarts logging into the same file.Nstarts a fresh file, old file untouched - optional custom name (blank = auto-generatedeping-log_<timestamp>.csv); a name that already exists is rejected, nothing is created.ESC/ENTERcancels. - Logging off: same dialog, no clear option -
START LOGGINGstarts a fresh file right away, same optional custom name.
Web GUI header
Header: eping.py vX.XX · © Ewald Jeitler · supervised by Nelly · tools.jeitler.cc · www.jeitler.cc, paw icons, matching epinga.py's report footer/favicon. CLI header:
eping.py version X.XX by Ewald Jeitler (no SVG support).
Update notice (CLI)
If a newer version is available (see -du), a one-line hint shows in the top bar. On
exit, a full notice prints once:
A new version of eping.py is available! (installed: vX.XX, latest: vY.YY)
Install it with:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/ewaldj/eping/refs/heads/main/e-install.sh)"
Or visit:
https://www.jeitler.cc
https://github.com/ewaldj/eping
Shown on any terminal-driven exit (CLI [E]/Ctrl-C, -web's EXIT/Ctrl-C in its
terminal). The web GUI's in-browser banner is separate and shorter.
Run analysis on exit
On stop, with logging on and a non-empty logfile, eping.py asks:
Run an analysis of this logfile with epinga.py now? [y/N]:
y (case-insensitive) runs epinga.py -f <logfile> before exit; anything else skips
it. Only asked on a terminal-driven exit (CLI [E]/Ctrl-C, or -wv/-wvc's own
keyboard [E]/Ctrl-C); exiting via a browser's EXIT button never asks. No prompt if
logging is off or the logfile is empty/missing.
GENERATE REPORT (web gui) / ANALYSE NOW (CLI N)
Runs epinga.py against one or more logfiles in the background while eping.py keeps
running - not just at exit. Web: GENERATE REPORT dropdown, two entries - ACTIVE LOGFILE analyses the active CSV log (needs logging on, non-empty logfile, else the tab
closes and a footer error is shown), CHOOSE LOGFILE picks one or more .csv files in
the working dir - table (name/size/date), "select all" checkbox, nothing preselected;
up to 25 files per report, checking a 26th is refused.
More than one selected file is merged chronologically (by mtime) into one temporary
CSV, analysed as a single logfile, then the temp file is removed. Result opens in a new
tab; if a selected file was invalid or has meanwhile been removed (e.g. by log rotation
pruning it between picking and clicking GENERATE), the tab closes and a footer error is
shown instead of sitting on "please wait" forever. CLI: N always analyses the active
logfile only (needs logging on, non-empty logfile, else a notice is shown); result
path/error shown once done. Only one run at a time either way. See epinga.py below for
the report, and Called from eping.py under epinga.py for the invocation.
VIEW FILE FROM SERVER (web gui only)
Read-only viewer for one or more .csv/.txt files in the working dir - FILE
OPERATIONS > VIEW FILE FROM SERVER, table picker (name/size/date), "select all". Each
selected file opens in its own tab: raw content, COPY (clipboard) and DOWNLOAD buttons,
no editing. Selecting more than one file opens the first tab right away; that tab shows
a centered "N more file(s) selected / OPEN NEXT FILE" box to open the next one, and so
on (browsers only allow one new tab per click, so the rest open one click at a time).
Max 200MB per file - larger files are refused with a message pointing at DOWNLOAD
instead, and the picker greys those files out, labeled "TOO LARGE", with the current
limit shown in the modal text.
Address modes (PREFER HOSTNAME / SWITCH TO IP ONLY / GET NAMES)
PREFER HOSTNAME (-ph): drops a raw-IP host from pinging when another entry resolves
to the same address. Redundancy check cached -dns seconds. PREFER IP ADDRESS: the
mirror - drops a hostname entry once its resolved address is already covered by a
raw-IP entry. Both non-destructive, restored by switching to another mode. Starting
with -ph resolves every hostname first (in parallel): the CLI shows a PLEASE WAIT
box with an elapsed counter meanwhile, the web mode a line in the terminal.
SWITCH TO IP ONLY (-ipo): resolves every hostname to its address (v4/v6 per
-4/-6, A preferred by default) and renames it in place (history/uptime carry over).
CLI: a hostname whose address collides with another host is dropped and not restored.
Web GUI: colliding/unresolvable hosts are hidden (not pinged) while active, restored
automatically when switching away.
CLI P and the web GUI's address mode select/P picker reach the same 4 exclusive
modes: HOSTNAME & IP (default, no dedup), PREFER HOSTNAME, PREFER IP ADDRESS,
SWITCH TO IP ONLY. The web GUI additionally has its own P/I keyboard shortcuts
that toggle PREFER HOSTNAME / SWITCH TO IP ONLY directly (see Web GUI). Leaving
SWITCH TO IP ONLY restores hostnames before applying the new mode.
GET NAMES/G (-gn): reverse-DNS every raw IP with no hostname counterpart, renames
on a PTR match (history/uptime carry over). Stays an IP if: no PTR record, name
collides with an existing host, PTR name shared by more than one candidate IP, or no
matching forward A/AAAA record back to the same IP. One-shot, not a toggle.
Runs on a background thread (only -gn at startup blocks). While running: CLI
header/web status line show "GET NAMES running in background (N host(s))..."; result
message shows for 3s after. Re-triggering while running shows "already running".
Match filter
M (CLI) / match filter field (web): case-insensitive regex, display only, matched
against shown name, resolved IP and the inventory fields (CSV hostname, serial
number, model, location, sysLocation, type, comment). Every host keeps being pinged regardless. Empty
value turns it off. CLI: replaces the version banner with MATCH FILTER '<regex>' active (N of M hosts shown, all still pinged). Invalid regex: error shown, previous
filter unchanged.
IPv6
IPv4/IPv6 mixed freely. Resolution follows -4/-6 (preference, not restriction; A
preferred by default). IPv4-mapped IPv6 (::ffff:a.b.c.d) falls back to plain IPv4.
PREFER HOSTNAMES/PREFER IP ADDRESS/GET NAMES consider every resolved address.
fping runs one process per family when both are present (-dg shows a /v6 group).
CIDR/IP-range expansion IPv4-only; IPv6 needs /128 (e.g. 2001:db8::1/128), any
other mask rejected. IPv6 addresses are always stored in shortest form.
Diagnostics (-dg)
FPING 11.46 [full 865(-r 3,-i 5ms) 4.31s reduced 3242(-r 1,-i 1ms) 11.46s]
|| DNS 0.00 STATE 0.01 BUILD 0.00 WAIT 0.50 DRAW 0.11
FPING: round wall time, then per-group wall time (parallel, max not sum). Remaining
phases: eping's own work (~0.12s on 4109 hosts).
Notes
- ICMP echo requests only. Use only on authorised networks.
-p> 1 and-i 0reduce accuracy (false DOWN) — defaults avoid both.-dr 0produces flapping hosts in practice — keep the default of 1.
epinga.py 2.35
Analyses an eping.py CSV log: terminal summary + self-contained HTML report (no server, no external assets) with per-host detail, state-change timelines, and always-UP/flapping/always-DOWN/no-DNS buckets.
Quick start
./epinga.py # interactive menu - pick a *.csv
./epinga.py -f eping-log_2026-09-05.csv # analyse a specific logfile
./epinga.py -f FILE --open # analyse and open the report
Output: <base>_report.txt and <base>_report.html (--html FILE overrides).
Options
| Option | Effect |
|---|---|
-f FILE, --logfile FILE |
CSV logfile (omit for interactive picker) |
-H HOST, --host HOST |
only this host (repeatable) |
-s, --start YYYY-MM-DD HH:MM:SS |
rows from this timestamp on |
-e, --end YYYY-MM-DD HH:MM:SS |
rows up to this timestamp |
-S, --sort {name,flapping,uptime,rtt} |
summary sort order (default name) |
--no-detail |
summary only |
--no-changes |
omit state-change list |
--html FILE |
custom HTML filename |
--open |
open HTML report automatically |
-q, --quiet |
suppress progress bar |
--no-version-check |
skip online update check |
Called from eping.py
GENERATE REPORT (web gui) and N/ANALYSE NOW (CLI) both run epinga.py in a
background thread: stdin closed, --no-version-check -q --html <logfile-base>_report.html. Web: a blank tab opens right away, navigates to the report
once done (1s poll). CLI: result path/error shown via a notice once done. Either way,
one run at a time, never overwrites - repeat run for the same logfile gets
_report-1.html, _report-2.html, etc. Also used by Run analysis on exit
(epinga.py -f <logfile>, in-process, no thread).
HTML report
Everything inlined into one .html (CSS/JS/data as JSON) - portable, works offline.
Top bar: total/UP/flapping/DOWN/no-DNS/duplicate-host counts. Toolbar:
| Control | Does |
|---|---|
| Filter | text or regex (case-insensitive), hostname + IP + inventory fields (CSV hostname, serial, model, location, sysLocation, type, comment); invalid regex falls back to substring |
| Show | restrict to one state (flapping independent of UP/DOWN/NO-DNS) |
| Sort | name / uptime% / avg RTT / changes; click a header, shift+click adds a tie-breaker (①②③ badge), shift+click again flips direction |
| IP View | toggle primary label hostname↔IP (table + buckets); independent of dedup |
| Deduplication | No dedup / Prefer IP / Prefer hostname - hides the redundant side across table, buckets, top-bar cards; DUPLICATES card is 0 once a mode is active |
| Reset | clears Filter, Show and the inventory drop-downs (sort, IP View and deduplication stay) |
| Download | saves the report exactly as shown (theme/dedup/sort/filter/collapsed state) as a standalone .html, client-side; hidden on file:// |
Inventory filters (logs with inventory columns, see Inventory CSV import): to the
right of the top-bar counters, one drop-down each for Model, Location, sysLocation,
Type and Comment, listing the values found in the log with their host count ((empty) for hosts
without a value). They combine with each other and with Filter/Show and affect the
Host List only. A column without any value gets no drop-down; serial number and CSV
hostname are unique per device and searched via Filter instead. The drop-downs are
narrow; the one in use widens while it has focus and the others move aside. A host's detail shows
all inventory values, the Host List CSV download adds them as columns.
Comments: section above Host List from #COMMENT# rows, collapsed by default,
timestamp + text in log order. Also appear inline in a host's STATE CHANGES timeline
(orange, 💬 marker), HTML-escaped. Same merge in text output (PER-HOST DETAIL,
COMMENT: prefix, no emoji). Standalone COMMENTS (N) block before PER-HOST DETAIL
in text output.
Host List (filterable/sortable table) + six buckets (Always UP, UP+FLAPPING,
Flapping, Always DOWN, DOWN+FLAPPING, No-DNS), independently collapsible. Host List and
DOWN+FLAPPING start expanded, the rest collapsed; state survives IP View/Dedup changes.
Each bucket: Download (<base>-<up|down|flap|nodns>-hosts.txt) + Copy (clipboard, with
execCommand fallback). Host List itself: Download (CSV) + Copy.
Row click expands: state-change history with timestamps, per-host stats (IP, uptime, downtime, span, first/last seen, RTT min/avg/max).
esplit.py 1.14
Splits a large CSV logfile into smaller parts by size.
./esplit.py # interactive menu
./esplit.py -i eping-log_2026-09-05.csv -o parts -s 20 # ~20MB parts
| Option | Effect |
|---|---|
-i, --input FILE |
CSV file to split (omit for interactive picker) |
-o, --output DIR |
output folder (created if missing) |
-s, --size MB |
max size per part |
Each part: part_NNN.csv, own header row. Rows never split across parts; a
#COMMENT# row lands in whichever part it falls into.
Metadata
Release files for eping 3.65
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| eping-3.65.tar.gz | 192.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| eping-3.65-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 359.9 kB
Release files / eping-3.65.tar.gz
| Download URL | eping-3.65.tar.gz |
|---|---|
| Size | 192.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d987b43f9a542b26607161698c12460cb85b259e3d49baf35c8d92261b9d7326
|
|
BLAKE2b-256 checksum How to use checksums |
33ed086d0a73d8be7470162dec6e337858f74126be5260b225642a9b073afcf6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.13
|
Release files / eping-3.65-py3-none-any.whl
| Download URL | eping-3.65-py3-none-any.whl |
|---|---|
| Size | 167.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ca621e333bc29ee3bca527c2d3238a418e903a3e4e745b49079d3c580666429b
|
|
BLAKE2b-256 checksum How to use checksums |
caa85cddbe522418e6355fe7749d53a3a674a13c85624e69456333d5cbff0505
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.13
|
Security for eping 3.65
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.