You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测调用Python脚本的Shell?为自制Hobby OS开发fetch工具

检测调用Python脚本的交互式Shell(适用于脚本嵌套调用场景)

问题原因

常规方法失效的核心原因:

  • os.getenv("SHELL") 返回的是用户默认登录Shell,而非当前实际调用脚本的Shell
  • echo $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}")

代码说明

  1. 父进程遍历:从Python进程的PID出发,不断获取父进程PID,直到找到目标Shell或系统init进程
  2. Shell进程识别:通过/proc/[pid]/stat提取进程名称,匹配常见Shell列表
  3. 交互式验证:读取进程环境变量(/proc/[pid]/environ),检查是否存在PS1——这是交互式Shell的典型标记

适配Hobby OS的注意事项

  • 确保你的自定义OS已挂载/proc文件系统
  • 保证/proc/[pid]/stat、/proc/[pid]/environ等文件能正确返回进程信息

内容的提问来源于stack exchange,提问作者Hushm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 11:35:19