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.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  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. tmpfile=$(mktemp -t check_audiostream.XXXXXXXXX)
  265. sz="$2"
  266. if [ -z "$sz" ]
  267. then
  268. sz="128kb"
  269. fi
  270. if [ "$verbose" -gt 1 ]
  271. then
  272. logdate INFO "$tc_name: Running mplayer on '$1' for $sz" 3
  273. fi
  274. mplayer -endpos $sz -ao pcm:file=$tmpfile "$1" 1>/dev/null 2>/dev/null
  275. res=$?
  276. bytes=$(du $tmpfile | cut -f1)
  277. rm $tmpfile 2>/dev/null
  278. if [ "$bytes" -lt 1024 ]
  279. then
  280. fail "mplayer retrieved ${bytes}B of stream instead of expected $sz"
  281. return
  282. fi
  283. if [ "$res" -eq 0 ]
  284. then
  285. success "mplayer retrieved $sz of stream on $1"
  286. else
  287. fail "mplayer failed to retrieve stream on $1"
  288. fi
  289. }
  290. check_ping() {
  291. ns=$1
  292. count=$2
  293. if [ -z "$count" ]
  294. then
  295. count=5
  296. fi
  297. ping -i 0.2 -c $count $ns 2>/dev/null >/dev/null
  298. res=$?
  299. if [ "$res" -ne 0 ]
  300. then
  301. fail "unable to ping '$ns'"
  302. else
  303. success "successfully send $count ping to '$ns'"
  304. fi
  305. }
  306. check_git_repo() {
  307. tmpdir=$(mktemp -d -t check_git.XXXXXXXXX)
  308. git clone $1 $tmpdir 2>/dev/null 1>/dev/null
  309. res=$?
  310. rm -Rf $tmpdir
  311. if [ "$res" -ne 0 ]
  312. then
  313. fail "unable to clone git repo '$1'"
  314. else
  315. success "git repo '$1' cloned'"
  316. fi
  317. }
  318. #
  319. # Jabber XMPP checks
  320. #
  321. __xmpp_probe() {
  322. serv=$1
  323. timeout=$2
  324. type=$3
  325. 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"
  326. if [ "$verbose" -gt 2 ]
  327. then
  328. echo -e $payload | sed -e "s/^/$(datetime) [ DEBUG] Sent : /" >&2
  329. fi
  330. echo -e $payload
  331. sleep $timeout
  332. }
  333. _xmpp_probe() {
  334. serv=$1
  335. port=$2
  336. timeout=$3
  337. type=$4
  338. tmpres=$(mktemp -t xmpp_probe.XXXXXXXXX)
  339. echo "$(__xmpp_probe $serv $timeout $type| nc -q2 $serv $port)</stream:stream>" | xmllint --format - > $tmpres
  340. if [ "$verbose" -gt 2 ]
  341. then
  342. cat $tmpres | sed -e "s/^/$(datetime) [ DEBUG] Recv : /" >&2
  343. fi
  344. cat $tmpres
  345. rm $tmpres
  346. }
  347. _check_xmpp_ns() {
  348. ns1=$1
  349. expt_ns=$2
  350. expt_port=$3
  351. dnsq="_xmpp-${4}._tcp.$1"
  352. rep="$(dig $dnsq srv +short | cut -d" " -f3,4)"
  353. if [ "$rep" = "$expt_port ${expt_ns}." ]
  354. then
  355. success "$dnsq = '$rep'"
  356. else
  357. fail "$dnsq = '$rep' but '$expt_port ${expt_ns}.' expected"
  358. fi
  359. }
  360. check_xmpp_serv_ns() {
  361. _check_xmpp_ns "$1" "$2" "$3" "server"
  362. }
  363. check_xmpp_client_ns() {
  364. _check_xmpp_ns "$1" "$2" "$3" "client"
  365. }
  366. _check_xmpp_server() {
  367. serv=$1
  368. port=$2
  369. timeout=$3
  370. type=$4
  371. if [ -z "$port" ]
  372. then
  373. port=5222
  374. fi
  375. if [ -z "$timeout" ]
  376. then
  377. timeout=2
  378. fi
  379. if [ "$verbose" -gt 1 ]
  380. then
  381. tpe="client"
  382. if [ "$type" = "server" ]
  383. then
  384. tpe="S2S"
  385. fi
  386. logdate INFO "$tc_name: Connecting to XMPP $serv $tpe port $port (timeout=${timeout}s)" 3
  387. fi
  388. stream=$(_xmpp_probe $serv $port $timeout $type| head -n2 | tail -n1)
  389. if [ -z "$stream" ]
  390. then
  391. fail "Empty reply from $serv:$port"
  392. return
  393. fi
  394. if [ "$type" = "client" ]
  395. then
  396. infos=$(echo $stream | sed -E 's/^<([^ ]+).* xmlns="([^"]+)".* from="([^"]+)" .*$/\1 \2 \3/')
  397. else
  398. infos="$(echo $stream | sed -E 's/^<([^ ]+).* xmlns="([^"]+)" .*$/\1 \2/') $serv"
  399. fi
  400. if [ "$(echo $infos | cut -d ' ' -f1,2)" = "stream:stream jabber:$type" ]
  401. then
  402. if [ "$(echo $infos | cut -d ' ' -f3)" = "$serv" ]
  403. then
  404. success "Successfully connected to XMPP $type $serv:$port"
  405. else
  406. fail "Server $serv:$port announce itself as $(echo $infos | cut -f3)"
  407. fi
  408. else
  409. fail "Unexpected reply from $serv:$port : $infos"
  410. fi
  411. }
  412. check_xmpp_server_client() {
  413. _check_xmpp_server "$1" "$2" "$3" "client"
  414. }
  415. check_xmpp_server_s2s() {
  416. _check_xmpp_server "$1" "$2" "$3" "server"
  417. }
  418. check_xmpp_ssl() {
  419. serv=$1
  420. port=$2
  421. if [ -z "$port" ]
  422. then
  423. port=5222
  424. fi
  425. openssl s_client -connect $serv:$port </dev/null -starttls xmpp >/dev/null 2>/dev/null
  426. rep=$?
  427. if [ "$rep" -eq 0 ]
  428. then
  429. success "Openssl successfully negociating XMPP ssl with $serv:$port"
  430. else
  431. fail "Openssl failed negociating XMPP ssl with $serv:$port"
  432. fi
  433. }
  434. #
  435. # SSH checks
  436. #
  437. check_ssh_nc() {
  438. host=$1
  439. port=$2
  440. if [ -z "$port" ]
  441. then
  442. port=22
  443. fi
  444. rep="$(nc -q1 $host $port </dev/null)"
  445. res=$?
  446. if [ "$res" -ne "0" ]
  447. then
  448. fail "Netcat unable to connect to $host:$port"
  449. return
  450. fi
  451. if echo $rep | grep "^SSH-2.0-OpenSSH" >/dev/null
  452. then
  453. success "OpenSSH replied on $host:$port"
  454. else
  455. fail "Bad replie from $host:$port : '$rep'"
  456. fi
  457. }
  458. check_mpc() {
  459. # check_mpc [$host [$port] ]
  460. # tests if you can contact an MPD server in a client way
  461. # returns the current state of the server
  462. host=$1
  463. port=$2
  464. if [ -z "$host" ]
  465. then
  466. host=127.0.0.1
  467. fi
  468. if [ -z "$port" ]
  469. then
  470. port=6600
  471. fi
  472. if echo "status" | nc -w 1 "$host" "$port" | head -1 | grep "^OK MPD"
  473. then
  474. success "MPD server can be contacted on $host:$port"
  475. status=$(echo "status" | nc -w 1 "$host" "$port" | grep "^state:"|cut -d: -f2)
  476. success "It's state is : $status"
  477. fi
  478. }