Posts Tagged ‘bash’

Upgrade WordPress automatically

Sunday, July 7th, 2013

WordPress has a one-click upgrade feature, but it requires you to give it your FTP/SFTP credentials. If you log into SSH with keys instead of passwords, you can’t use it. I wrote a script that runs on the server (thus it needs no password or special permissions) to back up your current files, then upgrade.

Lines 6 through 10 features variables that you’ll probably want to alter before you run this script.

A few notes:

  • It only backs up the files, not the database, so if WordPress has a database update that breaks your database, hopefully you’ve got some other backup in place.
  • Sometimes after an update, WordPress will prompt you to please update the database. This script will not do that step – you still need to log in and click the button. This script will send you a reminder that an upgrade has been performed and which will allow you to both confirm that nothing was broken, and click the aforementioned button. I don’t trust myself to act on that reminder promptly, so I haven’t set this script to automatically run. Instead, I have a reminder on my phone to go run it manually.
  • A future version might delete all the old backups (both WordPress versions and websites).


#!/bin/bash
# Created Sept 1, 2012
# Last updated July 7, 2013
# Automatically update WordPress.
 
# Alter these to reflect your environment
website='~/public_html' # website and htdocs might be the same. If unsure, keep them identical.
htdocs='~/public_html/htdocs'
email='you@example.com'
sitename='My web site'
 
date=`date +%y-%m-%d`
log=wp_upgrade_${date}.txt
 
if [ -f latest.zip ]; then
rm latest.zip
echo Removed old latest.zip >> $log
fi
 
wget http://wordpress.org/latest.zip
echo Got latest version of WordPress >> $log
 
unzip latest.zip
echo Unzipped latest version of WordPress >> $log
 
# Create old/ if DNE
if [ ! -d old ]; then
mkdir old
echo Created directory for old stuff >> $log
fi
 
# Create a backup of your website before making changes
htdocs_dir=`basename $htdocs`
new_htdocs=${htdocs_dir}_{$date}
cp -Rv $htdocs old/$new_htdocs
 
echo Copied htdocs to $new_htdocs >> $log
 
# Put the files for the new WordPress version into your website.
cp wordpress/* $htdocs -Rv
 
echo Dumped new WordPress into htdocs >> $log
 
# Archive this version of WordPress. You could probably delete it, but I like to have a clean copy around in case I muck up the code.
mv wordpress/ old/wordpress_${date}
 
echo Copied pristine WordPress code into old/ >> $log
 
# Sometimes it has database upgrades and a human needs to visit the site
# to tell it to go ahead, so this e-mail serves as your reminder.
mail $email -s "Wordpress updated on $sitename - go check it out" < $log

Assuming you store this in ~/bin/upgrade_wordpress.sh, you can run this script monthly automatically with the following steps:

  1. At a prompt, type 'crontab -e'
  2. On most systems, this will open vi. Type "i" to insert text.
  3. Paste:
    0 0 1 * * ~/bin/upgrade_wordpress.sh
  4. Push the ESC key to exit insert mode.
  5. Type ":wq" to write changes then quit vi

Text a reminder to the members of your houseshold

Thursday, October 4th, 2012

Every week we forget trash day, so I’ve been meaning to write a script to remind all of us the night before to put the trash cans out.

I only wanted to type the phone numbers once, so I hard-coded them as variables into the script. Turning the command line argument ‘kj’ into the value of $kj was by far the most difficult because I had to look up how to do indirect references in bash, which, as it turns out, is kind of a pain.

In an effort to spare you that same pain, I’m posting the code here.

Usage

If you call the file text_reminder.sh, the usage is as follows:
text_reminder.sh [path to reminder] [recipient(s)]

[path to reminder]

This script can be used to send you several reminders. It looks for a file at the specified path, then uses the text of that file as the body of the e-mail/text. Be sure to create the reminder file before you run this script. For the purposes of example, let us assume it’s in ~/reminders/reminder.txt. Remember to keep it brief – it will be split into 140-character increments, so if you send an 1,000-character reminder, it’s going to arrive as eight annoying, disjointed texts.

[recipient(s)]

I hard-coded shortcuts into the code so I can use aliases instead of relying on myself to having to type a phone number more than once. You can set up as many recipients you want, but note that the code, as it is pasted below, will fail because there are no real recipients set up. You’ll need to add at least one to get any use out of this code.

Setting up a recipient is fairly simple: most (all?) cell phone companies allow you to text message customers via e-mail with an address following the format [10-digit phone number]@[domain]. Finding the value of [domain] is the most time-consuming part, because each company has a different domain, so you need to ask each potential recipient who their cell phone company is, then dig up the corresponding domain. I used this page as a reference, but it may be out of date by the time you read it. If your phone number is (503)555-1234, and you’re a T-Mobile customer, the address at which my phone receives texts is 5035551234@tmomail.net.

As always, send several tests before using it for real.

Code


kj='number@provider.com' # CHANGE THIS
eric='number@provider.com'
# etc, you can set up as many aliases as you like.
 
if [ "$#" -lt 2 ]; then

    echo Usage $0 [path to reminder] [recipients]
    echo Recipients defined: kj, eric # CHANGE THIS

    exit
else
    reminder=$1
    if [ ! -f $reminder ]; then
        echo The reminder you specified, $reminder, does not exist.
        exit
    fi
 
    let i=2;
    while [ $i -le $# ]; do
        numvar=\$$i
        varname=`eval echo $numvar`
        vartoeval=`eval echo $varname`
        recipient2=\$$vartoeval
        recipient=`eval echo $recipient2`
 
        if [ "$recipient" == "" ]; then
            echo I do not understand the recipient $recipient
        else
            echo mail "$recipient" -s 'Friendly reminder' -r kj@kjcoop.com -a $reminder
            mail "$recipient" -s 'Friendly reminder' -r "kj@kjcoop.com" < $reminder
        fi
    let i=i+1
    done
fi

Cron job

In order to make this run regularly, you’ll need to create a cron job. You can do that by running “crontab -e”. On most systems, this will default to vi, which can be kind of scary to the uninitiated, so here’s a cheat sheet.

I’m going to assume you’re uninitiated: Copy and paste the following into a text editor you feel comfortable with:
0 21 * * 1 ~/bin/text_reminder.sh ~/reminders/reminder.txt kj eric

This will send a text to each recipient listed reminder at 9 PM every Monday night contain. Change the path and recipient(s) to your liking, then copy the whole thing. Switch to the window where you ran “crontab -e” and vi awaits you. Type “i” to enter “insert” mode – this will allow you to use vi like a normal text editor. Paste.

Hit the “esc” key (top left side of your keyboard) to exit “insert” mode. Type “:wq” to save your changes and exit. If you screw up and you don’t want to save your changes, you can exit with “:q!”.

Potential improvements

This was pretty quick and dirty, but a couple glaring improvements stand out:

  • Allow the user to specify a subject. At the very least, make the hard-coded subject a variable so that it remains uniform between the line that sends the mail, and the line below that prints the send command used.
  • I could have put the aliases in some kind of array, which would have allowed for more robust error-checking and prevented the user from having to manually change the usage instructions.
  • Some of the variable names in the while loop are awful.