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 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  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. if [ -z "$color" ]
  18. then
  19. color=1
  20. fi
  21. if [ -z "$verbose" ]
  22. then
  23. verbose=1
  24. fi
  25. if [ -z "$exit_on_fail" ]
  26. then
  27. exit_on_fail=1
  28. fi
  29. alias echo="/bin/echo -e"
  30. col_reset() {
  31. if [ "$color" -gt 0 ]
  32. then
  33. tput sgr0
  34. fi
  35. }
  36. col_set() {
  37. if [ -z "$1" ]
  38. then
  39. return
  40. fi
  41. if [ "$color" -gt 0 ]
  42. then
  43. tput setaf $1
  44. fi
  45. }
  46. log() {
  47. echo "$(col_set $3)[$(printf "%7s" "$1")]$(col_reset) $2"
  48. }
  49. datetime() {
  50. date -Iseconds
  51. }
  52. logdate() {
  53. echo "$(date -Iseconds) $(col_set $3)[$(printf "%7s" "$1")]$(col_reset) $2"
  54. }
  55. fail() {
  56. if [ "$verbose" -lt 2 ]
  57. then
  58. echo "" #for the dot printed with -n
  59. fi
  60. test_msg="$1"
  61. test_status=1
  62. }
  63. err() {
  64. msg="$(log ERR "$1" 1)"
  65. test_msg="$1"
  66. test_status=-1
  67. }
  68. success() {
  69. msg="$(log OK "$1" 2)"
  70. test_msg="$1"
  71. test_status=0
  72. }
  73. #
  74. # Tests & testcase functions
  75. #
  76. tc_name=""
  77. tc_infos=""
  78. tc_fail=0
  79. tc_run=0
  80. total_fail=0
  81. total_run=0
  82. test_msg=""
  83. test_status=0
  84. _test_setup() {
  85. test_status=0
  86. test_msg=""
  87. }
  88. TC_INIT() {
  89. tc_name=$1
  90. tc_infos=$2
  91. tc_fail=0
  92. tc_run=0
  93. msg="Running testcase '$tc_name'"
  94. if [ -n "$tc_infos" ]
  95. then
  96. msg="${msg} ($tc_infos)"
  97. fi
  98. if [ "$verbose" -gt 0 ]
  99. then
  100. logdate TESTCASE "$msg" 4
  101. fi
  102. }
  103. TC_END() {
  104. if [ "$tc_fail" -gt 0 ]
  105. then
  106. if [ "$verbose" -gt 1 ]
  107. then
  108. logdate TESTCASE "-------------$tc_name END------------" 1
  109. fi
  110. logdate FAIL "Testcase '$tc_name' tests: ${tc_run} fails: $(col_set 1)${tc_fail}$(col_reset)" 1
  111. if [ "$exit_on_fail" -ne 0 ]
  112. then
  113. CHECK_REPORT
  114. fi
  115. elif [ "$verbose" -eq 1 ]
  116. then
  117. echo "" #for the dot printed with -n
  118. logdate TESTCASE "Testcase '$tc_name' tests:${tc_run} fails: $tc_fail" 2
  119. elif [ "$verbose" -gt 1 ]
  120. then
  121. logdate TESTCASE "-------------$tc_name END------------" 4
  122. fi
  123. tc_name=""
  124. tc_infos=""
  125. tc_fail=0
  126. tc_run=0
  127. }
  128. TC_RUN() {
  129. _test_setup
  130. cmd=$1
  131. shift
  132. args=""
  133. case $#
  134. in
  135. 1)$cmd "$1";;
  136. 2)$cmd "$1" "$2";;
  137. 3)$cmd "$1" "$2" "$3";;
  138. 4)$cmd "$1" "$2" "$3" "$4";;
  139. *)fail "To many arguments for $cmd"
  140. esac
  141. #$cmd $args
  142. tc_run=$(expr $tc_run + 1)
  143. total_run=$(expr $total_run + 1)
  144. if [ "$test_status" -ne 0 ]
  145. then
  146. err_type="FAIL"
  147. if [ "$test_status" -lt 0 ]
  148. then
  149. err_type="ERR"
  150. fi
  151. tc_fail=$(expr $tc_fail + 1)
  152. total_fail=$(expr $total_fail + 1)
  153. logdate $err_type "$tc_name: $test_msg" 1 >&2
  154. elif [ "$verbose" -gt 1 ]
  155. then
  156. logdate OK "$tc_name: $test_msg" 2
  157. else
  158. echo -n '.'
  159. fi
  160. }
  161. CHECK_START() {
  162. logdate STATUS "Starting tests" 3
  163. }
  164. CHECK_REPORT() {
  165. if [ "$verbose" -eq 0 -a "$tc_fail" -eq "0" ]
  166. then
  167. echo "" # for dot printed with -n
  168. fi
  169. if [ "$verbose" -gt 0 ]
  170. then
  171. logdate STATUS "All tests done" 3
  172. fi
  173. if [ "$total_fail" -gt 0 ]
  174. then
  175. logdate FAIL "Summary : tests: ${total_run} fails: $(col_set 1)${total_fail}$(col_reset)" 1
  176. exit 1
  177. else
  178. logdate OK "Summary : tests:${total_run} fails: $total_fail" 2
  179. exit 0
  180. fi
  181. }
  182. #
  183. # HTTP/HTTPS tests
  184. #
  185. _check_http_status() {
  186. # $1 url
  187. # $2 status
  188. # $* curl options
  189. url=$1
  190. shift 1
  191. expt=$1
  192. if [ -z "$1" ]
  193. then
  194. expt=200
  195. fi
  196. shift 1
  197. status=$(curl -s -o /dev/null -w "%{http_code}" $* $url)
  198. if [ "$status" -ne "$expt" ]
  199. then
  200. fail "Check http status $expt for $url : $status returned"
  201. elif [ "$verbose" -gt 0 ]
  202. then
  203. success "Check http status $status for $url"
  204. fi
  205. }
  206. check_http_status() {
  207. # $1 url
  208. # $2 status
  209. _check_http_status $1 $2
  210. }
  211. check_http_200() {
  212. _check_http_status $1 200
  213. }
  214. check_https_cert() {
  215. # Check that SSL Cert is valid
  216. # $1 URL
  217. status=$(curl -s -o /dev/null -w "%{http_code}" https://$1)
  218. rep=$?
  219. if [ "$rep" -eq 0 ]
  220. then
  221. success "https://$1 cert verified"
  222. return
  223. fi
  224. status=$(curl -k -s -o /dev/null -q "%{http_code}" https://$1)
  225. rep=$?
  226. if [ "$rep" -eq 0 ]
  227. then
  228. fail "https://$1 cert invalid"
  229. else
  230. err "Unable to curl https://$1"
  231. fi
  232. }
  233. check_html_title() {
  234. url="$1"
  235. expt="$2"
  236. tmpxsl=$(mktemp -t XSL.XXXXXXXXXXX)
  237. echo '<?xml version="1.0"?>
  238. <xsl:stylesheet version="1.0"
  239. xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  240. <xsl:output method = "text"/>
  241. <xsl:template match="/">
  242. <xsl:value-of select="/html/head/title"/>
  243. </xsl:template>
  244. </xsl:stylesheet>' > $tmpxsl
  245. tmphtml=$(mktemp -t html.XXXXXXXXX)
  246. curl --silent $url > $tmphtml
  247. title=$(xsltproc --html --novalid $tmpxsl $tmphtml 2>/dev/null)
  248. if [ "$?" -ne "0" ]
  249. then
  250. title=$(xsltproc --novalid $tmpxsl $tmphtml 2>/dev/null)
  251. fi
  252. if [ "$title" = "$expt" ]
  253. then
  254. success "$url HTML title is '$expt'"
  255. else
  256. fail "$url HTML title is '$title' but '$expt' expected"
  257. fi
  258. rm $tmpxsl $tmphtml 2>/dev/null
  259. }
  260. check_audiostream() {
  261. # Uses mplayer to fetch 128Kb of stream
  262. # $1 Stream URL
  263. # $2 size
  264. MPLAYER=$(whereis mplayer|cut -d' ' -f2)
  265. MPV=$(whereis mpv|cut -d' ' -f2)
  266. if [ -x $MPLAYER ]
  267. then
  268. check_audiostream_mplayer "$1" "$2"
  269. elif [ -x $MPV ]
  270. then
  271. check_audiostream_mpv "$1" "$2"
  272. else
  273. fail "Unable to find mplayer nor mpv"
  274. fi
  275. }
  276. check_audiostream_mplayer() {
  277. # Uses mplayer to fetch 128Kb of stream
  278. # $1 Stream URL
  279. # $2 size
  280. tmpfile=$(mktemp -t check_audiostream.XXXXXXXXX)
  281. sz="$2"
  282. if [ -z "$sz" ]
  283. then
  284. sz="128"
  285. fi
  286. sz_kb="${sz}kb"
  287. expt_sz="`expr $sz \* 8`"
  288. if [ "$verbose" -gt 1 ]
  289. then
  290. logdate INFO "$tc_name: Running mplayer on '$1' for $sz" 3
  291. fi
  292. $MPLAYER -endpos $sz_kb -ao pcm:file=$tmpfile "$1" 1>/dev/null 2>/dev/null
  293. res=$?
  294. bytes=$(du $tmpfile | cut -f1)
  295. rm $tmpfile 2>/dev/null
  296. logdate INFO "$bytes $sz" 3
  297. if [ "$bytes" -lt $expt_sz ]
  298. then
  299. fail "mplayer retrieved ${bytes}B of stream instead of expected $sz"
  300. return
  301. fi
  302. echo "$bytes / $sz"
  303. if [ "$res" -eq 0 ]
  304. then
  305. success "mplayer retrieved $sz of stream on $1"
  306. else
  307. fail "mplayer failed to retrieve stream on $1"
  308. fi
  309. }
  310. check_audiostream_mpv() {
  311. # Uses mpv to fetch 128Kb of stream
  312. # $1 Stream URL
  313. # $2 size
  314. tmpfile=$(mktemp -t check_audiostream.XXXXXXXXX)
  315. sz="$2"
  316. if [ -z "$sz" ]
  317. then
  318. sz="128kb"
  319. fi
  320. if [ "$verbose" -gt 1 ]
  321. then
  322. logdate INFO "$tc_name: Running mpv on '$1' for $sz" 3
  323. fi
  324. $MPV --vo=null --ao=null --o=$tmpfile --of=wav --length 1 "$1" &> /dev/null
  325. bytes=$(du $tmpfile | cut -f1)
  326. rm $tmpfile 2>/dev/null
  327. if [ "$bytes" -ge 1 ]
  328. then
  329. success "mpv read successfully $1"
  330. else
  331. fail "mpv could not read $1"
  332. fi
  333. }
  334. check_ping() {
  335. ns=$1
  336. count=$2
  337. if [ -z "$count" ]
  338. then
  339. count=5
  340. fi
  341. ping -i 0.2 -c $count $ns 2>/dev/null >/dev/null
  342. res=$?
  343. if [ "$res" -ne 0 ]
  344. then
  345. fail "unable to ping '$ns'"
  346. else
  347. success "successfully send $count ping to '$ns'"
  348. fi
  349. }
  350. check_git_repo() {
  351. tmpdir=$(mktemp -d -t check_git.XXXXXXXXX)
  352. git clone $1 $tmpdir 2>/dev/null 1>/dev/null
  353. res=$?
  354. rm -Rf $tmpdir
  355. if [ "$res" -ne 0 ]
  356. then
  357. fail "unable to clone git repo '$1'"
  358. else
  359. success "git repo '$1' cloned'"
  360. fi
  361. }
  362. #
  363. # Jabber XMPP checks
  364. #
  365. __xmpp_probe() {
  366. serv=$1
  367. timeout=$2
  368. type=$3
  369. 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"
  370. if [ "$verbose" -gt 2 ]
  371. then
  372. echo -e $payload | sed -e "s/^/$(datetime) [ DEBUG] Sent : /" >&2
  373. fi
  374. echo -e $payload
  375. sleep $timeout
  376. }
  377. _xmpp_probe() {
  378. serv=$1
  379. port=$2
  380. timeout=$3
  381. type=$4
  382. tmpres=$(mktemp -t xmpp_probe.XXXXXXXXX)
  383. echo "$(__xmpp_probe $serv $timeout $type| nc -q2 $serv $port)</stream:stream>" | xmllint --format - > $tmpres
  384. if [ "$verbose" -gt 2 ]
  385. then
  386. cat $tmpres | sed -e "s/^/$(datetime) [ DEBUG] Recv : /" >&2
  387. fi
  388. cat $tmpres
  389. rm $tmpres
  390. }
  391. _check_xmpp_ns() {
  392. ns1=$1
  393. expt_ns=$2
  394. expt_port=$3
  395. dnsq="_xmpp-${4}._tcp.$1"
  396. rep="$(dig $dnsq srv +short | cut -d" " -f3,4)"
  397. if [ "$rep" = "$expt_port ${expt_ns}." ]
  398. then
  399. success "$dnsq = '$rep'"
  400. else
  401. fail "$dnsq = '$rep' but '$expt_port ${expt_ns}.' expected"
  402. fi
  403. }
  404. check_xmpp_serv_ns() {
  405. _check_xmpp_ns "$1" "$2" "$3" "server"
  406. }
  407. check_xmpp_client_ns() {
  408. _check_xmpp_ns "$1" "$2" "$3" "client"
  409. }
  410. _check_xmpp_server() {
  411. serv=$1
  412. port=$2
  413. timeout=$3
  414. type=$4
  415. if [ -z "$port" ]
  416. then
  417. port=5222
  418. fi
  419. if [ -z "$timeout" ]
  420. then
  421. timeout=2
  422. fi
  423. if [ "$verbose" -gt 1 ]
  424. then
  425. tpe="client"
  426. if [ "$type" = "server" ]
  427. then
  428. tpe="S2S"
  429. fi
  430. logdate INFO "$tc_name: Connecting to XMPP $serv $tpe port $port (timeout=${timeout}s)" 3
  431. fi
  432. stream=$(_xmpp_probe $serv $port $timeout $type| head -n2 | tail -n1)
  433. if [ -z "$stream" ]
  434. then
  435. fail "Empty reply from $serv:$port"
  436. return
  437. fi
  438. if [ "$type" = "client" ]
  439. then
  440. infos=$(echo $stream | sed -E 's/^<([^ ]+).* xmlns="([^"]+)".* from="([^"]+)" .*$/\1 \2 \3/')
  441. else
  442. infos="$(echo $stream | sed -E 's/^<([^ ]+).* xmlns="([^"]+)" .*$/\1 \2/') $serv"
  443. fi
  444. if [ "$(echo $infos | cut -d ' ' -f1,2)" = "stream:stream jabber:$type" ]
  445. then
  446. if [ "$(echo $infos | cut -d ' ' -f3)" = "$serv" ]
  447. then
  448. success "Successfully connected to XMPP $type $serv:$port"
  449. else
  450. fail "Server $serv:$port announce itself as $(echo $infos | cut -f3)"
  451. fi
  452. else
  453. fail "Unexpected reply from $serv:$port : $infos"
  454. fi
  455. }
  456. check_xmpp_server_client() {
  457. _check_xmpp_server "$1" "$2" "$3" "client"
  458. }
  459. check_xmpp_server_s2s() {
  460. _check_xmpp_server "$1" "$2" "$3" "server"
  461. }
  462. check_xmpp_ssl() {
  463. serv=$1
  464. port=$2
  465. if [ -z "$port" ]
  466. then
  467. port=5222
  468. fi
  469. openssl s_client -connect $serv:$port </dev/null -starttls xmpp >/dev/null 2>/dev/null
  470. rep=$?
  471. if [ "$rep" -eq 0 ]
  472. then
  473. success "Openssl successfully negociating XMPP ssl with $serv:$port"
  474. else
  475. fail "Openssl failed negociating XMPP ssl with $serv:$port"
  476. fi
  477. }
  478. #
  479. # SSH checks
  480. #
  481. check_ssh_nc() {
  482. host=$1
  483. port=$2
  484. if [ -z "$port" ]
  485. then
  486. port=22
  487. fi
  488. rep="$(nc -w1 $host $port </dev/null)"
  489. res=$?
  490. if [ "$res" -ne "0" ]
  491. then
  492. fail "Netcat unable to connect to $host:$port"
  493. return
  494. fi
  495. if echo $rep | grep "^SSH-2.0-OpenSSH" >/dev/null
  496. then
  497. success "OpenSSH replied on $host:$port"
  498. else
  499. fail "Bad reply from $host:$port : '$rep'"
  500. fi
  501. }
  502. check_ssh_key() {
  503. host="$1"
  504. testkey="$2"
  505. keytype="$3"
  506. port="$4"
  507. if [ -z "$port" ]
  508. then
  509. port=22
  510. fi
  511. if [ -z "$keytype" ]
  512. then
  513. keytype="rsa"
  514. fi
  515. key=$(ssh-keyscan -p $port -t $keytype $host 2>/dev/null | cut -d " " -f3)
  516. if [ -z "$key" ]
  517. then
  518. fail "SSH server not responding"
  519. return
  520. elif [ "$key" = "$testkey" ]
  521. then
  522. success "OpenSSH $host:$port key is $testkey"
  523. return
  524. else
  525. fail "OpenSSH $host:$port missmatch : "
  526. logdate ERR "Expected : $testkey" 1
  527. logdate ERR "Received : $key" 1
  528. return
  529. fi
  530. }
  531. check_mpc() {
  532. # check_mpc [$host [$port] ]
  533. # tests if you can contact an MPD server in a client way
  534. # returns the current state of the server
  535. host=$1
  536. port=$2
  537. if [ -z "$host" ]
  538. then
  539. host=127.0.0.1
  540. fi
  541. if [ -z "$port" ]
  542. then
  543. port=6600
  544. fi
  545. if echo "status" | nc -w 1 "$host" "$port" | head -1 | grep "^OK MPD"
  546. then
  547. success "MPD server can be contacted on $host:$port"
  548. status=$(echo "status" | nc -w 1 "$host" "$port" | grep "^state:"|cut -d: -f2)
  549. success "It's state is : $status"
  550. fi
  551. }