pkg_updatecheck.sh 10.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
#!/bin/sh

# Copyright (C) 2014 Deciso B.V.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
#    this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.


# USAGE:
29
# Add this file to a CRON job to check for package updates regularly
30 31 32 33 34 35
#
# This script generates a json structured file with the following content:
# connection: error|ok
# repository: error|ok
# last_ckeck: <date_time_stamp>
# updates: <#num_of_updates>
36
# core_version: unknown|<current core version>
37 38 39
# download_size: none|<size_of_total_downloads>
# extra_space_required: none|<size_of_total_extra_space_required>
# new_packages: array with { name: <package_name>, version: <package_version> }
40
# reinstall_packages: array with { name: <package_name>, version: <package_version> }
41 42 43 44 45 46 47
# upgrade_packages: array with { name: <package_name>, current_version: <current_version>, new_version: <new_version> }

# TODO: Add object with items that will be removed or uninstalled

# Variables used
connection="error"
repository="error"
48
upgrade_needs_reboot="0"
49 50 51 52 53 54 55 56 57 58 59
updates=""
core_version=""
pkg_running=""
packes_output=""
last_check="unknown"
packages_upgraded=""
packages_new=""
required_space="none"
download_size="none"
itemcount=0
linecount=0
60 61
timer=0
timeout=30 # Wait for a maximum number of seconds to determine connection issues
62 63 64 65 66 67

# File location variables
tmp_pkg_output_file="/tmp/packages.output"
tmp_pkg_update_file="/tmp/pkg_updates.output"

# Check if pkg is already runnig
68
pkg_running=`ps -x | grep "pkg " | grep -v "grep"`
69 70
if [ "$pkg_running" == "" ]; then
      # start pkg update
71 72 73 74
      pkg update -f > $tmp_pkg_update_file &
      pkg_running="started" # Set running state to arbitrary value
      timer=$timeout # Reset our timer

75 76
      # Lets get coreversion first
      core_version=`pkg info opnsense | grep 'Version' | awk -F '[:]' '{print $2}'` # Changed to reflect current installed core version
77

78
      # Timeout loop for pkg update -f
79
      while [ "$pkg_running" != "" ] && [ $timer -ne 0 ];
80 81 82 83 84
      do
        sleep 1 # wait for 1 second
        pkg_running=`ps -x | grep "pkg " | grep -v "grep"`
        timer=`echo $timer - 1 | bc`
      done
85

86 87
      ## check if timeout is not reached
      if [ $timer -gt 0 ] ; then
88 89
        # Connection is ok
        connection="ok"
90 91 92 93 94 95 96
        # Now check if there are upgrades
        pkg upgrade -n > $tmp_pkg_output_file &
        # Reset timer before getting upgrade info
        timer=$timeout # Reset our timer
        pkg_running="started" # Set running state to arbitrary value

        # Timeout loop for pkg upgrade -n
97
        while [ "$pkg_running" != "" ] && [ $timer -ne 0 ];
98 99 100 101 102 103 104 105 106 107 108 109 110 111
        do
          sleep 1 # wait for 1 second
          #pkg_running=`ps | grep 'pkg update -f' | grep -v 'grep' | tail -n 1 | awk -F '[ ]' '{print $1}'`
          pkg_running=`ps -x | grep "pkg " | grep -v "grep"`
          timer=`echo $timer - 1 | bc`
        done

        ## check if timeout is not reached
        if [ $timer -gt 0 ] ; then
          # Check for additional repository errors
          repo_ok=`cat $tmp_pkg_output_file | grep 'Unable to update repository'`
          if [ "$repo_ok" == "" ]; then
            # Repository can be used for updates
            repository="ok"
112
            updates=`cat $tmp_pkg_output_file | grep 'The following' | awk -F '[ ]' '{print $3}'`
113 114 115 116 117 118 119 120 121 122 123 124
            if [ "$updates" == "" ]; then
              # There are no updates
              updates="0"
            else
              required_space=`cat $tmp_pkg_output_file | grep 'The process will require' | awk -F '[ ]' '{print $5$6}'`
              if [ "$required_space" == "" ]; then
                required_space="none"
              fi
              download_size=`cat $tmp_pkg_output_file | grep 'to be downloaded' | awk -F '[ ]' '{print $1$2}'`
              if [ "$download_size" == "" ]; then
                download_size="none"
              fi
125

126 127
              upgrade_needs_reboot=`pkg upgrade -nq os-update | grep UPGRADED | wc -l | awk '{print $1;}'`

128 129 130 131 132 133
              # First check if there are new packages that need to be installed
              for i in $(cat $tmp_pkg_output_file); do
                if [ "$itemcount" -gt "$linecount" ]; then
                  if [  `echo $linecount + 2 | bc` -eq "$itemcount" ]; then
                    if [ "`echo $i | grep ':'`" == "" ]; then
                      itemcount=0 # This is not a valid item so reset item count
134
                    else
135
                      i=`echo $i | tr -d :`
136
                      #echo "name:$i"
137
                      if [ "$packages_new" == "" ]; then
138 139 140 141
                        packages_new=$packages_new"{\"name\":\"$i\"," # If it is the first item then we do not want a seperator
                      else
                        packages_new=$packages_new", {\"name\":\"$i\","
                      fi
142 143
                    fi
                  fi
144 145 146 147
                  if [  `echo $linecount + 1 | bc` -eq "$itemcount" ]; then
                    packages_new=$packages_new"\"version\":\"$i\"}"
                    itemcount=`echo $itemcount + 2 | bc` # Get ready for next item
                  fi
148
                fi
149 150 151
                linecount=`echo $linecount + 1 | bc`
                if [ "$i" == "INSTALLED:" ]; then
                  itemcount=`echo $linecount + 2 | bc`
152
                fi
153
              done
154

155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
              # Check if there are packages that need to be reinstalled
              for i in $(cat $tmp_pkg_output_file | cut -d '(' -f1); do
                #echo $i
                if [ "$itemcount" -gt "$linecount" ]; then
                  #echo $i
                  if [  `echo $linecount + 1 | bc` -eq "$itemcount" ]; then
                    if [ "`echo $i | grep '-'`" == "" ]; then
                      itemcount=0 # This is not a valid item so reset item count
                    else
                      name=`echo $i | cut -d '-' -f1`
                      version=`echo $i | cut -d '-' -f2`
                      itemcount=`echo $itemcount + 1 | bc` # Get ready for next item
                      if [ "$packages_reinstall" == "" ]; then
                        packages_reinstall=$packages_reinstall"{\"name\":\"$name\"," # If it is the first item then we do not want a seperator
                        packages_reinstall=$packages_reinstall"\"version\":\"$version\"}"
                      else
                        packages_reinstall=$packages_reinstall", {\"name\":\"$name\","
                        packages_reinstall=$packages_reinstall"\"version\":\"$version\"}"
                      fi
                    fi
                  fi
                fi
                linecount=`echo $linecount + 1 | bc`
                if [ "$i" == "REINSTALLED:" ]; then
                  itemcount=`echo $linecount + 1 | bc`
                fi
              done

183 184 185 186 187 188
              # Now check if there are upgrades to install
              for i in $(cat $tmp_pkg_output_file); do
                if [ "$itemcount" -gt "$linecount" ]; then
                  if [  `echo $linecount + 4 | bc` -eq "$itemcount" ]; then
                    if [ "`echo $i | grep ':'`" == "" ]; then
                      itemcount=0 # This is not a valid item so reset item count
189
                    else
190
                      i=`echo $i | tr -d :`
191
                      if [ "$packages_upgraded" == "" ]; then
192 193 194 195
                        packages_upgraded=$packages_upgraded"{\"name\":\"$i\"," # If it is the first item then we do not want a seperator
                      else
                        packages_upgraded=$packages_upgraded", {\"name\":\"$i\","
                      fi
196 197
                    fi
                  fi
198 199 200 201 202 203 204
                  if [  `echo $linecount + 3 | bc` -eq "$itemcount" ]; then
                    packages_upgraded=$packages_upgraded"\"current_version\":\"$i\","
                  fi
                  if [  `echo $linecount + 1 | bc` -eq "$itemcount" ]; then
                    packages_upgraded=$packages_upgraded"\"new_version\":\"$i\"}"
                    itemcount=`echo $itemcount + 4 | bc` # Get ready for next item
                  fi
205
                fi
206 207 208
                linecount=`echo $linecount + 1 | bc`
                if [ "$i" == "UPGRADED:" ]; then
                  itemcount=`echo $linecount + 4 | bc`
209
                fi
210 211 212
              done
              if [ "$core_version" == "" ]; then
                core_version="unknown"
213 214 215
              fi
            fi
          fi
216 217 218 219 220 221 222
        else
          # We have an connection issue and could not reach the pkg repository in timely fashion
          # Kill all running pkg instances
          pkg_running=`ps -x | grep "pkg " | grep -v "grep"`
          if [ "$pkg_running" != "" ]; then
            killall pkg
          fi
223 224 225
        fi
      else
          # We have an connection issue and could not reach the pkg repository in timely fashion
226 227 228 229 230
          # Kill all running pkg instances
          pkg_running=`ps -x | grep "pkg " | grep -v "grep"`
          if [ "$pkg_running" != "" ]; then
            killall pkg
          fi
231
      fi
232
      # Get date/timestamp
233
      last_check=`date`
234
      # Write our json structure to disk
235
      echo "{\"connection\":\"$connection\",\"repository\":\"$repository\",\"last_check\":\"$last_check\",\"updates\":\"$updates\",\"core_version\":\"$core_version\",\"download_size\":\"$download_size\",\"extra_space_required\":\"$required_space\",\"new_packages\":[$packages_new],\"reinstall_packages\":[$packages_reinstall],\"upgrade_packages\":[$packages_upgraded],\"upgrade_needs_reboot\":\"$upgrade_needs_reboot\"}"
236 237 238
else
  # pkg is already running, quitting
fi