Repository navigation
Expand file tree
/
Copy pathcapture.sh
More file actions
119 lines (96 loc) · 2.91 KB
/
Copy pathcapture.sh
File metadata and controls
119 lines (96 loc) · 2.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#!/usr/bin/env bash
set -u
DURATION="${1:-20}"
RATE="${2:-20}"
TIMESTAMP="$(date '+%Y%m%d-%H%M%S')"
OUTPUT_DIR="$HOME/Desktop/qortal-python-profile-$TIMESTAMP"
if ! command -v py-spy >/dev/null 2>&1; then
if command -v brew >/dev/null 2>&1; then
echo "Installing py-spy..."
brew install py-spy || exit 1
else
echo "Homebrew is unavailable. Install py-spy manually."
exit 1
fi
fi
PYSPY="$(command -v py-spy)"
mkdir -p "$OUTPUT_DIR"
# Anchored patterns prevent the script, Codex, grep, and py-spy itself
# from being mistaken for Qortal processes.
BRIDGE_PIDS="$(
pgrep -f '^/Applications/.*/Python .*\/presence_bridge\.py --config ' || true
)"
RNSD_PIDS="$(
pgrep -f '^/Applications/.*/Python .*\/rnsd --config ' || true
)"
if [ -z "$BRIDGE_PIDS" ] && [ -z "$RNSD_PIDS" ]; then
echo "No Qortal presence_bridge or rnsd processes were found."
echo "Start Qortal Hub and run this script again."
exit 1
fi
echo "Output directory: $OUTPUT_DIR"
echo "Bridge PIDs: ${BRIDGE_PIDS:-none}"
echo "rnsd PIDs: ${RNSD_PIDS:-none}"
echo
echo "Requesting administrator access..."
sudo -v || exit 1
{
echo "Captured: $(date)"
echo "Duration: ${DURATION}s"
echo "Rate: ${RATE} samples/second"
echo "py-spy: $PYSPY"
echo
uname -a
echo
echo "Qortal Python processes:"
for pid in $BRIDGE_PIDS $RNSD_PIDS; do
ps -p "$pid" -o pid=,ppid=,%cpu=,etime=,command=
done
} > "$OUTPUT_DIR/system-info.txt"
capture_process() {
local label="$1"
local pid="$2"
local profile="$OUTPUT_DIR/${label}-${pid}-profile.json"
local log="$OUTPUT_DIR/${label}-${pid}-profile.log"
local threads="$OUTPUT_DIR/${label}-${pid}-threads.txt"
local fallback="$OUTPUT_DIR/${label}-${pid}-macos-sample.txt"
echo "Preparing $label PID $pid..."
ps -p "$pid" -o pid=,ppid=,%cpu=,etime=,command= \
> "$OUTPUT_DIR/${label}-${pid}-process.txt"
sudo "$PYSPY" dump \
--nonblocking \
--pid "$pid" \
> "$threads" 2>&1 || true
(
sudo "$PYSPY" record \
--nonblocking \
--rate "$RATE" \
--duration "$DURATION" \
--pid "$pid" \
--format speedscope \
--output "$profile" \
> "$log" 2>&1
if [ ! -s "$profile" ]; then
echo "py-spy failed; collecting macOS sample fallback." >> "$log"
sample "$pid" "$DURATION" 10 -file "$fallback" \
>> "$log" 2>&1 || true
fi
) &
}
for pid in $BRIDGE_PIDS; do
capture_process "presence-bridge" "$pid"
done
for pid in $RNSD_PIDS; do
capture_process "rnsd" "$pid"
done
echo
echo "Recording simultaneously for ${DURATION} seconds..."
wait
echo
echo "Capture results:"
find "$OUTPUT_DIR" -type f -maxdepth 1 -exec ls -lh {} \;
ZIP_PATH="$OUTPUT_DIR.zip"
ditto -c -k --sequesterRsrc --keepParent \
"$OUTPUT_DIR" "$ZIP_PATH"
echo
echo "Finished: $ZIP_PATH"