pkg_updatecheck.sh 10.6 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 68

# 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
69
pkg_running=`ps -x | grep "pkg " | grep -v "grep"`
70 71
if [ "$pkg_running" == "" ]; then
      # start pkg update
72 73 74 75
      pkg update -f > $tmp_pkg_update_file &
      pkg_running="started" # Set running state to arbitrary value
      timer=$timeout # Reset our timer

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

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

87 88
      ## check if timeout is not reached
      if [ $timer -gt 0 ] ; then
89 90
        # Connection is ok
        connection="ok"
91 92 93 94 95 96 97
        # 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
98
        while [ "$pkg_running" != "" ] && [ $timer -ne 0 ];
99 100 101 102 103 104 105 106 107 108 109 110 111 112
        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"
113
            updates=`cat $tmp_pkg_output_file | grep 'The following' | awk -F '[ ]' '{print $3}'`
114 115 116 117 118 119 120 121 122 123 124 125
            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
126

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

129 130 131 132 133 134
              # 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
135
                    else
136
                      i=`echo $i | tr -d :`
137
                      #echo "name:$i"
138
                      if [ "$packages_new" == "" ]; then
139 140 141 142
                        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
143 144
                    fi
                  fi
145 146 147 148
                  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
149
                fi
150 151 152
                linecount=`echo $linecount + 1 | bc`
                if [ "$i" == "INSTALLED:" ]; then
                  itemcount=`echo $linecount + 2 | bc`
153
                fi
154
              done
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 183
              # 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

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

# output json data
242
if [ -f $package_json_output ]; then
243 244
      cat $package_json_output
fi