pkg_updatecheck.sh 10.3 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 48 49 50 51 52 53 54 55 56 57 58
# 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"
updates=""
core_version=""
pkg_running=""
packes_output=""
last_check="unknown"
packages_upgraded=""
packages_new=""
required_space="none"
download_size="none"
itemcount=0
linecount=0
59 60
timer=0
timeout=30 # Wait for a maximum number of seconds to determine connection issues
61 62 63 64 65 66 67

# File location variables
package_json_output="/tmp/pkg_status.json"
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 85 86 87
      do
        sleep 1 # wait for 1 second
        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
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 125 126 127 128 129 130
            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
              # 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
131
                    else
132
                      i=`echo $i | tr -d :`
133
                      #echo "name:$i"
134
                      if [ "$packages_new" == "" ]; then
135 136 137 138
                        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
139 140
                    fi
                  fi
141 142 143 144
                  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
145
                fi
146 147 148
                linecount=`echo $linecount + 1 | bc`
                if [ "$i" == "INSTALLED:" ]; then
                  itemcount=`echo $linecount + 2 | bc`
149
                fi
150
              done
151

152 153 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
              # 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

180 181 182 183 184 185
              # 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
186
                    else
187
                      i=`echo $i | tr -d :`
188
                      if [ "$packages_upgraded" == "" ]; then
189 190 191 192
                        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
193 194
                    fi
                  fi
195 196 197 198 199 200 201
                  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
202
                fi
203 204 205
                linecount=`echo $linecount + 1 | bc`
                if [ "$i" == "UPGRADED:" ]; then
                  itemcount=`echo $linecount + 4 | bc`
206
                fi
207 208 209
              done
              if [ "$core_version" == "" ]; then
                core_version="unknown"
210 211 212
              fi
            fi
          fi
213 214 215 216 217 218 219
        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
220 221 222
        fi
      else
          # We have an connection issue and could not reach the pkg repository in timely fashion
223 224 225 226 227
          # Kill all running pkg instances
          pkg_running=`ps -x | grep "pkg " | grep -v "grep"`
          if [ "$pkg_running" != "" ]; then
            killall pkg
          fi
228
      fi
229
      # Get date/timestamp
230
      last_check=`date`
231
      # Write our json structure to disk
232
      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]}" > $package_json_output
233 234 235
else
  # pkg is already running, quitting
fi