eping 3.84__tar.gz → 3.86__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eping
3
- Version: 3.84
3
+ Version: 3.86
4
4
  Summary: Continuous ICMP reachability monitor built on fping, with a CSV logfile analyser (epinga)
5
5
  Author-email: Ewald Jeitler <ewald@jeitler.cc>
6
6
  License: GPL-3.0-or-later
@@ -17,7 +17,7 @@ Description-Content-Type: text/markdown
17
17
  License-File: LICENSE
18
18
  Dynamic: license-file
19
19
 
20
- # eping.py 3.84
20
+ # eping.py 3.86
21
21
 
22
22
  Continuous ICMP reachability monitor built on `fping`. Scans a host list in a loop,
23
23
  reports each host UP/DOWN/NO-DNS, counts state changes. CLI (curses) or web GUI.
@@ -40,14 +40,12 @@ Via pip (installs `eping` and `epinga` as commands, `fping` still required separ
40
40
  pip install eping
41
41
  ```
42
42
 
43
- Standalone scripts (installs/updates `eping.py`, `epinga.py`, `esplit.py`):
43
+ Standalone scripts (installs/updates `eping.py`, `epinga.py`):
44
44
 
45
45
  ```sh
46
46
  /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/ewaldj/eping/refs/heads/main/e-install.sh)"
47
47
  ```
48
48
 
49
- `esplit.py` isn't part of the pip package - use the standalone install for it.
50
-
51
49
  ## Windows
52
50
 
53
51
  Portable Windows version (web GUI only, no installation): download and unpack
@@ -149,7 +147,8 @@ named `*.txt` are never treated as CSV - they keep the plain host file format ab
149
147
  - **Columns used**: `IP Address`, `Hostname`, `Serial Number`, `Model`, `Location`,
150
148
  `sysLocation`, `Type`, `Comment`. All other columns are ignored.
151
149
  - **Host entry**: the `Hostname` (default; rows without an IP are pinged by name too,
152
- NO-DNS if it does not resolve). A name that is not a valid hostname falls back to the
150
+ NO-DNS if it does not resolve). A name without DNS record is pinged by the row's
151
+ IP instead (marked in the host popup, `-ncf` turns this off). A name that is not a valid hostname falls back to the
153
152
  IP; rows without a usable entry are ignored. In the IP modes (`-ipo`, PREFER IP
154
153
  ADDRESS, also when active while the file is added) the entry is the IP address
155
154
  instead and rows without a valid IP are ignored. `-ph` is not needed for a CSV.
@@ -255,7 +254,7 @@ Single self-contained page, no external resources.
255
254
  | Entry | Does |
256
255
  |---|---|
257
256
  | ADD HOSTS FILE FROM SERVER | picks one or more `.txt` files or inventory `.csv` files already on the server, adds their hosts; a `.csv` without the inventory header, e.g. an eping log, is refused |
258
- | ADD HOSTS FILE FROM CLIENT | local file picker (`.txt`/`.csv`), adds the hosts; a file can also be dropped anywhere on the page |
257
+ | ADD HOSTS FILE FROM CLIENT | dialog with a file picker (`.txt`/`.csv`; works in Safari), adds the hosts; a file can also be dropped anywhere on the page |
259
258
  | SAVE HOSTS FILE ON SERVER | confirmation, then saves the currently displayed hosts; blank name overwrites the active `-f` hostfile (first one, if eping.py was started with one) or, with none active, the default `eping-hosts.txt`; a typed name always saves as that new file instead, `.txt` appended once, active hostfile left untouched. If the displayed hosts carry inventory values (CSV import) an inventory `.csv` is written instead (`;` delimited, columns as in *Inventory CSV import*); a `.txt` name or hostfile then becomes `.csv`, the default is `eping-hosts.csv`. The options that differ from the default are written first as `opt:` lines (see *Host file format*); for a `.csv` the checkboxes `include options (opt: lines)` (default on) and `save as .txt (hosts only, no inventory)` (default off) are offered |
260
259
  | UPLOAD FILE TO SERVER | picks a local `.txt`/`.csv`, saves as-is server-side, no host parsing; never overwrites, appends `-1`/`-2`/... |
261
260
  | DOWNLOAD ALL HOSTS | full reference list: inventory `.csv` if the hosts carry inventory values, else `.txt`; non-default options first as `opt:` lines (`.csv`: checkboxes `include options`, default on, and `save as .txt`, default off) |
@@ -435,6 +434,7 @@ separated) · `-r` IP range (comma separated, shortened end)
435
434
  | `-ipo` | — | off | start with IP ONLY |
436
435
  | `-gn` | — | off | GET NAMES once at startup |
437
436
  | `-ncs` | — | off | skip `--check-source` |
437
+ | `-ncf` | — | off | CSV: do not ping the CSV IP of a name without DNS record |
438
438
  | `-up` | — | 0 | learning phase: after N rounds keep only hosts seen UP |
439
439
  | `-setref` | — | off | with `-up`: hosts seen UP become new reference list |
440
440
 
@@ -728,21 +728,3 @@ Each bucket: Download (`<base>-<up|down|flap|nodns>-hosts.txt`) + Copy (clipboar
728
728
 
729
729
  Row click expands: state-change history with timestamps, per-host stats (IP, uptime,
730
730
  downtime, span, first/last seen, RTT min/avg/max).
731
-
732
- # esplit.py 1.14
733
-
734
- Splits a large CSV logfile into smaller parts by size.
735
-
736
- ```sh
737
- ./esplit.py # interactive menu
738
- ./esplit.py -i eping-log_2026-09-05.csv -o parts -s 20 # ~20MB parts
739
- ```
740
-
741
- | Option | Effect |
742
- |---|---|
743
- | `-i`, `--input FILE` | CSV file to split (omit for interactive picker) |
744
- | `-o`, `--output DIR` | output folder (created if missing) |
745
- | `-s`, `--size MB` | max size per part |
746
-
747
- Each part: `part_NNN.csv`, own header row. Rows never split across parts; a
748
- `#COMMENT#` row lands in whichever part it falls into.
@@ -1,4 +1,4 @@
1
- # eping.py 3.84
1
+ # eping.py 3.86
2
2
 
3
3
  Continuous ICMP reachability monitor built on `fping`. Scans a host list in a loop,
4
4
  reports each host UP/DOWN/NO-DNS, counts state changes. CLI (curses) or web GUI.
@@ -21,14 +21,12 @@ Via pip (installs `eping` and `epinga` as commands, `fping` still required separ
21
21
  pip install eping
22
22
  ```
23
23
 
24
- Standalone scripts (installs/updates `eping.py`, `epinga.py`, `esplit.py`):
24
+ Standalone scripts (installs/updates `eping.py`, `epinga.py`):
25
25
 
26
26
  ```sh
27
27
  /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/ewaldj/eping/refs/heads/main/e-install.sh)"
28
28
  ```
29
29
 
30
- `esplit.py` isn't part of the pip package - use the standalone install for it.
31
-
32
30
  ## Windows
33
31
 
34
32
  Portable Windows version (web GUI only, no installation): download and unpack
@@ -130,7 +128,8 @@ named `*.txt` are never treated as CSV - they keep the plain host file format ab
130
128
  - **Columns used**: `IP Address`, `Hostname`, `Serial Number`, `Model`, `Location`,
131
129
  `sysLocation`, `Type`, `Comment`. All other columns are ignored.
132
130
  - **Host entry**: the `Hostname` (default; rows without an IP are pinged by name too,
133
- NO-DNS if it does not resolve). A name that is not a valid hostname falls back to the
131
+ NO-DNS if it does not resolve). A name without DNS record is pinged by the row's
132
+ IP instead (marked in the host popup, `-ncf` turns this off). A name that is not a valid hostname falls back to the
134
133
  IP; rows without a usable entry are ignored. In the IP modes (`-ipo`, PREFER IP
135
134
  ADDRESS, also when active while the file is added) the entry is the IP address
136
135
  instead and rows without a valid IP are ignored. `-ph` is not needed for a CSV.
@@ -236,7 +235,7 @@ Single self-contained page, no external resources.
236
235
  | Entry | Does |
237
236
  |---|---|
238
237
  | ADD HOSTS FILE FROM SERVER | picks one or more `.txt` files or inventory `.csv` files already on the server, adds their hosts; a `.csv` without the inventory header, e.g. an eping log, is refused |
239
- | ADD HOSTS FILE FROM CLIENT | local file picker (`.txt`/`.csv`), adds the hosts; a file can also be dropped anywhere on the page |
238
+ | ADD HOSTS FILE FROM CLIENT | dialog with a file picker (`.txt`/`.csv`; works in Safari), adds the hosts; a file can also be dropped anywhere on the page |
240
239
  | SAVE HOSTS FILE ON SERVER | confirmation, then saves the currently displayed hosts; blank name overwrites the active `-f` hostfile (first one, if eping.py was started with one) or, with none active, the default `eping-hosts.txt`; a typed name always saves as that new file instead, `.txt` appended once, active hostfile left untouched. If the displayed hosts carry inventory values (CSV import) an inventory `.csv` is written instead (`;` delimited, columns as in *Inventory CSV import*); a `.txt` name or hostfile then becomes `.csv`, the default is `eping-hosts.csv`. The options that differ from the default are written first as `opt:` lines (see *Host file format*); for a `.csv` the checkboxes `include options (opt: lines)` (default on) and `save as .txt (hosts only, no inventory)` (default off) are offered |
241
240
  | UPLOAD FILE TO SERVER | picks a local `.txt`/`.csv`, saves as-is server-side, no host parsing; never overwrites, appends `-1`/`-2`/... |
242
241
  | DOWNLOAD ALL HOSTS | full reference list: inventory `.csv` if the hosts carry inventory values, else `.txt`; non-default options first as `opt:` lines (`.csv`: checkboxes `include options`, default on, and `save as .txt`, default off) |
@@ -416,6 +415,7 @@ separated) · `-r` IP range (comma separated, shortened end)
416
415
  | `-ipo` | — | off | start with IP ONLY |
417
416
  | `-gn` | — | off | GET NAMES once at startup |
418
417
  | `-ncs` | — | off | skip `--check-source` |
418
+ | `-ncf` | — | off | CSV: do not ping the CSV IP of a name without DNS record |
419
419
  | `-up` | — | 0 | learning phase: after N rounds keep only hosts seen UP |
420
420
  | `-setref` | — | off | with `-up`: hosts seen UP become new reference list |
421
421
 
@@ -709,21 +709,3 @@ Each bucket: Download (`<base>-<up|down|flap|nodns>-hosts.txt`) + Copy (clipboar
709
709
 
710
710
  Row click expands: state-change history with timestamps, per-host stats (IP, uptime,
711
711
  downtime, span, first/last seen, RTT min/avg/max).
712
-
713
- # esplit.py 1.14
714
-
715
- Splits a large CSV logfile into smaller parts by size.
716
-
717
- ```sh
718
- ./esplit.py # interactive menu
719
- ./esplit.py -i eping-log_2026-09-05.csv -o parts -s 20 # ~20MB parts
720
- ```
721
-
722
- | Option | Effect |
723
- |---|---|
724
- | `-i`, `--input FILE` | CSV file to split (omit for interactive picker) |
725
- | `-o`, `--output DIR` | output folder (created if missing) |
726
- | `-s`, `--size MB` | max size per part |
727
-
728
- Each part: `part_NNN.csv`, own header row. Rows never split across parts; a
729
- `#COMMENT#` row lands in whichever part it falls into.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "eping"
7
- version = "3.84"
7
+ version = "3.86"
8
8
  description = "Continuous ICMP reachability monitor built on fping, with a CSV logfile analyser (epinga)"
9
9
  readme = "README.md"
10
10
  license = { text = "GPL-3.0-or-later" }
@@ -7,7 +7,7 @@
7
7
  # I knew how it worked.
8
8
  # Now, only god knows it!
9
9
  # - - - - - - - - - - - - - - - - - - - - - - - -
10
- VERSION = '3.84'
10
+ VERSION = '3.86'
11
11
  version = VERSION # legacy alias (kept for existing references)
12
12
 
13
13
  # --- scaling limits ---
@@ -516,6 +516,8 @@ def create_sample_csv(filename=SAMPLE_CSV_NAME):
516
516
  return False # a read-only directory must not stop eping
517
517
 
518
518
  use_check_source = True # set from --no_check_source in main
519
+ csv_ip_fallback = True # set from --no_csv_fallback in main: a CSV hostname that does not resolve is pinged by its CSV IP
520
+ _csv_fb_names = frozenset() # hostnames pinged by their CSV IP in the last round (host popup)
519
521
  web_readonly = False # True with --web_view: the CLI drives, the browser only looks
520
522
 
521
523
  _fping_caps = None
@@ -902,14 +904,23 @@ def prepare_targets(hosts, ttl, progress_cb=None):
902
904
  for n in pending:
903
905
  resolve_name(n, ttl)
904
906
 
907
+ global _csv_fb_names
905
908
  targets = []
906
909
  name_map = {}
907
910
  unresolved = []
911
+ fallback = set()
908
912
  for h in hosts:
909
913
  if is_ip_host(h):
910
914
  target = h
911
915
  else:
912
916
  target = resolve_name(h, ttl)
917
+ if not target and csv_ip_fallback:
918
+ # no DNS record, but the inventory CSV has an address for this host: ping that
919
+ target = host_csv_ip.get(h) or ''
920
+ if target and is_ip_host(target):
921
+ fallback.add(h)
922
+ else:
923
+ target = ''
913
924
  if not target:
914
925
  unresolved.append(h)
915
926
  continue
@@ -917,6 +928,7 @@ def prepare_targets(hosts, ttl, progress_cb=None):
917
928
  name_map[target] = []
918
929
  targets.append(target)
919
930
  name_map[target].append(h)
931
+ _csv_fb_names = frozenset(fallback)
920
932
  return targets, name_map, unresolved
921
933
 
922
934
 
@@ -2363,6 +2375,8 @@ def run_ping_round(active_hosts_list, threads_arg, rate_pps=DEFAULT_RATE_PPS,
2363
2375
  scan_desc += (' (--rate %d not reachable, -i floor 1ms)' % rate_pps)
2364
2376
  if use_check_source and '--check-source' in fping_capabilities():
2365
2377
  scan_desc += ', check-source'
2378
+ if _csv_fb_names:
2379
+ scan_desc += ', %d by CSV IP (no DNS)' % len(_csv_fb_names)
2366
2380
  if _scan_error:
2367
2381
  scan_desc += ' | ERROR: ' + _scan_error
2368
2382
 
@@ -2834,6 +2848,16 @@ WEB_INDEX_HTML = r"""<!DOCTYPE html>
2834
2848
  </div>
2835
2849
  </div>
2836
2850
  </div>
2851
+ <div id="addFromClientModal" class="modal-overlay" style="display:none">
2852
+ <div class="modal-box">
2853
+ <h3>ADD FROM CLIENT</h3>
2854
+ <p>Choose a `.txt` or `.csv` hosts file from this computer to add its hosts.</p>
2855
+ <input type="file" id="fileInputVis" accept=".txt,.csv,.list,text/plain" style="margin-bottom:14px;color:var(--fg)">
2856
+ <div class="modal-buttons">
2857
+ <button id="modalBtnAddFromClientCancel">CANCEL</button>
2858
+ </div>
2859
+ </div>
2860
+ </div>
2837
2861
  <div id="chooseReportModal" class="modal-overlay" style="display:none">
2838
2862
  <div class="modal-box wide xwide">
2839
2863
  <h3>CHOOSE LOGFILE</h3>
@@ -4073,9 +4097,21 @@ document.getElementById('btnClear').onclick = function(){
4073
4097
 
4074
4098
  /* ---- host file upload ---- */
4075
4099
  var fileInput = document.getElementById('fileInput');
4100
+ var fileInputVis = document.getElementById('fileInputVis');
4101
+ var addFromClientModal = document.getElementById('addFromClientModal');
4102
+ function closeAddFromClient(){ addFromClientModal.style.display = 'none'; fileInputVis.value = ''; }
4103
+ function addFromClientOpen(){ return addFromClientModal.style.display === 'flex'; }
4104
+ document.getElementById('modalBtnAddFromClientCancel').onclick = closeAddFromClient;
4105
+ fileInputVis.addEventListener('change', function(){
4106
+ var f = fileInputVis.files && fileInputVis.files[0];
4107
+ closeAddFromClient();
4108
+ if(f) uploadHostsFile(f, null);
4109
+ });
4076
4110
  fileInput.addEventListener('change', function(){
4077
4111
  var f = fileInput.files && fileInput.files[0];
4078
- if(!f) return;
4112
+ if(f) uploadHostsFile(f, fileInput);
4113
+ });
4114
+ function uploadHostsFile(f, inp){
4079
4115
  var rd = new FileReader();
4080
4116
  rd.onload = function(){
4081
4117
  note('uploading ' + f.name + ' ...', true);
@@ -4083,10 +4119,10 @@ fileInput.addEventListener('change', function(){
4083
4119
  body: rd.result}).then(function(r){ return r.json(); }).then(function(j){
4084
4120
  if(!j.ok){ note('upload failed: ' + (j.error||''), false); }
4085
4121
  }).catch(function(){ note('upload failed', false); });
4086
- fileInput.value = '';
4122
+ if(inp) inp.value = '';
4087
4123
  };
4088
4124
  rd.readAsText(f);
4089
- });
4125
+ }
4090
4126
 
4091
4127
  var uploadServerFileInput = document.getElementById('uploadServerFileInput');
4092
4128
  uploadServerFileInput.addEventListener('change', function(){
@@ -4353,7 +4389,7 @@ document.getElementById('selDownload').onchange = function(){
4353
4389
  this.value = ''; // reset - a select, not a toggle
4354
4390
  if(!what) return;
4355
4391
  if(what === 'add_from_server'){ openAddFromServer(); return; }
4356
- if(what === 'add_from_client'){ fileInput.click(); return; }
4392
+ if(what === 'add_from_client'){ addFromClientModal.style.display = 'flex'; return; } // visible input: Safari blocks click() from select change
4357
4393
  if(what === 'choose_logfile'){ openChooseLog(); return; }
4358
4394
  if(what === 'delete_files'){ openDeleteFiles(); return; }
4359
4395
  if(what === 'view_file'){ openViewFile(); return; }
@@ -4475,6 +4511,10 @@ document.addEventListener('keydown', function(e){
4475
4511
  if(sk === 'y' || e.key === 'Enter'){ runSaveHostsFile(); e.preventDefault(); }
4476
4512
  return;
4477
4513
  }
4514
+ if(addFromClientOpen()){
4515
+ if(e.key === 'Escape'){ closeAddFromClient(); e.preventDefault(); }
4516
+ return;
4517
+ }
4478
4518
  if(chooseLogOpen()){
4479
4519
  if(e.key === 'Escape'){ closeChooseLog(); e.preventDefault(); }
4480
4520
  return;
@@ -4698,6 +4738,7 @@ function tipRowsOf(d){
4698
4738
  }
4699
4739
  add('state', d.state, up ? 'up' : 'down');
4700
4740
  if(d.changes > 0) add('previous', d.prev);
4741
+ if(d.dns_fb) add('dns', 'no DNS record - pinged by the CSV address', 'down');
4701
4742
  if(d.ip && d.ip !== d.host) add('address', d.ip);
4702
4743
  add('rtt (ms)', d.rtt && d.rtt.indexOf('-') !== 0 ? d.rtt : '');
4703
4744
  add('last check', d.last_check);
@@ -5305,7 +5346,7 @@ _OPT_ARGS = None
5305
5346
  _ARG_DEFAULTS = {}
5306
5347
  # flag-less switches: dest -> flag
5307
5348
  _OPT_SWITCHES = (('disable_versioncheck', '-du'), ('force_ipv4', '-4'), ('force_ipv6', '-6'),
5308
- ('diag', '-dg'), ('no_check_source', '-ncs'), ('web', '-web'),
5349
+ ('diag', '-dg'), ('no_check_source', '-ncs'), ('no_csv_fallback', '-ncf'), ('web', '-web'),
5309
5350
  ('web_view', '-wv'), ('web_view_control', '-wvc'))
5310
5351
  # ADV OPTIONS key -> argparse dest of its default
5311
5352
  _OPT_KEY_DEST = {'backoff': 'backoff', 'timeout': 'timeout', 'retries': 'retries',
@@ -5986,6 +6027,7 @@ def host_details(name, tz_offset=0):
5986
6027
  'prev': str(row[4]).strip() if row[4] else '', 'last_check': str(row[2]),
5987
6028
  'rtt': str(row[3]), 'changes': row[5], 'change_ts': str(row[6] or ''),
5988
6029
  'since_s': since, 'csv_ip': host_csv_ip.get(name, ''),
6030
+ 'dns_fb': name in _csv_fb_names,
5989
6031
  'csv_hostname': meta[0], 'serial': meta[1], 'model': meta[2],
5990
6032
  'location': meta[3], 'sysloc': meta[4], 'type': meta[5], 'comment': meta[6],
5991
6033
  'hist': hist_list(name, tz_offset)}
@@ -6319,6 +6361,8 @@ def build_cli_snapshot(args, backoff, timeout, retries, down_retries, flap_windo
6319
6361
  parts.append('-lmf ' + str(args.log_max_files))
6320
6362
  if args.no_check_source:
6321
6363
  parts.append('-ncs')
6364
+ if args.no_csv_fallback:
6365
+ parts.append('-ncf')
6322
6366
  if args.web:
6323
6367
  parts.append('-web')
6324
6368
  if args.web_view:
@@ -7053,6 +7097,7 @@ if __name__=='__main__':
7053
7097
  parser.add_argument('-cf', '--confirm', default=str(CONFIRM_DEF), dest='confirm', help="consecutive DOWN observations before a host leaves UP (default: " + str(CONFIRM_DEF) + ", 1 = report every single observation)")
7054
7098
  parser.add_argument('-ds', '--down_slices', default=str(DOWN_SLICES_DEF), dest='down_slices', help="spread the known DOWN hosts over N rounds, range 1-" + str(DOWN_SLICES_MAX) + " (default: " + str(DOWN_SLICES_DEF) + ", 1 = probe all of them every round)")
7055
7099
  parser.add_argument('-fs', '--full_sweep', default=str(FULL_SWEEP_DEF), dest='full_sweep', help="every Nth run probes every host with full retries, range 0-" + str(FULL_SWEEP_MAX) + " (default: " + str(FULL_SWEEP_DEF) + ", 0 = disabled/never)")
7100
+ parser.add_argument('-ncf', '--no_csv_fallback', action="store_true", dest='no_csv_fallback', help="do not ping the CSV address of a host whose name does not resolve (default: it is pinged by the CSV IP and marked in the host popup)")
7056
7101
  parser.add_argument('-ncs', '--no_check_source', action="store_true", dest='no_check_source', help="do not pass --check-source to fping (only needed for hosts replying from a different address)")
7057
7102
  parser.add_argument('-web', '--web', action="store_true", dest='web', help="start the web gui instead of the terminal (CLI) output")
7058
7103
  parser.add_argument('-wv', '--web_view', action="store_true", dest='web_view', help="CLI mode plus a read-only web view on --port (browser shows the same data, no controls)")
@@ -7095,6 +7140,7 @@ if __name__=='__main__':
7095
7140
  retries = args.retries
7096
7141
  interval = args.interval
7097
7142
  use_check_source = not args.no_check_source
7143
+ csv_ip_fallback = not args.no_csv_fallback
7098
7144
  dns_family = '4' if args.force_ipv4 else ('6' if args.force_ipv6 else 'auto')
7099
7145
 
7100
7146
  # check online current version
@@ -7345,6 +7391,7 @@ if __name__=='__main__':
7345
7391
  "# opt: -ds 4 # spread known DOWN hosts over N rounds\n",
7346
7392
  "# opt: -fs 10 # every Nth run: full retries for everyone (0 = never)\n",
7347
7393
  "# opt: -ncs # do not pass --check-source to fping\n",
7394
+ "# opt: -ncf # CSV: do not ping the CSV IP of a name without DNS record\n",
7348
7395
  "# opt: -web # start the web gui instead of the CLI\n",
7349
7396
  "# opt: -wv # CLI mode plus a read-only web view\n",
7350
7397
  "# opt: -port 8080 # http port for -web / -wv\n",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: eping
3
- Version: 3.84
3
+ Version: 3.86
4
4
  Summary: Continuous ICMP reachability monitor built on fping, with a CSV logfile analyser (epinga)
5
5
  Author-email: Ewald Jeitler <ewald@jeitler.cc>
6
6
  License: GPL-3.0-or-later
@@ -17,7 +17,7 @@ Description-Content-Type: text/markdown
17
17
  License-File: LICENSE
18
18
  Dynamic: license-file
19
19
 
20
- # eping.py 3.84
20
+ # eping.py 3.86
21
21
 
22
22
  Continuous ICMP reachability monitor built on `fping`. Scans a host list in a loop,
23
23
  reports each host UP/DOWN/NO-DNS, counts state changes. CLI (curses) or web GUI.
@@ -40,14 +40,12 @@ Via pip (installs `eping` and `epinga` as commands, `fping` still required separ
40
40
  pip install eping
41
41
  ```
42
42
 
43
- Standalone scripts (installs/updates `eping.py`, `epinga.py`, `esplit.py`):
43
+ Standalone scripts (installs/updates `eping.py`, `epinga.py`):
44
44
 
45
45
  ```sh
46
46
  /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/ewaldj/eping/refs/heads/main/e-install.sh)"
47
47
  ```
48
48
 
49
- `esplit.py` isn't part of the pip package - use the standalone install for it.
50
-
51
49
  ## Windows
52
50
 
53
51
  Portable Windows version (web GUI only, no installation): download and unpack
@@ -149,7 +147,8 @@ named `*.txt` are never treated as CSV - they keep the plain host file format ab
149
147
  - **Columns used**: `IP Address`, `Hostname`, `Serial Number`, `Model`, `Location`,
150
148
  `sysLocation`, `Type`, `Comment`. All other columns are ignored.
151
149
  - **Host entry**: the `Hostname` (default; rows without an IP are pinged by name too,
152
- NO-DNS if it does not resolve). A name that is not a valid hostname falls back to the
150
+ NO-DNS if it does not resolve). A name without DNS record is pinged by the row's
151
+ IP instead (marked in the host popup, `-ncf` turns this off). A name that is not a valid hostname falls back to the
153
152
  IP; rows without a usable entry are ignored. In the IP modes (`-ipo`, PREFER IP
154
153
  ADDRESS, also when active while the file is added) the entry is the IP address
155
154
  instead and rows without a valid IP are ignored. `-ph` is not needed for a CSV.
@@ -255,7 +254,7 @@ Single self-contained page, no external resources.
255
254
  | Entry | Does |
256
255
  |---|---|
257
256
  | ADD HOSTS FILE FROM SERVER | picks one or more `.txt` files or inventory `.csv` files already on the server, adds their hosts; a `.csv` without the inventory header, e.g. an eping log, is refused |
258
- | ADD HOSTS FILE FROM CLIENT | local file picker (`.txt`/`.csv`), adds the hosts; a file can also be dropped anywhere on the page |
257
+ | ADD HOSTS FILE FROM CLIENT | dialog with a file picker (`.txt`/`.csv`; works in Safari), adds the hosts; a file can also be dropped anywhere on the page |
259
258
  | SAVE HOSTS FILE ON SERVER | confirmation, then saves the currently displayed hosts; blank name overwrites the active `-f` hostfile (first one, if eping.py was started with one) or, with none active, the default `eping-hosts.txt`; a typed name always saves as that new file instead, `.txt` appended once, active hostfile left untouched. If the displayed hosts carry inventory values (CSV import) an inventory `.csv` is written instead (`;` delimited, columns as in *Inventory CSV import*); a `.txt` name or hostfile then becomes `.csv`, the default is `eping-hosts.csv`. The options that differ from the default are written first as `opt:` lines (see *Host file format*); for a `.csv` the checkboxes `include options (opt: lines)` (default on) and `save as .txt (hosts only, no inventory)` (default off) are offered |
260
259
  | UPLOAD FILE TO SERVER | picks a local `.txt`/`.csv`, saves as-is server-side, no host parsing; never overwrites, appends `-1`/`-2`/... |
261
260
  | DOWNLOAD ALL HOSTS | full reference list: inventory `.csv` if the hosts carry inventory values, else `.txt`; non-default options first as `opt:` lines (`.csv`: checkboxes `include options`, default on, and `save as .txt`, default off) |
@@ -435,6 +434,7 @@ separated) · `-r` IP range (comma separated, shortened end)
435
434
  | `-ipo` | — | off | start with IP ONLY |
436
435
  | `-gn` | — | off | GET NAMES once at startup |
437
436
  | `-ncs` | — | off | skip `--check-source` |
437
+ | `-ncf` | — | off | CSV: do not ping the CSV IP of a name without DNS record |
438
438
  | `-up` | — | 0 | learning phase: after N rounds keep only hosts seen UP |
439
439
  | `-setref` | — | off | with `-up`: hosts seen UP become new reference list |
440
440
 
@@ -728,21 +728,3 @@ Each bucket: Download (`<base>-<up|down|flap|nodns>-hosts.txt`) + Copy (clipboar
728
728
 
729
729
  Row click expands: state-change history with timestamps, per-host stats (IP, uptime,
730
730
  downtime, span, first/last seen, RTT min/avg/max).
731
-
732
- # esplit.py 1.14
733
-
734
- Splits a large CSV logfile into smaller parts by size.
735
-
736
- ```sh
737
- ./esplit.py # interactive menu
738
- ./esplit.py -i eping-log_2026-09-05.csv -o parts -s 20 # ~20MB parts
739
- ```
740
-
741
- | Option | Effect |
742
- |---|---|
743
- | `-i`, `--input FILE` | CSV file to split (omit for interactive picker) |
744
- | `-o`, `--output DIR` | output folder (created if missing) |
745
- | `-s`, `--size MB` | max size per part |
746
-
747
- Each part: `part_NNN.csv`, own header row. Rows never split across parts; a
748
- `#COMMENT#` row lands in whichever part it falls into.
File without changes
File without changes
File without changes
File without changes
File without changes