-
Notifications
You must be signed in to change notification settings - Fork 1
/
syncd_spawn
executable file
·165 lines (142 loc) · 3.8 KB
/
syncd_spawn
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
#!/bin/bash
# Author: Pradeep Jindal <pradeep@helpshift.com>
# Description: Amazing little tool, read the code and know what it does
function usage() {
cat <<END
Spawns the given command only if it can acquire (create) the given node in ZK.
Waits on if the given node already exists or exits with error otherwise, simple as that.
Useful for running programs in distributed environments where the runs need to be synchronized.
$0 -n NODE -C CONTENT [options] <COMMAND>
-d run in debug mode, prints lot of information for debugging
-c LOCKPICKCMD path to lockpick command, default is lockpick cmd in your PATH
-s ZK_SERVERS zk servers to connect to host1[:port1][,host2[:port2]]... format, default is localhost:2181
-r PATH zk chroot to use, default is /devops
-S SECONDS numbers of seconds to wait between retrying for a lock, default is 5 seconds
-i RETRIES number of times to retry acquiring lock, default is infinite
-n NODE zk node path to lock, for example /service/api, REQUIRED
-l LOCKTYPE lock type to use, options are: [lock, rlock, wlock], REQUIRED
-C CONTENT content to put in the zk node, useful for debugging/informative purposes, REQUIRED
END
}
while getopts 'c:s:r:i:S:n:l:C:hd' opts
do
case $opts in
c)
LOCKPICKCMD="$OPTARG";;
s)
ZK_SERVERS="$OPTARG";;
r)
ZKCHROOT="$OPTARG";;
S)
SLEEP="$OPTARG";;
n)
NODE="$OPTARG";;
l)
LOCKTYPE="$OPTARG";;
C)
CONTENT="$OPTARG";;
i)
RETRIES="$OPTARG";;
d)
export DEBUG="yes";;
h|*)
usage; exit 1;;
esac
done
# Take rest of args as the command
shift $(($OPTIND -1))
if echo "$*" | grep -qE '\S+';then
COMMAND="$*"
fi
if [ -z "$NODE" -o -z "$LOCKTYPE" -o -z "$CONTENT" -o -z "$COMMAND" ];then
echo
echo "ERROR: -n -C -l & COMMAND are mandatory"
echo
usage
exit 1
fi
if [[ ! "$LOCKTYPE" =~ [rw]?lock ]]; then
echo "ERROR: Unknown -l LOCKTYPE '$LOCKTYPE' passed"
echo "Usage: "
usage
exit 1
fi
## Set vars
ZKCHROOT="${ZKCHROOT:-/devops}"
ZK_SERVERS="${ZK_SERVERS:-localhost:2181}"
LOCKPICKCMD="${LOCKPICKCMD:-lockpick}"
LOCKPICK="$LOCKPICKCMD -s $ZK_SERVERS -c $ZKCHROOT"
SLEEP="${SLEEP:-5}"
RETRIES="${RETRIES:-3}"
## Functions
function runit() {
[[ -n "$NOOUT" ]] && OUTREDIRECT=' >/dev/null 2>&1' || OUTREDIRECT=""
CMD="${@}${OUTREDIRECT}"
eval "$CMD"
RET=$?
[[ -n "$DEBUG" ]] && echo "Executed: '$CMD', exited with $RET"
return $RET
}
function _lockpick_lock() {
local LOCK_TYPE=$1
local NODE="${2%/}"
local CONTENT="$3"
local RETRIES=${4:-1}
local SLEEP=${5:-5}
CMDOUT="$(runit $LOCKPICK -i "'$CONTENT'" -r $RETRIES -p $SLEEP $LOCK_TYPE $NODE)"
if [[ $? -eq 0 ]]; then
# stdout should only contain the ZK LOCKPATH
echo "Got lock on $NODE" >&2
echo $CMDOUT
else
echo "Couldn't lock '$NODE': $CMDOUT" >&2
return 1
fi
}
function lockpick_wlock() {
_lockpick_lock wlock "$@"
return $?
}
function lockpick_rlock() {
_lockpick_lock rlock "$@"
return $?
}
function lockpick_lock() {
lockpick_wlock "$@"
return $?
}
function lockpick_unlock() {
local NODE="${1%/}"
local VERIFY_DATA="$2"
if [[ -n $VERIFY_DATA ]]; then
VERIFY_DATA_OPTS="-i '$VERIFY_DATA'"
else
VERIFY_DATA_OPTS=""
fi
runit $LOCKPICK $VERIFY_DATA_OPTS unlock $NODE
RET=$?
if [[ $RET -ne 0 ]]; then
echo "Couldn't unlock '$NODE'"
else
echo "Unlocked '$NODE'"
fi
return $RET
}
function lock_cleanup() {
lockpick_unlock "$1" "$2"
}
function runcmd() {
echo "Running your command $COMMAND"
runit $COMMAND
export COMMAND_EXIT=$?
exit $COMMAND_EXIT
}
## MAIN
LOCKPATH=$(lockpick_$LOCKTYPE "$NODE" "$CONTENT" "$RETRIES" "$SLEEP")
if [[ $? -eq 0 ]]; then
# The following handles SIGINT and SIGTERM along with normal EXIT
trap 'lock_cleanup $LOCKPATH "$CONTENT"' EXIT
runcmd
else
exit 1
fi