Skip to content

Instantly share code, notes, and snippets.

@FabianBartl
Last active January 4, 2026 01:24
Show Gist options
  • Select an option

  • Save FabianBartl/9b3537c681570bf672235202b31ea3e2 to your computer and use it in GitHub Desktop.

Select an option

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.
# 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)")
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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment