Last active
September 3, 2025 15:03
-
-
Save ActiveTK/9d62b3a067f1d6f1930ef67d001f59b6 to your computer and use it in GitHub Desktop.
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
| #!/usr/bin/env python3 | |
| import os, sys, signal, subprocess, threading, time, shutil, datetime, urllib.request, urllib.parse, mimetypes, random, string, glob, tarfile, tempfile, codecs, pty, select, re, fcntl, struct, termios | |
| # 機能 | |
| # | |
| # これを実行するだけでGPU(複数枚でもOK)でBitcoin Puzzleの71番を解き始められる | |
| # 結果はTelegramで取得できる(一定周期ごとにサーバー情報を送信 & パズル完了の時にも情報送信) | |
| # GPUだけ酷使しててCPUリソースはほぼ使わないのは可哀そうないのでとりあえずmkp224oでOnionのバニティも同時に走らせてみる | |
| # つかいかた | |
| # | |
| # 1. https://btcpuzzle.info/ でアカウント作成 → トークンを取得 | |
| # 下のBCR_ENVのBC_USERTOKENを取得したトークンで置き換える | |
| # BC_WORKERNAMEのところはワーカーの名前(適当で良いが公開される、「my_gpuserver」みたいなのが無難)を指定 | |
| # あと諸々のBCR_ENVの設定で変えたいところがあればChatGPTに聞いてくれ! | |
| # | |
| # 2. Telegramの通知を設定するために、まずはTelegramのbotを作り、そのbotにDMを送ってルームを作る | |
| # 詳しいやり方はGeminiに聞いてくれ | |
| # 作ったbotのトークンをTGRAM_TOKENに設定して、ルームのChatIDをTGRAM_CHATIDに指定する | |
| # STATUS_PERIODに通知を受け取る周期を秒単位で指定する(テスト用に60秒に指定してある) | |
| # | |
| # 3. mkp224oの設定 | |
| # MKP_THREADSが利用するスレッド数で、MKP_TARGETSに探したい文字列を入れる(複数指定可能) | |
| # もし鍵を見つけたら、自動で鍵をgzip圧縮してTelegramで送ってくれます | |
| # | |
| # 4. 実行 | |
| # 以下のURLにあるテンプレートを利用してvast.aiで鯖を借りる | |
| # ただし RTX 5000シリーズのみ対応しているので注意 | |
| # RTX 4000シリーズでやりたければ ilkercndk/bitcrackrandomiser:latest でイメージを自作すること | |
| # | |
| # https://cloud.vast.ai?ref_id=293592&template_id=8d4bf52b582f6d9e4202de7718090eb0 | |
| # | |
| # 複数GPUでも対応しているが、まずは安い1枚の鯖でやってみると良いかも | |
| # 鯖を立ち上げたらコンソールから以下を実行 | |
| # > cd /app/ | |
| # > nano init.py | |
| # このPythonスクリプトを貼り付けて Ctrl+O で保存、Ctrl+X で終了 | |
| # > python3 init.py | |
| # Telegramに通知が来たら成功です | |
| # ログは /app/init.log に書き込まれるので cat init.log で見れるはず | |
| # なんかエラー出てたら教えてくれ、以上! | |
| # | |
| TGRAM_TOKEN = "Telegramのbotのトークン" | |
| TGRAM_CHATID = "TelegramのbotとのDM画面のChatID" | |
| STATUS_PERIOD = 60 | |
| BCR_ENV = { | |
| "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/share/dotnet", | |
| "BC_PUZZLE": "71", | |
| "BC_USERTOKEN": "btcpuzzle.infoのユーザートークン", | |
| "BC_WORKERNAME": "myworker", | |
| "BC_APP_TYPE": "vanitysearch", | |
| "BC_APP": "/app/VanitySearch/vanitysearch", | |
| "BC_GPUSEPERATEDRANGE": "true", | |
| "BC_TELEGRAM_SHARE": "true", | |
| "BC_TELEGRAM_ACCESS_TOKEN": TGRAM_TOKEN, | |
| "BC_TELEGRAM_CHAT_ID": TGRAM_CHATID, | |
| "BC_TELEGRAM_SHARE_EACHKEY": "true", | |
| "BC_UNTRUSTED_COMPUTER": "true", | |
| "DOTNET_ROOT": "/usr/share/dotnet", | |
| "DOTNET_CLI_TELEMETRY_OPTOUT": "1", | |
| "DOTNET_SYSTEM_GLOBALIZATION_INVARIANT": "1", | |
| } | |
| MKP_THREADS = 4 | |
| MKP_TARGETS = ["hogehoge", "fugafuga"] | |
| # 設定はここまでやぞ!by ActiveTK. (2025.9.3) | |
| HOST = subprocess.getoutput("hostname -f 2>/dev/null || hostname").strip() or "unknown" | |
| BASE = "/app" | |
| MKPDIR = os.path.join(BASE, "mkp224o") | |
| MKPOUTDIR = os.path.join(MKPDIR, "logs") | |
| LOGDIR = "/var/log/bitcrack_ops" | |
| BCRLOG = os.path.join(LOGDIR, "bcr.log") | |
| MKPLOG = os.path.join(LOGDIR, "mkp.log") | |
| PIDFILE = "/var/run/init_py_daemon.pid" | |
| BCR_SH = "/app/bitcrackrandomiser/bitcrackrandomiser.sh" | |
| INITLOG = os.path.abspath(os.path.join(os.getcwd(), "init.log")) | |
| PRINT_TO_STDOUT = {"print": False} | |
| INIT_FH = None | |
| ANSI_RE = re.compile(r"\x1B\[[0-9;?]*[ -/]*[@-~]") | |
| CSI_PATTERN = r"\x1B\[[0-9;?]*" | |
| RE_TTY_LINEBREAK = re.compile(rf"(?:\r|{CSI_PATTERN}[G]|{CSI_PATTERN}[Hf]|{CSI_PATTERN}K{CSI_PATTERN}[G]|{CSI_PATTERN}2K{CSI_PATTERN}[G])") | |
| OSC_RE = re.compile(r"\x1B\][^\a]*\a") | |
| def now(): | |
| return datetime.datetime.now(datetime.timezone.utc).isoformat() | |
| def send_text(text): | |
| data = urllib.parse.urlencode({"chat_id": TGRAM_CHATID, "text": text}).encode() | |
| req = urllib.request.Request(f"https://api.telegram.org/bot{TGRAM_TOKEN}/sendMessage", data=data) | |
| try: | |
| urllib.request.urlopen(req, timeout=15).read() | |
| except Exception: | |
| pass | |
| def _mp(fields, files): | |
| boundary = "".join(random.choices(string.ascii_letters + string.digits, k=30)) | |
| body = bytearray() | |
| for k, v in fields.items(): | |
| body.extend(("--"+boundary+"\r\n").encode()) | |
| body.extend((f'Content-Disposition: form-data; name="{k}"\r\n\r\n').encode()) | |
| body.extend((str(v)+"\r\n").encode()) | |
| for k, path in files.items(): | |
| fn = os.path.basename(path) | |
| ct = mimetypes.guess_type(fn)[0] or "application/octet-stream" | |
| body.extend(("--"+boundary+"\r\n").encode()) | |
| body.extend((f'Content-Disposition: form-data; name="{k}"; filename="{fn}"\r\n').encode()) | |
| body.extend((f"Content-Type: {ct}\r\n\r\n").encode()) | |
| with open(path, "rb") as f: | |
| body.extend(f.read()) | |
| body.extend("\r\n".encode()) | |
| body.extend(("--"+boundary+"--\r\n").encode()) | |
| return boundary, bytes(body) | |
| def send_document(path, caption): | |
| fields = {"chat_id": TGRAM_CHATID, "caption": caption} | |
| files = {"document": path} | |
| b, body = _mp(fields, files) | |
| req = urllib.request.Request(f"https://api.telegram.org/bot{TGRAM_TOKEN}/sendDocument", data=body) | |
| req.add_header("Content-Type", f"multipart/form-data; boundary={b}") | |
| try: | |
| urllib.request.urlopen(req, timeout=30).read() | |
| except Exception: | |
| pass | |
| def sanitize_status_line(s): | |
| if s is None: | |
| return "" | |
| t = s | |
| t = RE_TTY_LINEBREAK.sub("\n", t) | |
| t = t.replace("\r\n", "\n").replace("\r", "\n").split("\n")[-1] | |
| t = OSC_RE.sub("", t) | |
| t = ANSI_RE.sub("", t).strip() | |
| return t | |
| def _normalize_stream_text(s): | |
| s = RE_TTY_LINEBREAK.sub("\n", s) | |
| s = s.replace("\r\n", "\n").replace("\r", "\n") | |
| s = OSC_RE.sub("", s) | |
| return s | |
| def pty_reader(master_fd, logfile_path, lastline_holder, print_flag): | |
| os.makedirs(os.path.dirname(logfile_path), exist_ok=True) | |
| decoder = codecs.getincrementaldecoder("utf-8")("replace") | |
| carry = "" | |
| MAX_CARRY = 1000000 | |
| with open(logfile_path, "a", buffering=1) as lf: | |
| while True: | |
| r, _, _ = select.select([master_fd], [], [], 0.5) | |
| if master_fd not in r: | |
| if carry: | |
| normalized = _normalize_stream_text(carry) | |
| parts = normalized.split("\n") | |
| carry = parts.pop() | |
| for line in parts: | |
| lf.write(line + "\n") | |
| if print_flag.get("print"): | |
| try: | |
| sys.stdout.write(line + "\n"); sys.stdout.flush() | |
| except Exception: | |
| pass | |
| ls = sanitize_status_line(line) | |
| if ls: | |
| lastline_holder["last"] = line | |
| lastline_holder["last_nonempty"] = ls | |
| if len(carry) > MAX_CARRY: | |
| lf.write(carry + "\n") | |
| if print_flag.get("print"): | |
| try: | |
| sys.stdout.write(carry + "\n"); sys.stdout.flush() | |
| except Exception: | |
| pass | |
| lastline_holder["last"] = carry | |
| lastline_holder["last_nonempty"] = sanitize_status_line(carry) | |
| carry = "" | |
| continue | |
| try: | |
| chunk = os.read(master_fd, 4096) | |
| except OSError: | |
| break | |
| if not chunk: | |
| break | |
| try: | |
| s = decoder.decode(chunk) | |
| except Exception: | |
| s = chunk.decode(errors="replace") | |
| carry += s | |
| normalized = _normalize_stream_text(carry) | |
| parts = normalized.split("\n") | |
| carry = parts.pop() | |
| for line in parts: | |
| lf.write(line + "\n") | |
| if print_flag.get("print"): | |
| try: | |
| sys.stdout.write(line + "\n"); sys.stdout.flush() | |
| except Exception: | |
| pass | |
| ls = sanitize_status_line(line) | |
| if ls: | |
| lastline_holder["last"] = line | |
| lastline_holder["last_nonempty"] = ls | |
| if len(carry) > MAX_CARRY: | |
| lf.write(carry + "\n") | |
| if print_flag.get("print"): | |
| try: | |
| sys.stdout.write(carry + "\n"); sys.stdout.flush() | |
| except Exception: | |
| pass | |
| lastline_holder["last"] = carry | |
| lastline_holder["last_nonempty"] = sanitize_status_line(carry) | |
| carry = "" | |
| tail = decoder.decode(b"", final=True) | |
| if tail: | |
| carry += tail | |
| if carry: | |
| carry = _normalize_stream_text(carry) | |
| lf.write(carry + "\n") | |
| if print_flag.get("print"): | |
| try: | |
| sys.stdout.write(carry + "\n"); sys.stdout.flush() | |
| except Exception: | |
| pass | |
| ls = sanitize_status_line(carry) | |
| if ls: | |
| lastline_holder["last"] = carry | |
| lastline_holder["last_nonempty"] = ls | |
| try: | |
| os.close(master_fd) | |
| except Exception: | |
| pass | |
| def line_reader(proc, logfile_path, lastline_holder, print_flag): | |
| os.makedirs(os.path.dirname(logfile_path), exist_ok=True) | |
| decoder = codecs.getincrementaldecoder("utf-8")("replace") | |
| carry = "" | |
| MAX_CARRY = 1000000 | |
| with open(logfile_path, "a", buffering=1) as lf: | |
| reader = proc.stdout | |
| readfn = getattr(reader, "read1", reader.read) | |
| while True: | |
| chunk = readfn(65536) | |
| if not chunk: | |
| break | |
| try: | |
| s = decoder.decode(chunk) | |
| except Exception: | |
| s = chunk.decode(errors="replace") | |
| if not s: | |
| continue | |
| carry += s | |
| normalized = _normalize_stream_text(carry) | |
| parts = normalized.split("\n") | |
| carry = parts.pop() | |
| for line in parts: | |
| lf.write(line + "\n") | |
| if print_flag.get("print"): | |
| try: | |
| sys.stdout.write(line + "\n"); sys.stdout.flush() | |
| except Exception: | |
| pass | |
| ls = sanitize_status_line(line) | |
| if ls: | |
| lastline_holder["last"] = line | |
| lastline_holder["last_nonempty"] = ls | |
| if len(carry) > MAX_CARRY: | |
| lf.write(carry + "\n") | |
| if print_flag.get("print"): | |
| try: | |
| sys.stdout.write(carry + "\n"); sys.stdout.flush() | |
| except Exception: | |
| pass | |
| lastline_holder["last"] = carry | |
| lastline_holder["last_nonempty"] = sanitize_status_line(carry) | |
| carry = "" | |
| tail = decoder.decode(b"", final=True) | |
| if tail: | |
| carry += tail | |
| if carry: | |
| carry = _normalize_stream_text(carry) | |
| lf.write(carry + "\n") | |
| if print_flag.get("print"): | |
| try: | |
| sys.stdout.write(carry + "\n"); sys.stdout.flush() | |
| except Exception: | |
| pass | |
| ls = sanitize_status_line(carry) | |
| if ls: | |
| lastline_holder["last"] = carry | |
| lastline_holder["last_nonempty"] = ls | |
| try: | |
| proc.stdout.close() | |
| except Exception: | |
| pass | |
| def set_oom_protect(pid): | |
| try: | |
| with open(f"/proc/{pid}/oom_score_adj","w") as f: | |
| f.write("-1000") | |
| except Exception: | |
| pass | |
| def run(cmd, cwd=None, check=True): | |
| return subprocess.run(cmd, cwd=cwd, stdout=INIT_FH, stderr=INIT_FH, check=check) | |
| def ensure_dotnet(): | |
| if shutil.which("dotnet"): | |
| return | |
| try: | |
| subprocess.run(["apt-get","update","-y"], stdout=INIT_FH, stderr=INIT_FH, check=False) | |
| subprocess.run(["apt-get","install","-y","wget","gpg","ca-certificates","apt-transport-https","curl"], stdout=INIT_FH, stderr=INIT_FH, check=False) | |
| tmpd = tempfile.mkdtemp() | |
| deb = os.path.join(tmpd,"packages-microsoft-prod.deb") | |
| subprocess.run(["curl","-L","https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb","-o",deb], stdout=INIT_FH, stderr=INIT_FH, check=True) | |
| subprocess.run(["dpkg","-i",deb], stdout=INIT_FH, stderr=INIT_FH, check=False) | |
| subprocess.run(["apt-get","update","-y"], stdout=INIT_FH, stderr=INIT_FH, check=False) | |
| subprocess.run(["apt-get","install","-y","dotnet-runtime-8.0"], stdout=INIT_FH, stderr=INIT_FH, check=True) | |
| except Exception: | |
| pass | |
| def ensure_mkp224o(): | |
| os.makedirs(BASE, exist_ok=True) | |
| if not os.path.isdir(MKPDIR) or not os.path.isfile(os.path.join(MKPDIR,"configure.ac")): | |
| tmp = os.path.join(BASE, f".mkp224o_tmp_{int(time.time())}") | |
| if os.path.isdir(tmp): | |
| shutil.rmtree(tmp, ignore_errors=True) | |
| run(["git","clone","https://github.com/cathugger/mkp224o", tmp], cwd=BASE, check=True) | |
| for _ in range(30): | |
| if os.path.isdir(tmp) and os.path.isfile(os.path.join(tmp,"autogen.sh")): | |
| break | |
| time.sleep(1) | |
| if os.path.isdir(MKPDIR): | |
| shutil.rmtree(MKPDIR, ignore_errors=True) | |
| os.rename(tmp, MKPDIR) | |
| for _ in range(5): | |
| if os.path.isfile(os.path.join(MKPDIR,"autogen.sh")): | |
| break | |
| time.sleep(1) | |
| if not os.path.isfile(os.path.join(MKPDIR,"autogen.sh")): | |
| run(["autoreconf","-fi"], cwd=MKPDIR, check=True) | |
| else: | |
| run(["/bin/sh","autogen.sh"], cwd=MKPDIR, check=False) | |
| run(["./configure"], cwd=MKPDIR, check=True) | |
| run(["make","-j","1"], cwd=MKPDIR, check=True) | |
| os.makedirs(MKPOUTDIR, exist_ok=True) | |
| def sanitize_sh(path): | |
| try: | |
| with open(path,"rb") as f: | |
| data = f.read() | |
| if data.startswith(b"\xEF\xBB\xBF"): | |
| data = data[3:] | |
| data = data.replace(b"\r\n", b"\n").replace(b"\r", b"\n") | |
| if not data.startswith(b"#!/"): | |
| data = b"#!/bin/sh\n"+data | |
| with open(path,"wb") as f: | |
| f.write(data) | |
| os.chmod(path,0o755) | |
| except Exception: | |
| pass | |
| def _set_winsize(fd, rows=60, cols=180): | |
| try: | |
| fcntl.ioctl(fd, termios.TIOCSWINSZ, struct.pack("HHHH", rows, cols, 0, 0)) | |
| except Exception: | |
| pass | |
| def start_bcr(print_flag): | |
| sanitize_sh(BCR_SH) | |
| env = dict(BCR_ENV) | |
| env.setdefault("TERM", "xterm") | |
| env.setdefault("COLUMNS", "180") | |
| env.setdefault("LINES", "60") | |
| master, slave = pty.openpty() | |
| try: | |
| _set_winsize(slave, rows=int(env["LINES"]), cols=int(env["COLUMNS"])) | |
| except Exception: | |
| pass | |
| proc = subprocess.Popen( | |
| ["/bin/sh", os.path.basename(BCR_SH)], | |
| stdin=slave, | |
| stdout=slave, | |
| stderr=slave, | |
| env=env, | |
| text=False, | |
| bufsize=0, | |
| cwd="/app/bitcrackrandomiser", | |
| start_new_session=True, | |
| preexec_fn=None, | |
| close_fds=True, | |
| ) | |
| try: | |
| os.close(slave) | |
| except Exception: | |
| pass | |
| set_oom_protect(proc.pid) | |
| last = {"last": "", "last_nonempty": ""} | |
| t = threading.Thread(target=pty_reader, args=(master, BCRLOG, last, print_flag), daemon=True) | |
| t.start() | |
| return proc, last | |
| def start_mkp(print_flag): | |
| args = [os.path.join(MKPDIR,"mkp224o")] + MKP_TARGETS + ["-v","-s","-t",str(MKP_THREADS),"-d",MKPOUTDIR] | |
| proc = subprocess.Popen( | |
| args, | |
| cwd=MKPDIR, | |
| stdout=subprocess.PIPE, | |
| stderr=subprocess.STDOUT, | |
| text=False, | |
| bufsize=0, | |
| start_new_session=True, | |
| preexec_fn=None, | |
| ) | |
| set_oom_protect(proc.pid) | |
| last = {"last": "", "last_nonempty": ""} | |
| t = threading.Thread(target=line_reader, args=(proc, MKPLOG, last, print_flag), daemon=True) | |
| t.start() | |
| return proc, last | |
| def ship_tail_logs(): | |
| bt="/tmp/bcr_tail.log"; mt="/tmp/mkp_tail.log" | |
| try: | |
| with open(BCRLOG,"rb") as f: | |
| open(bt,"wb").write(f.read()[-200000:]) | |
| except Exception: | |
| pass | |
| try: | |
| with open(MKPLOG,"rb") as f: | |
| open(mt,"wb").write(f.read()[-200000:]) | |
| except Exception: | |
| pass | |
| if os.path.exists(bt) and os.path.getsize(bt)>0: | |
| send_document(bt,"bcr.log tail") | |
| if os.path.exists(mt) and os.path.getsize(mt)>0: | |
| send_document(mt,"mkp.log tail") | |
| def detach_to_background(): | |
| PRINT_TO_STDOUT["print"] = False | |
| try: | |
| pid = os.fork() | |
| if pid > 0: | |
| return True | |
| except OSError: | |
| return False | |
| os.setsid() | |
| signal.signal(signal.SIGHUP, signal.SIG_IGN) | |
| try: | |
| pid = os.fork() | |
| if pid > 0: | |
| os._exit(0) | |
| except OSError: | |
| os._exit(1) | |
| os.chdir("/") | |
| os.umask(0) | |
| try: | |
| with open(PIDFILE,"w") as f: | |
| f.write(str(os.getpid())) | |
| except Exception: | |
| pass | |
| return False | |
| def fmt_status(phase, bcr_state, bcr_pid, mkp_state, mkp_pid, threads, last_bcr, last_mkp): | |
| lb = sanitize_status_line(last_bcr) if last_bcr else "" | |
| lm = sanitize_status_line(last_mkp) if last_mkp else "" | |
| return ( | |
| f"【status::{HOST}】\n\n" | |
| f"Date: {now()}\n" | |
| f"Phase: {phase}\n" | |
| f"process_bcr={bcr_state} pid={bcr_pid}\n" | |
| f"process_mkp={mkp_state} pid={mkp_pid} ({threads} threads)\n" | |
| f"bcr -> {lb}\n" | |
| f"mkp -> {lm}" | |
| ) | |
| def main(): | |
| if detach_to_background(): | |
| return | |
| global INIT_FH | |
| INIT_FH = open(INITLOG, "ab", buffering=0) | |
| os.makedirs(LOGDIR, exist_ok=True); os.makedirs(MKPOUTDIR, exist_ok=True) | |
| open(BCRLOG,"a").close(); open(MKPLOG,"a").close() | |
| try: | |
| subprocess.run(["apt-get","update","-y"], stdout=INIT_FH, stderr=INIT_FH, check=False) | |
| subprocess.run(["apt-get","install","-y","curl","git","build-essential","autoconf","automake","libtool","pkg-config","libsodium-dev","ca-certificates","coreutils","procps","autoconf-archive","htop"], stdout=INIT_FH, stderr=INIT_FH, check=False) | |
| except Exception: | |
| pass | |
| ensure_dotnet() | |
| ensure_mkp224o() | |
| try: | |
| if os.path.exists(BCR_SH): | |
| sanitize_sh(BCR_SH) | |
| except Exception: | |
| pass | |
| prev_dirs = set() | |
| try: | |
| prev_dirs = set(d for d in os.listdir(MKPOUTDIR) if d.endswith(".onion") and os.path.isdir(os.path.join(MKPOUTDIR,d))) | |
| except Exception: | |
| pass | |
| bcr, bcr_last = start_bcr(PRINT_TO_STDOUT) | |
| mkp, mkp_last = start_mkp(PRINT_TO_STDOUT) | |
| phase = "running" | |
| next_status = time.monotonic() + STATUS_PERIOD | |
| while True: | |
| time.sleep(1) | |
| lastline_bcr_nonempty = bcr_last.get("last_nonempty","") | |
| if time.monotonic() >= next_status: | |
| bcr_state = "RUNNING" if bcr.poll() is None else "NOT_RUNNING" | |
| bcr_pid = bcr.pid if bcr.poll() is None else "-" | |
| mkp_state = "RUNNING" if mkp.poll() is None else "NOT_RUNNING" | |
| mkp_pid = mkp.pid if mkp.poll() is None else "-" | |
| msg = ( | |
| f"【status::{HOST}】\n\n" | |
| f"Date: {now()}\n" | |
| f"Phase: {phase}\n" | |
| f"process_bcr={bcr_state} pid={bcr_pid}\n" | |
| f"process_mkp={mkp_state} pid={mkp_pid} ({MKP_THREADS} threads)\n" | |
| f"bcr -> {lastline_bcr_nonempty}\n" | |
| f"mkp -> {sanitize_status_line(mkp_last.get('last',''))}" | |
| ) | |
| send_text(msg) | |
| next_status = time.monotonic() + STATUS_PERIOD | |
| if bcr.poll() is not None: | |
| ship_tail_logs() | |
| bcr_state = "EXITED" | |
| mkp_state = "RUNNING" if mkp.poll() is None else "NOT_RUNNING" | |
| mkp_pid = mkp.pid if mkp.poll() is None else "-" | |
| send_text( | |
| f"【status::{HOST}】\n\n" | |
| f"Date: {now()}\n" | |
| f"Phase: {phase}\n" | |
| f"process_bcr={bcr_state} pid=-\n" | |
| f"process_mkp={mkp_state} pid={mkp_pid} ({MKP_THREADS} threads)\n" | |
| f"bcr -> {lastline_bcr_nonempty}\n" | |
| f"mkp -> {sanitize_status_line(mkp_last.get('last',''))}" | |
| ) | |
| time.sleep(5) | |
| bcr, bcr_last = start_bcr({"print": False}) | |
| lastline_bcr_nonempty = "" | |
| send_text( | |
| f"【status::{HOST}】\n\n" | |
| f"Date: {now()}\n" | |
| f"Phase: {phase}\n" | |
| f"process_bcr=RUNNING pid={bcr.pid}\n" | |
| f"process_mkp={'RUNNING' if mkp.poll() is None else 'NOT_RUNNING'} pid={(mkp.pid if mkp.poll() is None else '-')} ({MKP_THREADS} threads)\n" | |
| f"bcr -> {lastline_bcr_nonempty}\n" | |
| f"mkp -> {sanitize_status_line(mkp_last.get('last',''))}" | |
| ) | |
| next_status = time.monotonic() + STATUS_PERIOD | |
| if mkp.poll() is not None: | |
| bcr_state = "RUNNING" if bcr.poll() is None else "NOT_RUNNING" | |
| bcr_pid = bcr.pid if bcr.poll() is None else "-" | |
| send_text( | |
| f"【status::{HOST}】\n\n" | |
| f"Date: {now()}\n" | |
| f"Phase: {phase}\n" | |
| f"process_bcr={bcr_state} pid={bcr_pid}\n" | |
| f"process_mkp=EXITED pid=- ({MKP_THREADS} threads)\n" | |
| f"bcr -> {lastline_bcr_nonempty}\n" | |
| f"mkp -> {sanitize_status_line(mkp_last.get('last',''))}" | |
| ) | |
| time.sleep(5) | |
| mkp, mkp_last = start_mkp({"print": False}) | |
| send_text( | |
| f"【status::{HOST}】\n\n" | |
| f"Date: {now()}\n" | |
| f"Phase: {phase}\n" | |
| f"process_bcr={'RUNNING' if bcr.poll() is None else 'NOT_RUNNING'} pid={(bcr.pid if bcr.poll() is None else '-')}\n" | |
| f"process_mkp=RUNNING pid={mkp.pid} ({MKP_THREADS} threads)\n" | |
| f"bcr -> {lastline_bcr_nonempty}\n" | |
| f"mkp -> {sanitize_status_line(mkp_last.get('last',''))}" | |
| ) | |
| next_status = time.monotonic() + STATUS_PERIOD | |
| try: | |
| cur_dirs = set(d for d in os.listdir(MKPOUTDIR) if d.endswith(".onion") and os.path.isdir(os.path.join(MKPOUTDIR,d))) | |
| except Exception: | |
| cur_dirs = set() | |
| new_dirs = sorted(list(cur_dirs - prev_dirs)) | |
| if new_dirs: | |
| for nd in new_dirs: | |
| full = os.path.join(MKPOUTDIR, nd) | |
| if os.path.isdir(full): | |
| send_text(f"alert\nhost={HOST}\ntime={now()}\nmkp224o_output_dir={nd}") | |
| tarpath = f"/tmp/{nd}.tar.gz" | |
| try: | |
| with tarfile.open(tarpath,"w:gz") as tar: | |
| tar.add(full, arcname=os.path.basename(full)) | |
| send_document(tarpath, f"mkp224o {nd}") | |
| except Exception: | |
| pass | |
| prev_dirs = cur_dirs | |
| if __name__ == "__main__": | |
| try: | |
| main() | |
| except KeyboardInterrupt: | |
| pass |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment