@misterhuydo/sentinel 1.0.26 → 1.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.cairn/.hint-lock
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2026-03-
|
|
1
|
+
2026-03-21T20:21:02.908Z
|
package/.cairn/session.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"message": "Auto-checkpoint at 2026-03-21T20:
|
|
3
|
-
"checkpoint_at": "2026-03-21T20:
|
|
2
|
+
"message": "Auto-checkpoint at 2026-03-21T20:27:04.713Z",
|
|
3
|
+
"checkpoint_at": "2026-03-21T20:27:04.714Z",
|
|
4
4
|
"active_files": [],
|
|
5
5
|
"notes": [],
|
|
6
6
|
"mtime_snapshot": {}
|
package/package.json
CHANGED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# fetch_log.sh — Generic SSH log fetcher
|
|
3
|
+
#
|
|
4
|
+
# Usage:
|
|
5
|
+
# ./fetch_log.sh # reads all *.properties in script dir
|
|
6
|
+
# ./fetch_log.sh SSOLWA.properties # specific file(s)
|
|
7
|
+
# ./fetch_log.sh SSOLWA.properties UAS.properties
|
|
8
|
+
# ./fetch_log.sh /path/to/SSOLWA.properties, /path/to/UAS.properties
|
|
9
|
+
#
|
|
10
|
+
# Properties file format:
|
|
11
|
+
# KEY=/path/to/ssh.pem (required)
|
|
12
|
+
# HOSTS=host1, ec2-user@host2, host3 (required, default user: ec2-user)
|
|
13
|
+
# LOGS=logs/app.log, logs/alarm.log (required, backslash or forward slash)
|
|
14
|
+
# REMOTE_SERVICE_USER=MyService (optional, defaults to properties filename)
|
|
15
|
+
# OUTPUT_DIR=/path/to/output (optional, defaults to script dir)
|
|
16
|
+
# TAIL=200 (optional, tail -n N)
|
|
17
|
+
# HEAD=100 (optional, head -n N; ignored if TAIL set)
|
|
18
|
+
# GREP_FILTER=WARN|ERROR (optional, grep -E filter)
|
|
19
|
+
# GREP_EXCLUDE=SSLTool|CommandValidate (optional, grep -iv exclude)
|
|
20
|
+
|
|
21
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
22
|
+
DEFAULT_SSH_USER="ec2-user"
|
|
23
|
+
|
|
24
|
+
show_help() {
|
|
25
|
+
cat << 'EOF'
|
|
26
|
+
fetch_log.sh — Generic SSH log fetcher
|
|
27
|
+
|
|
28
|
+
USAGE
|
|
29
|
+
./fetch_log.sh Read all *.properties in script dir
|
|
30
|
+
./fetch_log.sh FILE.properties ... One or more properties files
|
|
31
|
+
./fetch_log.sh /path/A.properties, /path/B.properties
|
|
32
|
+
|
|
33
|
+
OUTPUT
|
|
34
|
+
OUTPUT_DIR/<ServiceName>/<logname>-<node>.log
|
|
35
|
+
e.g. SSOLWA/INN-SSOLWA-1.log, SSOLWA/INN-SSOLWA-2.log
|
|
36
|
+
UAS/UserAdminService-1.log
|
|
37
|
+
|
|
38
|
+
PROPERTIES FILE FORMAT
|
|
39
|
+
Required:
|
|
40
|
+
KEY=/path/to/ssh.pem
|
|
41
|
+
HOSTS=host1, ec2-user@host2, host3
|
|
42
|
+
LOGS=logs/app.log, logs/alarm.log
|
|
43
|
+
|
|
44
|
+
Optional:
|
|
45
|
+
REMOTE_SERVICE_USER=MyService Defaults to properties filename.
|
|
46
|
+
Log path resolves to /home/<REMOTE_SERVICE_USER>/<LOGS>
|
|
47
|
+
OUTPUT_DIR=/path/to/output Defaults to script directory
|
|
48
|
+
TAIL=200 Fetch last N lines (tail -n N)
|
|
49
|
+
HEAD=100 Fetch first N lines (head -n N); ignored if TAIL set
|
|
50
|
+
GREP_FILTER=WARN|ERROR Keep only matching lines (grep -E)
|
|
51
|
+
GREP_EXCLUDE=SSLTool|hystrix Exclude matching lines (grep -iv)
|
|
52
|
+
|
|
53
|
+
Notes:
|
|
54
|
+
- HOSTS without user@ prefix default to ec2-user@<host>
|
|
55
|
+
- LOGS paths support both backslash and forward slash
|
|
56
|
+
- Lines starting with # are treated as comments
|
|
57
|
+
|
|
58
|
+
EXAMPLE (SSOLWA.properties)
|
|
59
|
+
KEY=/home/huy/.ssh/prod/sso-lwa.pem
|
|
60
|
+
HOSTS=ec2-1.eu-north-1.compute.amazonaws.com, ec2-2.eu-north-1.compute.amazonaws.com
|
|
61
|
+
LOGS=logs/INN-SSOLWA.log, logs/alarm.log
|
|
62
|
+
REMOTE_SERVICE_USER=SSOLoginWebApp
|
|
63
|
+
GREP_FILTER=WARN|ERROR
|
|
64
|
+
GREP_EXCLUDE=SSLTool|CommandValidate
|
|
65
|
+
TAIL=200
|
|
66
|
+
EOF
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
|
|
70
|
+
show_help
|
|
71
|
+
exit 0
|
|
72
|
+
fi
|
|
73
|
+
|
|
74
|
+
trim() {
|
|
75
|
+
local s="$*"
|
|
76
|
+
s="${s#"${s%%[![:space:]]*}"}"
|
|
77
|
+
s="${s%"${s##*[![:space:]]}"}"
|
|
78
|
+
printf '%s' "$s"
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
fetch_from_properties() {
|
|
82
|
+
local props_file="$1"
|
|
83
|
+
local KEY="" HOSTS="" LOGS="" TAIL="" HEAD=""
|
|
84
|
+
local OUTPUT_DIR="" REMOTE_SERVICE_USER="" GREP_FILTER="" GREP_EXCLUDE=""
|
|
85
|
+
|
|
86
|
+
while IFS='=' read -r raw_key raw_val || [[ -n "$raw_key" ]]; do
|
|
87
|
+
local k v
|
|
88
|
+
k="$(trim "$raw_key")"
|
|
89
|
+
v="$(trim "${raw_val:-}")"
|
|
90
|
+
v="${v%%\#*}" # strip inline comments
|
|
91
|
+
v="$(trim "$v")"
|
|
92
|
+
[[ "$k" =~ ^[[:space:]]*# || -z "$k" ]] && continue
|
|
93
|
+
case "$k" in
|
|
94
|
+
KEY) KEY="$v" ;;
|
|
95
|
+
HOSTS) HOSTS="$v" ;;
|
|
96
|
+
LOGS) LOGS="$v" ;;
|
|
97
|
+
TAIL) TAIL="$v" ;;
|
|
98
|
+
HEAD) HEAD="$v" ;;
|
|
99
|
+
OUTPUT_DIR) OUTPUT_DIR="$v" ;;
|
|
100
|
+
REMOTE_SERVICE_USER) REMOTE_SERVICE_USER="$v" ;;
|
|
101
|
+
GREP_FILTER) GREP_FILTER="$v" ;;
|
|
102
|
+
GREP_EXCLUDE) GREP_EXCLUDE="$v" ;;
|
|
103
|
+
esac
|
|
104
|
+
done < "$props_file"
|
|
105
|
+
|
|
106
|
+
if [[ -z "$KEY" || -z "$HOSTS" || -z "$LOGS" ]]; then
|
|
107
|
+
echo "SKIP: $props_file — missing required KEY, HOSTS, or LOGS"
|
|
108
|
+
return 0
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
local SERVICE_NAME
|
|
112
|
+
SERVICE_NAME="$(basename "$props_file" .properties)"
|
|
113
|
+
REMOTE_SERVICE_USER="${REMOTE_SERVICE_USER:-$SERVICE_NAME}"
|
|
114
|
+
OUTPUT_DIR="${OUTPUT_DIR:-$SCRIPT_DIR}"
|
|
115
|
+
|
|
116
|
+
local SERVICE_DIR="$OUTPUT_DIR/$SERVICE_NAME"
|
|
117
|
+
mkdir -p "$SERVICE_DIR"
|
|
118
|
+
|
|
119
|
+
# Parse comma-separated hosts
|
|
120
|
+
IFS=',' read -ra HOST_ARRAY <<< "$HOSTS"
|
|
121
|
+
# Parse comma-separated log paths
|
|
122
|
+
IFS=',' read -ra LOG_ARRAY <<< "$LOGS"
|
|
123
|
+
|
|
124
|
+
local node_idx=1
|
|
125
|
+
for raw_host in "${HOST_ARRAY[@]}"; do
|
|
126
|
+
local host_entry ssh_user ssh_host
|
|
127
|
+
host_entry="$(trim "$raw_host")"
|
|
128
|
+
[[ -z "$host_entry" ]] && continue
|
|
129
|
+
|
|
130
|
+
if [[ "$host_entry" == *"@"* ]]; then
|
|
131
|
+
ssh_user="${host_entry%%@*}"
|
|
132
|
+
ssh_host="${host_entry##*@}"
|
|
133
|
+
else
|
|
134
|
+
ssh_user="$DEFAULT_SSH_USER"
|
|
135
|
+
ssh_host="$host_entry"
|
|
136
|
+
fi
|
|
137
|
+
|
|
138
|
+
echo "--- [$SERVICE_NAME] node-$node_idx ($ssh_host) ---"
|
|
139
|
+
|
|
140
|
+
for raw_log in "${LOG_ARRAY[@]}"; do
|
|
141
|
+
local log_path
|
|
142
|
+
log_path="$(trim "$raw_log")"
|
|
143
|
+
log_path="${log_path//\\//}" # backslash → forward slash
|
|
144
|
+
log_path="${log_path#/}" # strip leading slash
|
|
145
|
+
|
|
146
|
+
local remote_path="/home/$REMOTE_SERVICE_USER/$log_path"
|
|
147
|
+
|
|
148
|
+
# Build remote command
|
|
149
|
+
local remote_cmd="sudo cat $remote_path 2>/dev/null"
|
|
150
|
+
[[ -n "$GREP_FILTER" ]] && remote_cmd+=" | grep -E '$GREP_FILTER'"
|
|
151
|
+
[[ -n "$GREP_EXCLUDE" ]] && remote_cmd+=" | grep -iv '$GREP_EXCLUDE'"
|
|
152
|
+
[[ -n "$TAIL" ]] && remote_cmd+=" | tail -n $TAIL"
|
|
153
|
+
[[ -n "$HEAD" ]] && [[ -z "$TAIL" ]] && remote_cmd+=" | head -n $HEAD"
|
|
154
|
+
|
|
155
|
+
local log_basename dest
|
|
156
|
+
log_basename="$(basename "$log_path")"
|
|
157
|
+
log_basename="${log_basename%.*}"
|
|
158
|
+
dest="$SERVICE_DIR/${log_basename}-${node_idx}.log"
|
|
159
|
+
|
|
160
|
+
ssh -i "$KEY" -o StrictHostKeyChecking=no -o ConnectTimeout=10 \
|
|
161
|
+
-l "$ssh_user" "$ssh_host" "$remote_cmd" > "$dest" 2>/dev/null \
|
|
162
|
+
&& echo " OK: $dest" \
|
|
163
|
+
|| echo " FAILED: $log_path on $ssh_host"
|
|
164
|
+
done
|
|
165
|
+
|
|
166
|
+
((node_idx++))
|
|
167
|
+
done
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
# ── Collect properties files ──────────────────────────────────────────────────
|
|
171
|
+
declare -a PROPS_FILES=()
|
|
172
|
+
|
|
173
|
+
if [[ $# -eq 0 ]]; then
|
|
174
|
+
while IFS= read -r -d '' f; do
|
|
175
|
+
PROPS_FILES+=("$f")
|
|
176
|
+
done < <(find "$SCRIPT_DIR" -maxdepth 1 -name '*.properties' -print0 2>/dev/null | sort -z)
|
|
177
|
+
else
|
|
178
|
+
for arg in "$@"; do
|
|
179
|
+
IFS=',' read -ra parts <<< "$arg"
|
|
180
|
+
for p in "${parts[@]}"; do
|
|
181
|
+
p="$(trim "$p")"
|
|
182
|
+
[[ -n "$p" ]] && PROPS_FILES+=("$p")
|
|
183
|
+
done
|
|
184
|
+
done
|
|
185
|
+
fi
|
|
186
|
+
|
|
187
|
+
if [[ ${#PROPS_FILES[@]} -eq 0 ]]; then
|
|
188
|
+
echo "No .properties files found."
|
|
189
|
+
exit 0
|
|
190
|
+
fi
|
|
191
|
+
|
|
192
|
+
for props in "${PROPS_FILES[@]}"; do
|
|
193
|
+
if [[ ! -f "$props" ]]; then
|
|
194
|
+
echo "SKIP: $props — file not found"
|
|
195
|
+
continue
|
|
196
|
+
fi
|
|
197
|
+
fetch_from_properties "$props"
|
|
198
|
+
echo ""
|
|
199
|
+
done
|
|
200
|
+
|
|
201
|
+
echo "Done."
|
|
@@ -115,7 +115,7 @@ class ConfigLoader:
|
|
|
115
115
|
# Load workspace-level config first (~/sentinel/sentinel.properties),
|
|
116
116
|
# then overlay per-project config so project values win.
|
|
117
117
|
d: dict[str, str] = {}
|
|
118
|
-
workspace_props = self.config_dir.parent.parent / "sentinel.properties"
|
|
118
|
+
workspace_props = self.config_dir.resolve().parent.parent / "sentinel.properties"
|
|
119
119
|
if workspace_props.exists():
|
|
120
120
|
d.update(_parse_properties(str(workspace_props)))
|
|
121
121
|
logger.debug("Loaded workspace config from %s", workspace_props)
|
|
@@ -159,6 +159,8 @@ class ConfigLoader:
|
|
|
159
159
|
return
|
|
160
160
|
self.log_sources = {}
|
|
161
161
|
for path in sorted(sources_dir.glob("*.properties")):
|
|
162
|
+
if path.name.startswith("_"):
|
|
163
|
+
continue
|
|
162
164
|
d = _parse_properties(str(path))
|
|
163
165
|
s = LogSourceConfig()
|
|
164
166
|
s.name = path.stem
|
|
@@ -181,6 +183,8 @@ class ConfigLoader:
|
|
|
181
183
|
return
|
|
182
184
|
self.repos = {}
|
|
183
185
|
for path in sorted(repos_dir.glob("*.properties")):
|
|
186
|
+
if path.name.startswith("_"):
|
|
187
|
+
continue
|
|
184
188
|
d = _parse_properties(str(path))
|
|
185
189
|
r = RepoConfig()
|
|
186
190
|
r.repo_name = path.stem
|