endlessh accepted connections continously for 1.02 days (87_711 sec)
max simultaneous connections: 9
total bytes transmitted: 288.67 kiB
total wait time: 51.31 hours
total host count: 350
top 10 seen hosts
[REDACTED HOST1] ################################################# 493
[REDACTED HOST2] ############ 129
[REDACTED HOST3] ########## 103
[REDACTED HOST4] ########## 102
[REDACTED HOST5] ###### 61
[REDACTED HOST6] ## 28
[REDACTED HOST7] ## 22
[REDACTED HOST8] ## 20
[REDACTED HOST9] ## 20
[REDACTED HOST10] # 18
top 10 total wait time per host [hour]
[REDACTED HOST1] ###################### 22.05
[REDACTED HOST2] ########## 10.43
[REDACTED HOST3] ### 3.71
[REDACTED HOST4] ### 3.69
[REDACTED HOST5] ## 2.44
[REDACTED HOST6] # 1.01
[REDACTED HOST7] 0.90
[REDACTED HOST8] 0.61
[REDACTED HOST9] 0.31
[REDACTED HOST10] 0.29
top 10 total bytes transmitted per host [kiB]
[REDACTED HOST1] ############################################################################################################################### 127.57
[REDACTED HOST2] ############################################################# 61.39
[REDACTED HOST3] ##################### 21.27
[REDACTED HOST4] #################### 20.84
[REDACTED HOST5] ############## 14.12
[REDACTED HOST6] ##### 5.70
[REDACTED HOST7] #### 4.97
[REDACTED HOST8] ### 3.68
[REDACTED HOST9] # 1.86
[REDACTED HOST10] # 1.80
highest wait time of single connection: [REDACTED HOST2] 20.67min (tx 2.13kiB)
most bytes transmitted over single connection: [REDACTED HOST2] 2.13kiB (took 20.67min)
Last active
January 4, 2026 01:24
-
-
Save FabianBartl/9b3537c681570bf672235202b31ea3e2 to your computer and use it in GitHub Desktop.
A quick and dirty script to show some stats for endlessh by parsing its log.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # download endlessh here: https://github.com/skeeto/endlessh | |
| import re | |
| import datetime as dt | |
| with open(r"endlessh.log", "r", encoding="utf-8") as fobj: | |
| lines = fobj.readlines() | |
| data = [] | |
| max_simcons = [] | |
| total_time_sec = 0 | |
| current_timestamp = None | |
| last_timestamp = None | |
| for line in lines: | |
| line = line.strip() | |
| if "CLOSE" in line: | |
| entry = {} | |
| if matched_host := re.findall(r"host=([^ ]+)", line): | |
| entry["host"] = matched_host[0] | |
| if matched_time := re.findall(r"time=([0-9]+\.[0-9]+)", line): | |
| entry["time"] = float(matched_time[0]) | |
| if matched_bytes := re.findall(r"bytes=([0-9]+)", line): | |
| entry["bytes"] = int(matched_bytes[0]) | |
| if not ("host" in entry and "time" in entry and "bytes" in entry): | |
| print(line) | |
| print(entry) | |
| else: | |
| data.append(entry) | |
| elif "ACCEPT" in line: | |
| if matched_simcon := re.findall(r"n=([0-9]+)/[0-9]+", line): | |
| max_simcons.append(int(matched_simcon[0])) | |
| last_timestamp = current_timestamp | |
| current_timestamp = dt.datetime.fromisoformat(line.split(" ", 1)[0].replace("Z", "+00:00")).timestamp() | |
| if "CLOSE" in line or "ACCEPT" in line: | |
| if last_timestamp is not None: | |
| total_time_sec += (current_timestamp - last_timestamp) | |
| else: | |
| last_timestamp = None | |
| total_time_sec = int(total_time_sec) | |
| print(f"\nendlessh accepted connections continously for {total_time_sec/60/60/24:.2f} days ({total_time_sec:_} sec)") | |
| max_simcon = max(max_simcons) | |
| print(f"\nmax simultaneous connections: {max_simcon}") | |
| total_bytes_tx = sum( entry["bytes"] for entry in data ) | |
| print(f"\ntotal bytes transmitted: {total_bytes_tx/1024:.2f} kiB") | |
| total_waittime = sum( entry["time"] for entry in data ) | |
| print(f"total wait time: {total_waittime/60/60:.2f} hours") | |
| total_host_count = len(set( e["host"] for e in data )) | |
| print(f"total host count: {total_host_count}") | |
| seen_hosts_count = {} | |
| for entry in data: | |
| host = entry["host"] | |
| if host not in seen_hosts_count: | |
| seen_hosts_count[host] = 0 | |
| seen_hosts_count[host] += 1 | |
| print(f"\ntop 10 seen hosts") | |
| for host, count in sorted(seen_hosts_count.items(), key=lambda i: i[1], reverse=True)[:10]: | |
| print(f"{host:>30} {int(count/10)*'#'} {count}") | |
| waittime_per_host = {} | |
| for entry in data: | |
| host = entry["host"] | |
| if host not in waittime_per_host: | |
| waittime_per_host[host] = 0 | |
| waittime_per_host[host] += entry["time"] | |
| print(f"\ntop 10 total wait time per host [hour]") | |
| for host, time in sorted(waittime_per_host.items(), key=lambda i: i[1], reverse=True)[:10]: | |
| print(f"{host:>30} {int(time/60/60)*'#'} {time/60/60:.2f}") | |
| bytes_tx_per_host = {} | |
| for entry in data: | |
| host = entry["host"] | |
| if host not in bytes_tx_per_host: | |
| bytes_tx_per_host[host] = 0 | |
| bytes_tx_per_host[host] += entry["bytes"] | |
| print(f"\ntop 10 total bytes transmitted per host [kiB]") | |
| for host, _bytes in sorted(bytes_tx_per_host.items(), key=lambda i: i[1], reverse=True)[:10]: | |
| print(f"{host:>30} {int(_bytes/1024)*'#'} {_bytes/1024:.2f}") | |
| most_waittime_per_conn = max(data, key=lambda e: e["time"]) | |
| print(f"\nhighest wait time of single connection: {most_waittime_per_conn['host']} {most_waittime_per_conn['time']/60:.2f}min (tx {most_waittime_per_conn['bytes']/1024:.2f}kiB)") | |
| most_tx_bytes_per_conn = max(data, key=lambda e: e["bytes"]) | |
| print(f"most bytes transmitted over single connection: {most_tx_bytes_per_conn['host']} {most_tx_bytes_per_conn['bytes']/1024:.2f}kiB (took {most_tx_bytes_per_conn['time']/60:.2f}min)") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment