Amazon S3 e Mac OS X (ma non solo)

cassaforte

Qualche tempo fa ho scritto un articolo entusiasta su Dropbox. Sull’onda di quell’entusiasmo ho approfondito un po’ la faccenda. Per chi non lo sapesse, Dropbox basa il suo servizio sullo spazio disco fornito da Amazon S3. Amazon S3 è un servizio di storage a pagamento orientato non all’utente finale, ma a soggetti intermedi che, a loro volta, forniscono servizi all’utente finale. Il target di Amazon S3 risulta evidente se si considera che l’accesso fornito è solamente a livello di API. Esempi di servizi basati su S3 sono lo stesso Dropbox, Jungle Disk ed altri.

Usare S3 a “basso livello”

Visto i bassi costi di gestione (lo storage viene fornito a $0,15 al mese per GB, e il trasferimento a $0,17 per GB) e l’affidabilità (ridondanza multipla dei dati su più continenti) S3 diventa appetibile rispetto a soluzioni di backup/archiviazione in proprio, come CD/DVD o dischi rigidi esterni. Avendo individuato alcuni limiti in Dropbox, ho cercato di capire se fosse possibile utilizzare Amazon S3 direttamente, per implementare un sistema più vicino alle mie esigenze: Dropbox è il sostituto ideale della classica chiavetta USB, nonché un ottimo sistema di sincronizzazione tra più utenti. Ma ha alcune limitazioni, tra cui:

  • non consente di “archiviare” i dati, ossia trasferirli sull’archivio remoto liberando spazio sul proprio disco rigido;
  • su Mac OS X, non salva gli attributi estesi e i resource fork dei file sui volumi HFS+.

Gli strumenti software

Dopo una rapida ricerca ho individuato alcuni strumenti open source che, unitamente ad un mio piccolo contributo, consentono di realizzare un sistema — almeno per me — soddisfacente:

»Cockpit — un’interfaccia grafica per S3.
Si tratta di un semplice programma in Java (che gira su Linux, Windows, e Mac OS X) che serve per creare e gestire i bucket (i volumi di memorizzazione di Amazon S3), nonché per trasferire oggetti (i file) nelle due direzioni, cancellarli, rinominarli etc. Naturalmente è necessario aver installato la macchina virtuale Java.
Fa parte di JetS3t, un toolkit completo per lavorare con Amazon S3. Si faccia riferimento alla homepage del progetto per ottenere maggiori informazioni.

»s3sync — l’alter ego di rsync.
Scritto in Ruby, assomiglia molto ad rsync, ma lavora con Amazon S3. Si lancia da linea di comando e sincronizza una cartella locale con una che sta su S3, o viceversa. Chi ha dimestichezza con rsync non troverà difficoltà ad utilizzare s3sync.
Gira su tutte le piattaforme su cui c’è l’interprete Ruby, quindi nessun problema di portabilità. Su Mac OS X è preinstallato; per Windows si può scaricare l’installer dal sito ufficiale; su Linux il metodo di installazione dipende dalla vostra distribuzione. Siete OK quando, da linea di comando,

ruby --version

restituisce il numero di versione dell’interprete.

»s3backup — questo è il mio modesto contributo.
È un wrapper per s3sync, scritto in linguaggio bash, che semplifica l’interazione con Amazon S3 e, su Mac OS X, consente di trasferire anche gli attributi estesi e i resource fork dei file sui volumi HFS+. Il supporto ai resource fork è fornito solamente se è presente sul sistema il comando SplitForks, facente parte di Xcode, l’ambiente di sviluppo per Mac OS X scaricabile gratuitamente da Apple (sono 996 MB da scaricare… è un po’ pesante, lo so, ma poi uno può installare solo i Tools e si può evitare di installarlo se non serve fare il backup dei resource fork).
s3backup gira su tutte le piattaforme su cui c’è la shell Bash, per cui nessun problema su Linux e Mac OS X. Per quanto riguarda Windows, un metodo veloce per avere la Bash può essere installare MSYS; un’alternativa più completa è Cygwin.

La procedura

Per essere operativi occorre svolgere i seguenti passi:

  1. creare un account Amazon S3 (lo ripeto: è a pagamento!);
  2. utilizzare Cockpit per creare un bucket su cui depositare i propri backup.
    In alternativa si può usare il comando da terminale s3cmd.rb, distribuito assieme a s3sync. Per maggiori informazioni, fare riferimento direttamente alla documentazione degli strumenti che si intende usare;
  3. esplodere da qualche parte sul proprio sistema i due archivi di s3sync e s3backup;
  4. editare lo script s3backup.sh impostando le variabili di configurazione, tra cui
    • AWS_ACCESS_KEY_ID e AWS_SECRET_ACCESS_KEY — le credenziali di accesso per Amazon S3
    • HTTP_PROXY_* — le impostazioni per il proxy http, se presente
    • BUCKET — il nome del bucket da usare (quello creato al punto 1)
    • PREFIX — il prefisso che viene utilizzato per tutti i backup. Se non impostato verrà utilizzato il nome di host del client
    • S3SYNC — il path completo dello script s3sync.rb

A questo punto si può lanciare il mio script, per “backuppare”, con il comando

$ $BASH s3backup.sh /cartella/da/salvare

oppure, per ripristinare, con il comando

$ $BASH s3restore.sh /cartella/da/ripristinare

Lo script è in realtà uno solo, di nome s3backup.sh, ma si comporta diversamente se chiamato con il nome s3restore.sh (che è un link simbolico). Accetta anche alcune opzioni: invocatelo senza alcun argomento per ottenere un aiuto.

Per chi trova troppo difficile questo approccio (ed è disposto a spendere $20,00 in più) c’è il validissimo Jungle Disk, un disco virtuale on line implementato sempre tramite S3 (cui si devono continuare a pagare le spese per lo storage) che fornisce il supporto anche ai resource fork di Mac OS X.

Appendice A – Note per Windows

  1. In Windows i link simbolici non esistono. Per ovviare al problema occorre cancellare il file s3restore.sh contenuto nell’archivio e ricrearlo come copia del file s3backup.sh;
  2. nell’ambiente Bash, sia con MSYS che con Cygwin, i percorsi dei file devono essere “unixizzati”.
    Ad esempio, il file C:\Pippo\Pluto\Topolino.txt nel prompt di MSYS diventa /c/Pippo/Pluto/Topolino.txt, e sotto Cygwin /cygdrive/c/Pippo/Pluto/Topolino.txt.

Appendice B – Il codice

#!/bin/bash
#
# Do a backup or a restore of a local folder on an Amazon S3 bucket, using
# the s3sync.rb script (http://s3sync.net/).
# Modified on $Date: 2008-12-03 18:36:10 +0100 (Mer, 03 Dic 2008) $
# SVN $Revision: 48 $
#
# If launched with the name "s3backup.sh" it does the backup, while if launched
# with the name "s3restore.sh" it does the restore.
#
# Copyright (C) - 2008
# Alessandro Morgantini - gpz500 at technologist dot com
# https://gpz500.wordpress.com/2008/11/30/amazon-s3-e-mac-os-x-ma-non-solo/
#
# Released under the terms of GPL2 (http://www.gnu.org/licenses/gpl-2.0.html).

################################################################################
# Script's configuration

# Amazon S3 access ID info.
# If not specified here, s3sync.rb will search these info in the following
# locations:
#
#   $S3CONF/s3config.yml
#   $HOME/.s3conf/s3config.yml
#   /etc/s3conf/s3config.yml
#
# Read the s3sync.rb readme file at
# http://s3.amazonaws.com/ServEdge_pub/s3sync/README.txt.
#AWS_ACCESS_KEY_ID=1111111111111111111111111
#AWS_SECRET_ACCESS_KEY=2222222222222222222222222

# HTTP proxy data, if any.
# If not specified here, s3sync.rb will search these info in the following
# locations:
#
#   $S3CONF/s3config.yml
#   $HOME/.s3conf/s3config.yml
#   /etc/s3conf/s3config.yml
#
# Read the s3sync.rb readme file at
# http://s3.amazonaws.com/ServEdge_pub/s3sync/README.txt.
#HTTP_PROXY_HOST=my.proxy.server
#HTTP_PROXY_PORT=8080
#HTTP_PROXY_USER=myusername
#HTTP_PROXY_PASSWORD=secret

# Name of Amazon S3 bucket to use
BUCKET=gpz500.wordpress.com

# s3sync.rb prefix to use. It defaults to the hostname, if not defined
PREFIX=mac-di-ale

# Absolute path of s3sync.rb script
S3SYNC=/Users/gpz500/s3sync/s3sync.rb

# End of script's configuration
################################################################################

# Export defined environment variables
if [ "x$AWS_ACCESS_KEY_ID" != "x" ]; then
	export AWS_ACCESS_KEY_ID
fi
if [ "x$AWS_SECRET_ACCESS_KEY" != "x" ]; then
	export AWS_SECRET_ACCESS_KEY
fi
if [ "x$HTTP_PROXY_HOST" != "x" ]; then
	export HTTP_PROXY_HOST
fi
if [ "x$HTTP_PROXY_PORT" != "x" ]; then
	export HTTP_PROXY_PORT
fi
if [ "x$HTTP_PROXY_USER" != "x" ]; then
	export HTTP_PROXY_USER
fi
if [ "x$HTTP_PROXY_PASSWORD" != "x" ]; then
	export HTTP_PROXY_PASSWORD
fi

# Init working variables
SRC_PATH=""
DEST_PATH=""
DELETE=""
NOMD5=""
DRYRUN=""
MAKEDIRS=""
VERBOSE=""
COMMAND_NAME=$(basename $0)
if [ "x$PREFIX" == "x" ]; then
	PREFIX=$(hostname | cut -f 1 -d .)
fi

# Check the correctness of name
if [ "$COMMAND_NAME" != s3backup.sh -a "$COMMAND_NAME" != s3restore.sh ]; then
	echo "Error: you must invoke this program as \"s3backup.sh\" or \"s3restore.sh\""
	exit 3
fi

# Print the usage instructions
usage ()
{
	echo "Usage: $COMMAND_NAME [options] /source/folder [/destination/folder]"
	echo ""
	echo "Options:   --delete, -d    Delete files in destination"
	echo "                           unless they are in the source."
	echo "           --dryrun, -n    Don't execute anything, actually."
	echo "           --make-dirs     Create intermediate folders"
	echo "                           when necessary."
	echo "           --no-md5        Disable the MD5 checksum on"
	echo "                           local files."
	echo "           --verbose, -v   Increase verbosity."
	echo ""
	echo "Warning: use only absolute paths"
}

# Discover if the supplied path is in a HFS+ volume
ishfs ()
{
	local RES=1
	if [ -x /Developer/Tools/SplitForks ]; then
		local TMPFILE="$1/s3backup$$.tmp"
		echo "This is a test file" >"$TMPFILE"
		/Developer/Tools/SplitForks "$TMPFILE" >/dev/null 2>&1
		RES=$?
		rm "$TMPFILE"
	fi

	return $RES
}

# Print the supplied string, only if VERBOSE is defined
writeout ()
{
	if [ -n "$VERBOSE" ]; then
		if [ "x$1" == "x-n" ]; then
			shift
			echo -n "$*"
		else
			echo "$*"
		fi
	fi
}

# Print info
if [ -z "$1" ]; then
	usage
	exit 0
fi

# Parse the parameters
while [ -n "$1" ]; do
	case $1 in
		--delete|-d)
			DELETE=--delete
			shift
			;;
		--dryrun|-n)
			DRYRUN=--dryrun
			shift
			;;
		--make-dirs)
			MAKEDIRS=--make-dirs
			shift
			;;
		--no-md5)
			NOMD5=--no-md5
			shift
			;;
		--verbose|-v)
			VERBOSE=--verbose
			shift
			;;
		-*)
			echo "Error: option \"$1\" is unknown"
			usage
			exit 2
			;;
		*)
			if [ "x$SRC_PATH" == "x" ]; then
				SRC_PATH=$1
			elif [ "x$DEST_PATH" == "x" ]; then
				DEST_PATH=$1
			else
				echo "Error: too many parameters"
				usage
				exit 3
			fi
			shift
			;;
	esac
done

# Check if the origin is correctly defined
if [ "${SRC_PATH:0:1}x" != "/x" ]; then
	echo "Error: you must supply an absolute path as source"
	usage
	exit 1
fi
if [ ! -d "$SRC_PATH" -a "$COMMAND_NAME" == s3backup.sh ]; then
	echo "Error: you must supply an existing folder as source"
	usage
	exit 4
fi

# If the destination path is not defined, set it equal to the source path.
# If there is a trailing slash, use the same name for destination also,
# if not, use the parent folder
if [ "x$DEST_PATH" == "x" ]; then
	if [[ $SRC_PATH == */ ]]; then
		DEST_PATH=$SRC_PATH
	else
		DEST_PATH=$(dirname "$SRC_PATH")
	fi
fi

# Check if the destination is correctly defined
if [ "${DEST_PATH:0:1}x" != "/x" ]; then
	echo "Error: you must supply an absolute path as destination"
	usage
	exit 5
fi
if [ ! -d "$DEST_PATH" -a "$COMMAND_NAME" == s3restore.sh ]; then
	echo "Error: you must supply an existing folder as destination"
	usage
	exit 6
fi

# Output some info
writeout "  I'm using the following settings"

# Run s3sync.rb
if [ "$COMMAND_NAME" == s3backup.sh ]; then
	writeout "  Source:      $SRC_PATH"
	writeout "  Destination: $BUCKET:$PREFIX$DEST_PATH"
	writeout ""
	writeout "  Starting s3sync... "
	ishfs "$SRC_PATH" && find "$SRC_PATH" -type f -xdev -exec /Developer/Tools/SplitForks {} \;
	ruby $S3SYNC -r $DELETE $NOMD5 $VERBOSE $DRYRUN $MAKEDIRS "$SRC_PATH" $BUCKET:$PREFIX"$DEST_PATH"
	ERROR=$?
	ishfs "$SRC_PATH" && dot_clean "$SRC_PATH"
else
	writeout "  Source:      $BUCKET:$PREFIX$SRC_PATH"
	writeout "  Destination: $DEST_PATH"
	writeout ""
	writeout "  Starting s3sync... "
	ruby $S3SYNC -r $DELETE $NOMD5 $VERBOSE $DRYRUN $MAKEDIRS $BUCKET:$PREFIX"$SRC_PATH" "$DEST_PATH"
	ERROR=$?
	ishfs "$DEST_PATH" && dot_clean "$DEST_PATH"
fi

writeout "  ... done."
exit $ERROR
Annunci

Un pensiero su &Idquo;Amazon S3 e Mac OS X (ma non solo)

  1. Pingback: Backup della roba “on the cloud” « gpz500′s Weblog

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...