Automating update.php

I've been playing around with scripting update.php for a while now. I remember having a working script a few months back, but I never really put it into production and it looks like there's been some Drupal core changes that broke what I wrote before anyhow. I've rewritten most of it, and from what I can tell, it works pretty well for Drupal 6.

One of the main goals of any Drupal shell script that I write, is that it works on any Drupal installation, without bootstrapping. This is essential for me at work since we run a lot of individual Drupal installs. I'm transitioning over to drush to replace some of my scripts, but drush gets information about the site by bootstrapping. This makes a lot of sense for what it does, but it takes a bit more setting up, and isn't as portable as a vanilla bash script.

So with that in mind, here are a couple things to note about this script (and any other Drupal-relation shell script I post):

#!/bin/bash
#===============================================================================
#
#          FILE:  drpl_update_db.sh
#
#         USAGE:  ./drpl_update_db.sh -u www.blah.com -p /var/www/wwww.blah.com -v 6
#
#   DESCRIPTION:  Runs update.php given the path and url of the site
#
#        AUTHOR:  msonnabaum
#==============================================================================

usage="usage: $0 -u url -p path -v version"

while getopts ":u:s:p:v:h" OPT
do
  case $OPT in
    u ) BASEURL=$OPTARG ;;
    s ) SITE=$OPTARG ;;
    p ) DRUPALPATH=${OPTARG%*/} ;;
    v ) DRUPALVERSION=$OPTARG ;;
    h ) echo $usage; exit 1 ;;
    \?) echo $usage; exit 1 ;;
    * ) echo $usage; exit 1 ;;
  esac
done

if [[ -z "${DRUPALPATH}" ]]
then
  DRUPALPATH=$(pwd)
fi

if [[ -z "${SITE}" ]]
then
  SITE='default'
fi

CURUSER=`whoami`

if [ "$CURUSER" != "root" ]
then
  USESUDO='sudo'
fi

get_vars() {
  SELECTTAG="${1}"
  NAME=$(echo "${1}" | awk -F'name="' '{print $2}' | awk -F\" '{print $1}')
  SELECTED=$(echo "${1}" |sed 's#>#\
  #g'
| grep "selected" | awk -F'value="' '{print $2}' | awk -F\" '{print $1}' )
  echo -n "$(echo ${NAME}| sed 's/\[/%5B/;s/\]/%5D/')=${SELECTED}"
}

get_module_updates() {
  MODULES=$(cat "${1}"| egrep -o "<select(.*)</select>")
  let count=0
  echo "${MODULES}" | while read line
  do
    MODULES[$count]="${line}"
    if [[ $count != 0 ]]
    then
      echo -n "&"
    fi
    get_vars "${MODULES[${count}]}"
    ((count++))
  done
}

get_url() {  
  URL=$(drpl_is_drupal.sh -u -d ${1} | grep http)
  echo ${URL}
}


if [[ -z "${BASEURL}" ]]
then
  BASEURL=$(get_url ${DRUPALPATH})
  echo "Using ${BASEURL}/update.php ...."
fi

update5() {
  # d5
  echo "TO DO!!!"
}

update6() {
 
  echo "${USESUDO} sed -i.bak -e '/^$update_free_access/s/FALSE/TRUE/g' $DRUPALPATH/sites/$SITE/settings.php "
  ${USESUDO} sed -i.bak -e '/^$update_free_access/s/FALSE/TRUE/g' $DRUPALPATH/sites/$SITE/settings.php

  TOKEN=$(curl -s -c /tmp/cookie.txt ${BASEURL}/update.php?op=info | grep token | sed 's#.*token=\(.*\)\"><in.*#\1#')

  tempsub=`basename $0`
  UPDATE_PAGE=`mktemp /tmp/${tempsub}.XXXXXX` || exit 1
 
  curl -s -F 'op=selection' -b /tmp/cookie.txt ${BASEURL}/update.php?token=${TOKEN} > ${UPDATE_PAGE}
 
  FORMBUILDID=$(egrep -o "form_build_id(.*)>" ${UPDATE_PAGE} | sed 's#.*id=\"\(.*\)\".*value=".*#\1#')
 
  MODVARS=$(get_module_updates ${UPDATE_PAGE})
  FORMVARS=$(echo "op=selection&${MODVARS}&has_js=&op=Update&form_build_id=${FORMBUILDID}&form_id=update_script_selection_form")
 
  RESULT=$(curl -L -s -d "${FORMVARS}" -b /tmp/cookie.txt ${BASEURL}/update.php?token=${TOKEN})
  RESULTURL=$(echo ${RESULT} | sed 's#.*URL=\(.*js\).*#\1#')

  START=$(curl -L -s -m 30 -b /tmp/cookie.txt ${RESULTURL})
  STARTURL=$(echo ${START} | sed 's#.*URL=\(.*finished\).*#\1#')
  FINISHED=$(curl -L -s -m 30 -b /tmp/cookie.txt ${STARTURL})
 
  HTMLOUTPUT=$(echo ${BASEURL}| sed 's#.*//\(.*\)#\1#;s#/#_#g;s#\.#_#g')
  echo "${FINISHED}" > ${HTMLOUTPUT}_update.html

  echo "${USESUDO} mv $DRUPALPATH/sites/$SITE/settings.php.bak $DRUPALPATH/sites/$SITE/settings.php"
  ${USESUDO} mv $DRUPALPATH/sites/$SITE/settings.php.bak $DRUPALPATH/sites/$SITE/settings.php
}


if [ "${DRUPALVERSION}" = "5" ]
then
  update5
elif [ "${DRUPALVERSION}" = "6" ]
then
  echo "${DRUPALPATH}"
  update6
else
  echo "Must specify a Drupal version!"
  exit 1
fi

Syntax highlighting might have corrupted your script here.

There appear to be a lot of extraneous characters, such as "|>" after many of the close braces, for example:


curl -s -F 'op=selection' -b /tmp/cookie.txt ${BASEURL}|>/update.php?token=${TOKEN}|> > ${UPDATE_PAGE}|>

There may be other corruptions as well; I've been able to get the script to run by snipping out those "|>" characters, but still no luck. (Curl persistently complains, "curl: no URL specified!") Can you post it plain text?

Thanks for pointing that

Thanks for pointing that out!

Just updated to the latest geshi library and it seems to have cleared up.

I've since added another python script that gets called to parse the output. I'll try to post it soon...

Problem with TOKEN

Hi.
I have next code:

TOKEN=$(curl -s -c /tmp/cookie.txt ${BASEURL}/update.php?op=info | grep token | sed 's#.*token=\(.*\)\"><in.*#\1#')
echo "token = ${TOKEN}"

but i see:

token = <form method="post" action="update.php?op=selection&amp;token=0f8fe511ffeecf32138ac4ce6a0f227c"><p><input type="submit" value="Continue" /></p></form>

it not token it big string((

and:
curl: option -->: is unknown

Please, help me to fix this bug.

Awesome work

Great job, bud. Thanks for publishing this.