Skip to content

Embed URL

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Minimal Race-free Deployment
#!/bin/sh
# deploy.sh
N="`readlink \"$1\"`"
mv -T "$1.stage" "$1"
ln -s "$N" "$1.stage"
rm -rf "$N"
cp -aH "$1" "$N"
#!/bin/sh
# deploy.sh
N="`readlink \"$1.prev\"`"
cp -PT "$1" "$1.prev"
mv -T "$1.stage" "$1"
ln -s "$N" "$1.stage"
rm -rf "$N"
cp -aH "$1" "$N"
#!/bin/sh
# initialize-deployable.sh
mkdir "$1.d"
mv "$1" "$1.d/1"
ln -s "$1.d/1" "$1"
cp -aH "$1" "$1.d/2"
ln -s "$1.d/2" "$1.stage"
#!/bin/sh
# initialize-deployable.sh
mkdir "$1.d"
mv "$1" "$1.d/1"
ln -s "$1.d/1" "$1"
cp -aH "$1" "$1.d/2"
ln -s "$1.d/2" "$1.stage"
ln -s "$1.d/3" "$1.prev"
#!/bin/sh
# rollback.sh
[ ! -e "$1.prev" ] && echo "Can't roll back." && exit 1
N="`readlink \"$1.stage\"`"
cp -PT "$1" "$1.stage"
mv -T "$1.prev" "$1"
ln -s "$N" "$1.prev"
rm -rf "$N"
# Keep current as stage on rollback? If no, uncomment:
# mkdir "`readlink \"$1.stg\"`"
# cp -alH "$1" "$1.stg"
@ghost
Unknown commented

Good idea, but your rsyncs could probably use a --delete and copying the old version into the new directory before syncing is better done with the "-l" flag (to hardlink instead of duplicating them).

@czettnersandor

If somebody is looking for a more sophisticated method with the same idea for deploying Rails or PHP applications, it's better to check Capistrano. We are using it to deploy Magento changes as well.

@bitboxer

Yep, check cap or vlad the deployer. you don't need to reinvent the wheel.

@AlexSatrapa

The great advantage of this technique is that it is easily documented, and someone looking at the directory full of "web-20121009" and similar directories with a symlink "web" -> "web-2012-10-23" should be able to figure out what is going on.

It's simple, it works, and can be reverse-engineered relatively easily. The only caveat is the reliance on GNU "ln", but the atomic replacement of symlinks is only covering the few milliseconds it takes to replace the symlink. If your website users are that sensitive to documents changing from underneath them, you'll need a different solution such as switching VMs on the fly.

@aggsol
#!/bin/sh
ACTION=$1
NAME=$2

if [ $# -ne 2 ]
then
    echo "Usage: deploy-tool.sh <action> <dir> "
    echo "Actions:"
    echo "  init        Initialize an existig directory <dir> for deployment"
    echo "  deploy      Deploy the content <dir>.stage to <dir> also back up"
    echo "              to <dir>.prev"
    echo "  rollback    Rollback from <dir>.prev"
    exit 1
fi

if [ ! -d $NAME ]; then
    echo "Directory '"${NAME}"' does not exist."
    exit 1
fi

if [ $ACTION = "init" ]; then

    echo "Initialize dir '"${NAME}"'"
    mkdir "${NAME}.d"
    mv "${NAME}" "${NAME}.d/1"
    ln -s "${NAME}.d/1" "${NAME}"
    cp -aH "${NAME}" "${NAME}.d/2"
    ln -s "${NAME}.d/2" "${NAME}.stage"
    ln -s "${NAME}.d/3" "${NAME}.prev"

elif [ $ACTION = "deploy" ]; then

    echo "Backup from '"${NAME}"' to '"${NAME}".prev'"
    N="`readlink \"${NAME}.prev\"`"
    cp -PT "${NAME}" "${NAME}.prev"
    echo "Deploy from '"${NAME}".stage' to '"${NAME}"'"
    mv -T "${NAME}.stage" "${NAME}"
    ln -s "$N" "${NAME}.stage"
    rm -rf "$N"
    cp -aH "${NAME}" "$N"

elif [ $ACTION = "rollback" ]; then

    if [ ! -e "$NAME.prev" ]; then
        echo "Cannot roll back."
        exit 1
    fi

    N="`readlink \"$NAME.stage\"`"
    cp -PT "$NAME" "$NAME.stage"
    echo "Roll back from '"${NAME}".prev'"
    mv -T "$NAME.prev" "$NAME"
    ln -s "$N" "$NAME.prev"
    rm -rf "$N" 

else
    echo "Unknown action."
    exit 1
fi

echo "Done."
@azamat-sharapov

@czettnersandor , @bitboxer , capistrano and such other tools are usually used for deploying form local server to remote server directly. Our team needed automatic deployment from github to staging server, so I had to create my own wheel after hours of research about existing deployment tools.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.