astversion 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. #!/bin/bash
  2. #
  3. # astversion - determine version/source of components
  4. #
  5. # use: astverion {options}
  6. #
  7. # options:
  8. # --prefix=PATH - specify prefix from build
  9. # --exec=PATH - specify asterisk executable
  10. # --lib=PATH - specify asterisk library path
  11. # --src=PATH - specify source path to search
  12. #
  13. # Copyright (c) 2015, Digium, Inc.
  14. #
  15. # Written by Scott Griepentrog <sgriepentrog@digium.com>
  16. #
  17. # Distributed under the terms of the GNU General Public License
  18. # condense list of files when more than X in a set
  19. CONDENSE=3
  20. # libraries to provide the source/version of
  21. LIBRARIES=(
  22. libasteriskssl.so.1
  23. libspandsp.so.2
  24. libpjsip.so.2
  25. libpri.so.1.4
  26. )
  27. # possible library locations
  28. LIB_PATHS=(
  29. /usr/lib
  30. /usr/lib64
  31. /lib
  32. /lib64
  33. /usr/local/lib
  34. /usr/local/lib64
  35. /opt/lib
  36. /opt/lib64
  37. )
  38. # collection of files to search for
  39. FILES=()
  40. # source directories to search
  41. SRC_DIRS=()
  42. main()
  43. {
  44. TMPFILE="/tmp/astversion.$$"
  45. sanity_check
  46. locate_files "$@"
  47. locate_libraries
  48. locate_modules
  49. echo "Checking Asterisk versions on $HOSTNAME at $(date)"
  50. check_asterisk_version
  51. check_dahdi_version
  52. gather_packages
  53. if [ ! -z "$DISTRO" ]
  54. then
  55. search_packages
  56. else
  57. echo "WARNING: Unable to determine distro, skipping package search"
  58. fi
  59. search_source
  60. show_unknown_files
  61. rm -f $TMPFILE
  62. }
  63. sanity_check()
  64. {
  65. # insure that needed tools are present
  66. TOOLS=(uname basename fgrep cut head readlink find)
  67. # making assumption that rpm and dpkg always exist on their platforms
  68. for TOOL in ${TOOLS[@]}
  69. do
  70. if ! which $TOOL > /dev/null
  71. then
  72. echo "ERROR: please install package for $TOOL"
  73. exit 1
  74. fi
  75. done
  76. }
  77. locate_files()
  78. {
  79. # guess prefix from executable path
  80. SCRIPT_PREFIX="$(readlink -f ${0%/sbin/astversion} 2>/dev/null)"
  81. if [ -x $SCRIPT_PREFIX/sbin/asterisk ]
  82. then
  83. PREFIX=$SCRIPT_PREFIX
  84. ASTERISK_PATH=$SCRIPT_PREFIX/sbin/asterisk
  85. fi
  86. if [ -z "$ASTERISK_PATH" ]
  87. then
  88. ASTERISK_PATH=$(readlink -f $(which asterisk 2>/dev/null) 2>/dev/null)
  89. PREFIX=${ASTERISK_PATH%/sbin/asterisk}
  90. fi
  91. # parse user supplied information
  92. USER_PREFIX=""
  93. USER_EXEC=""
  94. for opt in "$@"
  95. do
  96. case "$opt" in
  97. -h|--help)
  98. echo "Use: astversion {--prefix=PATH} {--exec=PATH} {--lib=PATH}"
  99. exit 0
  100. ;;
  101. --prefix=*)
  102. USER_PREFIX=${opt:9}
  103. ;;
  104. --exec=*)
  105. USER_EXEC=${opt:7}
  106. ;;
  107. --lib=*)
  108. LIBDIR=${opt:6}
  109. ;;
  110. --src=*)
  111. SRC_DIRS+=${opt:6}
  112. ;;
  113. *)
  114. echo "ERROR: Unknown option: $opt"
  115. exit 1
  116. ;;
  117. esac
  118. done
  119. # apply user supplied values
  120. if [ ! -z "$USER_PREFIX" ]
  121. then
  122. PREFIX="$USER_PREFIX"
  123. ASTERISK_PATH=""
  124. fi
  125. if [ ! -z "$USER_EXEC" ]
  126. then
  127. ASTERISK_PATH="$USER_EXEC"
  128. fi
  129. # locate asterisk executable
  130. if [ -z "$ASTERISK_PATH" ]
  131. then
  132. ASTERISK_PATH="$PREFIX/sbin/asterisk"
  133. fi
  134. if [ ! -x "$ASTERISK_PATH" ]
  135. then
  136. echo "ERROR: the Asterisk executable is not found or not executable at $ASTERISK_PATH"
  137. exit 1
  138. fi
  139. FILES+=($ASTERISK_PATH)
  140. # locate dahdi_cfg executable
  141. DAHDI_CFG_PATH=$(readlink -f $(which dahdi_cfg 2>/dev/null) 2>/dev/null)
  142. if [ ! -z "$DAHDI_CFG_PATH" ]
  143. then
  144. FILES+=($DAHDI_CFG_PATH)
  145. fi
  146. # locate asterisk libdir
  147. if [ -z "$LIBDIR" ]
  148. then
  149. LIBDIR="$PREFIX/lib"
  150. if [ `uname -m` = "x86_64" -a -d "$PREFIX/lib64" ]
  151. then
  152. LIBDIR="$PREFIX/lib64"
  153. fi
  154. fi
  155. if [ ! -d "$LIBDIR/asterisk/modules" ]
  156. then
  157. echo "ERROR: asterisk module directory not found at $LIBDIR"
  158. exit 1
  159. fi
  160. }
  161. locate_libraries()
  162. {
  163. # LIBDIR should contain libasteriskssl, but others may be elsewhere
  164. # add LIBDIR to path list
  165. if ! [[ " ${LIB_PATHS[@]} " =~ " $LIBDIR " ]]
  166. then
  167. LIB_PATHS+=($LIBDIR)
  168. fi
  169. for LIBRARY in ${LIBRARIES[@]}
  170. do
  171. FOUND_LIB=()
  172. for LIB_PATH in ${LIB_PATHS[@]}
  173. do
  174. FULL_PATH="$LIB_PATH/$LIBRARY"
  175. if [ ! -L $LIB_PATH -a -f $FULL_PATH ]
  176. then
  177. FOUND_LIB+=($FULL_PATH)
  178. FILES+=($FULL_PATH)
  179. fi
  180. done
  181. if [ ${#FOUND_LIB[@]} -gt 1 ]
  182. then
  183. echo "### WARNING: duplicate libraries found: ${FOUND_LIB[@]}"
  184. fi
  185. done
  186. }
  187. check_asterisk_version()
  188. {
  189. # get the version that the executable says it is
  190. echo "Using Asterisk executable: $ASTERISK_PATH"
  191. AST_EXEC_VER=$($ASTERISK_PATH -V)
  192. if [ -z "$AST_EXEC_VER" ]
  193. then
  194. echo "### ERROR: Unable to find Asterisk version from executable"
  195. exit 1
  196. fi
  197. if [ "${AST_EXEC_VER:0:9}" != "Asterisk " ]
  198. then
  199. echo "### ERROR: Unexpected version from executable: $AST_EXEC_VER"
  200. exit 1
  201. fi
  202. # compare with the version that is running
  203. if ! $ASTERISK_PATH -rx "core show version" > $TMPFILE 2>/dev/null
  204. then
  205. echo "Installed version: $AST_EXEC_VER"
  206. echo "Asterisk is not running - more details are available when running."
  207. AST_RUN_VER=""
  208. else
  209. AST_RUN_VER=$(grep '^Asterisk [^e][^n][^d]' < $TMPFILE)
  210. if [ -z "$AST_RUN_VER" ]
  211. then
  212. echo "### ERROR: Unable to find Asterisk version from running instance"
  213. exit 1
  214. fi
  215. # is it running the same version? (note: space is significant!)
  216. if ! fgrep "$AST_EXEC_VER " < $TMPFILE > /dev/null
  217. then
  218. echo "Installed version: $AST_EXEC_VER"
  219. echo "### WARNING: Asterisk is running different version:"
  220. fi
  221. echo "$AST_RUN_VER"
  222. fi
  223. }
  224. check_dahdi_version()
  225. {
  226. if [ ! -f /sys/module/dahdi/version ]
  227. then
  228. echo "Dahdi kernel module is not installed"
  229. else
  230. DAHDI_KERNEL=$(cat /sys/module/dahdi/version)
  231. echo "Dahdi kernel module version: $DAHDI_KERNEL"
  232. fi
  233. if ! which dahdi_cfg >&/dev/null
  234. then
  235. echo "Dahdi tools are not installed"
  236. else
  237. DAHDI_TOOLS=$(dahdi_cfg -v |& head -1)
  238. echo "$DAHDI_TOOLS"
  239. fi
  240. if $ASTERISK_PATH -rx "dahdi show version" > $TMPFILE 2>/dev/null
  241. then
  242. DAHDI_CLI=$(grep ^DAHDI $TMPFILE)
  243. # may be empty if dahdi not installed
  244. if [ ! -z "$DAHDI_CLI" ]
  245. then
  246. echo "Asterisk reports: $DAHDI_CLI"
  247. else
  248. echo "Asterisk reports that Dahdi is not available"
  249. fi
  250. fi
  251. }
  252. scan_package_redhat()
  253. {
  254. PKGNAME="$1"
  255. if ! rpm -q $PKGNAME > /tmp/astversion-$PKGNAME-version
  256. then
  257. rm -f /tmp/astversion-$PKGNAME-version
  258. return 2
  259. fi
  260. rpm -ql $PKGNAME > /tmp/astversion-$PKGNAME-files
  261. rpm -V $PKGNAME > /tmp/astversion-$PKGNAME-verify
  262. return 0
  263. }
  264. scan_package_debian()
  265. {
  266. PKGNAME="$1"
  267. if ! dpkg -s $PKGNAME > $TMPFILE
  268. then
  269. rm -f /tmp/astversion-$PKGNAME-version
  270. return 2
  271. fi
  272. # prefix the version with the package name to mimic rpm
  273. echo -n "$PKGNAME " > /tmp/astversion-$PKGNAME-version
  274. cat $TMPFILE | fgrep Version |cut -d ' ' -f2 >> /tmp/astversion-$PKGNAME-version
  275. dpkg -L $PKGNAME > /tmp/astversion-$PKGNAME-files
  276. dpkg -V $PKGNAME > /tmp/astversion-$PKGNAME-verify
  277. }
  278. package_has_file()
  279. {
  280. PKGNAME="$1"
  281. PKGFILE="$2"
  282. if [ ! -f /tmp/astversion-$PKGNAME-version ]
  283. then
  284. return 1
  285. fi
  286. if [ ! -f /tmp/astversion-$PKGNAME-files ]
  287. then
  288. return 2
  289. fi
  290. if ! fgrep "$PKGFILE" /tmp/astversion-$PKGNAME-files >/dev/null
  291. then
  292. # package doesn't have that file
  293. return 3
  294. fi
  295. if fgrep "$PKGFILE" /tmp/astversion-$PKGNAME-verify >/dev/null
  296. then
  297. # file does not match package
  298. return 4
  299. fi
  300. return 0
  301. }
  302. gather_packages()
  303. {
  304. # build a list of installed packages that are likely to contain files of interest
  305. PACKAGES=()
  306. SEARCH=(asterisk dahdi libpri pjproject spandsp)
  307. DISTRO=""
  308. if [ -f /etc/redhat-release ]
  309. then
  310. DISTRO="redhat"
  311. for NAME in ${SEARCH[@]}
  312. do
  313. PACKAGES+=($(rpm -qa |fgrep $NAME))
  314. done
  315. fi
  316. if [ -f /etc/debian_version ]
  317. then
  318. DISTRO="debian"
  319. for NAME in ${SEARCH[@]}
  320. do
  321. PACKAGES+=($(dpkg --get-selections |cut -f1 |fgrep $NAME))
  322. done
  323. fi
  324. }
  325. locate_modules()
  326. {
  327. # build a list of files that need to be located
  328. MODULES=($LIBDIR/asterisk/modules/*.so)
  329. # add libraries and binaries that exist to the files list
  330. for MODULE in ${MODULES[@]}
  331. do
  332. FILES+=($MODULE)
  333. done
  334. }
  335. search_packages()
  336. {
  337. # search each package and report files that match
  338. for PACKAGE in ${PACKAGES[@]}
  339. do
  340. scan_package_$DISTRO "$PACKAGE"
  341. PKGVERSION=$(cat /tmp/astversion-$PKGNAME-version)
  342. FOUND=()
  343. for FILE in ${FILES[@]}
  344. do
  345. if package_has_file "$PACKAGE" "$FILE"
  346. then
  347. FOUND+=($FILE)
  348. FILES=(${FILES[@]/$FILE/})
  349. fi
  350. done
  351. if [ ! -z "$FOUND" ]
  352. then
  353. if [ ${#FOUND[@]} -le $CONDENSE ]
  354. then
  355. for FILEFOUND in ${FOUND[@]}
  356. do
  357. echo "Matched $FILEFOUND to package $PKGVERSION"
  358. done
  359. else
  360. echo "Matched ${#FOUND[@]} files to package $PKGVERSION"
  361. fi
  362. fi
  363. rm -f /tmp/astversion-$PKGNAME-version
  364. rm -f /tmp/astversion-$PKGNAME-files
  365. rm -f /tmp/astversion-$PKGNAME-verify
  366. done
  367. }
  368. search_source()
  369. {
  370. # look for source path locally (compiled on this machine)
  371. # - scan elfs for compilation directory
  372. # - compare the file to confirm match
  373. if [ -z "$FILES" ]
  374. then
  375. return
  376. fi
  377. # skip this check when without readelf tool (fedora 22)
  378. if ! which readelf >& /dev/null
  379. then
  380. echo "Warning: skipping source detection because readelf utility is not available"
  381. return
  382. fi
  383. # build a list of source paths
  384. DIRS=()
  385. for FILE in ${FILES[@]}
  386. do
  387. DEBUG_ELF=$(readelf -wi $FILE |fgrep DW_AT_comp_dir |head -1)
  388. COMP_DIR=${DEBUG_ELF##* }
  389. DIR=${COMP_DIR//[[:space:]]/}
  390. if [ -d $DIR ]
  391. then
  392. if ! [[ " ${DIRS[@]} " =~ " $DIR " ]]
  393. then
  394. DIRS+=($DIR)
  395. fi
  396. fi
  397. done
  398. # add in user specified directories last
  399. for DIR in ${SRC_DIRS[@]}
  400. do
  401. if ! [[ " ${DIRS[@]} " =~ " $DIR " ]]
  402. then
  403. DIRS+=($DIR)
  404. fi
  405. done
  406. # for each source path, look for target file
  407. for DIR in ${DIRS[@]}
  408. do
  409. FOUND=()
  410. for FILE in ${FILES[@]}
  411. do
  412. BINARY_FILE=$(basename $FILE)
  413. BINARY_PATH="$DIR/$BINARY_FILE"
  414. if [ ! -f "$BINARY_PATH" ]
  415. then
  416. # it may be hiding somewhere
  417. FIND_BINARY=$(find $DIR -name $BINARY_FILE |head -1)
  418. if [ ! -z "$FIND_BINARY" ]
  419. then
  420. BINARY_PATH=$FIND_BINARY
  421. fi
  422. fi
  423. if [ -f "$BINARY_PATH" ]
  424. then
  425. if cmp $BINARY_PATH $FILE >/dev/null
  426. then
  427. FOUND+=($FILE)
  428. FILES=(${FILES[@]/$FILE/})
  429. fi
  430. fi
  431. done
  432. if [ ! -z "$FOUND" ]
  433. then
  434. if [ ${#FOUND[@]} -le $CONDENSE ]
  435. then
  436. for FILEFOUND in ${FOUND[@]}
  437. do
  438. echo "Located $FILEFOUND compiled from $DIR"
  439. done
  440. else
  441. echo "Located ${#FOUND[@]} files compiled from $DIR"
  442. fi
  443. fi
  444. done
  445. }
  446. show_unknown_files()
  447. {
  448. # show a warning for any remaining files unaccounted for
  449. if [ -z "$FILES" ]
  450. then
  451. echo "Success: all files accounted for."
  452. else
  453. echo ""
  454. echo "WARNING: source of the following files was not found:"
  455. if ! which readelf >& /dev/null
  456. then
  457. for FILE in ${FILES[@]}
  458. do
  459. echo " ### $FILE"
  460. done
  461. else
  462. for FILE in ${FILES[@]}
  463. do
  464. DEBUG_ELF=$(readelf -wi $FILE |fgrep DW_AT_comp_dir |head -1)
  465. if [ -z "$DEBUG_ELF" ]
  466. then
  467. COMP_DIR="(no debug info)"
  468. else
  469. COMP_DIR=${DEBUG_ELF##* }
  470. fi
  471. echo " ### $FILE - $COMP_DIR"
  472. done
  473. fi
  474. fi
  475. }
  476. main "$@"