| 1 | #!/bin/sh |
|---|
| 2 | |
|---|
| 3 | # cereal-admin: manage cereal sessions (runit service directory structure |
|---|
| 4 | # and runit run directory). |
|---|
| 5 | # |
|---|
| 6 | # The cereal scripts were written by |
|---|
| 7 | # Jameson Rollins <jrollins@fifthhorseman.net> |
|---|
| 8 | # and |
|---|
| 9 | # Daniel Kahn Gillmor <dkg-debian.org@fifthhorseman.net>. |
|---|
| 10 | # |
|---|
| 11 | # They are Copyright 2007, and are all released under the GPL, version 2 |
|---|
| 12 | # or later. |
|---|
| 13 | |
|---|
| 14 | ################################################## |
|---|
| 15 | CMD=$(basename $0) |
|---|
| 16 | |
|---|
| 17 | SHAREDIR=${SHAREDIR:-"/usr/share/cereal"} |
|---|
| 18 | export SHAREDIR |
|---|
| 19 | source "$SHAREDIR/common" |
|---|
| 20 | ################################################## |
|---|
| 21 | |
|---|
| 22 | usage() { |
|---|
| 23 | cat <<EOF |
|---|
| 24 | Usage: $CMD <subcommand> [options] [args] |
|---|
| 25 | Cereal session management program. |
|---|
| 26 | |
|---|
| 27 | subcommands: |
|---|
| 28 | create (c) SESSION TTY BAUD USER LOGGROUP create cereal session |
|---|
| 29 | start (s) [options] SESSION [SESSION]... start cereal session(s) |
|---|
| 30 | -a (--all) start all sessions |
|---|
| 31 | stop (k) [options] SESSION [SESSION]... stop cereal session(s) |
|---|
| 32 | -a (--all) stop all sessions |
|---|
| 33 | restart (r) [options] SESSION [SESSION]... restart cereal session(s) |
|---|
| 34 | -a (--all) restart all sessions |
|---|
| 35 | -r (--running) restart any currently running |
|---|
| 36 | sessions |
|---|
| 37 | destroy (d) [options] SESSION [SESSION]... destroy cereal session(s) |
|---|
| 38 | -a (--all) destroy all sessions |
|---|
| 39 | list (l) [SESSION]... list session(s) |
|---|
| 40 | help (h,?) this help |
|---|
| 41 | |
|---|
| 42 | EOF |
|---|
| 43 | } |
|---|
| 44 | |
|---|
| 45 | # create session |
|---|
| 46 | create() { |
|---|
| 47 | (( $# < 5 )) && failure "Not enough input arguments. Type '$CMD help' for more info." |
|---|
| 48 | |
|---|
| 49 | SESSION="$1" |
|---|
| 50 | TTY="$2" |
|---|
| 51 | BAUD="$3" |
|---|
| 52 | SUSER="$4" |
|---|
| 53 | SGROUP=$(ls -l "$TTY" | awk '{ print $4 }') |
|---|
| 54 | LOGUSER='cereal' |
|---|
| 55 | LOGGROUP="$5" |
|---|
| 56 | |
|---|
| 57 | if [ -d "$SESSIONDIR/$SESSION" ] ; then |
|---|
| 58 | failure "A session named '$SESSION' already exists." |
|---|
| 59 | fi |
|---|
| 60 | |
|---|
| 61 | check_is_tty "$TTY" |
|---|
| 62 | check_is_session_tty "$TTY" |
|---|
| 63 | check_user "$SUSER" |
|---|
| 64 | check_group "$SGROUP" |
|---|
| 65 | check_user "$LOGUSER" |
|---|
| 66 | check_group "$LOGGROUP" |
|---|
| 67 | check_tty_rw "$SUSER" "$SGROUP" "$TTY" |
|---|
| 68 | |
|---|
| 69 | mkdir -p "$SESSIONDIR/$SESSION" |
|---|
| 70 | |
|---|
| 71 | # create run script |
|---|
| 72 | ln -s "$SHAREDIR/mainrun" "$SESSIONDIR/$SESSION/run" |
|---|
| 73 | |
|---|
| 74 | # store environment variables |
|---|
| 75 | mkdir -p "$SESSIONDIR/$SESSION/env" |
|---|
| 76 | echo "$SESSION" > "$SESSIONDIR/$SESSION/env/SESSION" |
|---|
| 77 | echo "$TTY" > "$SESSIONDIR/$SESSION/env/TTY" |
|---|
| 78 | echo "$BAUD" > "$SESSIONDIR/$SESSION/env/BAUD" |
|---|
| 79 | echo "$SUSER" > "$SESSIONDIR/$SESSION/env/USER" |
|---|
| 80 | echo "$SGROUP" > "$SESSIONDIR/$SESSION/env/GROUP" |
|---|
| 81 | echo "$LOGUSER" > "$SESSIONDIR/$SESSION/env/LOGUSER" |
|---|
| 82 | echo "$LOGGROUP" > "$SESSIONDIR/$SESSION/env/LOGGROUP" |
|---|
| 83 | |
|---|
| 84 | # create logging script |
|---|
| 85 | mkdir -p -m 750 "$SESSIONDIR/$SESSION/log/main" |
|---|
| 86 | touch "$SESSIONDIR/$SESSION/log/main/current" |
|---|
| 87 | chmod 640 "$SESSIONDIR/$SESSION/log/main/current" |
|---|
| 88 | chown -R "$LOGUSER" "$SESSIONDIR/$SESSION/log/main" |
|---|
| 89 | chgrp -R "$LOGGROUP" "$SESSIONDIR/$SESSION/log" |
|---|
| 90 | |
|---|
| 91 | mkfifo "$SESSIONDIR/$SESSION/socket" |
|---|
| 92 | chown "$SUSER:$LOGGROUP" "$SESSIONDIR/$SESSION/socket" |
|---|
| 93 | chmod 0640 "$SESSIONDIR/$SESSION/socket" |
|---|
| 94 | ln -s "$SHAREDIR/logrun" "$SESSIONDIR/$SESSION/log/run" |
|---|
| 95 | |
|---|
| 96 | echo "Created session '$SESSION':" |
|---|
| 97 | display_session "$SESSION" |
|---|
| 98 | } |
|---|
| 99 | |
|---|
| 100 | start_check() { |
|---|
| 101 | check_tty_rw "$USER" "$GROUP" "$TTY" |
|---|
| 102 | } |
|---|
| 103 | export -f start_check |
|---|
| 104 | |
|---|
| 105 | # start_session SESSION |
|---|
| 106 | start_session() { |
|---|
| 107 | local SESSION="$1" |
|---|
| 108 | ln -s "$SESSIONDIR/$SESSION" "$SERVICE.$SESSION" |
|---|
| 109 | log_write "$SESSION" "session '$SESSION' started." |
|---|
| 110 | } |
|---|
| 111 | export -f start_session |
|---|
| 112 | |
|---|
| 113 | # start session |
|---|
| 114 | start() { |
|---|
| 115 | local ERR=0 |
|---|
| 116 | |
|---|
| 117 | if [ -z "$1" ] ; then |
|---|
| 118 | failure "Not enough input arguments. Type '$CMD help' for more info." |
|---|
| 119 | elif [ "$1" = '--all' -o "$1" = '-a' ] ; then |
|---|
| 120 | SESSIONS=$(list | cut -d ' ' -f 2) |
|---|
| 121 | else |
|---|
| 122 | SESSIONS="$@" |
|---|
| 123 | fi |
|---|
| 124 | |
|---|
| 125 | for SESSION in $SESSIONS ; do |
|---|
| 126 | if ! is_session "$SESSION" ; then |
|---|
| 127 | echo "Session '$SESSION' not found." |
|---|
| 128 | ((ERR++)) |
|---|
| 129 | continue |
|---|
| 130 | elif is_running "$SESSION" ; then |
|---|
| 131 | echo "Session '$SESSION' already be running." |
|---|
| 132 | ((ERR++)) |
|---|
| 133 | continue |
|---|
| 134 | elif ! chpst -e "$SESSIONDIR/$SESSION/env/" sh -c start_check ; then |
|---|
| 135 | echo "Session '$SESSION' no properly configured." |
|---|
| 136 | ((ERR++)) |
|---|
| 137 | continue |
|---|
| 138 | else |
|---|
| 139 | start_session "$SESSION" || failure "Session '$SESSION' could not be started." |
|---|
| 140 | echo "Started session '$SESSION'." |
|---|
| 141 | fi |
|---|
| 142 | done |
|---|
| 143 | |
|---|
| 144 | return "$ERR" |
|---|
| 145 | } |
|---|
| 146 | |
|---|
| 147 | # stop_session SESSION |
|---|
| 148 | stop_session() { |
|---|
| 149 | local SESSION="$1" |
|---|
| 150 | log_write "$SESSION" "stopping session '$SESSION'..." |
|---|
| 151 | sv exit "$SERVICE.$SESSION" |
|---|
| 152 | rm "$SERVICE.$SESSION" |
|---|
| 153 | } |
|---|
| 154 | export -f stop_session |
|---|
| 155 | |
|---|
| 156 | # stop session |
|---|
| 157 | stop() { |
|---|
| 158 | local ERR=0 |
|---|
| 159 | |
|---|
| 160 | if [ -z "$1" ] ; then |
|---|
| 161 | failure "Not enough input arguments. Type '$CMD help' for more info." |
|---|
| 162 | elif [ "$1" = '--all' -o "$1" = '-a' ] ; then |
|---|
| 163 | SESSIONS=$(list | cut -d ' ' -f 2) |
|---|
| 164 | else |
|---|
| 165 | SESSIONS="$@" |
|---|
| 166 | fi |
|---|
| 167 | |
|---|
| 168 | for SESSION in $SESSIONS ; do |
|---|
| 169 | if ! is_session "$SESSION" ; then |
|---|
| 170 | echo "Session '$SESSION' not found." |
|---|
| 171 | ((ERR++)) |
|---|
| 172 | continue |
|---|
| 173 | elif ! is_running "$SESSION" ; then |
|---|
| 174 | echo "Session '$SESSION' not running." |
|---|
| 175 | ((ERR++)) |
|---|
| 176 | continue |
|---|
| 177 | else |
|---|
| 178 | stop_session "$SESSION" || failure "Session '$SESSION' could not be stopped." |
|---|
| 179 | echo "Stopped session '$SESSION'." |
|---|
| 180 | fi |
|---|
| 181 | done |
|---|
| 182 | |
|---|
| 183 | return "$ERR" |
|---|
| 184 | } |
|---|
| 185 | |
|---|
| 186 | # restart_session SESSION |
|---|
| 187 | restart_session() { |
|---|
| 188 | local SESSION="$1" |
|---|
| 189 | log_write "$SESSION" "restarting session '$SESSION'..." |
|---|
| 190 | sv restart "$SERVICE.$SESSION" |
|---|
| 191 | } |
|---|
| 192 | export -f restart_session |
|---|
| 193 | |
|---|
| 194 | # restart session |
|---|
| 195 | restart() { |
|---|
| 196 | local ERR=0 |
|---|
| 197 | |
|---|
| 198 | if [ -z "$1" ] ; then |
|---|
| 199 | failure "Not enough input arguments. Type '$CMD help' for more info." |
|---|
| 200 | elif [ "$1" = '--all' -o "$1" = '-a' ] ; then |
|---|
| 201 | SESSIONS=$(list | cut -d ' ' -f 2) |
|---|
| 202 | elif [ "$1" = '--running' -o "$1" = '-r' ] ; then |
|---|
| 203 | SESSIONS=$(list | grep '^+' | cut -d ' ' -f 2) |
|---|
| 204 | [ "$SESSIONS" ] || failure "There are no running sessions." 0 |
|---|
| 205 | else |
|---|
| 206 | SESSIONS="$@" |
|---|
| 207 | fi |
|---|
| 208 | |
|---|
| 209 | for SESSION in $SESSIONS ; do |
|---|
| 210 | if ! is_session "$SESSION" ; then |
|---|
| 211 | echo "Session '$SESSION' not found." |
|---|
| 212 | ((ERR++)) |
|---|
| 213 | continue |
|---|
| 214 | elif ! is_running "$SESSION" ; then |
|---|
| 215 | start_session "$SESSION" || failure "Session '$SESSION' could not be started." |
|---|
| 216 | echo "Started session '$SESSION'." |
|---|
| 217 | else |
|---|
| 218 | restart_session "$SESSION" || failure "Session '$SESSION' could not be restarted." |
|---|
| 219 | echo "Restarted session '$SESSION'." |
|---|
| 220 | fi |
|---|
| 221 | done |
|---|
| 222 | |
|---|
| 223 | return "$ERR" |
|---|
| 224 | } |
|---|
| 225 | |
|---|
| 226 | # destroy_session SESSION |
|---|
| 227 | destroy_session() { |
|---|
| 228 | rm -rf "$SESSIONDIR/$1" |
|---|
| 229 | } |
|---|
| 230 | export -f destroy_session |
|---|
| 231 | |
|---|
| 232 | # destroy session |
|---|
| 233 | destroy() { |
|---|
| 234 | local ERR=0 |
|---|
| 235 | |
|---|
| 236 | if [ -z "$1" ] ; then |
|---|
| 237 | failure "Not enough input arguments. Type '$CMD help' for more info." |
|---|
| 238 | elif [ "$1" = '--all' -o "$1" = '-a' ] ; then |
|---|
| 239 | SESSIONS=$(list | cut -d ' ' -f 2) |
|---|
| 240 | else |
|---|
| 241 | SESSIONS="$@" |
|---|
| 242 | fi |
|---|
| 243 | |
|---|
| 244 | for SESSION in $SESSIONS ; do |
|---|
| 245 | if ! is_session "$SESSION" ; then |
|---|
| 246 | echo "Session '$SESSION' not found." |
|---|
| 247 | ((ERR++)) |
|---|
| 248 | continue |
|---|
| 249 | elif is_running "$SESSION" ; then |
|---|
| 250 | echo "Session '$SESSION' is currently running." |
|---|
| 251 | read -p "Really stop and destroy session? [Y|n]: " OK |
|---|
| 252 | if [ -z "$OK" -o "${OK/y/Y}" = 'Y' ] ; then |
|---|
| 253 | stop_session "$SESSION" || failure "Session '$SESSION' could not be stopped." |
|---|
| 254 | destroy_session "$SESSION" || failure "Session '$SESSION' could not be destroyed." |
|---|
| 255 | echo "Stopped and destroyed session '$SESSION'." |
|---|
| 256 | else |
|---|
| 257 | echo "Session '$SESSION' not stopped." |
|---|
| 258 | ((ERR++)) |
|---|
| 259 | continue |
|---|
| 260 | fi |
|---|
| 261 | else |
|---|
| 262 | read -p "Really destroy session '$SESSION'? [Y|n]: " OK |
|---|
| 263 | if [ -z "$OK" -o "${OK/y/Y}" = 'Y' ] ; then |
|---|
| 264 | destroy_session "$SESSION" || failure "Session '$SESSION' could not be destroyed." |
|---|
| 265 | echo "Destroyed session '$SESSION'." |
|---|
| 266 | else |
|---|
| 267 | echo "Session '$SESSION' not destroyed." |
|---|
| 268 | ((ERR++)) |
|---|
| 269 | continue |
|---|
| 270 | fi |
|---|
| 271 | fi |
|---|
| 272 | done |
|---|
| 273 | |
|---|
| 274 | return "$ERR" |
|---|
| 275 | } |
|---|
| 276 | |
|---|
| 277 | ############################################################### |
|---|
| 278 | ### MAIN |
|---|
| 279 | |
|---|
| 280 | COMMAND="$1" |
|---|
| 281 | [ "$COMMAND" ] || failure "Type '$CMD help' for usage." |
|---|
| 282 | shift |
|---|
| 283 | |
|---|
| 284 | case $COMMAND in |
|---|
| 285 | 'create'|'c') |
|---|
| 286 | create "$@" |
|---|
| 287 | ;; |
|---|
| 288 | 'start'|'s') |
|---|
| 289 | start "$@" |
|---|
| 290 | ;; |
|---|
| 291 | 'restart'|'r') |
|---|
| 292 | restart "$@" |
|---|
| 293 | ;; |
|---|
| 294 | 'stop'|'k') |
|---|
| 295 | stop "$@" |
|---|
| 296 | ;; |
|---|
| 297 | 'destroy'|'d') |
|---|
| 298 | destroy "$@" |
|---|
| 299 | ;; |
|---|
| 300 | 'list'|'l') |
|---|
| 301 | list "$@" |
|---|
| 302 | ;; |
|---|
| 303 | 'help'|'h'|'?') |
|---|
| 304 | usage |
|---|
| 305 | ;; |
|---|
| 306 | *) |
|---|
| 307 | failure "Unknown command: '$COMMAND' |
|---|
| 308 | Type '$CMD help' for usage." |
|---|
| 309 | ;; |
|---|
| 310 | esac |
|---|