Small sh "framework" to test some server responses
sh
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

check.sh 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. #!/bin/sh
  2. #check.sh : functionnal check functions for various server
  3. #Copyright (C) 2016 Weber Yann
  4. #
  5. #This program is free software; you can redistribute it and/or modify
  6. #it under the terms of the GNU General Public License as published by
  7. #the Free Software Foundation; either version 3 of the License, or
  8. #any later version.
  9. #
  10. #This program is distributed in the hope that it will be useful,
  11. #but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. #GNU General Public License for more details.
  14. #
  15. #You should have received a copy of the GNU General Public License
  16. #along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. alias echo="/bin/echo -e"
  18. color=1
  19. verbose=2
  20. exit_on_fail=0
  21. col_reset() {
  22. if [ "$color" -gt 0 ]
  23. then
  24. tput sgr0
  25. fi
  26. }
  27. col_set() {
  28. if [ -z "$1" ]
  29. then
  30. return
  31. fi
  32. if [ "$color" -gt 0 ]
  33. then
  34. tput setaf $1
  35. fi
  36. }
  37. log() {
  38. echo "$(col_set $3)[$(printf "%7s" "$1")]$(col_reset) $2"
  39. }
  40. datetime() {
  41. date -Iseconds
  42. }
  43. logdate() {
  44. echo "$(date -Iseconds) $(col_set $3)[$(printf "%7s" "$1")]$(col_reset) $2"
  45. }
  46. fail() {
  47. if [ "$verbose" -lt 2 ]
  48. then
  49. echo "" #for the dot printed with -n
  50. fi
  51. test_msg="$1"
  52. test_status=1
  53. }
  54. err() {
  55. msg="$(log ERR "$1" 1)"
  56. test_msg="$1"
  57. test_status=-1
  58. }
  59. success() {
  60. msg="$(log OK "$1" 2)"
  61. test_msg="$1"
  62. test_status=0
  63. }
  64. #
  65. # Tests & testcase functions
  66. #
  67. tc_name=""
  68. tc_infos=""
  69. tc_fail=0
  70. tc_run=0
  71. total_fail=0
  72. total_run=0
  73. test_msg=""
  74. test_status=0
  75. _test_setup() {
  76. test_status=0
  77. test_msg=""
  78. }
  79. TC_INIT() {
  80. tc_name=$1
  81. tc_infos=$2
  82. tc_fail=0
  83. tc_run=0
  84. msg="Running testcase '$tc_name'"
  85. if [ -n "$tc_infos" ]
  86. then
  87. msg="${msg} ($tc_infos)"
  88. fi
  89. if [ "$verbose" -gt 0 ]
  90. then
  91. logdate TESTCASE "$msg" 4
  92. fi
  93. }
  94. TC_END() {
  95. if [ "$tc_fail" -gt 0 ]
  96. then
  97. if [ "$verbose" -gt 1 ]
  98. then
  99. logdate TESTCASE "-------------$tc_name END------------" 1
  100. fi
  101. logdate FAIL "Testcase '$tc_name' tests: ${tc_run} fails: $(col_set 1)${tc_fail}$(col_reset)" 1
  102. if [ "$exit_on_fail" -ne 0 ]
  103. then
  104. CHECK_REPORT
  105. fi
  106. elif [ "$verbose" -eq 1 ]
  107. then
  108. echo "" #for the dot printed with -n
  109. logdate TESTCASE "Testcase '$tc_name' tests:${tc_run} fails: $tc_fail" 2
  110. elif [ "$verbose" -gt 1 ]
  111. then
  112. logdate TESTCASE "-------------$tc_name END------------" 4
  113. fi
  114. tc_name=""
  115. tc_infos=""
  116. tc_fail=0
  117. tc_run=0
  118. }
  119. TC_RUN() {
  120. _test_setup
  121. cmd=$1
  122. shift
  123. args=""
  124. case $#
  125. in
  126. 1)$cmd "$1";;
  127. 2)$cmd "$1" "$2";;
  128. 3)$cmd "$1" "$2" "$3";;
  129. 4)$cmd "$1" "$2" "$3" "$4";;
  130. *)fail "To many arguments for $cmd"
  131. esac
  132. #$cmd $args
  133. tc_run=$(expr $tc_run + 1)
  134. total_run=$(expr $total_run + 1)
  135. if [ "$test_status" -ne 0 ]
  136. then
  137. err_type="FAIL"
  138. if [ "$test_status" -lt 0 ]
  139. then
  140. err_type="ERR"
  141. fi
  142. tc_fail=$(expr $tc_fail + 1)
  143. total_fail=$(expr $total_fail + 1)
  144. logdate $err_type "$tc_name: $test_msg" 1 >&2
  145. elif [ "$verbose" -gt 1 ]
  146. then
  147. logdate OK "$tc_name: $test_msg" 2
  148. else
  149. echo -n '.'
  150. fi
  151. }
  152. CHECK_START() {
  153. logdate STATUS "Starting tests" 3
  154. }
  155. CHECK_REPORT() {
  156. if [ "$verbose" -eq 0 -a "$tc_fail" -eq "0" ]
  157. then
  158. echo "" # for dot printed with -n
  159. fi
  160. if [ "$verbose" -gt 0 ]
  161. then
  162. logdate STATUS "All tests done" 3
  163. fi
  164. if [ "$total_fail" -gt 0 ]
  165. then
  166. logdate FAIL "Summary : tests: ${total_run} fails: $(col_set 1)${total_fail}$(col_reset)" 1
  167. exit 1
  168. else
  169. logdate OK "Summary : tests:${total_run} fails: $total_fail" 2
  170. exit 0
  171. fi
  172. }
  173. #
  174. # HTTP/HTTPS tests
  175. #
  176. _check_http_status() {
  177. # $1 url
  178. # $2 status
  179. # $* curl options
  180. url=$1
  181. shift 1
  182. expt=$1
  183. if [ -z "$1" ]
  184. then
  185. expt=200
  186. fi
  187. shift 1
  188. status=$(curl -s -o /dev/null -w "%{http_code}" $* $url)
  189. if [ "$status" -ne "$expt" ]
  190. then
  191. fail "Check http status $expt for $url : $status returned"
  192. elif [ "$verbose" -gt 0 ]
  193. then
  194. success "Check http status $status for $url"
  195. fi
  196. }
  197. check_http_status() {
  198. # $1 url
  199. # $2 status
  200. _check_http_status http://$1 $2
  201. }
  202. check_http_200() {
  203. _check_http_status http://$1 200
  204. }
  205. check_https_status() {
  206. # $1 url
  207. # $2 status
  208. _check_http_status https://$1 $2
  209. }
  210. check_https_200() {
  211. _check_http_status https://$1 200
  212. }
  213. check_https_cert() {
  214. # Check that SSL Cert is valid
  215. # $1 URL
  216. status=$(curl -s -o /dev/null -w "%{http_code}" https://$1)
  217. rep=$?
  218. if [ "$rep" -eq 0 ]
  219. then
  220. success "https://$1 cert verified"
  221. return
  222. fi
  223. status=$(curl -k -s -o /dev/null -q "%{http_code}" https://$1)
  224. rep=$?
  225. if [ "$rep" -eq 0 ]
  226. then
  227. fail "https://$1 cert invalid"
  228. else
  229. err "Unable to curl https://$1"
  230. fi
  231. }
  232. check_html_title() {
  233. url="$1"
  234. expt="$2"
  235. tmpxsl=$(mktemp -t XSL.XXXXXXXXXXX)
  236. echo '<?xml version="1.0"?>
  237. <xsl:stylesheet version="1.0"
  238. xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  239. <xsl:output method = "text"/>
  240. <xsl:template match="/">
  241. <xsl:value-of select="/html/head/title"/>
  242. </xsl:template>
  243. </xsl:stylesheet>' > $tmpxsl
  244. tmphtml=$(mktemp -t html.XXXXXXXXX)
  245. curl --silent $url > $tmphtml
  246. title=$(xsltproc --html --novalid $tmpxsl $tmphtml 2>/dev/null)
  247. if [ "$?" -ne "0" ]
  248. then
  249. title=$(xsltproc --novalid $tmpxsl $tmphtml 2>/dev/null)
  250. fi
  251. if [ "$title" = "$expt" ]
  252. then
  253. success "$url HTML title is '$expt'"
  254. else
  255. fail "$url HTML title is '$title' but '$expt' expected"
  256. fi
  257. rm $tmpxsl $tmphtml 2>/dev/null
  258. }
  259. check_audiostream() {
  260. # Uses mplayer to fetch 128Kb of stream
  261. # $1 Stream URL
  262. tmpfile=$(mktemp -t check_audiostream.XXXXXXXXX)
  263. sz="128kb"
  264. if [ "$verbose" -gt 1 ]
  265. then
  266. logdate INFO "$tc_name: Running mplayer on '$1' for $sz" 3
  267. fi
  268. mplayer -endpos $sz -ao pcm:file=$tmpfile "$1" 1>/dev/null 2>/dev/null
  269. res=$?
  270. bytes=$(du $tmpfile | cut -f1)
  271. rm $tmpfile 2>/dev/null
  272. if [ "$bytes" -lt 1024 ]
  273. then
  274. fail "mplayer retrieved ${bytes}B of stream instead of expected $sz"
  275. return
  276. fi
  277. if [ "$res" -eq 0 ]
  278. then
  279. success "mplayer retrieved $sz of stream on $1"
  280. else
  281. fail "mplayer failed to retrieve stream on $1"
  282. fi
  283. }
  284. check_ping() {
  285. ns=$1
  286. count=$2
  287. if [ -z "$count" ]
  288. then
  289. count=5
  290. fi
  291. ping -i 0.2 -c $count $ns 2>/dev/null >/dev/null
  292. res=$?
  293. if [ "$res" -ne 0 ]
  294. then
  295. fail "unable to ping '$ns'"
  296. else
  297. success "successfully send $count ping to '$ns'"
  298. fi
  299. }
  300. check_git_repo() {
  301. tmpdir=$(mktemp -d -t check_git.XXXXXXXXX)
  302. git clone $1 $tmpdir 2>/dev/null 1>/dev/null
  303. res=$?
  304. rm -Rf $tmpdir
  305. if [ "$res" -ne 0 ]
  306. then
  307. fail "unable to clone git repo '$1'"
  308. else
  309. success "git repo '$1' cloned'"
  310. fi
  311. }
  312. #
  313. # Jabber XMPP checks
  314. #
  315. __xmpp_probe() {
  316. serv=$1
  317. timeout=$2
  318. type=$3
  319. payload="<?xml version=\"1.0\"?>\n<stream:stream xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\" xmlns=\"jabber:$type\" to=\"${1}\" xml:lang=\"en\" xmlns:xml=\"http://www.w3.org/XML/1998/namespace\">\n"
  320. if [ "$verbose" -gt 2 ]
  321. then
  322. echo -e $payload | sed -e "s/^/$(datetime) [ DEBUG] Sent : /" >&2
  323. fi
  324. echo -e $payload
  325. sleep $timeout
  326. }
  327. _xmpp_probe() {
  328. serv=$1
  329. port=$2
  330. timeout=$3
  331. type=$4
  332. tmpres=$(mktemp -t xmpp_probe.XXXXXXXXX)
  333. echo "$(__xmpp_probe $serv $timeout $type| nc -q2 $serv $port)</stream:stream>" | xmllint --format - > $tmpres
  334. if [ "$verbose" -gt 2 ]
  335. then
  336. cat $tmpres | sed -e "s/^/$(datetime) [ DEBUG] Recv : /" >&2
  337. fi
  338. cat $tmpres
  339. rm $tmpres
  340. }
  341. _check_xmpp_ns() {
  342. ns1=$1
  343. expt_ns=$2
  344. expt_port=$3
  345. dnsq="_xmpp-${4}._tcp.$1"
  346. rep="$(dig $dnsq srv +short | cut -d" " -f3,4)"
  347. if [ "$rep" = "$expt_port ${expt_ns}." ]
  348. then
  349. success "$dnsq = '$rep'"
  350. else
  351. fail "$dnsq = '$rep' but '$expt_port ${expt_ns}.' expected"
  352. fi
  353. }
  354. check_xmpp_serv_ns() {
  355. _check_xmpp_ns "$1" "$2" "$3" "server"
  356. }
  357. check_xmpp_client_ns() {
  358. _check_xmpp_ns "$1" "$2" "$3" "client"
  359. }
  360. _check_xmpp_server() {
  361. serv=$1
  362. port=$2
  363. timeout=$3
  364. type=$4
  365. if [ -z "$port" ]
  366. then
  367. port=5222
  368. fi
  369. if [ -z "$timeout" ]
  370. then
  371. timeout=2
  372. fi
  373. if [ "$verbose" -gt 1 ]
  374. then
  375. tpe="client"
  376. if [ "$type" = "server" ]
  377. then
  378. tpe="S2S"
  379. fi
  380. logdate INFO "$tc_name: Connecting to XMPP $serv $tpe port $port (timeout=${timeout}s)" 3
  381. fi
  382. stream=$(_xmpp_probe $serv $port $timeout $type| head -n2 | tail -n1)
  383. if [ -z "$stream" ]
  384. then
  385. fail "Empty reply from $serv:$port"
  386. return
  387. fi
  388. if [ "$type" = "client" ]
  389. then
  390. infos=$(echo $stream | sed -E 's/^<([^ ]+).* xmlns="([^"]+)".* from="([^"]+)" .*$/\1 \2 \3/')
  391. else
  392. infos="$(echo $stream | sed -E 's/^<([^ ]+).* xmlns="([^"]+)" .*$/\1 \2/') $serv"
  393. fi
  394. if [ "$(echo $infos | cut -d ' ' -f1,2)" = "stream:stream jabber:$type" ]
  395. then
  396. if [ "$(echo $infos | cut -d ' ' -f3)" = "$serv" ]
  397. then
  398. success "Successfully connected to XMPP $type $serv:$port"
  399. else
  400. fail "Server $serv:$port announce itself as $(echo $infos | cut -f3)"
  401. fi
  402. else
  403. fail "Unexpected reply from $serv:$port : $infos"
  404. fi
  405. }
  406. check_xmpp_server_client() {
  407. _check_xmpp_server "$1" "$2" "$3" "client"
  408. }
  409. check_xmpp_server_s2s() {
  410. _check_xmpp_server "$1" "$2" "$3" "server"
  411. }
  412. check_xmpp_ssl() {
  413. serv=$1
  414. port=$2
  415. if [ -z "$port" ]
  416. then
  417. port=5222
  418. fi
  419. openssl s_client -connect $serv:$port </dev/null -starttls xmpp >/dev/null 2>/dev/null
  420. rep=$?
  421. if [ "$rep" -eq 0 ]
  422. then
  423. success "Openssl successfully negociating XMPP ssl with $serv:$port"
  424. else
  425. fail "Openssl failed negociating XMPP ssl with $serv:$port"
  426. fi
  427. }
  428. #
  429. # SSH checks
  430. #
  431. check_ssh_nc() {
  432. host=$1
  433. port=$2
  434. if [ -z "$port" ]
  435. then
  436. port=22
  437. fi
  438. rep="$(nc -q1 z3.zered.net $port </dev/null)"
  439. res=$?
  440. if [ "$res" -ne "0" ]
  441. then
  442. fail "Netcat unable to connect to $host:$port"
  443. return
  444. fi
  445. if echo $rep | grep "^SSH-2.0-OpenSSH" >/dev/null
  446. then
  447. success "OpenSSH replied on $host:$port"
  448. else
  449. fail "Bad replie from $host:$port : '$rep'"
  450. fi
  451. }