import os
import subprocess
import uuid
import datetime
import json
import errno
import platform
from typing import List, Any, Union, Tuple
try:
import psutil
except ImportError:
psutil = None
def run_nuclei(target: str, args: str) -> Tuple[str, int]:
executable = "/root/go/bin/nuclei"
output_dir = os.path.join(os.getcwd(), "output")
os.makedirs(output_dir, exist_ok=True)
ts = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
uid = uuid.uuid4().hex
filename = f"{ts}_{uid}.json"
output_path = os.path.join(output_dir, filename)
args_list = args.split() if args else []
cmd = [executable, "-target", target] + args_list + ["-json-export", output_path]
if os.name == 'nt':
proc = subprocess.Popen(
cmd,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP
)
else:
proc = subprocess.Popen(
cmd,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
start_new_session=True
)
pid = proc.pid
if psutil and platform.system() == "Windows":
try:
parent = psutil.Process(proc.pid)
for child in parent.children(recursive=True):
if child.name().lower().startswith("nuclei"):
pid = child.pid
break
except Exception:
pass
return output_path, pid
def _is_process_running(pid: int) -> bool:
try:
os.kill(pid, 0)
except OSError as e:
if getattr(e, 'errno', None) == errno.ESRCH:
return False
if getattr(e, 'errno', None) == errno.EPERM:
return True
return False
except ValueError:
return True
return True
def get_nuclei_output(file_path: str, pid: int) -> Union[str, List[Any]]:
running = _is_process_running(pid)
if running and not os.path.isfile(file_path):
return f"Scan running with PID {pid}"
if not os.path.isfile(file_path):
raise FileNotFoundError(f"Output file not found (scan PID {pid} has exited): {file_path}")
results: List[Any] = []
with open(file_path, 'r', encoding='utf-8') as f:
for line in f:
line = line.strip()
if line:
results.append(json.loads(line))
return results