kill old processes

This commit is contained in:
Thephaseless 2024-12-13 22:38:47 +00:00
parent 36f8262ad7
commit 709c9b6ef6
6 changed files with 64 additions and 17 deletions

View File

@ -2,10 +2,13 @@
An alternative to [FlareSolverr](https://github.com/FlareSolverr/FlareSolverr) as a drop-in replacement, build with [seleniumbase](https://seleniumbase.io/) and [FastAPI](https://fastapi.tiangolo.com).
> [!WARNING]
> [!CAUTION]
> From now on, Byparr will clear all chrome processes longer than specified in `MAX_CHROME_LIFETIME` environment variable (default is 300 seconds). To disable this behavior, set `MAX_CHROME_LIFETIME` to `0`.
> [!IMPORTANT]
> Due to recent challenge changes, this software does not guarantee that the Cloudflare challenge will be bypassed. Cloudflare likely requires valid network traffic originating from the users public IP address to mark a connection as legitimate. While this tool may bypass the initial browser check, it does not ensure that requests will consistently pass Cloudflare's validation. More testing and data are required to understand how Cloudflare identifies connections and requests as valid. Invalid requests will result in Byparr's looping and eventually time-outing.
> [!WARNING]
> [!IMPORTANT]
> Support for NAS devices (like Synology) is minimal. Please report issues, but do not expect it to be fixed quickly. The only ARM device I have is a free Ampere Oracle VM, so I can only test ARM support on that. See [#22](https://github.com/ThePhaseless/Byparr/issues/22) and [#3](https://github.com/ThePhaseless/Byparr/issues/3)
> [!NOTE]
@ -27,15 +30,7 @@ An alternative to [FlareSolverr](https://github.com/FlareSolverr/FlareSolverr) a
### Docker Compose
```yaml
services:
byparr:
image: ghcr.io/thephaseless/byparr:latest
environment:
- LOG_LEVEL=INFO # optional
ports:
- "8191:8191" # Optional if needed to make make requests/check docs on host
```
See `docker-compose.yaml`
### Docker

View File

@ -6,5 +6,6 @@ services:
dockerfile: Dockerfile
environment:
- LOG_LEVEL=INFO
- MAX_CHROME_LIFETIME=300
ports:
- "8191:8191"

14
main.py
View File

@ -12,10 +12,11 @@ from sbase import SB, BaseCase
import src
import src.utils
from src.utils import consts
import src.utils.consts
from src.models.requests import LinkRequest, LinkResponse, Solution
from src.utils import logger
from src.utils.consts import LOG_LEVEL
from src.utils.consts import LOG_LEVEL, kill_chromium_processes
app = FastAPI(debug=LOG_LEVEL == logging.DEBUG, log_level=LOG_LEVEL)
@ -25,18 +26,19 @@ cookies = []
@app.get("/")
def read_root():
"""Redirect to /docs."""
logger.info("Redirecting to /docs")
logger.debug("Redirecting to /docs")
return RedirectResponse(url="/docs", status_code=301)
@app.get("/health")
async def health_check():
"""Health check endpoint."""
logger.info("Health check")
health_check_request = read_item(
LinkRequest.model_construct(url="https://prowlarr.servarr.com/v1/ping")
)
if consts.MAX_CHROME_LIFETIME>0:
kill_chromium_processes()
if health_check_request.solution.status != HTTPStatus.OK:
raise HTTPException(
status_code=500,
@ -66,9 +68,9 @@ def read_item(request: LinkRequest) -> LinkResponse:
source = sb.get_page_source()
source_bs = BeautifulSoup(source, "html.parser")
title_tag = source_bs.title
logger.info(f"Got webpage: {request.url}")
logger.debug(f"Got webpage: {request.url}")
if title_tag and title_tag.string in src.utils.consts.CHALLENGE_TITLES:
logger.info("Challenge detected")
logger.debug("Challenge detected")
sb.uc_gui_click_captcha()
logger.info("Clicked captcha")

View File

@ -10,6 +10,7 @@ readme = "README.md"
dependencies = [
"beautifulsoup4==4.12.3",
"fastapi[standard]==0.115.6",
"psutil==6.1.0",
"pyautogui==0.9.54",
"pydantic==2.10.3",
"seleniumbase==4.33.10",

View File

@ -1,5 +1,10 @@
import logging
import os
import time
import psutil
from src.utils import logger
def get_version_from_env():
@ -21,12 +26,38 @@ def get_version_from_env():
return version_env.removeprefix("v")
def kill_chromium_processes():
# Define the prefix and time threshold
prefix = "chromium"
time_threshold = 300 # 5 minutes in seconds
# Get the current time
current_time = time.time()
# Iterate through all processes
for proc in psutil.process_iter(['pid', 'name', 'create_time']):
try:
# Extract process details
pid = proc.info['pid']
name:str = proc.info['name']
create_time = proc.info['create_time']
# Check if the process name starts with the prefix and has been running longer than the threshold
if name and name.startswith(prefix) and (current_time - create_time > time_threshold):
logger.info(f"Terminating process {name} (PID: {pid}) running for {int(current_time - create_time)} seconds")
psutil.Process(pid).terminate() # Terminate the process
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
# Ignore processes that no longer exist or can't be accessed
pass
LOG_LEVEL = os.getenv("LOG_LEVEL") or "INFO"
LOG_LEVEL = logging.getLevelNamesMapping()[LOG_LEVEL.upper()]
VERSION = get_version_from_env() or "unknown"
MAX_CHROME_LIFETIME= int(os.getenv("MAX_CHROME_LIFETIME", 300))
CHALLENGE_TITLES = [
# Cloudflare

17
uv.lock generated
View File

@ -66,6 +66,7 @@ source = { virtual = "." }
dependencies = [
{ name = "beautifulsoup4" },
{ name = "fastapi", extra = ["standard"] },
{ name = "psutil" },
{ name = "pyautogui" },
{ name = "pydantic" },
{ name = "seleniumbase" },
@ -90,6 +91,7 @@ test = [
requires-dist = [
{ name = "beautifulsoup4", specifier = "==4.12.3" },
{ name = "fastapi", extras = ["standard"], specifier = "==0.115.6" },
{ name = "psutil", specifier = ">=6.1.0" },
{ name = "pyautogui", specifier = "==0.9.54" },
{ name = "pydantic", specifier = "==2.10.3" },
{ name = "seleniumbase", specifier = "==4.33.10" },
@ -594,6 +596,21 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 },
]
[[package]]
name = "psutil"
version = "6.1.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/26/10/2a30b13c61e7cf937f4adf90710776b7918ed0a9c434e2c38224732af310/psutil-6.1.0.tar.gz", hash = "sha256:353815f59a7f64cdaca1c0307ee13558a0512f6db064e92fe833784f08539c7a", size = 508565 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/01/9e/8be43078a171381953cfee33c07c0d628594b5dbfc5157847b85022c2c1b/psutil-6.1.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:6e2dcd475ce8b80522e51d923d10c7871e45f20918e027ab682f94f1c6351688", size = 247762 },
{ url = "https://files.pythonhosted.org/packages/1d/cb/313e80644ea407f04f6602a9e23096540d9dc1878755f3952ea8d3d104be/psutil-6.1.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:0895b8414afafc526712c498bd9de2b063deaac4021a3b3c34566283464aff8e", size = 248777 },
{ url = "https://files.pythonhosted.org/packages/65/8e/bcbe2025c587b5d703369b6a75b65d41d1367553da6e3f788aff91eaf5bd/psutil-6.1.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9dcbfce5d89f1d1f2546a2090f4fcf87c7f669d1d90aacb7d7582addece9fb38", size = 284259 },
{ url = "https://files.pythonhosted.org/packages/58/4d/8245e6f76a93c98aab285a43ea71ff1b171bcd90c9d238bf81f7021fb233/psutil-6.1.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:498c6979f9c6637ebc3a73b3f87f9eb1ec24e1ce53a7c5173b8508981614a90b", size = 287255 },
{ url = "https://files.pythonhosted.org/packages/27/c2/d034856ac47e3b3cdfa9720d0e113902e615f4190d5d1bdb8df4b2015fb2/psutil-6.1.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d905186d647b16755a800e7263d43df08b790d709d575105d419f8b6ef65423a", size = 288804 },
{ url = "https://files.pythonhosted.org/packages/ea/55/5389ed243c878725feffc0d6a3bc5ef6764312b6fc7c081faaa2cfa7ef37/psutil-6.1.0-cp37-abi3-win32.whl", hash = "sha256:1ad45a1f5d0b608253b11508f80940985d1d0c8f6111b5cb637533a0e6ddc13e", size = 250386 },
{ url = "https://files.pythonhosted.org/packages/11/91/87fa6f060e649b1e1a7b19a4f5869709fbf750b7c8c262ee776ec32f3028/psutil-6.1.0-cp37-abi3-win_amd64.whl", hash = "sha256:a8fb3752b491d246034fa4d279ff076501588ce8cbcdbb62c32fd7a377d996be", size = 254228 },
]
[[package]]
name = "pyautogui"
version = "0.9.54"