SlackCheck allows users to keep many Slackware machines up to date with the latest packages. All upgrades are performed from single machine though SSH (or RSH). It generates an upgrade script and list of non-standard packages for every machine. https://georgi.unixsol.org/programs/slackcheck/
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.

slcheck.sh 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. #!/bin/sh
  2. # SlackCheck
  3. #
  4. # $Id: slcheck.sh,v 1.43 2009/05/20 10:55:22 gf Exp $
  5. #
  6. # Copyright (c) 2002-2006 Georgi Chorbadzhiyski, Sofia, Bulgaria
  7. # All rights reserved.
  8. #
  9. # Redistribution and use of this script, with or without modification, is
  10. # permitted provided that the following conditions are met:
  11. #
  12. # 1. Redistributions of this script must retain the above copyright
  13. # notice, this list of conditions and the following disclaimer.
  14. #
  15. # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  16. # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  17. # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
  18. # EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  19. # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  20. # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  21. # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  22. # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  23. # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  24. # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. #
  26. echo "SlackCheck v3.80"
  27. echo
  28. cd $(dirname $0)
  29. INC_CONFIG="0"
  30. . ./config.sh
  31. if [ "$INC_CONFIG" = "0" ]
  32. then
  33. echo "*** Error including ./config.sh"
  34. exit
  35. fi
  36. # Show usage information
  37. usage() {
  38. echo "Usage: $(basename $0) [options]"
  39. echo
  40. echo " OPTIONS:"
  41. echo
  42. echo " --local Operate on local machine"
  43. echo " --host h1 h2 h3 Upgrade this host(s)"
  44. echo " --file filename Read list of hosts from this file"
  45. echo
  46. echo " --sync Get latest list of packages from the WWW/FTP/Local file"
  47. echo
  48. echo " --collect Build package lists for hosts that'll be upgraded"
  49. echo
  50. echo " --gen Generate upgrade scripts"
  51. echo
  52. echo " --upgrade Upgrade hosts using generated scripts"
  53. echo " --dist Only copy upgrade scripts to hosts, do not updgrade"
  54. echo
  55. echo " --skip-ignore Skip checks for ignored packages"
  56. echo
  57. echo " --verbose Show more info when update scripts are generated"
  58. echo
  59. echo " HOW TO UPGRADE CURRENT HOST"
  60. echo " Run: $(basename $0) --local --sync --collect --gen --upgrade"
  61. echo
  62. echo " HOW TO UPGRADE MULTIPLE HOSTS:"
  63. echo " Edit: \"update_hosts\" file to add your slackware machines"
  64. echo " Run: $(basename $0) --sync --collect --gen"
  65. echo " Edit: ${DIR_UPD}/${FILE_UPDATES}*"
  66. echo " Run: $(basename $0) --upgrade (for automatic upgrade)"
  67. echo " or"
  68. echo " Run: $(basename $0) --dist (for manual upgrade after that)"
  69. echo
  70. echo " HOW TO UPGRADE SINGLE HOST:"
  71. echo " Run: $(basename $0) --host blah.example.org --sync --collect --gen --upgrade"
  72. echo
  73. exit 1
  74. }
  75. # Get newest package list
  76. sync_master_list() {
  77. echo "===> Getting newest package list..."
  78. WD=$(pwd)
  79. mkdir $DIR_PKG 2>/dev/null
  80. cd $DIR_PKG
  81. TMPDIR=".Tmp"
  82. rm -rf $TMPDIR 2>/dev/null
  83. mkdir $TMPDIR && cd $TMPDIR
  84. ${DL_PRG} ${DL_PRG_OPTS} ${DL_HOST}/CHECKSUMS.md5
  85. # Parse file
  86. grep -E "\.t[a-z]z$" CHECKSUMS.md5 | grep patches | cut -d" " -f3 | sed -e 's|\./||' > ../${FILE_NEWEST}
  87. grep -E "\.t[a-z]z$" CHECKSUMS.md5 | grep slackware | cut -d" " -f3 | sed -e 's|\./||' >> ../${FILE_NEWEST}
  88. if [ $(LANG=C ls -l ../${FILE_NEWEST} | tr -s ' ' | cut -d" " -f 5) = "0" ]
  89. then
  90. grep -E "\.t[a-z]z$" CHECKSUMS.md5 | cut -d" " -f3 | sed -e 's|\./||' >> ../${FILE_NEWEST}
  91. fi
  92. rev < ../${FILE_NEWEST} | cut -d- -f4- | rev | sed -e 's|.*/||;s|[^A-Za-z0-9_]|_|g' > ../.${FILE_NEWEST}.base
  93. paste ../.${FILE_NEWEST}.base ../${FILE_NEWEST} | sed -e 's|\.\(t[a-z]z\)| \1|' > ../.${FILE_NEWEST}.paste
  94. cd ..
  95. rm -rf $TMPDIR 2>/dev/null
  96. cd $WD
  97. }
  98. # Generate list of packages for every host
  99. collect_package_lists() {
  100. [ -d $DIR_PKG ] || mkdir -p $DIR_PKG
  101. echo "===> Collecting package lists..."
  102. for HOST in $SLACK_HOSTS
  103. do
  104. echo " ---> $HOST"
  105. # Localhost
  106. if [ "$HOST" == "$(hostname)" -o \
  107. "$HOST" == "$(hostname -f)" -o \
  108. "$HOST" == "localhost" ]
  109. then
  110. ls /var/log/packages > ${DIR_PKG}/$HOST
  111. # Remote host
  112. else
  113. ${RSH_LISTS} $HOST "ls /var/log/packages" > ${DIR_PKG}/${HOST}.tmp
  114. mv ${DIR_PKG}/${HOST}.tmp ${DIR_PKG}/${HOST} 2>/dev/null
  115. fi
  116. done
  117. }
  118. # Generate upgrade scripts
  119. generate_upgrade_scripts() {
  120. [ -d ${DIR_UPD} ] || mkdir ${DIR_UPD}
  121. echo "===> Generating upgrade scripts..."
  122. if [ ! -f ${DIR_PKG}/.${FILE_NEWEST}.paste ]
  123. then
  124. sync_master_list
  125. fi
  126. # Init \$basepkg variables
  127. while read basepkg hostpkg ext
  128. do
  129. eval $basepkg=$hostpkg
  130. eval E_$basepkg=$hostpkg.$ext
  131. done < ${DIR_PKG}/.${FILE_NEWEST}.paste
  132. for HOST in $SLACK_HOSTS
  133. do
  134. UPDATED=0
  135. SKIPPED=0
  136. CURRENT=0
  137. UNKNOWN=0
  138. TOTAL=0
  139. CHECKED=0
  140. FILL=$((28 - $(echo $HOST | wc -c)))
  141. if [ $FILL -le 0 ]
  142. then
  143. FILL=4
  144. fi
  145. FL="$(yes "_" | head -$FILL | xargs echo | sed -e 's| ||g;s|_| |g')"
  146. # Check if package list exist
  147. if [ -f ${DIR_PKG}/${HOST} ]
  148. then
  149. if [ "$VERBOSE" != "1" ]; then
  150. echo -n " => $HOST "
  151. else
  152. echo " => $HOST "
  153. fi
  154. # Cleanup old files
  155. rm ${DIR_UPD}/${FILE_UNKPACKS}${HOST} >/dev/null 2>&1
  156. rm ${DIR_UPD}/${FILE_UPDATES}${HOST} >/dev/null 2>&1
  157. rm ${DIR_UPD}/${FILE_UPDATES}${HOST}.* >/dev/null 2>&1
  158. # Generate file with package basenames
  159. rev < ${DIR_PKG}/$HOST | cut -d- -f4- | rev | sed -e 's|.*/||;s|[^A-Za-z0-9_]|_|g' > ${DIR_UPD}/${FILE_UPDATES}${HOST}.base
  160. paste ${DIR_PKG}/$HOST ${DIR_UPD}/${FILE_UPDATES}${HOST}.base > ${DIR_UPD}/${FILE_UPDATES}${HOST}.paste
  161. TOTAL=$(wc -l < ${DIR_UPD}/${FILE_UPDATES}${HOST}.paste)
  162. while read hostpkg basepkg
  163. do
  164. CHECKED=$(($CHECKED + 1))
  165. # aaa_elflibs should not be updated
  166. if [ "$basepkg" = "aaa_elflibs" ]; then
  167. continue
  168. fi
  169. # Get package from the distro packages
  170. # This contains FULL directory + package name
  171. eval distro_package="\$$basepkg"
  172. eval distro_package_ext="\$E_$basepkg"
  173. if [ "$distro_package" != "" -a "$distro_package" != "\$" ]
  174. then # Host package exist in the distro packages
  175. distropkg="${distro_package##*/}" # Faster basename using build-in BASH tricks
  176. if [ "$distropkg" != "$hostpkg" ]
  177. then
  178. UPDATED=$(($UPDATED + 1))
  179. echo "\
  180. UPDATE=\"\$UPDATE ${distro_package_ext}\" # EXISTING: ${hostpkg} \
  181. " >> ${DIR_UPD}/${FILE_UPDATES}${HOST}.newpkgs
  182. if [ "$VERBOSE" == "1" ]; then
  183. echo " UPD: $hostpkg -> $distropkg ($distro_package_ext)"
  184. fi
  185. else
  186. CURRENT=$(($CURRENT + 1))
  187. if [ "$VERBOSE" == "1" ]; then
  188. echo " CURR: $hostpkg -> $distropkg ($distro_package_ext)"
  189. fi
  190. fi
  191. else # Add to unknown packages
  192. UNKNOWN=$(($UNKNOWN+1))
  193. if [ "$VERBOSE" == "1" ]; then
  194. echo " UNKN: $hostpkg"
  195. fi
  196. echo "$hostpkg" >> ${DIR_UPD}/${FILE_UNKPACKS}${HOST}
  197. fi
  198. if [ "$VERBOSE" != "1" ]; then
  199. echo -n " => ${HOST}${FL} Check $CHECKED of $TOTAL"
  200. fi
  201. done < ${DIR_UPD}/${FILE_UPDATES}${HOST}.paste
  202. # Skip ignored packages
  203. if [ -s ${DIR_UPD}/${FILE_UPDATES}${HOST}.newpkgs -a \
  204. -f "do_not_update" -a \
  205. "$SKIP_IGNORE" != "1" ]
  206. then
  207. ignore_packs=$(grep ^${HOST}: do_not_update | sed -e 's|^.*:|/|g;s| |\||g' | xargs echo | sed -e 's| |\||g')
  208. if [ "$ignore_packs" != "" ]
  209. then
  210. grep -v -E "${ignore_packs}" ${DIR_UPD}/${FILE_UPDATES}${HOST}.newpkgs > ${DIR_UPD}/.${HOST}.newpkgs.tmp
  211. if [ -f ${DIR_UPD}/.${HOST}.newpkgs.tmp ]
  212. then
  213. skip1=$(wc -l < ${DIR_UPD}/${FILE_UPDATES}${HOST}.newpkgs)
  214. skip2=$(wc -l < ${DIR_UPD}/.${HOST}.newpkgs.tmp)
  215. SKIPPED=$(($skip1 - $skip2))
  216. UPDATED=$(($UPDATED - $SKIPPED))
  217. fi
  218. mv ${DIR_UPD}/.${HOST}.newpkgs.tmp ${DIR_UPD}/${FILE_UPDATES}${HOST}.newpkgs
  219. if [ ! -s ${DIR_UPD}/${FILE_UPDATES}${HOST}.newpkgs ]
  220. then
  221. rm ${DIR_UPD}/${FILE_UPDATES}${HOST}.newpkgs
  222. fi
  223. fi
  224. fi
  225. status="${UPDATED} for update "
  226. if [ "$UPDATED" = "0" ]; then
  227. status="Up to date "
  228. fi
  229. if [ "$CURRENT" = "0" ]; then
  230. status="No host info "
  231. fi
  232. echo -n " => ${HOST}${FL} ${status}/cr ${CURRENT} un ${UNKNOWN} sk ${SKIPPED} new ${UPDATED}/"
  233. echo
  234. # Add intereter
  235. if [ -s ${DIR_UPD}/${FILE_UPDATES}${HOST}.newpkgs ]
  236. then
  237. sort ${DIR_UPD}/${FILE_UPDATES}${HOST}.newpkgs > ${DIR_UPD}/.${HOST}.newpkgs.tmp
  238. mv ${DIR_UPD}/.${HOST}.newpkgs.tmp ${DIR_UPD}/${FILE_UPDATES}${HOST}.newpkgs
  239. (echo '#!/bin/sh'
  240. echo
  241. echo "DL_HOST=\"${DL_HOST}\""
  242. echo "DL_PRG=\"${DL_PRG}\""
  243. echo "DL_PRG_OPTS=\"${DL_PRG_OPTS}\""
  244. echo
  245. echo "MD5_CHECK=\"${MD5_CHECK}\""
  246. echo "SIG_CHECK=\"${SIG_CHECK}\""
  247. echo
  248. echo "REMOTE_DIR=\"${REMOTE_DIR}\""
  249. echo "REMOTE_DIR_DEL=\"${REMOTE_DIR_DEL}\""
  250. echo
  251. echo "SMART_UPGRADE=\"${SMART_UPGRADE}\""
  252. echo
  253. echo "GENERATED=\"1\""
  254. echo
  255. echo "# If you don't want package to be updated just delete the line."
  256. echo
  257. # pkgtools and tar must be first
  258. # glibc and elflibs next
  259. cat ${DIR_UPD}/${FILE_UPDATES}${HOST}.newpkgs | grep a/pkgtools
  260. cat ${DIR_UPD}/${FILE_UPDATES}${HOST}.newpkgs | grep a/tar
  261. cat ${DIR_UPD}/${FILE_UPDATES}${HOST}.newpkgs | grep a/glibc
  262. cat ${DIR_UPD}/${FILE_UPDATES}${HOST}.newpkgs | grep a/elflibs
  263. cat ${DIR_UPD}/${FILE_UPDATES}${HOST}.newpkgs | grep -v -E "a/(pkgtools|tar|glibc|elflibs)"
  264. echo "PKG_LIBCAP=\"`grep libcap- ${DIR_PKG}/${FILE_NEWEST} 2>/dev/null`\"";
  265. echo "PKG_XZ=\"`grep xz- ${DIR_PKG}/${FILE_NEWEST} 2>/dev/null`\"";
  266. echo "PKG_SED=\"`grep sed- ${DIR_PKG}/${FILE_NEWEST} 2>/dev/null`\"";
  267. echo "PKG_COREUTILS=\"`grep coreutils- ${DIR_PKG}/${FILE_NEWEST} 2>/dev/null`\"";
  268. echo "PKG_UTEMPTER=\"`grep utempter- ${DIR_PKG}/${FILE_NEWEST} 2>/dev/null`\"";
  269. echo "PKG_MODULEINITTOOLS=\"`grep module-init-tools- ${DIR_PKG}/${FILE_NEWEST} 2>/dev/null`\"";
  270. echo "PKG_AAAELFLIBS=\"`grep aaa_elflibs- ${DIR_PKG}/${FILE_NEWEST} 2>/dev/null`\"";
  271. echo
  272. grep -v ^# update_script.sh
  273. ) > ${DIR_UPD}/${FILE_UPDATES}${HOST}
  274. fi
  275. # Cleanup
  276. rm ${DIR_UPD}/${FILE_UPDATES}${HOST}.* 2>/dev/null
  277. fi
  278. done
  279. echo
  280. }
  281. # Upgrade remote hosts
  282. upgrade_machines() {
  283. NOW=$(date +%Y-%m-%d)
  284. echo "===> Upgrating hosts..."
  285. for HOST in $SLACK_HOSTS
  286. do
  287. hname=$(hostname 2>/dev/null)
  288. hname_full=$(hostname -f 2>/dev/null)
  289. if [ -f ${DIR_UPD}/${FILE_UPDATES}${HOST} ]
  290. then
  291. # Localhost
  292. if [ "$HOST" == "$hname" -o \
  293. "$HOST" == "$hname_full" -o \
  294. "$HOST" == "localhost" ]
  295. then
  296. echo " ---> $HOST (Local machine)"
  297. # Use su if we're running not as root
  298. if [ "$(id -u)" != "0" ]; then
  299. echo " Enter root password"
  300. (su -c "/bin/sh ${DIR_UPD}/${FILE_UPDATES}${HOST}") 2>&1 | tee ${DIR_UPD}/log_${FILE_UPDATES}${HOST}
  301. else
  302. (/bin/sh ${DIR_UPD}/${FILE_UPDATES}${HOST}) 2>&1 | tee ${DIR_UPD}/log_${FILE_UPDATES}${HOST}
  303. fi
  304. # Remote host
  305. else
  306. echo " ---> $HOST"
  307. (cat ${DIR_UPD}/${FILE_UPDATES}${HOST} | \
  308. ${RSH_UPGRADE} ${HOST} \
  309. "cat - > ${FILE_UPDATES}${HOST}_${NOW}; \
  310. /bin/sh ${FILE_UPDATES}${HOST}_${NOW};") 2>&1 | tee ${DIR_UPD}/log_${FILE_UPDATES}${HOST}
  311. fi
  312. fi
  313. done
  314. }
  315. # Send upgrade scripts to hosts
  316. distribute_up_scripts() {
  317. NOW=$(date +%Y-%m-%d)
  318. echo "===> Copying upgrade scripts..."
  319. for HOST in $SLACK_HOSTS
  320. do
  321. if [ -f ${DIR_UPD}/${FILE_UPDATES}${HOST} ]
  322. then
  323. # Localhost
  324. if [ "$HOST" == "$(hostname)" -o \
  325. "$HOST" == "$(hostname -f)" -o \
  326. "$HOST" == "localhost" ]
  327. then
  328. echo " ---> $HOST (Local machine - no need to copy upgrade script)"
  329. # Remote host
  330. else
  331. echo " ---> $HOST"
  332. cat ${DIR_UPD}/${FILE_UPDATES}${HOST} | \
  333. ${RSH_UPGRADE} ${HOST} \
  334. "cat - > ${FILE_UPDATES}${HOST}_${NOW}"
  335. fi
  336. fi
  337. done
  338. }
  339. if [ "$1" = "" ]; then
  340. usage
  341. fi
  342. # Process command line arguments
  343. while [ "$1" != "" ]; do
  344. param=$1
  345. shift
  346. case "$param" in
  347. --local)
  348. SLACK_HOSTS="localhost"
  349. ;;
  350. --host)
  351. if [ "$1" != "" ]; then
  352. SLACK_HOSTS=""
  353. fi
  354. while [ "$1" != "" ]; do
  355. param=$1
  356. case "$param" in
  357. --*)
  358. break
  359. ;;
  360. *)
  361. SLACK_HOSTS="$SLACK_HOSTS $param"
  362. ;;
  363. esac
  364. shift
  365. done
  366. ;;
  367. --file)
  368. HOSTS_FILE="$1"
  369. if [ "$HOSTS_FILE" = "" -o ! -f "$HOSTS_FILE" ]; then
  370. echo "*** --file parameter is missing or file not found."
  371. echo
  372. usage
  373. exit 1
  374. fi
  375. SLACK_HOSTS=`grep -v ^# $HOSTS_FILE`
  376. shift
  377. ;;
  378. --sync)
  379. DO_SYNC="1"
  380. ;;
  381. --collect)
  382. DO_COLLECT="1"
  383. ;;
  384. --gen)
  385. DO_GEN="1"
  386. ;;
  387. --dist)
  388. DO_DIST="1"
  389. ;;
  390. --skip-ignore)
  391. SKIP_IGNORE="1"
  392. ;;
  393. --upgrade)
  394. DO_UPGRADE="1"
  395. ;;
  396. --verbose)
  397. VERBOSE="1"
  398. ;;
  399. *)
  400. usage
  401. ;;
  402. esac
  403. done
  404. if [ "$SLACK_HOSTS" = "" ]; then
  405. echo "*** No hosts. Check --host parameter, --file parameter ot 'upgrade_hosts' file."
  406. echo
  407. exit 1
  408. fi
  409. echo -n "---> Hosts: "
  410. echo $SLACK_HOSTS
  411. echo
  412. [ "$DO_SYNC" = "1" ] && sync_master_list
  413. [ "$DO_COLLECT" = "1" ] && collect_package_lists
  414. [ "$DO_GEN" = "1" ] && generate_upgrade_scripts
  415. [ "$DO_DIST" = "1" ] && distribute_up_scripts
  416. [ "$DO_UPGRADE" = "1" ] && upgrade_machines