Skip to content

Loading…

Create .pid files for package builds #49

Merged
merged 5 commits into from

2 participants

@jaredmorrow

To properly support OS startup / shutdown scripts (sysvinit for example) we would like to enable the creation/deletion of .pid files. The issue with .pid creation in the init files (as is standard) is the system can get into a bad state if for example init is used for runner startup, but then ./runner stop is used for shutdown.

This PR attempts to address that by creating the .pid files in the runner script itself. No attempt was made to make this setup work for devrel (multi-node, single machine) builds because those are typically run as non-root.

@jaredmorrow

Here's a sample run of the latest code

bakers% ls -l /var/run/riak
ls: cannot access /var/run/riak: No such file or directory
bakers% riak ping
Node 'riak@127.0.0.1' not responding to pings.
bakers% riak start
Unable to access /var/run/riak, permission denied, run script as root
bakers% riak stop
Unable to access /var/run/riak, permission denied, run script as root
bakers% sudo riak start
bakers% riak ping
pong
bakers% riak version
1.4wip-62bc7a5a
bakers% riak getpid
18912
bakers% riak start
Unable to access /var/run/riak, permission denied, run script as root
bakers% sudo riak start
Node is already running!
bakers% cat /var/run/riak/riak.pid
18912
bakers% riak stop
Unable to access /var/run/riak, permission denied, run script as root
bakers% sudo riak stop
ok
bakers% riak ping
Node 'riak@127.0.0.1' not responding to pings.
bakers% ls -l /var/run/riak
total 0
bakers%
@Vagabond

+1 on visual and conceptual review. I didn't actually test it because testing branches of node_package sucks.

@jaredmorrow jaredmorrow merged commit 6ef0017 into master
@jaredmorrow jaredmorrow deleted the jem-pidfile branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 143 additions and 7 deletions.
  1. +68 −1 priv/base/env.sh
  2. +75 −6 priv/base/runner
View
69 priv/base/env.sh
@@ -27,6 +27,13 @@ PIPE_DIR={{pipe_dir}}
RUNNER_USER={{runner_user}}
APP_VERSION={{app_version}}
+# Variables needed to support creation of .pid files
+# PID directory and pid file name of this app
+# ex: /var/run/riak & /var/run/riak/riak.pid
+RUN_DIR="/var/run" # for now hard coded unless we find a platform that differs
+PID_DIR=$RUN_DIR/$RUNNER_SCRIPT
+PID_FILE=$PID_DIR/$RUNNER_SCRIPT.pid
+
# Threshold where users will be warned of low ulimit file settings
# default it if it is not set
ULIMIT_WARN={{runner_ulimit_warn}}
@@ -88,11 +95,71 @@ ping_node() {
$NODETOOL ping < /dev/null
}
+# Attempts to create a pid directory like /var/run/APPNAME and then
+# changes the permissions on that directory so the $RUNNER_USER can
+# read/write/delete .pid files during startup/shutdown
+create_pid_dir() {
+ # Validate RUNNER_USER is set and they have permissions to write to /var/run
+ # Don't continue if we've already sudo'd to RUNNER_USER
+ if ([ "$RUNNER_USER" ] && [ "x$WHOAMI" != "x$RUNNER_USER" ]); then
+ if [ -w $RUN_DIR ]; then
+ mkdir -p $PID_DIR
+ ES=$?
+ if [ "$ES" -ne 0 ]; then
+ return 1
+ else
+ # Change permissions on $PID_DIR
+ chown $RUNNER_USER $PID_DIR
+ ES=$?
+ if [ "$ES" -ne 0 ]; then
+ return 1
+ else
+ return 0
+ fi
+ fi
+ else
+ # If we don't have permissions, fail
+ return 1
+ fi
+ fi
+
+ # If RUNNER_USER is not set this is probably a test setup (devrel) and does
+ # not need a .pid file, so do not return error
+ return 0
+}
+
+# Attempt to create a pid file for the process
+# This function assumes the process is already up and running and can
+# respond to a getpid call. It also assumes that two processes
+# with the same name will not be run on the machine
+# Do not print any error messages as failure to create a pid file because
+# pid files are strictly optional
+# This function should really only be called in a "start" function
+# you have been warned
+create_pid_file() {
+ # Validate a pid directory even exists
+ if [ -w $PID_DIR ]; then
+ # Grab the proper pid from getpid
+ get_pid
+ ES=$?
+ if [ "$ES" -ne 0 ]; then
+ return $ES
+ else
+ # Remove pid file if it already exists since we do not
+ # plan for multiple identical runners on a single machine
+ rm -f $PID_FILE
+ echo $PID > $PID_FILE
+ return 0
+ fi
+ else
+ return 1
+ fi
+}
+
# Function to su into correct user
check_user() {
# Validate that the user running the script is the owner of the
# RUN_DIR.
-
if ([ "$RUNNER_USER" ] && [ "x$WHOAMI" != "x$RUNNER_USER" ]); then
type sudo > /dev/null 2>&1
if [ "$?" -ne 0 ]; then
View
81 priv/base/runner
@@ -7,12 +7,6 @@
# Pull environment for this install
. "{{runner_base_dir}}/lib/env.sh"
-# Make sure the user running this script is the owner and/or su to that user
-check_user $@
-ES=$?
-if [ "$ES" -ne 0 ]; then
- exit $ES
-fi
# Keep track of where script was invoked
ORIGINAL_DIR=$(pwd)
@@ -29,10 +23,38 @@ usage() {
echo " getpid | top [-interval N] [-sort reductions|memory|msg_q] [-lines N] }"
}
+# All commands must either call bootstrap or bootstrapd
+# Call bootstrap for non-daemon commands like ping or chkconfig
+# Call bootstrapd for daemon commands like start/stop/console
+bootstrap() {
+ # Make sure the user running this script is the owner and/or su to that user
+ check_user $@
+ ES=$?
+ if [ "$ES" -ne 0 ]; then
+ exit $ES
+ fi
+}
+
+bootstrapd() {
+ # Create PID directory if it does not exist before dropping permissiongs
+ # to the runner user
+ create_pid_dir
+ ES=$?
+ if [ "$ES" -ne 0 ]; then
+ echoerr "Unable to access $PID_DIR, permission denied, run script as root"
+ exit 1
+ fi
+
+ # Now call bootstrap to drop to $RUNNER_USER
+ bootstrap $@
+}
# Check the first argument for instructions
case "$1" in
start)
+ # Bootstrap daemon command (check perms & drop to $RUNNER_USER)
+ bootstrapd $@
+
# Make sure there is not already a node running
node_down_check
@@ -75,6 +97,8 @@ case "$1" in
fi
PROCESS=`$NODETOOL rpcterms erlang whereis "'${WAIT_FOR_PROCESS}'."`
if [ "$PROCESS" != "undefined" ]; then
+ # Attempt to create a .pid file for the process
+ create_pid_file
exit 0
fi
done
@@ -84,9 +108,15 @@ case "$1" in
echo "WAIT_FOR_ERLANG to the number of seconds to wait."
exit 1
fi
+
+ # Attempt to create .pid file
+ create_pid_file
;;
stop)
+ # Bootstrap daemon command (check perms & drop to $RUNNER_USER)
+ bootstrapd $@
+
get_pid
ES=$?
if [ "$ES" -ne 0 ] || [ -z $PID ]; then
@@ -103,9 +133,15 @@ case "$1" in
do
sleep 1
done
+
+ # remove pid file
+ rm -f $PID_FILE
;;
restart)
+ # Bootstrap daemon command (check perms & drop to $RUNNER_USER)
+ bootstrapd $@
+
## Restart the VM without exiting the process
$NODETOOL restart
ES=$?
@@ -115,6 +151,9 @@ case "$1" in
;;
reboot)
+ # Bootstrap daemon command (check perms & drop to $RUNNER_USER)
+ bootstrapd $@
+
## Restart the VM completely (uses heart to restart it)
$NODETOOL reboot
ES=$?
@@ -124,6 +163,9 @@ case "$1" in
;;
ping)
+ # Bootstrap command (simply drop to $RUNNER_USER)
+ bootstrap $@
+
## See if the VM is alive
ping_node
ES=$?
@@ -133,6 +175,9 @@ case "$1" in
;;
attach-direct)
+ # Bootstrap daemon command (check perms & drop to $RUNNER_USER)
+ bootstrapd $@
+
# Allow attaching to a node without pinging it
if [ "$2" = "-f" ]; then
echo "Forcing connection..."
@@ -146,6 +191,9 @@ case "$1" in
;;
attach)
+ # Bootstrap daemon command (check perms & drop to $RUNNER_USER)
+ bootstrapd $@
+
# Make sure a node is running
node_up_check
@@ -155,6 +203,9 @@ case "$1" in
;;
console)
+ # Bootstrap daemon command (check perms & drop to $RUNNER_USER)
+ bootstrapd $@
+
RES=`ping_node`
if [ "$?" -eq 0 ]; then
echo "Node is already running - use '$SCRIPT attach' instead"
@@ -198,7 +249,11 @@ case "$1" in
# Start the VM
exec $CMD
;;
+
top)
+ # Bootstrap command (simply drop to $RUNNER_USER)
+ bootstrap $@
+
# Make sure the local node IS running
node_up_check
@@ -212,20 +267,34 @@ case "$1" in
-node $NODE_NAME \
$* -tracing off
;;
+
ertspath)
echo $ERTS_PATH
;;
+
chkconfig)
+ # Bootstrap command (simply drop to $RUNNER_USER)
+ bootstrap $@
+
check_config
;;
+
escript)
+ # Bootstrap command (simply drop to $RUNNER_USER)
+ bootstrap $@
+
shift
$ERTS_PATH/escript "$@"
;;
+
version)
echo $APP_VERSION
;;
+
getpid)
+ # Bootstrap command (simply drop to $RUNNER_USER)
+ bootstrap $@
+
# Get the PID from nodetool
get_pid
ES=$?
Something went wrong with that request. Please try again.