♻️ refactor(av1-transfer): replace setproctitle with ctypes to fully hide cmdline args

Drop the setproctitle dependency. Use prctl(PR_SET_NAME) to change
/proc/self/comm and directly overwrite argv memory via Py_GetArgcArgv
to clear /proc/self/cmdline, so ps aux shows no arguments.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
FlintyLemming
2026-02-28 11:03:57 +08:00
parent a036b400d2
commit bf98b6d002

View File

@@ -17,13 +17,15 @@ AV1 视频批量转码脚本
""" """
import argparse import argparse
import ctypes
import ctypes.util
import queue import queue
import shutil import shutil
import subprocess import subprocess
import sys
from concurrent.futures import ThreadPoolExecutor, as_completed from concurrent.futures import ThreadPoolExecutor, as_completed
from pathlib import Path from pathlib import Path
import setproctitle
from tqdm import tqdm from tqdm import tqdm
# ================= 配置区域 ================= # ================= 配置区域 =================
@@ -35,6 +37,42 @@ VIDEO_EXTS = {".mp4", ".mkv", ".mov", ".avi", ".flv", ".ts", ".webm"}
SLOT_BAR_FORMAT = "{desc:<50} {percentage:3.0f}%|{bar}| {n:.0f}/{total:.0f}s" SLOT_BAR_FORMAT = "{desc:<50} {percentage:3.0f}%|{bar}| {n:.0f}/{total:.0f}s"
def _set_proc_title(title: str) -> None:
"""
通过两种方式彻底隐藏进程命令行:
1. prctl(PR_SET_NAME) — 改 /proc/self/commtop 默认显示的短名)
2. 直接覆盖 argv 内存 — 改 /proc/self/cmdlineps aux COMMAND 列)
"""
# 1. 改短名(/proc/self/comm最多 15 字节)
try:
libc_name = ctypes.util.find_library("c")
if libc_name:
libc = ctypes.CDLL(libc_name, use_errno=True)
libc.prctl(15, title.encode()[:15], 0, 0, 0) # PR_SET_NAME = 15
except Exception:
pass
# 2. 覆盖 argv 内存,清除 /proc/self/cmdline 里的参数
try:
argc = ctypes.c_int(0)
argv = ctypes.POINTER(ctypes.c_char_p)()
ctypes.pythonapi.Py_GetArgcArgv(ctypes.byref(argc), ctypes.byref(argv))
if argc.value == 0:
return
# argv 字符串在内存中连续排列,计算总占用字节数
start = ctypes.cast(argv[0], ctypes.c_void_p).value
end = ctypes.cast(argv[argc.value - 1], ctypes.c_void_p).value
end += len(argv[argc.value - 1]) + 1
size = end - start
# 用 title 填充开头,其余全部清零
enc = title.encode()[:size - 1]
buf = (ctypes.c_char * size).from_address(start)
buf[:len(enc)] = enc
buf[len(enc):] = b"\x00" * (size - len(enc))
except Exception:
pass
def get_duration(input_path): def get_duration(input_path):
"""用 ffprobe 获取视频时长(秒),失败返回 None""" """用 ffprobe 获取视频时长(秒),失败返回 None"""
result = subprocess.run( result = subprocess.run(
@@ -203,7 +241,7 @@ def main():
print(f"共发现 {len(tasks)} 个文件,准备使用 {max_workers} 个并行任务进行转码...") print(f"共发现 {len(tasks)} 个文件,准备使用 {max_workers} 个并行任务进行转码...")
if process_name: if process_name:
setproctitle.setproctitle(process_name) _set_proc_title(process_name)
print(f"进程别名: {process_name}") print(f"进程别名: {process_name}")
# 初始化进度条 # 初始化进度条