ipmg 3.1.0__tar.gz → 3.1.2__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.
- {ipmg-3.1.0/src/ipmg.egg-info → ipmg-3.1.2}/PKG-INFO +131 -86
- {ipmg-3.1.0 → ipmg-3.1.2}/README.md +130 -85
- {ipmg-3.1.0 → ipmg-3.1.2}/pyproject.toml +1 -1
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/__init__.py +1 -1
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/core/diff.py +3 -1
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/core/ping.py +7 -1
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/infrastructure/notify.py +21 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/web/static/js/demo.js +10 -2
- {ipmg-3.1.0 → ipmg-3.1.2/src/ipmg.egg-info}/PKG-INFO +131 -86
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_diff.py +3 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_notify.py +50 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_ping.py +50 -1
- {ipmg-3.1.0 → ipmg-3.1.2}/LICENSE +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/setup.cfg +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/__main__.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/cli/__init__.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/cli/commands.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/cli/config.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/cli/parser.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/core/__init__.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/core/discovery.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/core/engine.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/core/health.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/core/portscan.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/core/security.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/exceptions.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/infrastructure/__init__.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/infrastructure/database.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/infrastructure/file_io.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/infrastructure/incremental.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/reporting/__init__.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/reporting/diff_report.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/reporting/frames.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/reporting/live.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/reporting/machine.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/reporting/metrics.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/reporting/summary.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/reporting/ui.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/services/__init__.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/services/history_service.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/services/scan_service.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/utils/__init__.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/utils/helpers.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/web/__init__.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/web/app.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/web/db.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/web/manager.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/web/schemas.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/web/server.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/web/static/css/app.css +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/web/static/index.html +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/web/static/js/api.js +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/web/static/js/app.js +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/web/static/js/charts.js +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg/web/static/js/views.js +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg.egg-info/SOURCES.txt +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg.egg-info/dependency_links.txt +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg.egg-info/entry_points.txt +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg.egg-info/requires.txt +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/src/ipmg.egg-info/top_level.txt +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_api_contract.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_commands.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_config.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_database_history.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_diff_report.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_discover.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_engine.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_file_io.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_health.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_history_service.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_incremental.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_ipv6.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_live.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_machine_output.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_metrics.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_parser.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_ping_command.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_portscan.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_scan_service.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_ui.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_utils.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_web_api.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_web_db.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_web_manager.py +0 -0
- {ipmg-3.1.0 → ipmg-3.1.2}/tests/test_web_server.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ipmg
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.2
|
|
4
4
|
Summary: IP Management & Ping Monitoring CLI Tool
|
|
5
5
|
Author: Sameer Alam
|
|
6
6
|
Maintainer-email: Sameer Alam <sameeralam3127@gmail.com>
|
|
@@ -57,22 +57,21 @@ Dynamic: license-file
|
|
|
57
57
|

|
|
58
58
|
[](https://github.com/sameeralam3127/ipmg/actions/workflows/publish.yml)
|
|
59
59
|
|
|
60
|
-
**
|
|
60
|
+
**Know what changed on your network since the last scan.**
|
|
61
61
|
|
|
62
|
-
IPMG
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
62
|
+
IPMG keeps a history of every scan and tells you what moved between two of
|
|
63
|
+
them: hosts that went offline or appeared, IP addresses and hostnames that
|
|
64
|
+
moved, latency that shifted. Every change carries a severity, so you can send
|
|
65
|
+
only the ones that matter to Slack, Teams, a webhook, or email, or fail a cron
|
|
66
|
+
job or CI step with an exit code. Around that: parallel ping scanning of IPs,
|
|
67
|
+
CIDR blocks, and ranges (IPv4 and IPv6), IPMG Web, a local dashboard that
|
|
68
|
+
works offline, and reports in Excel, CSV, JSON, and Markdown.
|
|
66
69
|
|
|
67
70
|
<p align="center">
|
|
68
|
-
<img src="https://raw.githubusercontent.com/sameeralam3127/ipmg/main/docs/assets/ipmg-
|
|
71
|
+
<img src="https://raw.githubusercontent.com/sameeralam3127/ipmg/main/docs/assets/ipmg-compare.gif" alt="ipmg scans 13 hosts, a new address is added to the target file, and a second scan with --compare reports a new host (warning) and a latency change (info) against the first" width="820">
|
|
69
72
|
</p>
|
|
70
73
|
|
|
71
|
-
|
|
72
|
-
right now. IPMG also remembers every scan and tells you what changed since the
|
|
73
|
-
last one: the host that dropped off, the device that appeared, the latency that
|
|
74
|
-
doubled. It writes the report you would otherwise build by hand.
|
|
75
|
-
[How it compares](#how-it-compares)
|
|
74
|
+
[How it compares](#how-it-compares) to `nmap -sn`, `fping`, and Angry IP Scanner.
|
|
76
75
|
|
|
77
76
|
**Website:** [sameeralam3127.github.io/ipmg](https://sameeralam3127.github.io/ipmg/) ·
|
|
78
77
|
**Live demo:** [IPMG Web with sample data](https://sameeralam3127.github.io/ipmg/demo/) ·
|
|
@@ -80,7 +79,8 @@ doubled. It writes the report you would otherwise build by hand.
|
|
|
80
79
|
|
|
81
80
|
```bash
|
|
82
81
|
pip install ipmg
|
|
83
|
-
ipmg --discover
|
|
82
|
+
ipmg --discover # scan the network you are on, right now
|
|
83
|
+
ipmg --discover --compare # later: scan again and see what changed
|
|
84
84
|
```
|
|
85
85
|
|
|
86
86
|
> **Please read:** only scan networks you are authorized to scan. Unauthorized
|
|
@@ -89,11 +89,12 @@ ipmg --discover # scan the network you are on, right now
|
|
|
89
89
|
**Contents**
|
|
90
90
|
|
|
91
91
|
[How it compares](#how-it-compares) ·
|
|
92
|
+
[Requirements and platform support](#requirements-and-platform-support) ·
|
|
92
93
|
[Install](#install) ·
|
|
93
94
|
[Your first scan](#your-first-scan) ·
|
|
95
|
+
[Change detection](#change-detection) ·
|
|
94
96
|
[Common tasks](#common-tasks) ·
|
|
95
97
|
[Live results](#live-results) ·
|
|
96
|
-
[Change detection](#change-detection) ·
|
|
97
98
|
[IPMG Web](#ipmg-web) ·
|
|
98
99
|
[What you can scan](#what-you-can-scan) ·
|
|
99
100
|
[Reports](#reports) ·
|
|
@@ -108,15 +109,22 @@ ipmg --discover # scan the network you are on, right now
|
|
|
108
109
|
|
|
109
110
|
| | IPMG | `nmap -sn` | `fping` | Angry IP Scanner |
|
|
110
111
|
| --- | --- | --- | --- | --- |
|
|
111
|
-
| Parallel ping sweep | Yes | Yes | Yes | Yes |
|
|
112
|
+
| Parallel ping sweep | Yes, one system `ping` per host | Yes | Yes, fastest of the four | Yes |
|
|
112
113
|
| Scan history and "what changed" | Built in | Save XML, compare with `ndiff` | No | No |
|
|
114
|
+
| Change severities and alerts | critical / warning / info; Slack, Teams, webhook, email | No | No | No |
|
|
115
|
+
| Exit codes for cron and CI | `3` with `--fail-on-down`, `2` with `diff --fail-on-change` | No | Non-zero if any host is unreachable | No (GUI first) |
|
|
113
116
|
| Reports | Excel, CSV, JSON, Markdown | XML, grepable text | Plain text | CSV, TXT, XML |
|
|
114
|
-
| Browser UI | IPMG Web, local | No (Zenmap is a desktop app) | No | Desktop app (Java) |
|
|
115
|
-
| Port checks | Common TCP ports | Full port and OS scanner | No | Via fetchers |
|
|
117
|
+
| Browser UI | IPMG Web, local, works offline | No (Zenmap is a desktop app) | No | Desktop app (Java) |
|
|
118
|
+
| Port checks | Common TCP ports (connect only) | Full port, service, and OS scanner | No | Via fetchers |
|
|
116
119
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
+
Where the others are better: **nmap** is a real port, service, and OS
|
|
121
|
+
scanner, and IPMG does not try to be one. **fping** sends every probe from a
|
|
122
|
+
single process, so on large ranges it is much faster than IPMG, which starts
|
|
123
|
+
one `ping` per host (`--threads` at a time). Angry IP Scanner is a
|
|
124
|
+
point-and-click desktop app with a plugin system.
|
|
125
|
+
|
|
126
|
+
Reach for IPMG when you look after a network and need to know what moved since
|
|
127
|
+
yesterday, with a report you can hand to someone.
|
|
120
128
|
|
|
121
129
|
<p align="center">
|
|
122
130
|
<img src="https://raw.githubusercontent.com/sameeralam3127/ipmg/main/docs/assets/ipmg-web.png" alt="IPMG Web dashboard: scan totals, a status donut of 16 active, 1 timeout and 1 inactive host, a latency trend chart, and a list of recent scans" width="820">
|
|
@@ -124,6 +132,32 @@ you can hand to someone.
|
|
|
124
132
|
|
|
125
133
|
---
|
|
126
134
|
|
|
135
|
+
## Requirements and platform support
|
|
136
|
+
|
|
137
|
+
IPMG does not craft packets. It runs your operating system's `ping` command
|
|
138
|
+
once per host, as a direct process call with no shell, and reads its output.
|
|
139
|
+
That means:
|
|
140
|
+
|
|
141
|
+
- **Python 3.9 or newer**, unless you use the one-line installers, which
|
|
142
|
+
bring their own.
|
|
143
|
+
- **The system `ping` command.** macOS and Windows include it; minimal Linux
|
|
144
|
+
and container images may not ([how to install it](#the-one-thing-ipmg-needs-from-your-system)).
|
|
145
|
+
- **No root or administrator rights.** IPMG has exactly the privileges your
|
|
146
|
+
`ping` has: if `ping 8.8.8.8` works for your user, a scan works too. Port
|
|
147
|
+
checks (`--scan-ports`) are ordinary TCP connections.
|
|
148
|
+
|
|
149
|
+
| Platform | What IPMG runs | Status |
|
|
150
|
+
| --- | --- | --- |
|
|
151
|
+
| Linux (iputils or busybox `ping`) | `ping -c COUNT -W SECONDS` | Supported. CI runs the tests and a scan on Ubuntu; see [verified environments](#verified-environments) |
|
|
152
|
+
| macOS | `ping -c COUNT -W MILLISECONDS`; `ping6` for IPv6 | Supported. CI runs the tests and a scan on macOS |
|
|
153
|
+
| Windows | `ping -n COUNT -w MILLISECONDS` | Supported. CI runs the tests and a scan of `127.0.0.1` on `windows-latest`; not yet verified against a real LAN |
|
|
154
|
+
| FreeBSD, OpenBSD, NetBSD | the macOS flags | Untested. The code treats them like macOS, and their `ping` options may differ |
|
|
155
|
+
|
|
156
|
+
`--discover ipv6` reads the neighbour table with `ip -6 neigh` on Linux (the
|
|
157
|
+
`iproute2` package), `ndp -an` on macOS, and `netsh` on Windows.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
127
161
|
## Install
|
|
128
162
|
|
|
129
163
|
**Linux and macOS — one command, works on every distribution:**
|
|
@@ -377,71 +411,6 @@ exist yet. A file you name with `--input` must already exist.
|
|
|
377
411
|
|
|
378
412
|
---
|
|
379
413
|
|
|
380
|
-
## Common tasks
|
|
381
|
-
|
|
382
|
-
Not sure which flags you need? The
|
|
383
|
-
[command builder](https://sameeralam3127.github.io/ipmg/#builder) on the
|
|
384
|
-
website puts the command together as you pick what you want to know, and
|
|
385
|
-
explains every flag it adds.
|
|
386
|
-
|
|
387
|
-
<p align="center">
|
|
388
|
-
<a href="https://sameeralam3127.github.io/ipmg/#builder">
|
|
389
|
-
<img src="https://raw.githubusercontent.com/sameeralam3127/ipmg/main/docs/assets/ipmg-builder.png" alt="IPMG command builder: choose Scan, Compare, History, or Web, enter a target such as 192.168.1.0/24, switch on options like live results or hostnames, and copy the generated ipmg command with each flag explained" width="820">
|
|
390
|
-
</a>
|
|
391
|
-
</p>
|
|
392
|
-
|
|
393
|
-
Or pick a ready-made command:
|
|
394
|
-
|
|
395
|
-
| I want to… | Command |
|
|
396
|
-
| --- | --- |
|
|
397
|
-
| Scan the network I am on | `ipmg --discover` |
|
|
398
|
-
| Scan hosts listed in a file | `ipmg --input targets.txt` |
|
|
399
|
-
| Scan a file plus a few extra hosts | `ipmg --input targets.txt 10.0.0.0/30 10.0.0.5` |
|
|
400
|
-
| Get names, not just IP addresses | `ipmg --input targets.txt --resolve` |
|
|
401
|
-
| Get a report I can send to someone | `ipmg --input targets.txt --formats md csv` |
|
|
402
|
-
| Pipe the results into a script | `ipmg --input targets.txt --json \| jq .` |
|
|
403
|
-
| See hosts appear as they answer | `ipmg --input 192.168.1.0/24 --stream` |
|
|
404
|
-
| See what changed since last time | `ipmg --input targets.txt --compare` |
|
|
405
|
-
| Check which services are listening | `ipmg --input targets.txt --scan-ports` |
|
|
406
|
-
| Keep scanning every 5 minutes | `ipmg --input targets.txt --interval 5` |
|
|
407
|
-
| Look back at earlier scans | `ipmg history` |
|
|
408
|
-
| Compare two specific scans | `ipmg diff 12 14` |
|
|
409
|
-
| Use IPMG Web in your browser instead | `ipmg web` |
|
|
410
|
-
| See every available flag | `ipmg --help` |
|
|
411
|
-
|
|
412
|
-
---
|
|
413
|
-
|
|
414
|
-
## Live results
|
|
415
|
-
|
|
416
|
-
By default a scan prints its results once every host has been probed. On a
|
|
417
|
-
large range that is a long wait with nothing to look at, so `--stream` prints
|
|
418
|
-
each host the moment its probe finishes, above a progress bar that also carries
|
|
419
|
-
a running count of the hosts that answered:
|
|
420
|
-
|
|
421
|
-
```bash
|
|
422
|
-
ipmg --input 192.168.1.0/24 --stream
|
|
423
|
-
```
|
|
424
|
-
|
|
425
|
-
```text
|
|
426
|
-
Live
|
|
427
|
-
Status Host Latency
|
|
428
|
-
● Active 192.168.1.1 0.9 ms
|
|
429
|
-
● Active 192.168.1.24 3.1 ms
|
|
430
|
-
⠹ Scanning ━━━━━━━━━━━─────────── 48% 122/254 0:00:09 2 up
|
|
431
|
-
```
|
|
432
|
-
|
|
433
|
-
`--stream` shows only the hosts that answer, which is what makes a sparse range
|
|
434
|
-
readable. Add `--stream-all` to see every result, including timeouts and
|
|
435
|
-
unreachable hosts. The rows gain a `Name` column under `--resolve` and an
|
|
436
|
-
`Open ports` column under `--scan-ports`.
|
|
437
|
-
|
|
438
|
-
Streaming costs nothing in scan time: rows are printed by the thread that
|
|
439
|
-
collects results, so the workers never wait on the terminal. When output is
|
|
440
|
-
piped or redirected the progress bar is dropped and the rows are written as
|
|
441
|
-
plain lines, which makes `ipmg --stream-all >> scan.log` a usable live log.
|
|
442
|
-
|
|
443
|
-
---
|
|
444
|
-
|
|
445
414
|
## Change detection
|
|
446
415
|
|
|
447
416
|
Every scan is stored in a local SQLite history (`~/.ipmg/dashboard.db`), shared
|
|
@@ -458,6 +427,13 @@ ipmg diff --fail-on-change # exit 2 when anything changed (CI)
|
|
|
458
427
|
ipmg history --limit 10 # list stored scans
|
|
459
428
|
```
|
|
460
429
|
|
|
430
|
+
The same comparison is the **Changes** view in [IPMG Web](#ipmg-web), with
|
|
431
|
+
the summary exportable as Markdown, JSON, or CSV:
|
|
432
|
+
|
|
433
|
+
<p align="center">
|
|
434
|
+
<img src="https://raw.githubusercontent.com/sameeralam3127/ipmg/main/docs/assets/ipmg-changes.png" alt="IPMG Web Changes view comparing scan 23 with scan 24: 4 changes, 1 critical. A host back online, a latency change of +6.2 ms, a host offline, and a status change from Timeout to Inactive" width="820">
|
|
435
|
+
</p>
|
|
436
|
+
|
|
461
437
|
To hear about changes without watching the terminal, send them to Slack,
|
|
462
438
|
Microsoft Teams, any JSON webhook, or email. Any `--notify-*` flag turns on
|
|
463
439
|
`--compare`, and with `--interval` every pass that changes something alerts:
|
|
@@ -481,7 +457,7 @@ What counts as a change:
|
|
|
481
457
|
| New host | warning | An IP that the baseline never saw |
|
|
482
458
|
| Host removed | warning | An IP the current scan no longer covers |
|
|
483
459
|
| IP address changed | warning | A known hostname moved to a different IP |
|
|
484
|
-
|
|
|
460
|
+
| Status changed | warning | Status moved between failure modes (e.g. `Timeout` → `Unreachable`) |
|
|
485
461
|
| Host back online | info | Recovered since the baseline |
|
|
486
462
|
| Hostname changed | info | Same IP, different PTR record |
|
|
487
463
|
| Latency changed | info | Latency moved past both thresholds |
|
|
@@ -513,6 +489,75 @@ source**, so file-based and `--discover` runs do not get mixed up. Pass
|
|
|
513
489
|
|
|
514
490
|
---
|
|
515
491
|
|
|
492
|
+
## Common tasks
|
|
493
|
+
|
|
494
|
+
Not sure which flags you need? The
|
|
495
|
+
[command builder](https://sameeralam3127.github.io/ipmg/#builder) on the
|
|
496
|
+
website puts the command together as you pick what you want to know, and
|
|
497
|
+
explains every flag it adds.
|
|
498
|
+
|
|
499
|
+
<p align="center">
|
|
500
|
+
<a href="https://sameeralam3127.github.io/ipmg/#builder">
|
|
501
|
+
<img src="https://raw.githubusercontent.com/sameeralam3127/ipmg/main/docs/assets/ipmg-builder.png" alt="IPMG command builder: choose Scan, Compare, History, or Web, enter a target such as 192.168.1.0/24, switch on options like live results or hostnames, and copy the generated ipmg command with each flag explained" width="820">
|
|
502
|
+
</a>
|
|
503
|
+
</p>
|
|
504
|
+
|
|
505
|
+
Or pick a ready-made command:
|
|
506
|
+
|
|
507
|
+
| I want to… | Command |
|
|
508
|
+
| --- | --- |
|
|
509
|
+
| Scan the network I am on | `ipmg --discover` |
|
|
510
|
+
| Scan hosts listed in a file | `ipmg --input targets.txt` |
|
|
511
|
+
| Scan a file plus a few extra hosts | `ipmg --input targets.txt 10.0.0.0/30 10.0.0.5` |
|
|
512
|
+
| Get names, not just IP addresses | `ipmg --input targets.txt --resolve` |
|
|
513
|
+
| Get a report I can send to someone | `ipmg --input targets.txt --formats md csv` |
|
|
514
|
+
| Pipe the results into a script | `ipmg --input targets.txt --json \| jq .` |
|
|
515
|
+
| See hosts appear as they answer | `ipmg --input 192.168.1.0/24 --stream` |
|
|
516
|
+
| See what changed since last time | `ipmg --input targets.txt --compare` |
|
|
517
|
+
| Check which services are listening | `ipmg --input targets.txt --scan-ports` |
|
|
518
|
+
| Keep scanning every 5 minutes | `ipmg --input targets.txt --interval 5` |
|
|
519
|
+
| Look back at earlier scans | `ipmg history` |
|
|
520
|
+
| Compare two specific scans | `ipmg diff 12 14` |
|
|
521
|
+
| Use IPMG Web in your browser instead | `ipmg web` |
|
|
522
|
+
| See every available flag | `ipmg --help` |
|
|
523
|
+
|
|
524
|
+
---
|
|
525
|
+
|
|
526
|
+
## Live results
|
|
527
|
+
|
|
528
|
+
By default a scan prints its results once every host has been probed. On a
|
|
529
|
+
large range that is a long wait with nothing to look at, so `--stream` prints
|
|
530
|
+
each host the moment its probe finishes, above a progress bar that also carries
|
|
531
|
+
a running count of the hosts that answered:
|
|
532
|
+
|
|
533
|
+
```bash
|
|
534
|
+
ipmg --input 192.168.1.0/24 --stream
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
<p align="center">
|
|
538
|
+
<img src="https://raw.githubusercontent.com/sameeralam3127/ipmg/main/docs/assets/ipmg-demo.gif" alt="ipmg scanning 13 hosts in parallel: live results with reverse DNS names and latency, then a summary of 10 active and 3 timed out" width="820">
|
|
539
|
+
</p>
|
|
540
|
+
|
|
541
|
+
```text
|
|
542
|
+
Live
|
|
543
|
+
Status Host Latency
|
|
544
|
+
● Active 192.168.1.1 0.9 ms
|
|
545
|
+
● Active 192.168.1.24 3.1 ms
|
|
546
|
+
⠹ Scanning ━━━━━━━━━━━─────────── 48% 122/254 0:00:09 2 up
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
`--stream` shows only the hosts that answer, which is what makes a sparse range
|
|
550
|
+
readable. Add `--stream-all` to see every result, including timeouts and
|
|
551
|
+
unreachable hosts. The rows gain a `Name` column under `--resolve` and an
|
|
552
|
+
`Open ports` column under `--scan-ports`.
|
|
553
|
+
|
|
554
|
+
Streaming costs nothing in scan time: rows are printed by the thread that
|
|
555
|
+
collects results, so the workers never wait on the terminal. When output is
|
|
556
|
+
piped or redirected the progress bar is dropped and the rows are written as
|
|
557
|
+
plain lines, which makes `ipmg --stream-all >> scan.log` a usable live log.
|
|
558
|
+
|
|
559
|
+
---
|
|
560
|
+
|
|
516
561
|
## IPMG Web
|
|
517
562
|
|
|
518
563
|
Prefer clicking to typing? IPMG Web runs locally and shares the CLI's
|
|
@@ -5,22 +5,21 @@
|
|
|
5
5
|

|
|
6
6
|
[](https://github.com/sameeralam3127/ipmg/actions/workflows/publish.yml)
|
|
7
7
|
|
|
8
|
-
**
|
|
8
|
+
**Know what changed on your network since the last scan.**
|
|
9
9
|
|
|
10
|
-
IPMG
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
IPMG keeps a history of every scan and tells you what moved between two of
|
|
11
|
+
them: hosts that went offline or appeared, IP addresses and hostnames that
|
|
12
|
+
moved, latency that shifted. Every change carries a severity, so you can send
|
|
13
|
+
only the ones that matter to Slack, Teams, a webhook, or email, or fail a cron
|
|
14
|
+
job or CI step with an exit code. Around that: parallel ping scanning of IPs,
|
|
15
|
+
CIDR blocks, and ranges (IPv4 and IPv6), IPMG Web, a local dashboard that
|
|
16
|
+
works offline, and reports in Excel, CSV, JSON, and Markdown.
|
|
14
17
|
|
|
15
18
|
<p align="center">
|
|
16
|
-
<img src="https://raw.githubusercontent.com/sameeralam3127/ipmg/main/docs/assets/ipmg-
|
|
19
|
+
<img src="https://raw.githubusercontent.com/sameeralam3127/ipmg/main/docs/assets/ipmg-compare.gif" alt="ipmg scans 13 hosts, a new address is added to the target file, and a second scan with --compare reports a new host (warning) and a latency change (info) against the first" width="820">
|
|
17
20
|
</p>
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
right now. IPMG also remembers every scan and tells you what changed since the
|
|
21
|
-
last one: the host that dropped off, the device that appeared, the latency that
|
|
22
|
-
doubled. It writes the report you would otherwise build by hand.
|
|
23
|
-
[How it compares](#how-it-compares)
|
|
22
|
+
[How it compares](#how-it-compares) to `nmap -sn`, `fping`, and Angry IP Scanner.
|
|
24
23
|
|
|
25
24
|
**Website:** [sameeralam3127.github.io/ipmg](https://sameeralam3127.github.io/ipmg/) ·
|
|
26
25
|
**Live demo:** [IPMG Web with sample data](https://sameeralam3127.github.io/ipmg/demo/) ·
|
|
@@ -28,7 +27,8 @@ doubled. It writes the report you would otherwise build by hand.
|
|
|
28
27
|
|
|
29
28
|
```bash
|
|
30
29
|
pip install ipmg
|
|
31
|
-
ipmg --discover
|
|
30
|
+
ipmg --discover # scan the network you are on, right now
|
|
31
|
+
ipmg --discover --compare # later: scan again and see what changed
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
> **Please read:** only scan networks you are authorized to scan. Unauthorized
|
|
@@ -37,11 +37,12 @@ ipmg --discover # scan the network you are on, right now
|
|
|
37
37
|
**Contents**
|
|
38
38
|
|
|
39
39
|
[How it compares](#how-it-compares) ·
|
|
40
|
+
[Requirements and platform support](#requirements-and-platform-support) ·
|
|
40
41
|
[Install](#install) ·
|
|
41
42
|
[Your first scan](#your-first-scan) ·
|
|
43
|
+
[Change detection](#change-detection) ·
|
|
42
44
|
[Common tasks](#common-tasks) ·
|
|
43
45
|
[Live results](#live-results) ·
|
|
44
|
-
[Change detection](#change-detection) ·
|
|
45
46
|
[IPMG Web](#ipmg-web) ·
|
|
46
47
|
[What you can scan](#what-you-can-scan) ·
|
|
47
48
|
[Reports](#reports) ·
|
|
@@ -56,15 +57,22 @@ ipmg --discover # scan the network you are on, right now
|
|
|
56
57
|
|
|
57
58
|
| | IPMG | `nmap -sn` | `fping` | Angry IP Scanner |
|
|
58
59
|
| --- | --- | --- | --- | --- |
|
|
59
|
-
| Parallel ping sweep | Yes | Yes | Yes | Yes |
|
|
60
|
+
| Parallel ping sweep | Yes, one system `ping` per host | Yes | Yes, fastest of the four | Yes |
|
|
60
61
|
| Scan history and "what changed" | Built in | Save XML, compare with `ndiff` | No | No |
|
|
62
|
+
| Change severities and alerts | critical / warning / info; Slack, Teams, webhook, email | No | No | No |
|
|
63
|
+
| Exit codes for cron and CI | `3` with `--fail-on-down`, `2` with `diff --fail-on-change` | No | Non-zero if any host is unreachable | No (GUI first) |
|
|
61
64
|
| Reports | Excel, CSV, JSON, Markdown | XML, grepable text | Plain text | CSV, TXT, XML |
|
|
62
|
-
| Browser UI | IPMG Web, local | No (Zenmap is a desktop app) | No | Desktop app (Java) |
|
|
63
|
-
| Port checks | Common TCP ports | Full port and OS scanner | No | Via fetchers |
|
|
65
|
+
| Browser UI | IPMG Web, local, works offline | No (Zenmap is a desktop app) | No | Desktop app (Java) |
|
|
66
|
+
| Port checks | Common TCP ports (connect only) | Full port, service, and OS scanner | No | Via fetchers |
|
|
64
67
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
+
Where the others are better: **nmap** is a real port, service, and OS
|
|
69
|
+
scanner, and IPMG does not try to be one. **fping** sends every probe from a
|
|
70
|
+
single process, so on large ranges it is much faster than IPMG, which starts
|
|
71
|
+
one `ping` per host (`--threads` at a time). Angry IP Scanner is a
|
|
72
|
+
point-and-click desktop app with a plugin system.
|
|
73
|
+
|
|
74
|
+
Reach for IPMG when you look after a network and need to know what moved since
|
|
75
|
+
yesterday, with a report you can hand to someone.
|
|
68
76
|
|
|
69
77
|
<p align="center">
|
|
70
78
|
<img src="https://raw.githubusercontent.com/sameeralam3127/ipmg/main/docs/assets/ipmg-web.png" alt="IPMG Web dashboard: scan totals, a status donut of 16 active, 1 timeout and 1 inactive host, a latency trend chart, and a list of recent scans" width="820">
|
|
@@ -72,6 +80,32 @@ you can hand to someone.
|
|
|
72
80
|
|
|
73
81
|
---
|
|
74
82
|
|
|
83
|
+
## Requirements and platform support
|
|
84
|
+
|
|
85
|
+
IPMG does not craft packets. It runs your operating system's `ping` command
|
|
86
|
+
once per host, as a direct process call with no shell, and reads its output.
|
|
87
|
+
That means:
|
|
88
|
+
|
|
89
|
+
- **Python 3.9 or newer**, unless you use the one-line installers, which
|
|
90
|
+
bring their own.
|
|
91
|
+
- **The system `ping` command.** macOS and Windows include it; minimal Linux
|
|
92
|
+
and container images may not ([how to install it](#the-one-thing-ipmg-needs-from-your-system)).
|
|
93
|
+
- **No root or administrator rights.** IPMG has exactly the privileges your
|
|
94
|
+
`ping` has: if `ping 8.8.8.8` works for your user, a scan works too. Port
|
|
95
|
+
checks (`--scan-ports`) are ordinary TCP connections.
|
|
96
|
+
|
|
97
|
+
| Platform | What IPMG runs | Status |
|
|
98
|
+
| --- | --- | --- |
|
|
99
|
+
| Linux (iputils or busybox `ping`) | `ping -c COUNT -W SECONDS` | Supported. CI runs the tests and a scan on Ubuntu; see [verified environments](#verified-environments) |
|
|
100
|
+
| macOS | `ping -c COUNT -W MILLISECONDS`; `ping6` for IPv6 | Supported. CI runs the tests and a scan on macOS |
|
|
101
|
+
| Windows | `ping -n COUNT -w MILLISECONDS` | Supported. CI runs the tests and a scan of `127.0.0.1` on `windows-latest`; not yet verified against a real LAN |
|
|
102
|
+
| FreeBSD, OpenBSD, NetBSD | the macOS flags | Untested. The code treats them like macOS, and their `ping` options may differ |
|
|
103
|
+
|
|
104
|
+
`--discover ipv6` reads the neighbour table with `ip -6 neigh` on Linux (the
|
|
105
|
+
`iproute2` package), `ndp -an` on macOS, and `netsh` on Windows.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
75
109
|
## Install
|
|
76
110
|
|
|
77
111
|
**Linux and macOS — one command, works on every distribution:**
|
|
@@ -325,71 +359,6 @@ exist yet. A file you name with `--input` must already exist.
|
|
|
325
359
|
|
|
326
360
|
---
|
|
327
361
|
|
|
328
|
-
## Common tasks
|
|
329
|
-
|
|
330
|
-
Not sure which flags you need? The
|
|
331
|
-
[command builder](https://sameeralam3127.github.io/ipmg/#builder) on the
|
|
332
|
-
website puts the command together as you pick what you want to know, and
|
|
333
|
-
explains every flag it adds.
|
|
334
|
-
|
|
335
|
-
<p align="center">
|
|
336
|
-
<a href="https://sameeralam3127.github.io/ipmg/#builder">
|
|
337
|
-
<img src="https://raw.githubusercontent.com/sameeralam3127/ipmg/main/docs/assets/ipmg-builder.png" alt="IPMG command builder: choose Scan, Compare, History, or Web, enter a target such as 192.168.1.0/24, switch on options like live results or hostnames, and copy the generated ipmg command with each flag explained" width="820">
|
|
338
|
-
</a>
|
|
339
|
-
</p>
|
|
340
|
-
|
|
341
|
-
Or pick a ready-made command:
|
|
342
|
-
|
|
343
|
-
| I want to… | Command |
|
|
344
|
-
| --- | --- |
|
|
345
|
-
| Scan the network I am on | `ipmg --discover` |
|
|
346
|
-
| Scan hosts listed in a file | `ipmg --input targets.txt` |
|
|
347
|
-
| Scan a file plus a few extra hosts | `ipmg --input targets.txt 10.0.0.0/30 10.0.0.5` |
|
|
348
|
-
| Get names, not just IP addresses | `ipmg --input targets.txt --resolve` |
|
|
349
|
-
| Get a report I can send to someone | `ipmg --input targets.txt --formats md csv` |
|
|
350
|
-
| Pipe the results into a script | `ipmg --input targets.txt --json \| jq .` |
|
|
351
|
-
| See hosts appear as they answer | `ipmg --input 192.168.1.0/24 --stream` |
|
|
352
|
-
| See what changed since last time | `ipmg --input targets.txt --compare` |
|
|
353
|
-
| Check which services are listening | `ipmg --input targets.txt --scan-ports` |
|
|
354
|
-
| Keep scanning every 5 minutes | `ipmg --input targets.txt --interval 5` |
|
|
355
|
-
| Look back at earlier scans | `ipmg history` |
|
|
356
|
-
| Compare two specific scans | `ipmg diff 12 14` |
|
|
357
|
-
| Use IPMG Web in your browser instead | `ipmg web` |
|
|
358
|
-
| See every available flag | `ipmg --help` |
|
|
359
|
-
|
|
360
|
-
---
|
|
361
|
-
|
|
362
|
-
## Live results
|
|
363
|
-
|
|
364
|
-
By default a scan prints its results once every host has been probed. On a
|
|
365
|
-
large range that is a long wait with nothing to look at, so `--stream` prints
|
|
366
|
-
each host the moment its probe finishes, above a progress bar that also carries
|
|
367
|
-
a running count of the hosts that answered:
|
|
368
|
-
|
|
369
|
-
```bash
|
|
370
|
-
ipmg --input 192.168.1.0/24 --stream
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
```text
|
|
374
|
-
Live
|
|
375
|
-
Status Host Latency
|
|
376
|
-
● Active 192.168.1.1 0.9 ms
|
|
377
|
-
● Active 192.168.1.24 3.1 ms
|
|
378
|
-
⠹ Scanning ━━━━━━━━━━━─────────── 48% 122/254 0:00:09 2 up
|
|
379
|
-
```
|
|
380
|
-
|
|
381
|
-
`--stream` shows only the hosts that answer, which is what makes a sparse range
|
|
382
|
-
readable. Add `--stream-all` to see every result, including timeouts and
|
|
383
|
-
unreachable hosts. The rows gain a `Name` column under `--resolve` and an
|
|
384
|
-
`Open ports` column under `--scan-ports`.
|
|
385
|
-
|
|
386
|
-
Streaming costs nothing in scan time: rows are printed by the thread that
|
|
387
|
-
collects results, so the workers never wait on the terminal. When output is
|
|
388
|
-
piped or redirected the progress bar is dropped and the rows are written as
|
|
389
|
-
plain lines, which makes `ipmg --stream-all >> scan.log` a usable live log.
|
|
390
|
-
|
|
391
|
-
---
|
|
392
|
-
|
|
393
362
|
## Change detection
|
|
394
363
|
|
|
395
364
|
Every scan is stored in a local SQLite history (`~/.ipmg/dashboard.db`), shared
|
|
@@ -406,6 +375,13 @@ ipmg diff --fail-on-change # exit 2 when anything changed (CI)
|
|
|
406
375
|
ipmg history --limit 10 # list stored scans
|
|
407
376
|
```
|
|
408
377
|
|
|
378
|
+
The same comparison is the **Changes** view in [IPMG Web](#ipmg-web), with
|
|
379
|
+
the summary exportable as Markdown, JSON, or CSV:
|
|
380
|
+
|
|
381
|
+
<p align="center">
|
|
382
|
+
<img src="https://raw.githubusercontent.com/sameeralam3127/ipmg/main/docs/assets/ipmg-changes.png" alt="IPMG Web Changes view comparing scan 23 with scan 24: 4 changes, 1 critical. A host back online, a latency change of +6.2 ms, a host offline, and a status change from Timeout to Inactive" width="820">
|
|
383
|
+
</p>
|
|
384
|
+
|
|
409
385
|
To hear about changes without watching the terminal, send them to Slack,
|
|
410
386
|
Microsoft Teams, any JSON webhook, or email. Any `--notify-*` flag turns on
|
|
411
387
|
`--compare`, and with `--interval` every pass that changes something alerts:
|
|
@@ -429,7 +405,7 @@ What counts as a change:
|
|
|
429
405
|
| New host | warning | An IP that the baseline never saw |
|
|
430
406
|
| Host removed | warning | An IP the current scan no longer covers |
|
|
431
407
|
| IP address changed | warning | A known hostname moved to a different IP |
|
|
432
|
-
|
|
|
408
|
+
| Status changed | warning | Status moved between failure modes (e.g. `Timeout` → `Unreachable`) |
|
|
433
409
|
| Host back online | info | Recovered since the baseline |
|
|
434
410
|
| Hostname changed | info | Same IP, different PTR record |
|
|
435
411
|
| Latency changed | info | Latency moved past both thresholds |
|
|
@@ -461,6 +437,75 @@ source**, so file-based and `--discover` runs do not get mixed up. Pass
|
|
|
461
437
|
|
|
462
438
|
---
|
|
463
439
|
|
|
440
|
+
## Common tasks
|
|
441
|
+
|
|
442
|
+
Not sure which flags you need? The
|
|
443
|
+
[command builder](https://sameeralam3127.github.io/ipmg/#builder) on the
|
|
444
|
+
website puts the command together as you pick what you want to know, and
|
|
445
|
+
explains every flag it adds.
|
|
446
|
+
|
|
447
|
+
<p align="center">
|
|
448
|
+
<a href="https://sameeralam3127.github.io/ipmg/#builder">
|
|
449
|
+
<img src="https://raw.githubusercontent.com/sameeralam3127/ipmg/main/docs/assets/ipmg-builder.png" alt="IPMG command builder: choose Scan, Compare, History, or Web, enter a target such as 192.168.1.0/24, switch on options like live results or hostnames, and copy the generated ipmg command with each flag explained" width="820">
|
|
450
|
+
</a>
|
|
451
|
+
</p>
|
|
452
|
+
|
|
453
|
+
Or pick a ready-made command:
|
|
454
|
+
|
|
455
|
+
| I want to… | Command |
|
|
456
|
+
| --- | --- |
|
|
457
|
+
| Scan the network I am on | `ipmg --discover` |
|
|
458
|
+
| Scan hosts listed in a file | `ipmg --input targets.txt` |
|
|
459
|
+
| Scan a file plus a few extra hosts | `ipmg --input targets.txt 10.0.0.0/30 10.0.0.5` |
|
|
460
|
+
| Get names, not just IP addresses | `ipmg --input targets.txt --resolve` |
|
|
461
|
+
| Get a report I can send to someone | `ipmg --input targets.txt --formats md csv` |
|
|
462
|
+
| Pipe the results into a script | `ipmg --input targets.txt --json \| jq .` |
|
|
463
|
+
| See hosts appear as they answer | `ipmg --input 192.168.1.0/24 --stream` |
|
|
464
|
+
| See what changed since last time | `ipmg --input targets.txt --compare` |
|
|
465
|
+
| Check which services are listening | `ipmg --input targets.txt --scan-ports` |
|
|
466
|
+
| Keep scanning every 5 minutes | `ipmg --input targets.txt --interval 5` |
|
|
467
|
+
| Look back at earlier scans | `ipmg history` |
|
|
468
|
+
| Compare two specific scans | `ipmg diff 12 14` |
|
|
469
|
+
| Use IPMG Web in your browser instead | `ipmg web` |
|
|
470
|
+
| See every available flag | `ipmg --help` |
|
|
471
|
+
|
|
472
|
+
---
|
|
473
|
+
|
|
474
|
+
## Live results
|
|
475
|
+
|
|
476
|
+
By default a scan prints its results once every host has been probed. On a
|
|
477
|
+
large range that is a long wait with nothing to look at, so `--stream` prints
|
|
478
|
+
each host the moment its probe finishes, above a progress bar that also carries
|
|
479
|
+
a running count of the hosts that answered:
|
|
480
|
+
|
|
481
|
+
```bash
|
|
482
|
+
ipmg --input 192.168.1.0/24 --stream
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
<p align="center">
|
|
486
|
+
<img src="https://raw.githubusercontent.com/sameeralam3127/ipmg/main/docs/assets/ipmg-demo.gif" alt="ipmg scanning 13 hosts in parallel: live results with reverse DNS names and latency, then a summary of 10 active and 3 timed out" width="820">
|
|
487
|
+
</p>
|
|
488
|
+
|
|
489
|
+
```text
|
|
490
|
+
Live
|
|
491
|
+
Status Host Latency
|
|
492
|
+
● Active 192.168.1.1 0.9 ms
|
|
493
|
+
● Active 192.168.1.24 3.1 ms
|
|
494
|
+
⠹ Scanning ━━━━━━━━━━━─────────── 48% 122/254 0:00:09 2 up
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
`--stream` shows only the hosts that answer, which is what makes a sparse range
|
|
498
|
+
readable. Add `--stream-all` to see every result, including timeouts and
|
|
499
|
+
unreachable hosts. The rows gain a `Name` column under `--resolve` and an
|
|
500
|
+
`Open ports` column under `--scan-ports`.
|
|
501
|
+
|
|
502
|
+
Streaming costs nothing in scan time: rows are printed by the thread that
|
|
503
|
+
collects results, so the workers never wait on the terminal. When output is
|
|
504
|
+
piped or redirected the progress bar is dropped and the rows are written as
|
|
505
|
+
plain lines, which makes `ipmg --stream-all >> scan.log` a usable live log.
|
|
506
|
+
|
|
507
|
+
---
|
|
508
|
+
|
|
464
509
|
## IPMG Web
|
|
465
510
|
|
|
466
511
|
Prefer clicking to typing? IPMG Web runs locally and shares the CLI's
|
|
@@ -13,7 +13,7 @@ build-backend = "setuptools.build_meta"
|
|
|
13
13
|
|
|
14
14
|
[project]
|
|
15
15
|
name = "ipmg"
|
|
16
|
-
version = "3.1.
|
|
16
|
+
version = "3.1.2" # Managed automatically by semantic-release
|
|
17
17
|
description = "IP Management & Ping Monitoring CLI Tool"
|
|
18
18
|
readme = "README.md"
|
|
19
19
|
requires-python = ">=3.9"
|
|
@@ -64,7 +64,9 @@ CHANGE_LABELS: Dict[ChangeType, str] = {
|
|
|
64
64
|
ChangeType.IP_CHANGED: "IP address changed",
|
|
65
65
|
ChangeType.HOSTNAME_CHANGED: "Hostname changed",
|
|
66
66
|
ChangeType.LATENCY_CHANGED: "Latency changed",
|
|
67
|
-
|
|
67
|
+
# The key stays "service_changed" for existing JSON consumers; the change
|
|
68
|
+
# is a move between failure modes (Timeout -> Unreachable), not a service.
|
|
69
|
+
ChangeType.SERVICE_CHANGED: "Status changed",
|
|
68
70
|
}
|
|
69
71
|
|
|
70
72
|
|
|
@@ -146,7 +146,13 @@ def ping_ip(ip: str, timeout: int, count: int) -> Tuple[str, Optional[float]]:
|
|
|
146
146
|
|
|
147
147
|
latency = parse_latency(result.stdout)
|
|
148
148
|
|
|
149
|
-
|
|
149
|
+
answered = result.returncode == 0
|
|
150
|
+
if answered and latency is None and platform.system().lower() == "windows":
|
|
151
|
+
# Windows ping also exits 0 when a router replies "Destination host
|
|
152
|
+
# unreachable"; only a real echo reply prints round-trip times.
|
|
153
|
+
answered = False
|
|
154
|
+
|
|
155
|
+
if answered:
|
|
150
156
|
return "Active", latency
|
|
151
157
|
|
|
152
158
|
output = result.stdout.lower()
|