Save your bookmarks on Pinboard!

Why? Check this out:

  • Simplicity
    • List interface:2016-02-24-145849_1366x768_scrot
    • Bookmarking interface:2016-02-24-140756_1366x768_scrot
    • No ads
  • Price
  • Safety
    • Rock solid since I started using it in 2012
    • Backups in multiple portable formats
  • Privacy & security
  • Access via basically any means: browser extensions, JavaScript widgets, apps and API
  • Extensive FAQ
  • Likely to survive for long because of a simple, sustainable business model

Other than being a happy customer I am in no way affiliated with Pinboard.

WordPress.com blog daily backup

WordPress.com Blog Export, The Next Generation is now on GitHub! Please go there for any future updates (and more export/backup scripts).

Based on the following documents:

Automatic backups to remote machine

Update: SSH public key authentication isn’t supported on the system I want to backup to, so I’ve changed the procedure to create a cron job on the server instead of the client.

Backups are nice, but they can be a royal pain to set up and verify, and there’s a lot of tools available. Here’s the simplest recipe I could make using standard GNU/Linux tools. I’m no security or Linux expert, so don’t expect any guarantees, and verify anything you’re not sure about.

Text like this should be replaced by values relevant for your situation.

Login to the server:
ssh backup_server

Create SSH keys without password:
ssh-keygen -P "" -f ${HOME}/.ssh/backup_id

Verify that the file was created:
ls ${HOME}/.ssh/backup_id

Copy the public key to the client machine:
ssh-copy-id -i ${HOME}/.ssh/backup_id user@client

Verify that you can login without providing a password:
ssh -i ${HOME}/.ssh/backup_id user@client

Open crontab (CERN users, please see below):
crontab -e

Add the following to the file, save and exit:
@midnight ssh -i ${HOME}/.ssh/backup_id user@client "tar zcf - backup_directory" > ${HOME}/backup/$(date --iso-8601).tar.gz

CERN specific crontab setup on LXPlus:
acrontab -e
0 0 * * * lxplus ssh -i ${HOME}/.ssh/backup_id user@client "tar zcf - backup_directory" > ${HOME}/backup/$(date --iso-8601).tar.gz

Verify that backups are created:
ls -la ${HOME}/backup/

Please comment if you have any suggestions to improve the procedure, preferably with code or shell output.

Sources:

  • Passwordless logins: 1, 2, 3
  • RSA vs DSA: 1, 2
  • man pages

WordPress update script

This is a script to update a WordPress blog with the latest stable version from Subversion.

How to use:

  1. Download update-wordpress.sh.
  2. chmod u+x path/to/update-wordpress.sh
  3. path/to/update-wordpress.sh -fs ftp_server -wp /path/to/WordPress/on/FTP -ms mysql_server

Some features:

  • Works with plain /bin/sh, so it should work on any Linux / BSD distribution.
  • Flexible – There are input parameters for user names, passwords, and lots more.
  • It will ask for FTP and MySQL passwords (-FP and -MP parameters) only if these are not provided

update-wordpress.sh

#!/bin/sh
#
# $Id: update-wordpress.sh 393 2008-06-19 10:29:18Z vengmark $
#
# NAME
#    update-wordpress.sh - Update WordPress to latest stable version.
#
# SYNOPSIS
#    update-wordpress.sh [options]
#
# DESCRIPTION
#    Backs up the database and the most relevant files (.htaccess, robots.txt
#    and wp-config.php) before updating.
#
#    Uses instructions from
#    http://codex.wordpress.org/Installing/Updating_WordPress_with_Subversion to
#    get the latest stable version of WordPress and copy it to an FTP server.
#
#    For security reasons, the script will ask for all necessary passwords if
#    you don't provide them on the command line.
#
# OPTIONS
#    -v     Verbose output
#    -q     Quiet (non-interactive)
#    -fs    FTP server host name (mandatory)
#    -wp    WordPress path on FTP server (mandatory)
#    -fp    FTP server port
#    -fu    FTP user
#    -FP    FTP password
#    -ms    MySQL server host name (mandatory)
#    -mp    MySQL server port
#    -mu    MySQL user
#    -MP    MySQL password
#    -wd    WordPress database name
#    -wv    WordPress version
#    -b     Where to put the WordPress backup files
#
# BUGS
#    Should detect the newest security release (i.e., highest X for versions
#    2.5.X), perhaps from http://svn.automattic.com/wordpress/tags/.
#
#    Email bugs to victor dot engmark at gmail dot com. Please include the
#    output of running this script in verbose mode (-v).
#
# COPYRIGHT AND LICENSE
#    Copyright (C) 2008 Victor Engmark
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
################################################################################

# Init
PATH="/usr/bin:/bin"

# Hard-code values here if you don't want to provide parameters
backup_dir="${HOME}/.backup/WordPress"

# FTP
ftp_host=
ftp_port=21
ftp_user=`whoami`

# MySQL
mysql_host=
mysql_port=3306
mysql_user=`whoami`

# WordPress
wordpress_repository=http://svn.automattic.com/wordpress/tags/
wordpress_version="2.5.1"
wordpress_path=
wordpress_database=wordpress

cmdname=`basename $0`

#Error messages
errm_unknown="Unknown error in $cmdname" #Code 1
#Code 2 is reserved: http://www.faqs.org/docs/abs/HTML/exitcodes.html
usage="Usage: ${cmdname} [-v] [-q] -fs ftp_server -wp wordpress_path [-fp ftp_port] [-fu ftp_user] [-FP ftp_password] -ms mysql_server [-mp mysql_port] [-mu mysql_user] [-MP mysql_password] [-wd wordpress_database] [-wv wordpress_version] [-b backup_dir]" #Code 3

# Process parameters
until [ $# -eq 0 ]
do
  case $1 in
    -v)
      verbose=1
      shift
      ;;
    -q)
      quiet=1
      shift
      ;;
    -fs)
      if [ -z "$2" ]
      then
        echo "$usage" >&2
        exit 3
      fi
      ftp_host=$2
      shift 2
      ;;
    -fp)
      if [ -z "$2" ]
      then
        echo "$usage" >&2
        exit 3
      fi
      ftp_port=$2
      shift 2
      ;;
    -fu)
      if [ -z "$2" ]
      then
        echo "$usage" >&2
        exit 3
      fi
      ftp_user=$2
      shift 2
      ;;
    -FP)
      if [ -z "$2" ]
      then
        echo "$usage" >&2
        exit 3
      fi
      ftp_password=$2
      shift 2
      ;;
    -ms)
      if [ -z "$2" ]
      then
        echo "$usage" >&2
        exit 3
      fi
      mysql_host=$2
      shift 2
      ;;
    -mp)
      if [ -z "$2" ]
      then
        echo "$usage" >&2
        exit 3
      fi
      mysql_port=$2
      shift 2
      ;;
    -mu)
      if [ -z "$2" ]
      then
        echo "$usage" >&2
        exit 3
      fi
      mysql_user=$2
      shift 2
      ;;
    -MP)
      if [ -z "$2" ]
      then
        echo "$usage" >&2
        exit 3
      fi
      mysql_password=$2
      shift 2
      ;;
    -wp)
      if [ -z "$2" ]
      then
        echo "$usage" >&2
        exit 3
      fi
      wordpress_path="${2%\/}"
      shift 2
      ;;
    -wd)
      if [ -z "$2" ]
      then
        echo "$usage" >&2
        exit 3
      fi
      wordpress_database=$2
      shift 2
      ;;
    -wv)
      if [ -z "$2" ]
      then
        echo "$usage" >&2
        exit 3
      fi
      wordpress_version=$2
      shift 2
      ;;
    -b)
      if [ -z "$2" ]
      then
        echo "$usage" >&2
        exit 3
      fi
      backup_dir="${2%\/}"
      shift 2
      ;;
    *)
      #Unknown parameter
      if [ $verbose ]
      then
        echo "Unknown parameter: $1" >&2
      fi
      echo "$usage" >&2
      exit 3
      ;;
  esac
done

# Check input values
if [ ! $ftp_host ] || [ ! $mysql_host ] || [ ! $wordpress_path ]
then
  echo "$usage" >&2
  exit 3
fi

if [ -z "$mysql_password" ] && [ $quiet ]
then
  echo "Please provide the database password with the \"-MP\" parameter" >&2
  echo "$usage" >&2
  exit 3
fi

if [ -z "$ftp_password" ] && [ $quiet ]
then
  echo "Please provide the FTP password with the \"-FP\" parameter" >&2
  echo "$usage" >&2
  exit 3
fi

# Check for necessary programs
for application in bzip2 mysqldump ncftp svn
do
  if [ ! `which $application` ]
  then
    echo "Please install application '$application' first." >&2
    error_found=1
  fi
done
if [ $error_found ]
then
  exit 1
fi

# Build necessary variables from input
wordpress_repository="${wordpress_repository}${wordpress_version}"

# Summarize settings
if [ $verbose ]
then
  echo "Running $cmdname at `date`."
  echo
  echo "Backup directory: ${backup_dir}"
  echo
  echo "FTP connection: ${ftp_user}@${ftp_host}:${ftp_port}"
  echo "WordPress FTP path: ${wordpress_path}"
  echo
  echo "MySQL connection: ${mysql_user}@${mysql_host}:${mysql_port}"
  echo "WordPress database: ${wordpress_database}"
  echo
  echo "New WordPress version: ${wordpress_version}"
  echo "WordPress repository: ${wordpress_repository}"
  echo
fi

clean_up()
{
  if [ $verbose ]
  then
    echo "Cleaning up."
  fi
  rm -Rf $temp_dir
}

debug()
{
  if [ -z "$1" ]
  then
    echo "debug function syntax: debug \$command_name \$error_code"
    clean_up
    exit 1
  fi
  if [ $2 -ne 0 ]
  then
    echo "$1 failed with error code $2."
    exit 1
  elif [ $verbose ]
  then
    echo "$1 succeeded."
  fi
}

if [ $verbose ]
then
  echo "Creating the temporary folder."
fi

temp_dir=`mktemp -t -d ${cmdname}.XXXXXXXXXX` || debug "mktemp" $?

if [ ! -e $backup_dir ]
then
  if [ $verbose ]
  then
    echo "Creating the backup folder."
  fi
  mkdir -p $backup_dir
  debug "mkdir" $?
fi

# Back up database
if [ -z "$mysql_password" ]
then
  echo -n "Enter MySQL password: "
  stty -echo
  read mysql_password
  stty echo
  echo
fi

# Enable showing the string to the user before executing
dummy_password=PASSWORD
mysqldump_command="mysqldump --host=$mysql_host --opt --password="$dummy_password" --port=$mysql_port --user=$mysql_user $(if [ $verbose ]; then echo '-v'; fi;) --result-file=${backup_dir}/WordPress.sql $wordpress_database"
if [ $verbose ]
then
  echo "MySQLdump command:\n$mysqldump_command"
fi
mysqldump_command=$(echo $mysqldump_command | sed "s/${dummy_password}/${mysql_password}/") # Insert password in command

# Run backup
$mysqldump_command
debug "mysqldump" $?

# Download latest stable WordPress release
svn_dir=${temp_dir}/svn
svn_command="svn export $(if [ ! $verbose ]; then echo '--quiet'; fi;) $wordpress_repository $svn_dir"
if [ $verbose ]
then
  echo "Subversion command:\n$svn_command"
fi

$svn_command
debug "svn" $?

# Back up user files
if [ -z "$ftp_password" ]
then
  echo -n "Enter FTP password: "
  stty -echo
  read ftp_password
  stty echo
  echo
fi

ncftp <<EOD
open -u "$ftp_user" -p "$ftp_password" -P $ftp_port "$ftp_host"
lcd $backup_dir
cd $wordpress_path
get .htaccess
get robots.txt
get wp-config.php
lmkdir wp-content
lcd wp-content
lmkdir uploads
lcd uploads
cd wp-content/uploads
get -R *
quit
EOD
debug "ncftp" $?

# Make sure the site is ready to update
if [ ! $quiet ]
then
  echo -n "Please deactivate all your WordPress plugins, then press Enter to continue."
  read dummy
fi

# Update WordPress installation
ncftp <<EOD
open -u "$ftp_user" -p "$ftp_password" -P $ftp_port "$ftp_host"
lcd $svn_dir
cd $wordpress_path
put -R *
quit
EOD
debug "ncftp" $?

echo "Backup and update finished. To complete the installation, please go to the upgrade page (e.g., http://example.com/wordpress/wp-admin/upgrade.php)"
clean_up

# End
if [ $verbose ]
then
	echo "${cmdname} completed at `date`."
fi

exit 0