Для удобного запуска и контроля над приложениями на продакшене я использую supervisord. Перейду сразу к делу и покажу как это работает. После простой настройки сам процес выглядит примерно так:

$ supervisorctl status
projectname_celery                    RUNNING    pid 6704, uptime 1 day, 22:29:57
projectname_fcgi                      RUNNING    pid 29016, uptime 20:59:24
$ supervisorctl restart projectname_fcgi
$ supervisorctl stop projectname_fcgi
$ supervisorctl start projectname_fcgi
$ supervisorctl tail projectname_celery
[2011-09-08 07:16:26,636: INFO/MainProcess] Got task from broker: project.teasers.tasks...
...

Supervisord позволяет демонизировать что угодно, я использую его для запуска django, celery, tornado. Эта замечательная утилита проста в настройке, к тому же написана на питоне, поэтому установить её можно через setuptools. В репозитории CentOS была только старая ветка 2.*, поэтому поставим последнюю версию 3.*, между 2 и 3 есть обратные несовместимости.

$ pip install supervisor

Добавляем supervisord в автозапуск, например в /etc/rc.local или каким-либо другим способом, возможно скрипт в /etc/init.d/.

Конфиг по умолчанию лежит в /etc/supervisord.conf. Мой выглдит так:

[unix_http_server]
file=/tmp/supervisor.sock   ; (the path to the socket file)

[supervisord]
logfile=/tmp/supervisord.log ; (main log file;default $CWD/supervisord.log)
logfile_maxbytes=50MB       ; (max main logfile bytes b4 rotation;default 50MB)
logfile_backups=10          ; (num of main logfile rotation backups;default 10)
loglevel=info               ; (log level;default info; others: debug,warn,trace)
pidfile=/tmp/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
nodaemon=false              ; (start in foreground if true;default false)
minfds=1024                 ; (min. avail startup file descriptors;default 1024)
minprocs=200                ; (min. avail process descriptors;default 200)

[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL  for a unix socket

[program:projectname_fcgi]
command=/home/projectname/project/manage.py runfcgi method=prefork maxchildren=6 maxspare=8 minspare=4 maxrequests=1000 host=127.0.0.1 port=8000 daemonize=false
stdout_logfile=/home/projectname/logs/fcgi.log
stderr_logfile=/home/projectname/logs/fcgi_err.log
autostart=true
autorestart=true
redirect_stderr=true

[program:projectname_celery]
command=/home/projectname/project/manage.py celeryd --loglevel=INFO -B
stdout_logfile=/home/projectname/logs/celery.log
stderr_logfile=/home/projectname/logs/celery_err.log
redirect_stderr=true
autostart=true
autorestart=true
startsecs=5
; Need to wait for currently executing tasks to finish at shutdown.
; Increase this if you have very long running tasks.
stopwaitsecs = 60

Для manage.py runfcgi обязательно нужно добавить параметр daemonize=false.

По аналогии добавляем новые блоки [program:*] для запуска других своих приложений. После правки конфига не забываем перезапустить supervisord. Примечателен также параметр autorestart - в случае остановки процесса по каким-то причинам, supervisord перезапустит его.

Если понадобилось изменить конфиг супервизора, например, добавить процесс, перезапускать его не обязательно, можно перечитать конфиг командой supervisorctl update.