views:

157

answers:

10

I feel silly asking this...

I am not an expert on shell scripting, but I am finally in enough of a sysadmin role that I want to do this correctly.

I have a production server that hosts a webapp. Here is my routine.
1 - ssh to server
2 - cd django_src/django_apps/team_proj
3 - svn update
4 - sudo /etc/init.d/apache2 restart
5 - logout

I want to create a shell script for steps 2,3,4.

I can do this, but it will be a very plain and simple bash script simply containing the actual commands I type at the command line.

My question: What is the best way to script this kind of repetitive procedure in bash (Linux, Ubuntu) for a remote server?

Thanks!

+2  A: 

I'd setup a cron job doing that automatically.

+1  A: 

you can do this with the shell (bash,ksh,zsh + ssh + tools), or programming languages such as Python,Perl(Ruby or PHP or Java) etc, basically a language that supports SSH protocol and operating system functions. The "best" one is the one that you are more comfortable and have knowledge in. If you are doing sysadmin, the shell is the closest thing you can use. Then after you have done your script, you can use the crontab (cron) , or the at command to schedule your task. check their man page for more information

ghostdog74
+4  A: 

The best way is simply as you suggest. Some things you should do for your script would be:

  • put set -e at the top of the script (after the shebang). This will cause your script to stop if any of the commands fail. So if it cannot cd to the directory, it will not run svn update or restart apache. You can do this programmatically by putting || exit 0 after each command, but if that's all you're doing, you may as well use set -e
  • Use full paths in your script. Do not assume the directory that the script is run from. In this specific case, the cd command has a relative path. Use a full (absolute) path, or use an environment variable like $HOME.
  • You may want to set up sudo so that it can run the command without asking for a password. This makes your script non-interactive which means it can be run in the background and from cron jobs and such.

As time goes by, you may add features and take command line arguments to parameterise the script. But don't bother doing this up front. Just evolve your scripts as you need.

camh
great tips I have overlooked, thanks!
Art
how do you setup sudo so it doesn't requests a password?
Daniel Velkov
@djv: See `man sudoers` for the `NOPASSWD` tag.
Dennis Williamson
Don't forget to create a public/private key for ssh so you can run ssh from an automated script.
Earlz
+4  A: 

There is nothing wrong with a simple bash script simply containing the actual commands you type at the command line. Don't make it more complicated than necessary.

ammoQ
+1 for Keeping It Simple
therefromhere
+1 I did this most of the time.
silent
+1 I usually do the same
Art
+1  A: 

You can easily do the above using bash/Bourne etc.

However I would take the time and effort to learn Perl (or some similarly powerful scripting language). Why ?

  1. the language constructs are much more powerful
  2. there are no end of libraries to interface to the systems/features you want to script
  3. because of the library support, you won't have to spawn off different commands to achieve what you want (possibly valuable on a loaded system)
  4. you can decompose frequently-used scripts into your own libraries for later use

I choose Perl particularly because it's been designed (perhaps designed is too strong a word for Perl) for these sort of tasks. However you may want to check out Ruby/Python or other suggestions from SO contributers.

Brian Agnew
+1  A: 

For the basic steps look at camh's answer. If you plan to run the script via cron, then implement some simple logging, e.g. by appending start time of each command with exit code to a textfile which you can later analyze for failures of the script.

Residuum
+1  A: 

Expect -- scripting interactive applications

Expect is a tool for automating interactive applications such as telnet, ftp, passwd, fsck, rlogin, tip, etc.... Expect can make easy all sorts of tasks that are prohibitively difficult with anything else. You will find that Expect is an absolutely invaluable tool - using it, you will be able to automate tasks that you've never even thought of before - and you'll be able to do this automation quickly and easily.

http://expect.nist.gov

bonus: Your tax dollars at work!

Mark Harrison
+2  A: 

Since you're using python, check out fabric - you can use it to automate these kind of tasks. First install fabric:

$ sudo easy_install fabric

then write your fabric script:

from __future__ import with_statement
from fabric.api import *

def svnupdate():
    with cd('django_src/django_apps/team_proj'):
        run('svn update')
        sudo('/etc/init.d/apache2 restart')

Save as fabfile.py, then run using the fab command:

$ fab -H hostname svnupdate

Tell me that's not cool! :-)

Simon Whitaker
Who said the question asker was using Python ?
gareth_bowles
@gareth_bowles: he's deploying django app from internal svn - it might be safe to assume he knows at least a little bit of python ;)
viraptor
Good question! He's using django, which is a python framework for web development (a little like Ruby on Rails, but in python)
Simon Whitaker
Oh I know python ;) Do I need to install anything on the server to support fabric?
Art
Hi Art - dependencies are documented at http://docs.fabfile.org/0.9.0/installation.html - you need Python 2.5 or newer, Setuptools and PyCrypto. On every system I've used fabric on these dependencies have already been installed and fabric "just works". Check out the installation link for more info and pointers for where to find the dependencies if you don't already have them installed.
Simon Whitaker
A: 
rcarson
A: 

Just to add another tip - you should not give users access to some application in an unknown state. svn up might break during the update, users might see a page that's half-new half-old, etc. If you're deploying the whole application at once, I'd suggest doing svn export instead to a new directory and then either mv current old ; mv new current, or even keeping current as a link to the directory you're using now. Still not perfect and not blocking every possible race condition, but it definitely takes less time than svn up on the live copy.

viraptor