如何检测调用Python脚本的Shell?为自制Hobby OS开发fetch工具
检测调用Python脚本的交互式Shell(适用于脚本嵌套调用场景)
问题原因
常规方法失效的核心原因:
os.getenv("SHELL")返回的是用户默认登录Shell,而非当前实际调用脚本的Shellecho $0和readlink /proc/$$/exe获取的是直接调用Python的中间脚本进程,而非用户真正使用的交互式Shell
解决方案:遍历父进程链定位交互式Shell
利用Linux的/proc文件系统,从当前Python进程向上遍历父进程,找到带有交互式标记(如存在PS1环境变量)的Shell进程。
Python实现代码
import os def get_ppid(pid): """获取指定PID进程的父PID""" with open(f"/proc/{pid}/stat", "r") as f: stat_info = f.read().split() return int(stat_info[3]) def get_interactive_shell(): current_pid = os.getpid() common_shells = {"bash", "zsh", "fish", "sh", "ksh", "csh", "tcsh"} while True: ppid = get_ppid(current_pid) if ppid == 1: # 追溯到init进程,未找到有效Shell return "unknown" # 读取进程名称 with open(f"/proc/{ppid}/stat", "r") as f: stat_info = f.read().split() proc_name = stat_info[1].strip("()") if proc_name not in common_shells: current_pid = ppid continue # 验证是否为交互式Shell(存在PS1环境变量) with open(f"/proc/{ppid}/environ", "r") as f: environ_vars = f.read().split("\x00") has_ps1 = any(var.startswith("PS1=") for var in environ_vars) if has_ps1: return proc_name current_pid = ppid # 使用示例 if __name__ == "__main__": shell_name = get_interactive_shell() print(f"当前调用Shell: {shell_name}")
代码说明
- 父进程遍历:从Python进程的PID出发,不断获取父进程PID,直到找到目标Shell或系统init进程
- Shell进程识别:通过
/proc/[pid]/stat提取进程名称,匹配常见Shell列表 - 交互式验证:读取进程环境变量(
/proc/[pid]/environ),检查是否存在PS1——这是交互式Shell的典型标记
适配Hobby OS的注意事项
- 确保你的自定义OS已挂载
/proc文件系统 - 保证
/proc/[pid]/stat、/proc/[pid]/environ等文件能正确返回进程信息
内容的提问来源于stack exchange,提问作者Hushm
相关产品推荐
相关产品推荐

