master
sh 158 lines 3.79 KB
Raw
1 #!/usr/bin/env bash
2
3 # SPDX-License-Identifier: GPL-3.0-or-later
4
5 # This is a simple exporting proxy, written in BASH, using the nc command.
6 # Run the script without any parameters for help.
7
8 MODE="${1}"
9 MY_PORT="${2}"
10 EXPORTING_HOST="${3}"
11 EXPORTING_PORT="${4}"
12 FILE="${NETDATA_NC_EXPORTING_DIR-/tmp}/netdata-nc-exporting-${MY_PORT}"
13
14 log() {
15 logger --stderr --id=$$ --tag "netdata-nc-exporting" "${*}"
16 }
17
18 mync() {
19 local ret
20
21 log "Running: nc ${*}"
22 nc "${@}"
23 ret=$?
24
25 log "nc stopped with return code ${ret}."
26
27 return ${ret}
28 }
29
30 listen_save_replay_forever() {
31 local file="${1}" port="${2}" real_exporting_host="${3}" real_exporting_port="${4}" ret delay=1 started ended
32
33 while true
34 do
35 log "Starting nc to listen on port ${port} and save metrics to ${file}"
36
37 started=$(date +%s)
38 mync -l -p "${port}" | tee -a -p --output-error=exit "${file}"
39 ended=$(date +%s)
40
41 if [ -s "${file}" ]
42 then
43 if [ -n "${real_exporting_host}" ] && [ -n "${real_exporting_port}" ]
44 then
45 log "Attempting to send the metrics to the real external database at ${real_exporting_host}:${real_exporting_port}"
46
47 mync "${real_exporting_host}" "${real_exporting_port}" <"${file}"
48 ret=$?
49
50 if [ ${ret} -eq 0 ]
51 then
52 log "Successfully sent the metrics to ${real_exporting_host}:${real_exporting_port}"
53 mv "${file}" "${file}.old"
54 touch "${file}"
55 else
56 log "Failed to send the metrics to ${real_exporting_host}:${real_exporting_port} (nc returned ${ret}) - appending more data to ${file}"
57 fi
58 else
59 log "No external database configured - appending more data to ${file}"
60 fi
61 fi
62
63 # prevent a CPU hungry infinite loop
64 # if nc cannot listen to port
65 if [ $((ended - started)) -lt 5 ]
66 then
67 log "nc has been stopped too fast."
68 delay=30
69 else
70 delay=1
71 fi
72
73 log "Waiting ${delay} seconds before listening again for data."
74 sleep ${delay}
75 done
76 }
77
78 if [ "${MODE}" = "start" ]
79 then
80
81 # start the listener, in exclusive mode
82 # only one can use the same file/port at a time
83 {
84 flock -n 9
85 # shellcheck disable=SC2181
86 if [ $? -ne 0 ]
87 then
88 log "Cannot get exclusive lock on file ${FILE}.lock - Am I running multiple times?"
89 exit 2
90 fi
91
92 # save our PID to the lock file
93 echo "$$" >"${FILE}.lock"
94
95 listen_save_replay_forever "${FILE}" "${MY_PORT}" "${EXPORTING_HOST}" "${EXPORTING_PORT}"
96 ret=$?
97
98 log "listener exited."
99 exit ${ret}
100
101 } 9>>"${FILE}.lock"
102
103 # we can only get here if ${FILE}.lock cannot be created
104 log "Cannot create file ${FILE}."
105 exit 3
106
107 elif [ "${MODE}" = "stop" ]
108 then
109
110 {
111 flock -n 9
112 # shellcheck disable=SC2181
113 if [ $? -ne 0 ]
114 then
115 pid=$(<"${FILE}".lock)
116 log "Killing process ${pid}..."
117 kill -TERM "-${pid}"
118 exit 0
119 fi
120
121 log "File ${FILE}.lock has been locked by me but it shouldn't. Is a collector running?"
122 exit 4
123
124 } 9<"${FILE}.lock"
125
126 log "File ${FILE}.lock does not exist. Is a collector running?"
127 exit 5
128
129 else
130
131 cat <<EOF
132 Usage:
133
134 "${0}" start|stop PORT [EXPORTING_HOST EXPORTING_PORT]
135
136 PORT The port this script will listen
137 (configure netdata to use this as an external database)
138
139 EXPORTING_HOST The real host for the external database
140 EXPORTING_PORT The real port for the external database
141
142 This script can act as fallback database for netdata.
143 It will receive metrics from netdata, save them to
144 ${FILE}
145 and once netdata reconnects to the real external database,
146 this script will push all metrics collected to the real
147 external database too and wait for a failure to happen again.
148
149 Only one netdata can connect to this script at a time.
150 If you need fallback for multiple netdata, run this script
151 multiple times with different ports.
152
153 You can run me in the background with this:
154
155 screen -d -m "${0}" start PORT [EXPORTING_HOST EXPORTING_PORT]
156 EOF
157 exit 1
158 fi