如何在Python中对运行中的SSH命令输出进行过滤提取?
提取localhost.run转发URL的解决方案
你遇到的问题核心是没正确捕获ssh命令的输出,而且localhost.run的输出可能流向标准错误流(stderr),导致re.findall或grep无法获取到目标内容。下面是修改后的代码和关键说明:
修改后的完整代码
import requests, os import re from flask import Flask, Response from multiprocessing import Process import subprocess app = Flask(__name__) @app.route('/') def index(): return Response("<h1>123</h1>") def run_ssh_tunnel(): try: print("Starting ssh tunnel") # 捕获输出并合并标准错误流,text=True直接返回字符串格式 result = subprocess.run( ["ssh", "-R", "80:localhost:5000", "nokey@localhost.run"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True ) # 匹配localhost.run的转发URL,覆盖http/https及常见域名后缀 url_pattern = r'https?://[a-zA-Z0-9-]+\.(?:localhost\.run|lhr\.life)' matched_urls = re.findall(url_pattern, result.stdout) if matched_urls: print(f"提取到转发URL: {matched_urls[0]}") # 这里可以把URL保存到变量或文件,供后续使用 else: print("未找到有效的转发URL") except Exception as e: print("SSH隧道启动失败") print(e) # 分别启动Flask服务器和SSH隧道子进程 server_process = Process(target=app.run) ssh_process = Process(target=run_ssh_tunnel) try: server_process.start() ssh_process.start() # 等待进程结束(按需调整,若要后台运行可移除join) server_process.join() ssh_process.join() except Exception as e: print("ERR") print(e)
关键改进点
- 捕获输出流:用
stdout=subprocess.PIPE捕获命令输出,stderr=subprocess.STDOUT把错误流合并到标准流,确保不会遗漏localhost.run的输出内容 - 精准正则匹配:针对localhost.run的URL格式(如
https://xxxxxx.lhr.life或http://xxxxxx.localhost.run)编写正则,保证能准确提取 - 分离进程:把SSH隧道放到单独的子进程中,避免阻塞Flask服务器的运行
补充说明
如果之前尝试用终端管道grep无效,是因为ssh的输出默认到stderr,需要手动重定向:
ssh -R 80:localhost:5000 nokey@localhost.run 2>&1 | grep -E 'https?://[a-zA-Z0-9-]+\.(localhost\.run|lhr\.life)'
内容的提问来源于stack exchange,提问作者appelmoesDEV
相关产品推荐
相关产品推荐

