столкнулся с проблемой завершения subprocess
У меня есть один главный бот, который запускает много дочерних ботов (система подписки в боте главном работает), когда подписка истекла, то дочерний бот должен выключится, при старте всех дочерних ботов я сохраняю их process.pid, чтобы потом по нему можно было выключить, но не получается сколько не пробовал
Код:
import os
from bot_functions import *
import subprocess
from threading import Thread, Lock
import sqlite3
def get_db_connection():
return sqlite3.connect('users_malling.db')
def add_process(process, user_id):
conn = get_db_connection()
with conn:
cur = conn.cursor()
process_pid = process.pid # Get the PID of the process
print(process_pid, user_id)
cur.execute('INSERT INTO processes (process, user_id) VALUES (?, ?)', (int(process_pid), user_id))
conn.commit()
def get_all_bot_tokens():
tokens = []
user_ids = []
cur.execute("SELECT bot_token, user_id, banned FROM users WHERE bot_token IS NOT NULL")
rows = cur.fetchall()
for row in rows:
if row[2] == 0:
tokens.append(row[0])
user_ids.append(row[1])
return tokens, user_ids
lock = Lock()
bot_processes = {}
def start_bot(bot_token, user_id):
db_name = f"user_{user_id}.db"
command = f"python users_bots/bot_functions.py --token {bot_token} --db {db_name} --user {user_id}"
process = subprocess.Popen(command, shell=True)
proccess_pid = process.pid
add_process(process=process, user_id=user_id)
log_file_path = f"user_{user_id}_bot_output.txt"
logging.info(f"Logging output to {log_file_path}")
print(f"Added process for user_id {user_id} to bot_processes.")
print(bot_processes)
def stop_bot_process(user_id):
"""Остановить процесс бота по user_id."""
conn = get_db_connection()
with conn:
cur = conn.cursor()
cur.execute('SELECT process FROM processes WHERE user_id = ?', (user_id,))
result = cur.fetchone()
if result:
process_pid = int(result[0])
print(f"Retrieved process PID {process_pid} for user_id {user_id}.")
try:
# Using psutil to terminate the process
process = psutil.Process(process_pid)
print(f"Terminating process with PID {process_pid} for user_id {user_id}.")
process.terminate() # Gracefully terminate the process
os.kill(process_pid, signal.CTRL_C_EVENT)
process.wait() # Wait for the process to terminate
print(f"Process with PID {process_pid} terminated.")
with lock:
if user_id in bot_processes:
del bot_processes[user_id] # Remove the process from the dictionary
logging.info(f"Bot with user_id {user_id} stopped.")
print(f"Stopped bot process for user_id {user_id}.")
except psutil.NoSuchProcess:
logging.warning(f"No running bot found with PID {process_pid} for user_id {user_id}.")
print(f"No running bot found for PID {process_pid} and user_id {user_id}.")
except psutil.AccessDenied:
logging.error(f"Access denied when trying to terminate process PID {process_pid}.")
print(f"Access denied when trying to terminate process PID {process_pid}.")
except Exception as e:
logging.error(f"Error terminating process PID {process_pid}: {e}")
print(f"Error terminating process PID {process_pid}: {e}")
else:
logging.warning(f"No process found in the database for user_id {user_id}.")
print(f"No process found in the database for user_id {user_id}.")
def start_all_bots():
tokens, user_ids = get_all_bot_tokens()
for bot_token, user_id in zip(tokens, user_ids):
cur.execute("UPDATE users SET active = ? WHERE user_id = ?", (1, user_id))
db.db.commit()
thread = Thread(target=start_bot, args=(bot_token, user_id))
thread.start()
if __name__ == "__main__":
start_all_bots()
executor.start_polling(dp, on_startup=on_startup, skip_updates=False)