Advertisement
Valicek1

copy-to-target v1

Aug 28th, 2017
647
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 8.49 KB | None | 0 0
  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
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement