forked from DataIntellectTech/TorQ
-
Notifications
You must be signed in to change notification settings - Fork 0
/
torq.sh
executable file
·422 lines (381 loc) · 17.3 KB
/
torq.sh
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
#!/bin/bash
if [ "-bash" = $0 ]; then
dirpath="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
else
dirpath="$(cd "$(dirname "$0")" && pwd)"
fi
if [ -z "$SETENV" ]; then
SETENV=${dirpath}/setenv.sh # set environment if not predefined
fi
if [ -z "$RLWRAP" ]; then
RLWRAP="rlwrap" # set environment if not predefined
fi
if [ -z "$QCON" ]; then
QCON="qcon" # set default value if not already defined
fi
if [ -z "$QCMD" ]; then # set default value if not already defined
QCMD="q"
fi
if [ -f $SETENV ]; then # check script exists
. $SETENV # load the environment
else
echo "ERROR: Failed to load environment - $SETENV: No such file or directory" # show input file error
exit 1
fi
hostips=`hostname -I`
hostnames=`hostname -A`
#hostips=`ip -4 addr show scope global | grep inet | awk '{print $2}' | cut -d '/' -f 1` # hostips for Arch based Linux distributions
#hostnames=`getent hosts $hostips | awk '{print $2}'` # hostnames for Arch based Linux distributions
findcsvcol() {
head -1 $CSVPATH | tr ',' '\012' | grep -wn $1 | cut -f 1 -d ':' # find column number of inputted header name
}
getfield() {
fieldno=$(awk -F, '{if(NR==1) for(i=1;i<=NF;i++){if($i=="'$2'") print i}}' "$CSVPATH") # get number for field based on headers
fieldval=$(awk -F, '{if(NR == '$1') print $'$fieldno'}' "$CSVPATH") # pull one field from one line of file
echo "$fieldval" | envsubst # substitute env vars
}
parameter() {
fieldval=$(getfield "$1" "$2")
if [[ ("" == "$fieldval") || ("0" == "$fieldval" && "localtime" == "$2") ]]; then # check for empty string or 0 for localtime
echo ""
else
echo " -""$2" "$fieldval"
fi
}
findproc() {
procno=$(awk '/,'$1',/{print NR}' "$CSVPATH") # get line number for file
pgrep -f "\-stackid ${KDBBASEPORT} \-proctype $(getfield "$procno" proctype) \-procname $1 " # get pid of process
}
startline() {
procno=$(awk '/,'$1',/{print NR}' "$CSVPATH") # get line number for file
proctype=$(getfield "$procno" "proctype") # get proctype for process
params="U localtime g T w load" # list of params to read from config
sline="${TORQHOME}/torq.q -stackid ${KDBBASEPORT} -proctype $proctype -procname $1" # base part of startup line
for p in $params; do # iterate over params
a=$(parameter "$procno" "$p"); # get param
sline="$sline$a"; # append to startup line
done
qcmd=$(getfield "$procno" "qcmd")
if [ -z "$qcmd" ]; then # if qcmd is undefined then default to $QCMD
qcmd="$QCMD"
fi
sline="$qcmd $sline $(getfield "$procno" extras) -procfile $CSVPATH $EXTRAS" # append csv file and extra arguments to startup line
echo "$sline"
}
start() {
procno=$(awk '/,'$1',/{print NR}' "$CSVPATH")
host=$(getfield "$procno" "host")
if [[ $host == "localhost" || $host == `hostname -i` ||
${hostips[@]} =~ $host || ${hostnames[@]} =~ $host ]]; then
if [[ -z $(findproc "$1") ]]; then # check process not running
sline=$(startline "$1") # line to run each process
echo "$(date '+%H:%M:%S') | Starting $1..."
eval "nohup $sline </dev/null >${KDBLOG}/torq${1}.txt 2>&1 &" # run in background and redirect output to log file
else
echo "$(date '+%H:%M:%S') | $1 already running"
fi
else
echo "$(date '+%H:%M:%S') | $1 configured with host that does not match current hostname"
fi
}
startqcon() {
portcol=$(findcsvcol "port"); # get port column number
port=$(($(grep -w $1 $CSVPATH | cut -f $portcol -d ','|sed 's/[{}]//g'))); # port in format for evaluation
accesscmd="$RLWRAP $QCON :$port:$2"; # build command line equivalent of qcon
echo "Attempting to connect to $1..."; # user connection message
$accesscmd; # run command line
}
print() {
sline=$(startline "$1") # line to run each process
echo "Start line for $1:"
echo "nohup $sline </dev/null >${KDBLOG}/torq${1}.txt 2>&1 &" # echo not evaluate to print
}
debug() {
procno=$(awk '/,'$1',/{print NR}' "$CSVPATH")
host=$(getfield "$procno" "host")
if [[ $host == "localhost" || $host == `hostname -i` ||
${hostips[@]} =~ $host || ${hostnames[@]} =~ $host ]]; then
if [[ -z $(findproc "$1") ]]; then
sline=$(startline "$1") # get start line for process
printf "$(date '+%H:%M:%S') | Executing...\n$sline -debug\n\n"
eval "$RLWRAP $sline -debug" # append flag to start in debug mode
else
echo "$(date '+%H:%M:%S') | Debug failed - $1 already running"
fi
else
echo "$(date '+%H:%M:%S') | $1 configured with host that does not match current hostname"
fi
}
summary() {
procno=$(awk '/,'$1',/{print NR}' "$CSVPATH")
host=$(getfield "$procno" "host")
if [[ $host == "localhost" || $host == `hostname -i` || # check if process is configured to run on current host
${hostips[@]} =~ $host || ${hostnames[@]} =~ $host ]]; then
if [[ -z $(findproc "$1") ]]; then # check process not running
printf "%s | %s | down |" "$(date '+%H:%M:%S')" "$1" # summary table row for down process
else
pid=$((findproc "$1")|awk 'END{print}')
port=$(echo $(netstat -nlp 2>/dev/null | grep " $pid/" | awk '{ print $4 }' | awk -F: '{ print $2 }')) # get port process is running on
printf "%s | %s | up | %s | %s" "$(date '+%H:%M:%S')" "$1" "$pid" "$port" # summary table row for running process
fi
fi
}
top() {
pid=$(findproc "$1");
if [[ -z $pid ]]; then
echo "ERROR: Cannot run top because process is not running";
else
$QCMD ${KDBCODE}/profiler/top.q $pid;
fi
}
stop() {
procno=$(awk '/,'$1',/{print NR}' "$CSVPATH")
host=$(getfield "$procno" "host")
if [[ $host == "localhost" || $host == `hostname -i` ||
${hostips[@]} =~ $host || ${hostnames[@]} =~ $host ]]; then
kcmd="kill -15"
else
kcmd="$cmd"
fi
if [[ -z $(findproc "$1") ]]; then
echo "$(date '+%H:%M:%S') | $1 is not currently running"
else
echo "$(date '+%H:%M:%S') | Shutting down $1..."
procno=$(awk '/,'$1',/{print NR}' "$CSVPATH")
port=$(getfield "$procno" port)
# check if port is numerical, if not it is an expression that needs evaluated
if [[ ! $port =~ ^[0-9]+$ ]]; then
port=$(($(eval echo \$$port)))
fi
eval "$kcmd `lsof -i :$port -sTCP:LISTEN | awk '{if(NR>1)print $2}'`"
fi
}
getall() {
procs=$(awk -F, '{if(NR>1) print $4}' "$CSVPATH") # get all processes from csv
start=""
for a in $procs; do
procno=$(awk '/,'$a',/{print NR}' "$CSVPATH") # get line number for file
f=$(getfield "$procno" startwithall)
if [[ "1" == "$f" ]]; then # checks csv column startwithall equals 1
start="$start $a"
fi
done
echo "$start"
}
checkinput() {
input=$* # get all input process names
PROCS=$(awk -F, '{if(NR>1) print $4}' "$CSVPATH") # get all process names from csv
avail=()
for i in $input; do
if [[ $i == "-force" ]]; then # check for force flag
:
elif [[ $(echo "$PROCS" | grep -w "$i") ]]; then # check input process is valid
avail+="$i " # get only valid processes
else
echo "$(date '+%H:%M:%S') | $i failed - unavailable processname"
fi
done
PROCS=$avail # assign valid processes
}
getprocs() {
if [[ "$2" == "all" ]]; then
PROCS=$(getall) # get all processes
else
shift # ignore first argument
checkinput "$@" # check input process names
fi
}
flag() {
count=0
for i in ${BASH_ARGV[*]}; do
count=$((count+1))
if [[ $i == "-$1" ]]; then # find flag argument in command line
N=$((count-2)) # find index of flag arugment
fi
done
}
flagextras() {
flag "$*"
z=$N
while [ $z -ge 0 ]; do
EXTRAS+="${BASH_ARGV[$z]} " # get all parameters following extras flag
z=$((z-1))
done
}
flagcsv() {
flag "$*"
CSVPATH="${BASH_ARGV[$N]}" # assign specifed csv file
}
getextras() {
if [[ $(echo ${BASH_ARGV[*]} | grep -e extras) ]]; then
eval flagextras "extras"; # get arguments following flag
length=$(($#-N-2)); # number of arguments minus extras
array=${*:1:$length}; # arguments without extras
else
array=$*;
fi
}
getcsv() {
if [[ $(echo ${BASH_ARGV[*]} | grep -e csv) ]]; then
eval flagcsv "csv"; # get csv file following flag
length=$(($#-2)); # number of arguments minus csv
array=${*:1:$length}; # arguments without csv
getprocs $array;
else
CSVPATH=${TORQPROCESSES}; # set csv file to default
getprocs $array;
fi
}
getextrascsv() {
eval flagextras "extras"; # get arguments following flag
eval flagcsv "csv";
length=$(($#-N-2));
array=${*:1:$length}; # arguments without extras and csv
getprocs $array; # get process names from the remaining arguments
}
checkextrascsv() {
if [[ $(echo ${BASH_ARGV[*]} | grep -e extras) ]] && [[ $(echo ${BASH_ARGV[*]} | grep -e csv) ]]; then
getextrascsv $@; # gets extras and csv arguments
else
getextras $@; # checks if extras flag present
getcsv $@; # sets process csv file
fi
}
allcsv() {
if [[ $(echo ${BASH_ARGV[*]} | grep -e csv) ]]; then
eval flagcsv "csv"; # get all procs from csv without starting
else
CSVPATH=${TORQPROCESSES};
fi
}
startprocs() {
checkextrascsv "$*"; # checks if extra flags/csv included
for p in $PROCS; do
start "$p"; # start each process in variable
done
}
runtop() {
checkextrascsv "$*";
if [[ $(echo $PROCS | wc -w) -gt 1 ]] || [[ $(echo $input|wc -w) -ne 1 ]]; then
echo "ERROR: Cannot run top command for more than one process at a time"
else
for p in $PROCS; do
top "$p";
done
fi
}
stopprocs() {
if [[ $(echo ${BASH_ARGV[*]} | grep -e -force) ]]; then # check for force flag
cmd="kill -9"
echo "Force stop has been set"
else
cmd="kill -15"
fi
checkextrascsv $@; # checks if extra flags/csv included
for p in $PROCS; do
stop "$p"; # kill each process in variable
done
}
runprint() {
checkextrascsv "$*"; # checks if extra flags/csv included
for p in $PROCS; do
print "$p";
done
}
rundebug() {
checkextrascsv "$*"; # checks if extra flags/csv included
if [[ $(echo $PROCS | wc -w) -gt 1 ]] || [[ $(echo $input|wc -w) -ne 1 ]]; then
echo "ERROR: Cannot debug more than one process at a time"
else
for p in $PROCS; do
debug "$p";
done
fi
}
runsummary() {
allcsv "$*";
PROCS=$(awk -F, '{if(NR>1) print $4}' "$CSVPATH");
out="TIME | PROCESS | STATUS | PID | PORT"
for p in $PROCS; do
out="${out}\n$(summary "$p")";
done
echo -e $out | column -t
}
showprocs() {
allcsv "$*";
awk -F, '{if(NR>1) print $4}' "$CSVPATH" | tr " " "\n"
}
runqcon() {
CSVPATH=${TORQPROCESSES}
PROCS=$(awk -F, '{if(NR>1) print $4}' "$CSVPATH")
if [[ $(echo "$PROCS" | grep -w "$2") ]]; then
PROCS=$2
else
PROCS=()
fi
if [[ $# -gt 3 ]]; then
echo "ERROR: Cannot qcon more than one process at a time"
elif [[ $# -lt 3 ]] || [[ $(echo $PROCS | wc -w) -ne 1 ]]; then
echo "Requires arguments qcon <processname> <username>:<password>"
else
for p in $PROCS; do
startqcon $p $3;
done
fi
}
usage() {
printf -- "Arguments:\n"
printf -- " start all|<processname(s)> to start all|process(es)\n"
printf -- " stop all|<processname(s)> to stop all|process(es)\n"
printf -- " print all|<processname(s)> to view default startup lines\n"
printf -- " debug <processname(s)> to debug a single process\n"
printf -- " qcon <processname> <username>:<password> to qcon process\n"
printf -- " procs to list all processes\n"
printf -- " summary to view summary table\n"
printf -- " top <processname> to show top.q statistics for a single process\n"
printf -- "Optional flags:\n"
printf -- " -csv <fullcsvpath> to run a different csv file\n"
printf -- " -extras <args> to add/overwrite extras to the start line\n"
printf -- " -csv <fullcsvpath> -extras <args> to run both\n"
printf -- " -force to force stop process(es) using kill -9\n"
exit 1
}
case $1 in
start)
startprocs "$*";
;;
print)
runprint "$*";
;;
stop)
stopprocs "$@";
;;
restart)
checkextrascsv "$*";
echo Restarting $PROCS...
stopprocs "$@";
startprocs "$*";
;;
top)
runtop "$@";
;;
debug)
rundebug "$@";
;;
summary)
runsummary "$*";
;;
procs)
showprocs "$*";
;;
qcon)
runqcon "$@";
;;
"")
usage
;;
*)
echo "ERROR: Invalid argument(s)"
exit 1
;;
esac