如何区分Linux中由Apache或Cronjob启动的Python进程?
识别并区分Apache与Cron启动的Python进程
一、原生Linux方法判断启动方式
- 追踪父进程链:
针对目标Python进程PID,执行pstree -p <PID>或ps -ef | grep <PID>,查看父进程名称。Apache启动的进程父进程通常是apache2(或httpd),cron启动的进程父进程则是cron(或crond)。也可以用ps -o ppid= -p <进程PID>单独提取父进程ID,再通过ps -p <父进程PID> -o comm=确认父进程名称。 - 检查进程环境变量:
执行cat /proc/<PID>/environ | tr '\0' '\n'查看进程的环境变量列表。Apache启动的进程会包含APACHE_RUN_USER、SERVER_NAME这类专属变量;cron启动的进程则会带有CRON_TZ、SHELL等cron相关变量。
二、自定义识别方案(无原生便捷方法时)
- 为cron任务指定独立用户:
修改crontab配置,用su - 自定义用户名 -c "python3 /path/to/script.py"的方式启动脚本,让cron进程的用户与Apache的ubuntu区分开。后续直接用ps -u 自定义用户名筛选cron进程,ps -u ubuntu筛选Apache进程。 - 启动时给进程打标记:
- 命令行参数标记:给cron启动的脚本添加专属参数,比如
python3 /path/to/script.py --from-cron,后续用ps aux | grep "script.py --from-cron"快速识别cron进程。 - PID文件记录:cron启动时将进程ID写入
/tmp/cron_pids.txt,Apache启动时写入/tmp/apache_pids.txt,后续通过读取文件内容区分进程来源。
- 命令行参数标记:给cron启动的脚本添加专属参数,比如
三、Python脚本实现:终止Apache启动的进程
方法1:使用psutil库(需先安装pip install psutil)
import psutil def kill_apache_python_processes(): for proc in psutil.process_iter(['pid', 'name', 'ppid']): try: # 筛选Python进程 if proc.name() in ['python', 'python3']: parent_proc = psutil.Process(proc.ppid()) # 判断父进程是否为Apache if parent_proc.name() in ['apache2', 'httpd']: print(f"终止Apache启动的进程: PID {proc.pid}") proc.terminate() # 可选:超时未终止则强制杀死 # if proc.wait(timeout=3) is None: # proc.kill() except (psutil.NoSuchProcess, psutil.AccessDenied): continue if __name__ == "__main__": kill_apache_python_processes()
方法2:直接调用系统命令(无需第三方库)
import subprocess import os import signal def get_apache_python_pids(): # 获取所有进程的PID、父PID、命令行信息 ps_output = subprocess.run( ['ps', '-eo', 'pid,ppid,cmd'], capture_output=True, text=True ).stdout.strip().split('\n')[1:] apache_pids = [] for line in ps_output: parts = line.strip().split(maxsplit=2) if len(parts) < 3: continue pid, ppid, cmd = parts if 'python' in cmd.lower(): # 检查父进程是否为Apache parent_comm = subprocess.run( ['ps', '-p', ppid, '-o', 'comm='], capture_output=True, text=True ).stdout.strip() if parent_comm in ['apache2', 'httpd']: apache_pids.append(int(pid)) return apache_pids def kill_processes(pids): for pid in pids: try: os.kill(pid, signal.SIGTERM) print(f"已发送终止信号给PID {pid}") except OSError: print(f"无法终止PID {pid}") if __name__ == "__main__": target_pids = get_apache_python_pids() kill_processes(target_pids)
内容的提问来源于stack exchange,提问作者elPastor
相关产品推荐
相关产品推荐

