fa-mcp-sdk 0.2.84 → 0.2.92
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/bin/fa-mcp.js +46 -7
- package/cli-template/.env.example +0 -2
- package/cli-template/config/_local.yaml +3 -2
- package/cli-template/config/default.yaml +18 -8
- package/cli-template/deploy/{mcp-template.com.conf → NGINX/sites-enabled/mcp-template.com.conf} +1 -1
- package/cli-template/deploy/NGINX/snippets/ssl-params.conf +18 -0
- package/cli-template/deploy/NGINX/snippets/ssl-wildcard.conf +3 -0
- package/cli-template/deploy/srv.cjs +449 -0
- package/cli-template/deploy/srv.sh.readme.md +122 -259
- package/cli-template/update.cjs +32 -25
- package/dist/core/logger.d.ts.map +1 -1
- package/dist/core/logger.js +7 -3
- package/dist/core/logger.js.map +1 -1
- package/dist/core/token/token-core.js +4 -3
- package/dist/core/token/token-core.js.map +1 -1
- package/package.json +1 -1
- package/cli-template/deploy/srv.sh +0 -359
package/dist/core/logger.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/core/logger.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,qCAAqC;AAErC,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/core/logger.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,qCAAqC;AAErC,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,WAAW,EAAgD,MAAM,cAAc,CAAC;AAEzF,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC;AAE/D,0DAA0D;AAC1D,MAAM,WAAW,GAAG,SAAS,CAAC,GAAG,CAAC,aAAa,KAAK,OAAO,CAAC;AAE5D,IAAI,MAAuB,CAAC;AAC5B,IAAI,UAAkC,CAAC;AAEvC,IAAI,SAAS,CAAC,GAAG,CAAC,aAAa,KAAK,OAAO,EAAE,CAAC;IAC5C,MAAM,GAAG,EAAqB,CAAC;IAC/B,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,KAAa,EAAE,EAAE;QAC7F,aAAa;QACb,MAAO,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAe,EAAE,EAAE;YACtC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACjE,OAAO,SAAS,CAAC;QACnB,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,YAAY,GAAG,GAAG,EAAE;QACzB,OAAO,MAAO,CAAC;IACjB,CAAC,CAAC;AACJ,CAAC;KAAM,CAAC;IACN,MAAM,QAAQ,GAAoB;QAChC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,mCAAmC;QACzE,OAAO,EAAE,MAAM;QACf,IAAI,EAAE,SAAS;QACf,UAAU,EAAE,SAAS,CAAC,IAAI;QAC1B,UAAU,EAAE,CAAC;QACb,eAAe,EAAE,CAAC;QAClB,iBAAiB,EAAE,sDAAsD;QACzE,mBAAmB,EAAE,GAAG,GAAG,mBAAmB,KAAK,kBAAkB;QACrE,eAAe,EAAE;YACf,sBAAsB;YACtB,4BAA4B;YAC5B,kCAAkC;YAClC,6BAA6B;YAC7B,+BAA+B;YAC/B,wBAAwB;YACxB,qDAAqD;YACrD,mCAAmC;YACnC,sDAAsD;YACtD,kBAAkB;YAClB,2BAA2B;SAC5B;QACD,YAAY,EAAE,CAAC,OAAO,CAAC,aAAa,CAAC;KACtC,CAAC;IACF,IAAI,aAAa,IAAI,MAAM,EAAE,CAAC;QAC5B,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC;IAC3B,CAAC;IACD,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC5D,MAAM,GAAG,CAAC,CAAC;IACX,UAAU,GAAG,EAAE,CAAC;AAClB,CAAC;AAGD,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC"}
|
|
@@ -5,12 +5,13 @@ import { logger as lgr } from '../logger.js';
|
|
|
5
5
|
import { isObject, trim } from '../utils/utils.js';
|
|
6
6
|
import chalk from 'chalk';
|
|
7
7
|
const logger = lgr.getSubLogger({ name: chalk.cyan('token-auth') });
|
|
8
|
-
const
|
|
8
|
+
const pt = appConfig.webServer?.auth?.permanentServerTokens || [];
|
|
9
9
|
const permanentServerTokensSet = new Set(Array.isArray(pt) ? pt : [pt]);
|
|
10
|
+
const checkMCPName = appConfig.webServer?.auth?.token?.checkMCPName || false;
|
|
10
11
|
const ALGORITHM = 'aes-256-ctr';
|
|
11
12
|
const KEY = crypto
|
|
12
13
|
.createHash('sha256')
|
|
13
|
-
.update(String(
|
|
14
|
+
.update(String(appConfig.webServer?.auth?.token?.encryptKey || 'secret'))
|
|
14
15
|
.digest('base64')
|
|
15
16
|
.substring(0, 32);
|
|
16
17
|
export const tokenRE = /^(\d{13,})\.([\da-fA-F]{32,})$/;
|
|
@@ -115,7 +116,7 @@ export const checkToken = (arg) => {
|
|
|
115
116
|
errorReason: `JWT Token: user not match :: Expected '${expectedUser}' / obtained from the token: '${payload.user}'`,
|
|
116
117
|
};
|
|
117
118
|
}
|
|
118
|
-
if (
|
|
119
|
+
if (checkMCPName) {
|
|
119
120
|
if (expectedService && payload.service !== expectedService) {
|
|
120
121
|
return {
|
|
121
122
|
isTokenDecrypted: true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-core.js","sourceRoot":"","sources":["../../../src/core/token/token-core.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAExD,OAAO,EAAE,MAAM,IAAI,GAAG,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;AAEpE,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"token-core.js","sourceRoot":"","sources":["../../../src/core/token/token-core.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fa-mcp-sdk",
|
|
3
3
|
"productName": "FA MCP SDK",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.92",
|
|
5
5
|
"description": "Core infrastructure and templates for building Model Context Protocol (MCP) servers with TypeScript",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/core/index.js",
|
|
@@ -1,359 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/bash
|
|
2
|
-
|
|
3
|
-
# srv.sh - Unified systemd service management script
|
|
4
|
-
# Consolidates functionality from deploy/systemd-service/ scripts
|
|
5
|
-
# Can be run from project root or from deploy/ directory
|
|
6
|
-
|
|
7
|
-
# Colors for output
|
|
8
|
-
c="\e[1;36m"; lc="\e[0;36m";
|
|
9
|
-
g="\e[1;32m"; lg="\e[0;32m";
|
|
10
|
-
m="\e[1;35m"; lm="\e[0;35m";
|
|
11
|
-
r="\e[1;31m"; lr="\e[0;31m";
|
|
12
|
-
y="\e[1;33m"; ly="\e[0;33m";
|
|
13
|
-
c0='\033[0;0m'
|
|
14
|
-
|
|
15
|
-
# Script configuration
|
|
16
|
-
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
17
|
-
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" # Parent directory (project root)
|
|
18
|
-
SERVICE_NAME=""
|
|
19
|
-
NODE_VERSION=""
|
|
20
|
-
PORT=""
|
|
21
|
-
COMMAND=""
|
|
22
|
-
|
|
23
|
-
# Function to show usage
|
|
24
|
-
show_usage() {
|
|
25
|
-
echo "Usage:"
|
|
26
|
-
echo " $0 i|install [-n <service_name>] [-v <node_version>]"
|
|
27
|
-
echo " $0 d|delete [-n <service_name>] [-p <port>]"
|
|
28
|
-
echo " $0 r|reinstall [-n <service_name>] [-p <port>] [-v <node_version>]"
|
|
29
|
-
echo ""
|
|
30
|
-
echo "Commands:"
|
|
31
|
-
echo " i, install - Install and start systemd service"
|
|
32
|
-
echo " d, delete - Stop and remove systemd service"
|
|
33
|
-
echo " r, reinstall - Reinstall service (delete + install)"
|
|
34
|
-
echo ""
|
|
35
|
-
echo "Options:"
|
|
36
|
-
echo " -n <name> - Alternative service name (default: from package.json)"
|
|
37
|
-
echo " -v <version> - Node.js version (default: auto-detected)"
|
|
38
|
-
echo " -p <port> - Port number for service cleanup (default: auto-detected)"
|
|
39
|
-
echo ""
|
|
40
|
-
echo "Working directories:"
|
|
41
|
-
echo " Script location: $SCRIPT_DIR"
|
|
42
|
-
echo " Project root: $PROJECT_ROOT"
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
# Function to check if service exists
|
|
46
|
-
service_exists() {
|
|
47
|
-
local n=$1
|
|
48
|
-
if [[ $(systemctl list-units --all -t service --full --no-legend "$n.service" | sed 's/●//g' | sed 's/^\s*//g' | cut -f1 -d' ') == $n.service ]]; then
|
|
49
|
-
return 0
|
|
50
|
-
else
|
|
51
|
-
return 1
|
|
52
|
-
fi
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
# Function to detect Node.js version
|
|
56
|
-
detect_node_version() {
|
|
57
|
-
local version=""
|
|
58
|
-
|
|
59
|
-
# 1. Use provided version parameter
|
|
60
|
-
if [ -n "$NODE_VERSION" ]; then
|
|
61
|
-
version="$NODE_VERSION"
|
|
62
|
-
echo -e "$c**** Using provided Node.js version: $g$version$c ****$c0" >&2
|
|
63
|
-
# 2. Try to find version in .envrc (in project root)
|
|
64
|
-
elif [ -f "$PROJECT_ROOT/.envrc" ]; then
|
|
65
|
-
version=$(grep -E "^\s*nvm\s+use\s+" "$PROJECT_ROOT/.envrc" | sed -E 's/^\s*nvm\s+use\s+([0-9]+\.[0-9]+\.[0-9]+).*/\1/' | head -n1)
|
|
66
|
-
if [ -n "$version" ]; then
|
|
67
|
-
echo -e "$c**** Found Node.js version in .envrc: $g$version$c ****$c0" >&2
|
|
68
|
-
fi
|
|
69
|
-
fi
|
|
70
|
-
|
|
71
|
-
# 3. Fallback to current node version
|
|
72
|
-
if [ -z "$version" ]; then
|
|
73
|
-
version=$(node -v 2>/dev/null | sed 's/^v//')
|
|
74
|
-
if [ -n "$version" ]; then
|
|
75
|
-
echo -e "$c**** Using current Node.js version: $g$version$c ****$c0" >&2
|
|
76
|
-
else
|
|
77
|
-
echo -e "$r**** Error: Could not detect Node.js version ****$c0" >&2
|
|
78
|
-
exit 1
|
|
79
|
-
fi
|
|
80
|
-
fi
|
|
81
|
-
|
|
82
|
-
echo "$version"
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
# Function to find Node.js binary path
|
|
86
|
-
find_node_path() {
|
|
87
|
-
local version="$1"
|
|
88
|
-
local node_path=""
|
|
89
|
-
|
|
90
|
-
# Try NVM path first
|
|
91
|
-
local nvm_path="$HOME/.nvm/versions/node/v$version/bin/node"
|
|
92
|
-
if [ -f "$nvm_path" ]; then
|
|
93
|
-
node_path="$nvm_path"
|
|
94
|
-
echo -e "$c**** Found Node.js at NVM path: $g$node_path$c ****$c0" >&2
|
|
95
|
-
else
|
|
96
|
-
# Try system node
|
|
97
|
-
node_path=$(which node 2>/dev/null)
|
|
98
|
-
if [ -n "$node_path" ]; then
|
|
99
|
-
local current_version=$(node -v 2>/dev/null | sed 's/^v//')
|
|
100
|
-
if [ "$current_version" = "$version" ]; then
|
|
101
|
-
echo -e "$c**** Found Node.js at system path: $g$node_path$c ****$c0" >&2
|
|
102
|
-
else
|
|
103
|
-
echo -e "$y**** Warning: System Node.js version ($current_version) differs from target ($version) ****$c0" >&2
|
|
104
|
-
echo -e "$c**** Using system path anyway: $g$node_path$c ****$c0" >&2
|
|
105
|
-
fi
|
|
106
|
-
else
|
|
107
|
-
echo -e "$r**** Error: Could not find Node.js binary ****$c0" >&2
|
|
108
|
-
exit 1
|
|
109
|
-
fi
|
|
110
|
-
fi
|
|
111
|
-
|
|
112
|
-
echo "$node_path"
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
# Function to parse package.json
|
|
116
|
-
parse_package_json() {
|
|
117
|
-
local field="$1"
|
|
118
|
-
local package_file="$PROJECT_ROOT/package.json"
|
|
119
|
-
|
|
120
|
-
if [ ! -f "$package_file" ]; then
|
|
121
|
-
echo -e "$r**** Error: package.json not found at $package_file ****$c0" >&2
|
|
122
|
-
exit 1
|
|
123
|
-
fi
|
|
124
|
-
|
|
125
|
-
# Simple JSON parsing using node (execute from project root for proper require resolution)
|
|
126
|
-
local value=$(cd "$PROJECT_ROOT" && node -e "
|
|
127
|
-
try {
|
|
128
|
-
const pkg = require('./package.json');
|
|
129
|
-
console.log(pkg.$field || '');
|
|
130
|
-
} catch(e) {
|
|
131
|
-
process.exit(1);
|
|
132
|
-
}
|
|
133
|
-
" 2>/dev/null)
|
|
134
|
-
|
|
135
|
-
if [ $? -ne 0 ] || [ -z "$value" ]; then
|
|
136
|
-
echo -e "$r**** Error: Could not parse $field from package.json ****$c0" >&2
|
|
137
|
-
exit 1
|
|
138
|
-
fi
|
|
139
|
-
|
|
140
|
-
echo "$value"
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
# Function to get service name
|
|
144
|
-
get_service_name() {
|
|
145
|
-
if [ -n "$SERVICE_NAME" ]; then
|
|
146
|
-
echo "$SERVICE_NAME"
|
|
147
|
-
else
|
|
148
|
-
parse_package_json "name"
|
|
149
|
-
fi
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
# Function to detect port from config
|
|
153
|
-
detect_port() {
|
|
154
|
-
local port=""
|
|
155
|
-
|
|
156
|
-
if [ -n "$PORT" ]; then
|
|
157
|
-
port="$PORT"
|
|
158
|
-
else
|
|
159
|
-
# Try to get port from config using node (execute from project root for proper require resolution)
|
|
160
|
-
port=$(cd "$PROJECT_ROOT" && node -e 'try{const c=require("config");console.log(c.webServer?.port);}catch(e){import("config").then(c=>console.log(c.webServer?.port)).catch(()=>{});}' 2>/dev/null | grep -oE "[0-9]{2,5}" | head -n1)
|
|
161
|
-
|
|
162
|
-
if [ -z "$port" ]; then
|
|
163
|
-
echo -e "$r**** Error: Could not detect port from config ****$c0" >&2
|
|
164
|
-
exit 1
|
|
165
|
-
fi
|
|
166
|
-
fi
|
|
167
|
-
|
|
168
|
-
echo "$port"
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
# Function to generate systemd unit file
|
|
172
|
-
generate_unit_file() {
|
|
173
|
-
local service_name="$1"
|
|
174
|
-
local node_path="$2"
|
|
175
|
-
local main_file="$3"
|
|
176
|
-
local working_dir="$PROJECT_ROOT" # Always use project root as working directory
|
|
177
|
-
local serviceFile="/etc/systemd/system/${service_name}.service"
|
|
178
|
-
cat > "$serviceFile" << EOF
|
|
179
|
-
[Unit]
|
|
180
|
-
Description=$service_name
|
|
181
|
-
After=network.target
|
|
182
|
-
# https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html#StartLimitIntervalSec=interval
|
|
183
|
-
StartLimitIntervalSec=0
|
|
184
|
-
|
|
185
|
-
[Service]
|
|
186
|
-
User=root
|
|
187
|
-
WorkingDirectory=$working_dir
|
|
188
|
-
EnvironmentFile=$working_dir/.env
|
|
189
|
-
ExecStart=$node_path $main_file
|
|
190
|
-
Restart=always
|
|
191
|
-
RestartSec=3
|
|
192
|
-
|
|
193
|
-
[Install]
|
|
194
|
-
WantedBy=multi-user.target
|
|
195
|
-
EOF
|
|
196
|
-
|
|
197
|
-
echo -e "$c**** Generated unit file for $g$service_name$c ****$c0" >&2
|
|
198
|
-
echo -e "$lc WorkingDirectory: $g$working_dir$c0" >&2
|
|
199
|
-
echo -e "$lc ExecStart: $g$node_path $main_file$c0" >&2
|
|
200
|
-
echo -e "$lc View Service file: ${g}cat $serviceFile$c0" >&2
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
# Function to install service
|
|
204
|
-
install_service() {
|
|
205
|
-
echo -e "$c**** Installing service ****$c0"
|
|
206
|
-
|
|
207
|
-
# Detect Node.js version and path
|
|
208
|
-
local node_version=$(detect_node_version)
|
|
209
|
-
local node_path=$(find_node_path "$node_version")
|
|
210
|
-
|
|
211
|
-
# Get main entry point and service name
|
|
212
|
-
local main_file=$(parse_package_json "main")
|
|
213
|
-
local service_name=$(get_service_name)
|
|
214
|
-
|
|
215
|
-
echo -e "$c**** Service configuration ****$c0"
|
|
216
|
-
echo -e "$lc Service name: $g$service_name$c0"
|
|
217
|
-
echo -e "$lc Node.js version: $g$node_version$c0"
|
|
218
|
-
echo -e "$lc Node.js path: $g$node_path$c0"
|
|
219
|
-
echo -e "$lc Main file: $g$main_file$c0"
|
|
220
|
-
echo -e "$lc Project root: $g$PROJECT_ROOT$c0"
|
|
221
|
-
|
|
222
|
-
# Check if service already exists
|
|
223
|
-
if service_exists "$service_name"; then
|
|
224
|
-
echo -e "$c**** Service $g$service_name$c already installed ****$c0"
|
|
225
|
-
return 0
|
|
226
|
-
fi
|
|
227
|
-
|
|
228
|
-
# Generate and install unit file
|
|
229
|
-
generate_unit_file "$service_name" "$node_path" "$main_file"
|
|
230
|
-
|
|
231
|
-
# Reload systemd and enable service
|
|
232
|
-
systemctl daemon-reload
|
|
233
|
-
systemctl enable --now "$service_name"
|
|
234
|
-
|
|
235
|
-
if [ $? -eq 0 ]; then
|
|
236
|
-
echo -e "$c**** Service $g$service_name$c installed and started ****$c0"
|
|
237
|
-
echo ""
|
|
238
|
-
echo -e "${m}View status: ${y}systemctl -l status $service_name$c0"
|
|
239
|
-
echo -e "${m}View logs: ${y}journalctl -o cat -xefu $service_name$c0"
|
|
240
|
-
else
|
|
241
|
-
echo -e "$r**** Error: Failed to install service $service_name ****$c0"
|
|
242
|
-
exit 1
|
|
243
|
-
fi
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
# Function to delete service
|
|
247
|
-
delete_service() {
|
|
248
|
-
local service_name=$(get_service_name)
|
|
249
|
-
local port=$(detect_port)
|
|
250
|
-
|
|
251
|
-
echo -e "$c**** Removing service $g$service_name$c listening on port $g$port$c ****$c0"
|
|
252
|
-
|
|
253
|
-
if ! service_exists "$service_name"; then
|
|
254
|
-
echo -e "$c**** Service $g$service_name$c not found ****$c0"
|
|
255
|
-
return 0
|
|
256
|
-
fi
|
|
257
|
-
|
|
258
|
-
# Stop and disable service
|
|
259
|
-
systemctl stop "$service_name"
|
|
260
|
-
systemctl disable "$service_name"
|
|
261
|
-
|
|
262
|
-
# Remove unit file
|
|
263
|
-
rm -f "/etc/systemd/system/$service_name.service"
|
|
264
|
-
|
|
265
|
-
# Kill any remaining process on the port
|
|
266
|
-
local pid=$(lsof -i tcp:$port 2>/dev/null | grep $port | awk '{print $2}' | head -1)
|
|
267
|
-
if [ -n "$pid" ]; then
|
|
268
|
-
echo -e "$c**** Killing process $g$pid$c on port $g$port$c ****$c0"
|
|
269
|
-
kill -9 "$pid"
|
|
270
|
-
fi
|
|
271
|
-
|
|
272
|
-
# Reload systemd
|
|
273
|
-
systemctl daemon-reload
|
|
274
|
-
|
|
275
|
-
echo -e "$c**** Service $g$service_name$c removed ****$c0"
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
# Function to reinstall service
|
|
279
|
-
reinstall_service() {
|
|
280
|
-
echo -e "$c**** Reinstalling service ****$c0"
|
|
281
|
-
|
|
282
|
-
# Delete existing service
|
|
283
|
-
delete_service
|
|
284
|
-
|
|
285
|
-
# Install service
|
|
286
|
-
install_service
|
|
287
|
-
|
|
288
|
-
local service_name=$(get_service_name)
|
|
289
|
-
echo -e "$c**** Service $g$service_name$c reinstalled ****$c0"
|
|
290
|
-
|
|
291
|
-
# Show status and logs
|
|
292
|
-
systemctl status "$service_name"
|
|
293
|
-
echo ""
|
|
294
|
-
echo -e "${m}Following logs (Ctrl+C to exit): ${y}journalctl -o cat -xefu $service_name$c0"
|
|
295
|
-
journalctl -o cat -xefu "$service_name"
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
# Parse command line arguments
|
|
299
|
-
if [ $# -eq 0 ]; then
|
|
300
|
-
show_usage
|
|
301
|
-
exit 1
|
|
302
|
-
fi
|
|
303
|
-
|
|
304
|
-
# Parse command
|
|
305
|
-
case "$1" in
|
|
306
|
-
i|install)
|
|
307
|
-
COMMAND="install"
|
|
308
|
-
shift
|
|
309
|
-
;;
|
|
310
|
-
d|delete)
|
|
311
|
-
COMMAND="delete"
|
|
312
|
-
shift
|
|
313
|
-
;;
|
|
314
|
-
r|reinstall)
|
|
315
|
-
COMMAND="reinstall"
|
|
316
|
-
shift
|
|
317
|
-
;;
|
|
318
|
-
*)
|
|
319
|
-
echo -e "$r**** Error: Unknown command '$1' ****$c0"
|
|
320
|
-
show_usage
|
|
321
|
-
exit 1
|
|
322
|
-
;;
|
|
323
|
-
esac
|
|
324
|
-
|
|
325
|
-
# Parse options
|
|
326
|
-
while [[ $# -gt 0 ]]; do
|
|
327
|
-
case $1 in
|
|
328
|
-
-n)
|
|
329
|
-
SERVICE_NAME="$2"
|
|
330
|
-
shift 2
|
|
331
|
-
;;
|
|
332
|
-
-v)
|
|
333
|
-
NODE_VERSION="$2"
|
|
334
|
-
shift 2
|
|
335
|
-
;;
|
|
336
|
-
-p)
|
|
337
|
-
PORT="$2"
|
|
338
|
-
shift 2
|
|
339
|
-
;;
|
|
340
|
-
*)
|
|
341
|
-
echo -e "$r**** Error: Unknown option '$1' ****$c0"
|
|
342
|
-
show_usage
|
|
343
|
-
exit 1
|
|
344
|
-
;;
|
|
345
|
-
esac
|
|
346
|
-
done
|
|
347
|
-
|
|
348
|
-
# Execute command
|
|
349
|
-
case "$COMMAND" in
|
|
350
|
-
install)
|
|
351
|
-
install_service
|
|
352
|
-
;;
|
|
353
|
-
delete)
|
|
354
|
-
delete_service
|
|
355
|
-
;;
|
|
356
|
-
reinstall)
|
|
357
|
-
reinstall_service
|
|
358
|
-
;;
|
|
359
|
-
esac
|