bhtool 0.2.1__tar.gz → 0.2.3__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.
- {bhtool-0.2.1 → bhtool-0.2.3}/PKG-INFO +3 -2
- {bhtool-0.2.1 → bhtool-0.2.3}/README.md +1 -0
- {bhtool-0.2.1 → bhtool-0.2.3}/bhtool/cli.py +15 -0
- bhtool-0.2.3/bhtool/portkill.py +49 -0
- bhtool-0.2.3/bhtool/psword.py +53 -0
- {bhtool-0.2.1 → bhtool-0.2.3}/pyproject.toml +1 -1
- bhtool-0.2.1/bhtool/psword.py +0 -23
- bhtool-0.2.1/movie_mapping.json +0 -25
- {bhtool-0.2.1 → bhtool-0.2.3}/.gitignore +0 -0
- {bhtool-0.2.1 → bhtool-0.2.3}/.python-version +0 -0
- {bhtool-0.2.1 → bhtool-0.2.3}/bhtool/bumpver.py +0 -0
- {bhtool-0.2.1 → bhtool-0.2.3}/bhtool/clr_chmod.py +0 -0
- {bhtool-0.2.1 → bhtool-0.2.3}/bhtool/list_movies.py +0 -0
- {bhtool-0.2.1 → bhtool-0.2.3}/bhtool/npread.py +0 -0
- {bhtool-0.2.1 → bhtool-0.2.3}/bhtool/rm_npm.py +0 -0
- {bhtool-0.2.1 → bhtool-0.2.3}/bhtool/run.py +0 -0
- {bhtool-0.2.1 → bhtool-0.2.3}/bhtool/text.py +0 -0
- {bhtool-0.2.1 → bhtool-0.2.3}/bhtool/todict.py +0 -0
- {bhtool-0.2.1 → bhtool-0.2.3}/bhtool/utils.py +0 -0
- {bhtool-0.2.1 → bhtool-0.2.3}/jtools/jtools.js +0 -0
- {bhtool-0.2.1 → bhtool-0.2.3}/jtools/package.json +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: bhtool
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Assorted CLI utilities for Bosco’s workflows (dev, media, macOS, LLM helpers).
|
|
5
5
|
Author-email: Bosco Ho <apposite@gmail.com>
|
|
6
6
|
Requires-Python: >=3.13
|
|
@@ -39,6 +39,7 @@ Assorted CLI utilities that are handy in Bosco’s day-to-day work—version bum
|
|
|
39
39
|
| **clr-chmod** | Remove execute bit from non-shell files; tighten group/other write | |
|
|
40
40
|
| **npread** | Print the shape of NumPy`.npy` files | |
|
|
41
41
|
| **psword** | Find processes by name;`--kill` to terminate | |
|
|
42
|
+
| **portkill** | Find processes listening on TCP ports;`--kill` to terminate | |
|
|
42
43
|
| **rm-npm** | Recursively delete`node_modules` dirs and `package-lock.json` files | |
|
|
43
44
|
| **text** | Convert between Markdown, HTML, DOCX, and Pug (needs`pandoc` and related tools on `PATH`) | |
|
|
44
45
|
| **todict** | JSON or YAML file, or stdin, → Python`dict(...)`-style repr on stdout | |
|
|
@@ -23,6 +23,7 @@ Assorted CLI utilities that are handy in Bosco’s day-to-day work—version bum
|
|
|
23
23
|
| **clr-chmod** | Remove execute bit from non-shell files; tighten group/other write | |
|
|
24
24
|
| **npread** | Print the shape of NumPy`.npy` files | |
|
|
25
25
|
| **psword** | Find processes by name;`--kill` to terminate | |
|
|
26
|
+
| **portkill** | Find processes listening on TCP ports;`--kill` to terminate | |
|
|
26
27
|
| **rm-npm** | Recursively delete`node_modules` dirs and `package-lock.json` files | |
|
|
27
28
|
| **text** | Convert between Markdown, HTML, DOCX, and Pug (needs`pandoc` and related tools on `PATH`) | |
|
|
28
29
|
| **todict** | JSON or YAML file, or stdin, → Python`dict(...)`-style repr on stdout | |
|
|
@@ -60,6 +60,21 @@ def psword_cmd(*words: str, kill: bool = False):
|
|
|
60
60
|
psword_mod.psword(words, kill=kill)
|
|
61
61
|
|
|
62
62
|
|
|
63
|
+
@app.command(name="portkill")
|
|
64
|
+
def portkill_cmd(*ports: int, kill: bool = False):
|
|
65
|
+
"""Find processes listening on TCP ports and optionally kill them.
|
|
66
|
+
|
|
67
|
+
:param ports: TCP ports to inspect (one or more).
|
|
68
|
+
:param kill: If true, SIGKILL each listener; otherwise list them.
|
|
69
|
+
"""
|
|
70
|
+
if not ports:
|
|
71
|
+
app["portkill"].help_print()
|
|
72
|
+
return
|
|
73
|
+
import bhtool.portkill as portkill_mod
|
|
74
|
+
|
|
75
|
+
portkill_mod.portkill(ports, kill=kill)
|
|
76
|
+
|
|
77
|
+
|
|
63
78
|
@app.command(name="rm_npm")
|
|
64
79
|
def rm_npm_cmd():
|
|
65
80
|
"""Recursively remove node_modules directories and package-lock.json files."""
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
"""Find and kill processes listening on TCP ports"""
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import re
|
|
7
|
+
import signal
|
|
8
|
+
|
|
9
|
+
from bhtool.utils import run_output
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _lsof_pids(port: int) -> list[int]:
|
|
13
|
+
txt = run_output(f"lsof -nP -iTCP:{port} -sTCP:LISTEN -t")
|
|
14
|
+
return [int(line) for line in txt.splitlines() if line.strip().isdigit()]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _ss_pids(port: int) -> list[int]:
|
|
18
|
+
txt = run_output(f"ss -ltnp 'sport = :{port}'")
|
|
19
|
+
return [int(pid) for pid in re.findall(r"pid=(\d+)", txt)]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _command(pid: int) -> str:
|
|
23
|
+
cmd = run_output(f"ps -p {pid} -o command=").strip()
|
|
24
|
+
if len(cmd) > 80:
|
|
25
|
+
cmd = cmd[:80] + "..."
|
|
26
|
+
return cmd
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def find_listeners(port: int) -> list[tuple[int, str]]:
|
|
30
|
+
"""Return ``(pid, command)`` pairs for processes LISTENing on ``port``."""
|
|
31
|
+
pids = _lsof_pids(port) or _ss_pids(port)
|
|
32
|
+
return [(pid, _command(pid)) for pid in sorted(set(pids))]
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def portkill(ports: tuple[int, ...], kill: bool = False):
|
|
36
|
+
for port in ports:
|
|
37
|
+
listeners = find_listeners(port)
|
|
38
|
+
if not listeners:
|
|
39
|
+
print(f"no process listening on port {port}")
|
|
40
|
+
continue
|
|
41
|
+
for pid, cmd in listeners:
|
|
42
|
+
if kill:
|
|
43
|
+
print(f"kill target ({cmd})")
|
|
44
|
+
try:
|
|
45
|
+
os.kill(pid, signal.SIGKILL)
|
|
46
|
+
except ProcessLookupError:
|
|
47
|
+
print(f"process {pid} already gone")
|
|
48
|
+
else:
|
|
49
|
+
print(f"process {pid}: {cmd}")
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
"""Find processes with name"""
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import re
|
|
7
|
+
import signal
|
|
8
|
+
|
|
9
|
+
from bhtool.utils import run_output
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def own_pids() -> set[int]:
|
|
13
|
+
"""Our process and its ancestors, which must never be killed."""
|
|
14
|
+
parents = {
|
|
15
|
+
int(pid): int(ppid)
|
|
16
|
+
for pid, ppid in re.findall(
|
|
17
|
+
r"(\d+)\s+(\d+)", run_output("ps -o pid=,ppid= -ax")
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
pids = {os.getpid()}
|
|
21
|
+
pid = os.getpid()
|
|
22
|
+
while pid in parents and parents[pid] > 1 and parents[pid] not in pids:
|
|
23
|
+
pid = parents[pid]
|
|
24
|
+
pids.add(pid)
|
|
25
|
+
return pids
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def psword(words: tuple[str, ...], kill: bool = False):
|
|
29
|
+
killed: set[int] = set()
|
|
30
|
+
skip = own_pids()
|
|
31
|
+
for word in words:
|
|
32
|
+
txt = run_output(f"ps aux | grep {word}")
|
|
33
|
+
for line in txt.splitlines():
|
|
34
|
+
tokens = line.split(None, 10)
|
|
35
|
+
if len(tokens) < 11:
|
|
36
|
+
continue
|
|
37
|
+
cmd = tokens[10]
|
|
38
|
+
if cmd.startswith("grep ") or "ps aux | grep" in cmd:
|
|
39
|
+
continue
|
|
40
|
+
pid = int(tokens[1])
|
|
41
|
+
if pid in skip or pid in killed:
|
|
42
|
+
continue
|
|
43
|
+
if len(cmd) > 80:
|
|
44
|
+
cmd = cmd[:80] + "..."
|
|
45
|
+
if kill:
|
|
46
|
+
print(f"kill target ({cmd})")
|
|
47
|
+
try:
|
|
48
|
+
os.kill(pid, signal.SIGKILL)
|
|
49
|
+
killed.add(pid)
|
|
50
|
+
except (ProcessLookupError, PermissionError) as err:
|
|
51
|
+
print(f"could not kill {pid}: {err}")
|
|
52
|
+
else:
|
|
53
|
+
print(f"process {pid}: {cmd}")
|
bhtool-0.2.1/bhtool/psword.py
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
|
|
3
|
-
"""Find processes with name"""
|
|
4
|
-
|
|
5
|
-
from bhtool.utils import run, run_output
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def psword(words: tuple[str, ...], kill: bool = False):
|
|
9
|
-
for word in words:
|
|
10
|
-
txt = run_output(f"ps aux | grep {word}")
|
|
11
|
-
for line in txt.splitlines():
|
|
12
|
-
tokens = line.split()
|
|
13
|
-
i_process = tokens[1]
|
|
14
|
-
cmd = " ".join(tokens[10:])
|
|
15
|
-
if len(cmd) > 80:
|
|
16
|
-
cmd = cmd[:80] + "..."
|
|
17
|
-
if "psword" in line:
|
|
18
|
-
continue
|
|
19
|
-
if kill:
|
|
20
|
-
print(f"kill target ({cmd})")
|
|
21
|
-
run(f"kill -9 {i_process}")
|
|
22
|
-
else:
|
|
23
|
-
print(f"process {i_process}: {cmd}")
|
bhtool-0.2.1/movie_mapping.json
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"directories": [
|
|
3
|
-
{
|
|
4
|
-
"original": "bhtool",
|
|
5
|
-
"normalized": "Bhtool"
|
|
6
|
-
},
|
|
7
|
-
{
|
|
8
|
-
"original": "build",
|
|
9
|
-
"normalized": "Build"
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
"original": "dist",
|
|
13
|
-
"normalized": "Dist"
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
"original": "jtools",
|
|
17
|
-
"normalized": "Jtools"
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
"original": "src",
|
|
21
|
-
"normalized": "Src"
|
|
22
|
-
}
|
|
23
|
-
],
|
|
24
|
-
"files": []
|
|
25
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|