We explored ways of starting Hubot directly from command line. This method is great for testing things out, but in the end you will want to have something for the long run - a way to deploy your Hubot so that it survives system restart, random crashes introduced by broken scripts, etc. And then you need a way to manage all the environmental variables for Hubot.
If you don’t feel very comfortable around Linux, I recommend going for - a self-hosted web application that takes care of your Hubot maintenance and scripting needs. We’ll take a look into that later in the end of this chapter.
Enough playing around, we have to create a Hubot instance for production use. By now you should already know what adapter you will be using and how to make it work. Throughout the examples in this book I will use Campfire, since it has the best possible integration. It will be located in /home/hubot/campfire
and generated like this:
hubot@botserv:~$
hubot --adapter campfire --name hubot --create ~/campfire Creating a hubot install at /home/hubot/campfire
To avoid losing your work, it’s highly recommended to check Hubot in to SCM. Hubot generates .gitignore
file for you, therefore if you choose to use another SCM, add node_modules
directory to your ignore list.
Using is a vast topic which is far beyond the scope of this book, so the only example will be how to put your newly generated Hubot into a fresh Git repository.
hubot@botserv:~/campfire$
git config --global user.name "Tomas Varaneckas"
hubot@botserv:~/campfire$
git config --global user.email "
tomas.varaneckas@gm\
ail.com"
hubot@botserv:~/campfire$
git init . Initialized empty Git repository in /home/hubot/campfire/.git/
hubot@botserv:~/campfire$
git add . hubot@botserv:~/campfire$
git commit -m "Initial commit"
[master (root-commit) b29ebb9] Initial commit
21 files changed, 880 insertions(+)
<...>
hubot@botserv:~/campfire$
git remote add origin [email protected]:spajus/hubot-e\
xample.git
hubot@botserv:~/campfire$
git push -u origin master Counting objects: 25, done.
Compressing objects: 100% (21/21), done.
Writing objects: 100% (25/25), 12.00 KiB, done.
Total 25 (delta 0), reused 0 (delta 0)
To [email protected]:spajus/hubot-example.git
* [new branch] master -> master
Branch master set up to track remote branch master from origin.
You will be able to find code examples used in this book at .
Hubot is configured using environmental variables, and the best way to manage them is to have a separate shell script that sets them all.
We will be using a file /home/hubot/campfire/hubot.conf
for that. In example code repository it will appear as hubot.conf.example
, because I don’t want to publish my real API keys, so I will be keeping my hubot.conf
in .gitignore
.
You may also want to keep your variables somewhere safe for security reasons. You can use /etc/hubot/hubot.conf
instead and keep everything there.
Let’s make ourselves /etc/init.d/hubot
script that will allow us to start and stop Hubot as a daemon, and do it automatically on system boot. We will use start-stop-daemon
, which is available in Debian based Linux distributions, for RedHat branch you can use daemon
function from /etc/init.d/functions
.
In our example we will keep the startup script in hubot-example/misc/hubot.init.d.sh
, but in real world scenario this should be handled with Chef or Puppet. Symlink the script to /etc/init.d/hubot
and add it to system startup.
root@botserv:~#
ln -s /home/hubot/campfire/misc/hubot.init.d.sh /etc/init.d/h\
ubot
root@botserv:~#
insserv hubot
If you decide to remove Hubot from system startup, run this:
root@botserv:~#
insserv -r hubot
Contents of the startup script:
/etc/init.d/hubot
#! /bin/sh
### BEGIN INIT INFO
# Provides: hubot
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Hubot stat / stop script
# Description: Manages starting and stopping of Hubot node bot
### END INIT INFO
# Author: Tomas Varaneckas <[email protected]>
# Do NOT "set -e"
# PATH should only include /usr/* if it runs after the mountnfs.sh script
DESC
=
"Hubot node bot"
NAME
=
hubot USER
=
hubot GROUP
=
hubot BOT_PATH
=
/home/hubot/campfire PATH
=
/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin:$BOT_PATH
/node_modules:$BOT
\
_PATH/node_modules/hubot/node_modules DAEMON
=
$BOT_PATH
/bin/$NAME
DAEMON_ARGS
=
"--adapter campfire --name hubot"
PIDFILE
=
$BOT_PATH
/$NAME
.pid LOGFILE
=
$BOT_PATH
/$NAME
.log SCRIPTNAME
=
/etc/init.d/$NAME
INIT_VERBOSE
=
yes # Read configuration variable file if it is present
[
-r $BOT_PATH
/hubot.conf ]
&&
. $BOT_PATH
/hubot.conf # Load the VERBOSE setting and other rcS variables
. /lib/init/vars.sh # Define LSB log_* functions.
# Depend on lsb-base (>= 3.2-14) to ensure that this file is present
# and status_of_proc is working.
. /lib/lsb/init-functions do_start()
{
status
=
"0"
pidofproc -p $PIDFILE
node >/dev/null ||
status
=
"$?"
[
"$status"
=
0 ]
&&
return
2;
touch $PIDFILE
&&
chown $USER
:$GROUP
$PIDFILE
start-stop-daemon --no-close --user $USER
--quiet --start --pidfile $PIDFILE
\
-c $USER
:$GROUP
\
--make-pidfile \
--background --chdir $BOT_PATH
--exec $DAEMON
-- \
$DAEMON_ARGS
>> $LOGFILE
2>&
1 \
||
return
2 }
do_stop()
{
status
=
"0"
pidofproc -p $PIDFILE
node >/dev/null ||
status
=
"$?"
[
"$status"
=
3 ]
&&
return
1 start-stop-daemon --stop --quiet --pidfile $PIDFILE
RETVAL
=
"$?"
[
"$RETVAL"
=
2 ]
&&
return
2 rm -f $PIDFILE
return
"$RETVAL"
}
case
"$1"
in start)
[
"$VERBOSE"
!=
no ]
&&
log_daemon_msg "Starting $DESC"
"$NAME"
do_start case
"$?"
in 0|
1)
[
"$VERBOSE"
!=
no ]
&&
log_end_msg 0 ;;
2)
[
"$VERBOSE"
!=
no ]
&&
log_end_msg 1 ;;
esac
;;
stop)
[
"$VERBOSE"
!=
no ]
&&
log_daemon_msg "Stopping $DESC"
"$NAME"
do_stop case
"$?"
in 0|
1)
[
"$VERBOSE"
!=
no ]
&&
log_end_msg 0 ;;
2)
[
"$VERBOSE"
!=
no ]
&&
log_end_msg 1 ;;
esac
;;
status)
status_of_proc -p $PIDFILE
node $NAME
&&
exit
0 ||
exit
$?
;;
restart|
force-reload)
log_daemon_msg "Restarting $DESC"
"$NAME"
do_stop case
"$?"
in 0|
1)
do_start case
"$?"
in 0)
log_end_msg 0 ;;
1)
log_end_msg 1 ;;
# Old process is still running
*)
log_end_msg 1 ;;
# Failed to start
esac
;;
*)
# Failed to stop
log_end_msg 1 ;;
esac
;;
*)
echo
"Usage: $SCRIPTNAME {start|stop|status|restart|force-reload}"
>&
2 exit
3 ;;
esac
:
Don’t type it in, find a copy at
There is also RHEL/CentOS version at
Example use of this script:
hubot@focus:~/campfire$
/etc/init.d/hubot status [FAIL] hubot is not running ... failed!
hubot@focus:~/campfire$
/etc/init.d/hubot start [ ok ] Starting Hubot node bot: hubot.
hubot@focus:~/campfire$
/etc/init.d/hubot status [ ok ] hubot is running.
hubot@focus:~/campfire$
/etc/init.d/hubot restart [ ok ] Restarting Hubot node bot: hubot.
hubot@focus:~/campfire$
/etc/init.d/hubot status [ ok ] hubot is running.
hubot@focus:~/campfire$
/etc/init.d/hubot stop [ ok ] Stopping Hubot node bot: hubot.
hubot@focus:~/campfire$
tail -n 5 hubot.log [Thu Jan 09 2014 21:07:05 GMT+0200 (EET)] INFO Data for brain retrieved from \
Redis
[Thu Jan 09 2014 21:24:56 GMT+0200 (EET)] WARNING The HUBOT_AUTH_ADMIN enviro\
nment variable not set
[Thu Jan 09 2014 21:24:57 GMT+0200 (EET)] INFO Data for brain retrieved from \
Redis
[Thu Jan 09 2014 21:25:11 GMT+0200 (EET)] WARNING The HUBOT_AUTH_ADMIN enviro\
nment variable not set
[Thu Jan 09 2014 21:25:12 GMT+0200 (EET)] INFO Data for brain retrieved from \
Redis
Now your Hubot is a first class citizen in Linux.
If you like web interfaces, check out . You can use it for various things, like creating and controlling multiple Hubot instances, writing scripts, managing configuration. It has a built in script editor that has syntax highlighting and validation.
It’s far from being perfect, and you will probably be happier by setting everything up like this book suggests, with hubot.conf
and init.d
script.