sdfxa commited on
Commit
13712b0
·
verified ·
1 Parent(s): ef55883

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. x_node.py +123 -55
x_node.py CHANGED
@@ -1,3 +1,4 @@
 
1
  from __future__ import annotations
2
  import os
3
  import sys
@@ -7,36 +8,41 @@ import subprocess
7
  import platform
8
  import getpass
9
  import datetime
10
- from typing import Dict, Any
11
- import psutil
12
-
13
- #!/usr/bin/env python3
14
- """
15
- x_node.py
16
-
17
- 获取全部环境变量、当前进程信息,并检测 curl、wget 是否可调用(并尝试获取版本信息)。
18
- 输出 JSON 到 stdout,兼容 Linux/macOS/Windows。尽量不依赖第三方库,若安装 psutil 会提供更详细信息。
19
- """
20
-
21
 
22
  # Try to import psutil if available for richer process info
23
  try:
 
24
  except Exception:
25
  psutil = None # type: ignore
26
 
27
 
28
  def get_env_vars() -> Dict[str, str]:
29
  """Return all environment variables as a dict."""
 
30
  return dict(os.environ)
31
 
32
 
33
- def safe_run_version(cmd: list[str], timeout: float = 3.0) -> Dict[str, Any]:
34
- """Try to run `cmd --version` (cmd is full command list) and capture output."""
 
 
 
 
 
 
 
 
35
  try:
36
- p = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, timeout=timeout, check=False)
 
 
 
 
 
 
37
  out = p.stdout.decode(errors="replace").strip()
38
- # For long output, keep first few lines
39
- short_out = "\n".join(out.splitlines()[:5])
40
  return {"ok": True, "rc": p.returncode, "output": short_out}
41
  except FileNotFoundError:
42
  return {"ok": False, "error": "not found"}
@@ -46,32 +52,49 @@ def safe_run_version(cmd: list[str], timeout: float = 3.0) -> Dict[str, Any]:
46
  return {"ok": False, "error": str(e)}
47
 
48
 
49
- def check_tools(tools: list[str]) -> Dict[str, Dict[str, Any]]:
50
- """Check whether tools are callable (in PATH) and try to get version."""
 
 
 
 
51
  results: Dict[str, Dict[str, Any]] = {}
52
  for t in tools:
53
- path = shutil.which(t)
54
- info: Dict[str, Any] = {"path": path, "callable": bool(path)}
55
- if path:
56
- # Prefer conventional --version, fallback to -V, -v
57
- for flag in ("--version", "-V", "-v"):
58
- res = safe_run_version([t, flag])
59
- if res.get("ok") and res.get("output"):
60
- info["version_cmd"] = flag
61
- info["version_output"] = res.get("output")
62
- break
 
 
 
 
 
 
 
63
  else:
64
- # Try running with no args to see if there's any output
65
- res = safe_run_version([t])
66
- if res.get("ok"):
67
- info["version_cmd"] = None
68
- info["version_output"] = res.get("output")
69
- else:
70
- info["version_error"] = res.get("error")
71
  results[t] = info
72
  return results
73
 
74
 
 
 
 
 
 
 
 
 
75
  def get_process_info() -> Dict[str, Any]:
76
  """Collect basic process information. If psutil is available, include richer info."""
77
  info: Dict[str, Any] = {}
@@ -83,14 +106,16 @@ def get_process_info() -> Dict[str, Any]:
83
  info["python_version"] = platform.python_version()
84
  info["python_executable"] = sys.executable
85
  info["argv"] = sys.argv
86
- info["cwd"] = os.getcwd()
 
 
 
87
  info["pid"] = os.getpid()
88
- # ppid is available on most platforms
89
  try:
90
  info["ppid"] = os.getppid()
91
  except Exception:
92
  info["ppid"] = None
93
- info["user"] = getpass.getuser()
94
 
95
  # Add Unix-specific ids if available
96
  if hasattr(os, "getuid"):
@@ -105,24 +130,58 @@ def get_process_info() -> Dict[str, Any]:
105
  pass
106
 
107
  # Try using psutil for richer details
108
- if psutil:
109
  try:
110
  p = psutil.Process(info["pid"])
111
  with p.oneshot():
112
- info["exe"] = p.exe()
113
- info["cmdline"] = p.cmdline()
114
- info["create_time"] = datetime.datetime.fromtimestamp(p.create_time()).isoformat()
115
- info["cpu_percent"] = p.cpu_percent(interval=0.1)
116
- mem = p.memory_info()
117
- info["memory_rss"] = mem.rss
118
- info["memory_vms"] = mem.vms
119
- info["num_threads"] = p.num_threads()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  try:
121
  info["open_files"] = [f.path for f in p.open_files()]
122
  except Exception:
123
  info["open_files"] = None
 
124
  try:
125
- info["connections"] = [str(c) for c in p.connections()]
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  except Exception:
127
  info["connections"] = None
128
  except Exception:
@@ -137,13 +196,22 @@ def get_process_info() -> Dict[str, Any]:
137
 
138
 
139
  def main() -> int:
140
- env = get_env_vars()
141
- process = get_process_info()
142
- tools = check_tools(["curl", "wget"])
143
- result = {"env": env, "process": process, "tools": tools}
144
- # Print JSON
145
- print(json.dumps(result, indent=2, ensure_ascii=False))
146
- return 0
 
 
 
 
 
 
 
 
 
147
 
148
 
149
  main()
 
1
+ #!/usr/bin/env python3
2
  from __future__ import annotations
3
  import os
4
  import sys
 
8
  import platform
9
  import getpass
10
  import datetime
11
+ from typing import Dict, Any, Optional, Sequence
 
 
 
 
 
 
 
 
 
 
12
 
13
  # Try to import psutil if available for richer process info
14
  try:
15
+ import psutil # type: ignore
16
  except Exception:
17
  psutil = None # type: ignore
18
 
19
 
20
  def get_env_vars() -> Dict[str, str]:
21
  """Return all environment variables as a dict."""
22
+ # Convert to plain dict to avoid os._Environ metadata in output
23
  return dict(os.environ)
24
 
25
 
26
+ def _shorten_text(s: str, max_lines: int = 5, max_chars: int = 2000) -> str:
27
+ """Trim text to the given number of lines and characters to keep output small."""
28
+ out = "\n".join(s.splitlines()[:max_lines])
29
+ if len(out) > max_chars:
30
+ out = out[: max_chars - 3] + "..."
31
+ return out
32
+
33
+
34
+ def safe_run_version(cmd: Sequence[str], timeout: float = 3.0) -> Dict[str, Any]:
35
+ """Try to run `cmd` and capture stdout/stderr (combined)."""
36
  try:
37
+ p = subprocess.run(
38
+ list(cmd),
39
+ stdout=subprocess.PIPE,
40
+ stderr=subprocess.STDOUT,
41
+ timeout=timeout,
42
+ check=False,
43
+ )
44
  out = p.stdout.decode(errors="replace").strip()
45
+ short_out = _shorten_text(out)
 
46
  return {"ok": True, "rc": p.returncode, "output": short_out}
47
  except FileNotFoundError:
48
  return {"ok": False, "error": "not found"}
 
52
  return {"ok": False, "error": str(e)}
53
 
54
 
55
+ # Common flags to try for version/help info
56
+ TOOL_VERSION_FLAGS = ("--version", "-V", "-v", "--help")
57
+
58
+
59
+ def check_tools(tools: Sequence[str]) -> Dict[str, Dict[str, Any]]:
60
+ """Check whether tools are callable (in PATH) and try to get version/help output."""
61
  results: Dict[str, Dict[str, Any]] = {}
62
  for t in tools:
63
+ found_path: Optional[str] = shutil.which(t)
64
+ info: Dict[str, Any] = {"path": found_path, "callable": bool(found_path)}
65
+ # Whether we should try to run "t" or the absolute path
66
+ cmd_base = found_path or t
67
+ # Try common flags to get version/help output
68
+ for flag in TOOL_VERSION_FLAGS:
69
+ res = safe_run_version([cmd_base, flag])
70
+ if res.get("ok") and res.get("output"):
71
+ info["version_cmd"] = flag
72
+ info["version_output"] = res.get("output")
73
+ break
74
+ else:
75
+ # final fallback: attempt with no args (some tools print version/usage by default)
76
+ res = safe_run_version([cmd_base])
77
+ if res.get("ok") and res.get("output"):
78
+ info["version_cmd"] = None
79
+ info["version_output"] = res.get("output")
80
  else:
81
+ # If not found or error, pass the error info
82
+ info["version_error"] = res.get("error")
83
+ # Ensure callable is set correctly: if subprocess reports not found, set callable False
84
+ if res.get("error") == "not found":
85
+ info["callable"] = False
 
 
86
  results[t] = info
87
  return results
88
 
89
 
90
+ def _safe_get_user() -> Optional[str]:
91
+ try:
92
+ return getpass.getuser()
93
+ except Exception:
94
+ # Fallback to env variables
95
+ return os.environ.get("USER") or os.environ.get("USERNAME")
96
+
97
+
98
  def get_process_info() -> Dict[str, Any]:
99
  """Collect basic process information. If psutil is available, include richer info."""
100
  info: Dict[str, Any] = {}
 
106
  info["python_version"] = platform.python_version()
107
  info["python_executable"] = sys.executable
108
  info["argv"] = sys.argv
109
+ try:
110
+ info["cwd"] = os.getcwd()
111
+ except Exception:
112
+ info["cwd"] = None
113
  info["pid"] = os.getpid()
 
114
  try:
115
  info["ppid"] = os.getppid()
116
  except Exception:
117
  info["ppid"] = None
118
+ info["user"] = _safe_get_user()
119
 
120
  # Add Unix-specific ids if available
121
  if hasattr(os, "getuid"):
 
130
  pass
131
 
132
  # Try using psutil for richer details
133
+ if psutil is not None:
134
  try:
135
  p = psutil.Process(info["pid"])
136
  with p.oneshot():
137
+ try:
138
+ info["exe"] = p.exe()
139
+ except Exception:
140
+ info["exe"] = sys.executable
141
+ try:
142
+ info["cmdline"] = p.cmdline()
143
+ except Exception:
144
+ info["cmdline"] = sys.argv
145
+ try:
146
+ ct = p.create_time()
147
+ info["create_time"] = datetime.datetime.fromtimestamp(ct).isoformat()
148
+ except Exception:
149
+ info["create_time"] = None
150
+ try:
151
+ info["cpu_percent"] = p.cpu_percent(interval=0.1)
152
+ except Exception:
153
+ info["cpu_percent"] = None
154
+ try:
155
+ mem = p.memory_info()
156
+ info["memory_rss"] = getattr(mem, "rss", None)
157
+ info["memory_vms"] = getattr(mem, "vms", None)
158
+ except Exception:
159
+ info["memory_rss"] = None
160
+ info["memory_vms"] = None
161
+ try:
162
+ info["num_threads"] = p.num_threads()
163
+ except Exception:
164
+ info["num_threads"] = None
165
  try:
166
  info["open_files"] = [f.path for f in p.open_files()]
167
  except Exception:
168
  info["open_files"] = None
169
+ # p.connections() can be expensive and may require permissions; tolerate failures
170
  try:
171
+ # Modern psutil uses net_connections
172
+ conns = getattr(p, "connections", None)
173
+ if callable(conns):
174
+ conns_list = p.connections()
175
+ else:
176
+ net_conns = getattr(p, "net_connections", None)
177
+ if callable(net_conns):
178
+ conns_list = p.net_connections()
179
+ else:
180
+ conns_list = None
181
+ if conns_list is None:
182
+ info["connections"] = None
183
+ else:
184
+ info["connections"] = [str(c) for c in conns_list]
185
  except Exception:
186
  info["connections"] = None
187
  except Exception:
 
196
 
197
 
198
  def main() -> int:
199
+ try:
200
+ env = get_env_vars()
201
+ process = get_process_info()
202
+ tools = check_tools(["curl", "wget"])
203
+ result = {"env": env, "process": process, "tools": tools}
204
+ # Ensure stable JSON output
205
+ out = json.dumps(result, indent=2, ensure_ascii=False, sort_keys=False)
206
+ print(out, flush=True)
207
+ return 0
208
+ except Exception as e:
209
+ # Print error message in JSON form for easier parsing
210
+ try:
211
+ print(json.dumps({"error": str(e)}), flush=True)
212
+ except Exception:
213
+ print(f"error: {e}", flush=True)
214
+ return 2
215
 
216
 
217
  main()