daily pastebin goal
7%
SHARE
TWEET

copy-to-target v1

Valicek1 Aug 28th, 2017 419 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/env bash
  2. #
  3. # Filename: copy-to-target.bash
  4. # Version: ???
  5. # Release date: 2017-08-28
  6. # Intended compatibility: WSUS Offline Update Version 10.9.2 and newer
  7. # Tested, but use with eyes open - there are used some nasty tricks to
  8. #   make XCOPY and Rsync exclude files compatible!
  9. #
  10. # Author: Václav Valíček <vaclav@valicek.name>
  11. #
  12. # License
  13. #
  14. #     This file is free software: you can redistribute it and/or modify
  15. #     it under the terms of the GNU General Public License as published
  16. #     by the Free Software Foundation, either version 3 of the License,
  17. #     or (at your option) any later version.
  18. #
  19. #     This file is distributed in the hope that it will be useful,
  20. #     but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. #     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  22. #     General Public License for more details.
  23. #
  24. #     You should have received a copy of the GNU General
  25. #     Public License along with this program.  If not, see
  26. #     <http://www.gnu.org/licenses/>.
  27. #
  28.  
  29. # USAGE:
  30. # ./copy-to-target.bash UPDATE LANGUAGE OUTPUT_PATH [OPTION,[OPTION..]]
  31.  
  32. # Allowed UPDATE fields
  33. #  - see $WinTargets and $OfcTargets arrays
  34.  
  35. # Allowed LANGUAGE fields
  36. #  - see $WinLangs/$OfcLangs arrays respectively
  37.  
  38. # Allowed OUTPUT_PATH
  39. #  - anywhere you have write access
  40.  
  41. # Allowed Options
  42. # -excludesp        - Exclude ServicePacks
  43. # -excludesw        - Exclude MS Software
  44. # -includedotnet    - Include .NET
  45. # -includemsse      - Include MS Security Essentials
  46. # -includewddefs    - Include Windows Defender Definitions
  47. #             (W8.1 and W10)
  48. # -cleanup      - Purge Output directory before doing anything
  49. # -hardlinks        - Try to use Hardlinks to save some space
  50. #             (must be same mountpoint/device)
  51.  
  52.  
  53. # Unofficial bash strict mode
  54. # http://redsymbol.net/articles/unofficial-bash-strict-mode/
  55. set -euo pipefail
  56. IFS=$'\n\t'
  57.  
  58.  
  59. # Configuration
  60. readonly script_dir=$(dirname $(realpath $0))
  61. readonly temp_dir="/tmp/wsusoffline_temp"
  62. readonly timestamp_dir="../timestamps"
  63. readonly log_dir="../log"
  64. readonly logfile="${log_dir}/copy-to-target.log"
  65. readonly cache_dir="../cache"
  66. readonly filter_dir="../exclude"
  67.  
  68. # Windows Targets + ofc
  69. readonly WinTargets=(w60 w60-x64 w61 w61-x64 w62-x64 w63 w63-x64 w100 w100-x64)
  70. readonly WinLangs=(glb)
  71. # Defender vs msse
  72. # regular expression for installing Defender Defs, otherwise MSSE would be installed
  73. readonly WddefsTargets="w62|w63|w100"
  74. # Office Targets
  75. readonly OfcTargets=(ofc)
  76. readonly OfcLangs=(glb enu fra esn jpn kor rus ptg ptb deu nld ita chs cht plk hun csy sve trk ell ara heb dan nor fin)
  77.  
  78.  
  79.  
  80. # Log function
  81. # ========================================================================
  82. function log {
  83.     toPut="$(date "+%x %X") $@"
  84.     echo $toPut
  85.     echo "$toPut" >> $script_dir/$logfile
  86. }
  87.  
  88. # Die Function
  89. # die RC Log message
  90. # ========================================================================
  91. function die {
  92.     rc=$1
  93.     shift
  94.     log "$@"
  95.     exit $rc
  96. }
  97.  
  98.  
  99. # FINISH Trap (in the case of issue)
  100. # ========================================================================
  101. function finish {
  102.     log Cleaning up mess in $temp_dir
  103.     [ -d $temp_dir ] && rm -Rf $temp_dir
  104. }
  105.  
  106. # set the trap
  107. trap finish EXIT
  108.  
  109. # Does Array contain element?
  110. # Usage: containsElement "requested string" "${array[@]}"
  111. # ========================================================================
  112. function contains() {
  113.     local n=$#
  114.     local value=${!n}
  115.     for ((i=1;i < $#;i++)) {
  116.         if [ "${!i}" == "${value}" ]; then
  117.             return 0
  118.         fi
  119.     }
  120.     return 1
  121. }
  122.  
  123. # Run main Process
  124. # ========================================================================
  125.  
  126. # Write new block to logfile
  127. [ -f $logfile ] && echo "--------------------------------------------------------------------------" >> $logfile
  128. echo "copy-to-target script started" >> $logfile
  129. echo "--------------------------------------------------------------------------" >> $logfile
  130. log "CMD: $0 $@"
  131.  
  132. # Check number of arguments, at least two
  133. log "Checking arguments"
  134. [ $# -lt 3 ] && die 1 "You must specify at least three arguments!"
  135.  
  136. update=$1
  137. language=$2
  138. target_dir=$3
  139.  
  140. # Check, if its windows update
  141. if contains ${WinTargets[@]} $update
  142. then
  143.     # It's windows, check windows language
  144.     contains ${WinLangs[@]} $language || die 1 "Unknown Windows Language -> exiting"
  145. else
  146.     # It could be office or mistake
  147.     if contains ${OfcTargets[@]} $update
  148.     then
  149.         # It's office
  150.         contains ${OfcLangs[@]} $language || die 1 "Unknown Office Language -> exiting"
  151.     else
  152.         die 1 "Unknown UPDATE parameter -> exiting"
  153.     fi
  154. fi
  155.  
  156. log "UPDATE: $update"
  157. log "LANG:   $language"
  158. log "TARGET: $target_dir"
  159.  
  160. # End of main arguments parsing, parse also options
  161. # defaults
  162. opt_exclude_sp=0
  163. opt_exclude_sw=0
  164. opt_include_dotnet=0
  165. opt_include_msse=0
  166. opt_include_wddefs=0
  167. opt_cleanup=0
  168. opt_hardlinks=0
  169.  
  170. shift 3
  171. while [ $# -gt 0 ]
  172. do
  173.     case $1 in
  174.         "-excludesp") opt_exclude_sp=1
  175.             ;;
  176.         "-excludesw") opt_exclude_sw=1
  177.             ;;
  178.         "-includedotnet") opt_include_dotnet=1
  179.             ;;
  180.         "-includemsse") opt_include_msse=1
  181.             ;;
  182.         "-includewddefs")
  183.             if echo $update | grep -E $WddefsTargets > /dev/null
  184.             then
  185.                 opt_include_wddefs=1
  186.             else
  187.                 log "Uncompatlible Windows version and $1 flag,  setting -includemsse instead"
  188.                 opt_include_msse=1
  189.                 opt_include_wddefs=0
  190.             fi     
  191.             ;;
  192.         "-cleanup") opt_cleanup=1
  193.             ;;
  194.         "-hardlinks") opt_hardlinks=1
  195.             ;;
  196.         *) die 1 "Unknown option: $1 -> exiting!"
  197.             ;;
  198.     esac
  199.     shift
  200. done
  201.  
  202. [ $opt_exclude_sp -eq 1 ] && log "OPT: Exclude ServicePacks"
  203. [ $opt_exclude_sw -eq 1 ] && log "OPT: Exclude Updates of other SW"
  204. [ $opt_include_dotnet -eq 1 ] && log "OPT: Include .NET updates"
  205. [ $opt_include_msse -eq 1 ] && log "OPT: Include Microsoft Security Essentials"
  206. [ $opt_include_wddefs -eq 1 ] && log "OPT: Include Windows defender definitions"
  207. [ $opt_cleanup -eq 1 ] && log "OPT: Output path ($target_dir) will be purged"
  208.  
  209.  
  210. # Info
  211. log "Script dir: $script_dir"
  212. cd $script_dir
  213.  
  214. # Temp directory
  215. if [ ! -d $temp_dir ]
  216. then
  217.     log "Creating temp dir: $temp_dir"
  218.     mkdir $temp_dir
  219. else
  220.     log "Temp dir EXISTS!"
  221. fi
  222.  
  223. # Create filter
  224. log "Creating filter for $update ($language)"
  225. filter=$temp_dir/Filter-$update-$language
  226. excl_prefix=$filter_dir/ExcludeListUSB
  227.  
  228. # Main exclude for architecture
  229. [ -f $excl_prefix-$update.txt ] && cp $excl_prefix-$update.txt $filter || cp  $excl_prefix-$update-x86.txt $filter
  230.  
  231. # Customs
  232. [ -f $filter_dir/custom/ExcludeListUSB-$update.txt ] && cat $filter_dir/custom/ExcludeListUSB-$update.txt >> $filter
  233. # Customs x86
  234. [ -f $filter_dir/custom/ExcludeListUSB-$update-x86.txt ] && cat $filter_dir/custom/ExcludeListUSB-$update-x86.txt >> $filter
  235.  
  236. # Filter other locales than allowed ones
  237. locales=(${WinLangs[@]} ${OfcLangs[@]})
  238. for loc in ${locales[@]}
  239. do
  240.     # if locale is not same as chosen, add it to list
  241.     [ ! "$language" == "$loc" ] && echo "$loc/" >> $filter
  242. done
  243.  
  244. # Extend filter (with OPTS)
  245. [ $opt_exclude_sp -eq 1 ] && cat $filter_dir/ExcludeList-SPs.txt >> $filter
  246. [ $opt_exclude_sw -eq 1 ] && cat $filter_dir/ExcludeList-software.txt >> $filter
  247. [ $opt_include_dotnet -eq 0 ] && cat $filter_dir/ExcludeListISO-dotnet.txt >> $filter
  248. [ $opt_include_msse -eq 0 ] && cat $filter_dir/ExcludeList-msse.txt >> $filter
  249. [ $opt_include_wddefs -eq 0 ] && cat $filter_dir/ExcludeList-wddefs.txt >> $filter
  250.  
  251. # replace \ with /
  252. cat $filter | sed 's/\\/\//g' | sed 's/\r$//' > $filter.tmp
  253. # truncate file
  254. cat /dev/null > $filter
  255.  
  256. for line in $(cat $filter.tmp)
  257. do
  258.     # is it path (ends with slash)
  259.     if echo $line | grep -E '.*/$'  > /dev/null
  260.     then
  261.         echo $line >> $filter
  262.     else
  263.         printf '*%s*\n' $line >> $filter
  264.     fi
  265. done
  266.  
  267. [ -f $target_dir ] && rm -f $target_dir
  268.  
  269. if [ $opt_cleanup -eq 1 ]
  270. then
  271.     log "Clean UP"
  272.     rm -Rf $target_dir
  273.     log "Done"
  274. fi
  275.  
  276. mkdir -p $target_dir
  277.  
  278.  
  279. log "Synchronizing.."
  280.  
  281. cd ../client
  282.  
  283. if [ $opt_hardlinks -eq 1 ]
  284. then
  285.     src=$(realpath .)
  286.     tar=$(realpath $target_dir)
  287.     rsync -a  --log-file=$log_dir/rsync.txt --exclude-from=$filter --link-dest=$src $src/ $tar
  288. else
  289.     rsync -a  --log-file=$log_dir/rsync.txt --exclude-from=$filter  . $target_dir
  290. fi
  291.  
  292.  
  293. log "Sync done"
  294.  
  295. # Clean up Target
  296.  
  297. log "Cleaning up Target dir"
  298. for f in $(find $target_dir -printf "%P\n")
  299. do
  300.     # empty row - skip
  301.     [ "x$f" == "x" ] && continue
  302.  
  303.     # is it file or direcory?
  304.     if [ -f $target_dir/$f ]
  305.     then
  306.         # its a file
  307.         if [ ! -f $f ]
  308.         then
  309.             log "Remove file: $f"
  310.             rm -f $target_dir/$f
  311.         fi
  312.     else
  313.         # its a directory
  314.         if [ ! -d $f ]
  315.         then
  316.             log "Remove dir: $f"
  317.             rm -rf $target_dir/$f
  318.         fi
  319.     fi
  320. done
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top