一个统计日志中app访问云调用次数的脚本

本文详细介绍了如何使用bash脚本批量处理特定目录下的日志文件,通过遍历目录和子目录,读取日志文件内容,并统计每个日志文件中特定模式的出现频率及唯一appid的次数。脚本通过多层循环结构实现目录和文件的遍历,以及复杂条件判断来获取所需信息。
#!/bin/sh

log_path=/root/test

appids_y_m_d_h_m=()
declare -A map=()

year=`date +%Y`
month=`date +%m`
#day=`date +%d`
day='13'
hour=`date +%H`
#min=`date +%M`
min='13'


#业务列表
dir_list=(iat tts)

for dir in ${dir_list[*]}
do
    cd ${log_path}/$dir/$year/$month/$day
    for hour_dir in `ls  .`
    do
        #echo $hour_dir
        cd $hour_dir
        for min_dir in `ls  .`
        do
            #echo $min_dir
            cd $min_dir
            for log_file in `ls  .`
            do
                flag="false"
                #统计每个日志文件
                while read line
                do
                    enter_cnt=`echo $line | grep '_inst::deal_request | enter' | wc -l`
                    appid_cnt=`echo $line | grep 'appid=' | wc -l`
                     
                    #echo $enter_cnt---$appid_cnt

                    
                    if [ "$enter_cnt" = "1"  ]
                    then
                        flag="true"
                    fi

                    #出现enter
                    if [ "$flag" = "true" ]
                    then
                        #appid出现
                        if [ "$appid_cnt" = "1" ]
                        then
                            flag='false'
                            #记录appid次数
                            appid=`echo $line | sed -n 's/.*,appid=\([0-9a-zA-Z]*\),.*/\1/pg'`
                            #echo $appid
                            key=${appid}_${year}_${month}_${day}_${hour}_${min}
                            echo $key
                            if [ map['$key'] = "" ]
                            then
                                map['$key']=1
                            else
                                ((map['$key']=map["$key"]+1))
                            fi

                        fi
                    fi
                done < $log_file

                printf "|%10s|%10s|%10s|%10s|%10s|%10s|%10s|\n" "appid" "year" "month" "day" "hour" "min" "count"
                for key in ${!map[@]}
                do
                    echo $key | awk -F'_' '{for(i=1;i<=NF;++i){printf "|%10s",$i}}'
                    printf "|%10s|\n" ${map[$key]}
                done
            done
        done
    done
done

exit


<think>我们计划创建一个GUI工具,该工具能够扫描指定文件夹中的脚本文件(特别是adb脚本),并生成同名按钮来执行这些脚本。 主要功能点: 1. 扫描指定文件夹(如当前目录下的某个子目录)内的所有脚本文件(例如 .bat, .sh 等可执行文件) 2. 为每个脚本文件在GUI界面中生成一个按钮,按钮名为脚本文件名(不含扩展名) 3. 点击按钮后执行对应的脚本 4. 显示执行日志(输出和错误) 我们将使用Python的Tkinter库来创建GUI,同时使用subprocess模块来执行脚本并捕获输出。 设计思路: - 主窗口包含一个顶部框架(用于显示标题和配置按钮)和一个日志文本区域。 - 脚本按钮将动态生成在一个可滚动的区域中(例如使用Canvas和Frame组合,以便支持大量按钮)。 - 我们允许用户选择脚本目录(默认可以是当前目录下的'scripts'文件夹)。 步骤: 1. 创建主窗口和基本布局。 2. 实现扫描脚本目录的函数,获取脚本文件列表。 3. 根据脚本文件列表,动态创建按钮,并为每个按钮绑定执行对应脚本的函数。 4. 执行脚本时,使用子进程执行,并实时捕获输出显示在日志区域。 5. 考虑多线程,避免执行脚本时阻塞GUI。 注意:由于执行外部脚本可能需要时间,我们将使用线程来执行,避免界面卡死。 代码结构: class ScriptRunnerApp: def __init__(self, root): # 初始化窗口 self.script_dir = "scripts" # 默认脚本目录 self.setup_ui(root) def setup_ui(self, root): # 创建界面组件 def load_scripts(self): # 加载脚本文件,并为每个脚本创建按钮 def run_script(self, script_path): # 执行脚本并输出到日志区域 我们将使用一个自定义的TextHandler类来重定向stdout和stderr到日志文本区域。 由于Tkinter不是线程安全的,我们在更新GUI时需要将操作放入主线程队列(使用`after`方法)。 具体实现如下: </think>### 创建脚本调用GUI工具的实现方案 #### 核心思路与架构设计 我们将构建一个能够自动扫描文件夹中所有ADB脚本并为每个脚本创建同名执行按钮的GUI工具。核心组件包括: ```mermaid graph TD A[脚本扫描模块] --> B[动态按钮生成器] B --> C[脚本执行引擎] C --> D[日志输出系统] D --> E[状态监控面板] ``` #### 完整实现代码(Python + Tkinter) ```python import os import tkinter as tk from tkinter import ttk, scrolledtext import subprocess import threading import platform class AdbScriptRunner: def __init__(self, root): self.root = root root.title("ADB脚本执行器 v1.0") root.geometry("800x600") # 创建主框架 main_frame = ttk.Frame(root, padding=15) main_frame.pack(fill=tk.BOTH, expand=True) # 创建控制面板 self.create_control_panel(main_frame) # 创建脚本按钮区域 self.script_frame = ttk.LabelFrame(main_frame, text="可用脚本", padding=10) self.script_frame.pack(fill=tk.BOTH, expand=True, pady=10) # 创建日志区域 self.create_log_panel(main_frame) # 初始加载脚本 self.load_scripts() def create_control_panel(self, parent): """创建控制面板""" control_frame = ttk.Frame(parent) control_frame.pack(fill=tk.X, pady=(0, 10)) # 目录选择 ttk.Label(control_frame, text="脚本目录:").pack(side=tk.LEFT) self.dir_var = tk.StringVar(value=os.getcwd()) dir_entry = ttk.Entry(control_frame, textvariable=self.dir_var, width=40) dir_entry.pack(side=tk.LEFT, padx=5) browse_btn = ttk.Button(control_frame, text="浏览...", command=self.select_directory) browse_btn.pack(side=tk.LEFT) refresh_btn = ttk.Button(control_frame, text="刷新脚本", command=self.load_scripts) refresh_btn.pack(side=tk.RIGHT) def create_log_panel(self, parent): """创建日志面板""" log_frame = ttk.LabelFrame(parent, text="执行日志", padding=10) log_frame.pack(fill=tk.BOTH, expand=True) self.log_area = scrolledtext.ScrolledText( log_frame, wrap=tk.WORD, font=("Consolas", 10) ) self.log_area.pack(fill=tk.BOTH, expand=True) self.log_area.tag_config("error", foreground="red") self.log_area.tag_config("success", foreground="green") def select_directory(self): """选择脚本目录""" directory = tk.filedialog.askdirectory(initialdir=self.dir_var.get()) if directory: self.dir_var.set(directory) self.load_scripts() def load_scripts(self): """加载文件夹中的脚本文件""" # 清除现有按钮 for widget in self.script_frame.winfo_children(): widget.destroy() script_dir = self.dir_var.get() if not os.path.exists(script_dir): self.log("⚠️ 目录不存在: " + script_dir, "error") return # 检测脚本文件 scripts = [f for f in os.listdir(script_dir) if f.endswith(('.bat', '.sh', '.ps1'))] if not scripts: self.log("ℹ️ 目录中未找到脚本文件", "info") return # 创建脚本按钮 ttk.Label(self.script_frame, text="点击按钮执行脚本:").pack(anchor="w") button_frame = ttk.Frame(self.script_frame) button_frame.pack(fill=tk.X, pady=5) for idx, script in enumerate(scripts): btn = ttk.Button( button_frame, text=os.path.splitext(script)[0], command=lambda s=script: self.execute_script(s) ) btn.grid(row=idx//4, column=idx%4, padx=5, pady=5, sticky="w") def execute_script(self, script_name): """执行选定的脚本""" script_path = os.path.join(self.dir_var.get(), script_name) self.log(f"▶ 开始执行: {script_name}") # 根据平台选择执行方式 if platform.system() == "Windows": command = ["cmd", "/c", script_path] else: command = ["bash", script_path] # 使用线程防止GUI冻结 threading.Thread( target=self.run_subprocess, args=(command, script_name), daemon=True ).start() def run_subprocess(self, command, script_name): """运行子进程并捕获输出""" try: process = subprocess.Popen( command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, encoding="utf-8", errors="replace" ) # 实时捕获输出 while True: output = process.stdout.readline() if output == "" and process.poll() is not None: break if output: self.log(output.strip()) # 检查退出状态 if process.returncode == 0: self.log(f"✔ {script_name} 执行成功!", "success") else: self.log(f"✖ {script_name} 执行失败 (代码: {process.returncode})", "error") except Exception as e: self.log(f"⚠️ 执行错误: {str(e)}", "error") def log(self, message, tag=None): """记录日志到文本框""" self.log_area.configure(state="normal") self.log_area.insert(tk.END, message + "\n", tag) self.log_area.configure(state="disabled") self.log_area.see(tk.END) if __name__ == "__main__": root = tk.Tk() app = AdbScriptRunner(root) root.mainloop() ``` #### 关键功能实现原理 1. **脚本自动扫描**: ```python scripts = [f for f in os.listdir(script_dir) if f.endswith(('.bat', '.sh', '.ps1'))] ``` 使用文件扩展名过滤识别可执行脚本[^1] 2. **动态按钮生成**: ```python for idx, script in enumerate(scripts): btn = ttk.Button(..., command=lambda s=script: execute_script(s)) ``` 为每个脚本创建同名按钮并绑定执行函数 3. **跨平台执行支持**: ```python if platform.system() == "Windows": command = ["cmd", "/c", script_path] else: command = ["bash", script_path] ``` 自动适配Windows/Linux/macOS系统[^1] 4. **实时输出捕获**: ```python process = subprocess.Popen(..., stdout=subprocess.PIPE) while True: output = process.stdout.readline() self.log(output.strip()) ``` 实时显示脚本执行输出流 #### 部署和使用指南 1. **准备脚本目录**: ``` /scripts ├─ connect_device.bat → 生成"connect_device"按钮 ├─ screen_capture.sh → 生成"screen_capture"按钮 └─ install_apk.ps1 → 生成"install_apk"按钮 ``` 2. **运行流程**: ```mermaid sequenceDiagram 用户->>+GUI: 选择脚本目录 GUI->>+文件系统: 扫描脚本文件 文件系统-->>-GUI: 返回脚本列表 GUI->>+界面: 动态生成按钮 用户->>+GUI: 点击脚本按钮 GUI->>+子进程: 执行对应脚本 子进程-->>-GUI: 实时输出日志 GUI->>+界面: 显示执行结果 ``` 3. **打包为可执行文件**: ```bash pip install pyinstaller pyinstaller --onefile --add-data "assets;assets" script_runner.py ``` #### 安全增强措施 1. **脚本执行沙箱**: ```python # 在子进程中使用受限环境 process = subprocess.Popen(..., env={"PATH": "/safe/path"}, shell=False # 防止shell注入 ) ``` 2. **签名验证**: ```python import hashlib def verify_script(script_path): with open(script_path, "rb") as f: return hashlib.sha256(f.read()).hexdigest() in ALLOWED_HASHES ``` 3. **权限隔离**: ```python if platform.system() != "Windows": os.chmod(script_path, 0o755) # 设置适当权限 ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值