Commit 5dad053a82a824c61a813aaf608d1e9240e1020c
Exists in
master
and in
4 other branches
Merge pull request #4920 from Rovanion/init-rewrite
Rewrote init script.
Showing
2 changed files
with
202 additions
and
77 deletions
Show diff stats
CHANGELOG
1 | v 6.1.0 | 1 | v 6.1.0 |
2 | + - Rewrite: Init script now less prone to errors and keeps better track of the service. | ||
2 | - Link issues, merge requests, and commits when they reference each other with GFM | 3 | - Link issues, merge requests, and commits when they reference each other with GFM |
3 | - Close issues automatically when pushing commits with a special message | 4 | - Close issues automatically when pushing commits with a special message |
4 | - Project internal ids for issues, mr, milestones | 5 | - Project internal ids for issues, mr, milestones |
1 | -#! /bin/bash | 1 | +#! /bin/sh |
2 | 2 | ||
3 | # GITLAB | 3 | # GITLAB |
4 | # Maintainer: @randx | 4 | # Maintainer: @randx |
5 | +# Authors: rovanion.luckey@gmail.com, @randx | ||
5 | # App Version: 6.0 | 6 | # App Version: 6.0 |
6 | 7 | ||
7 | ### BEGIN INIT INFO | 8 | ### BEGIN INIT INFO |
@@ -14,102 +15,227 @@ | @@ -14,102 +15,227 @@ | ||
14 | # Description: GitLab git repository management | 15 | # Description: GitLab git repository management |
15 | ### END INIT INFO | 16 | ### END INIT INFO |
16 | 17 | ||
18 | +### Environment variables | ||
19 | +RAILS_ENV="production" | ||
17 | 20 | ||
18 | -APP_ROOT="/home/git/gitlab" | ||
19 | -APP_USER="git" | ||
20 | -DAEMON_OPTS="-c $APP_ROOT/config/unicorn.rb -E production" | ||
21 | -PID_PATH="$APP_ROOT/tmp/pids" | ||
22 | -SOCKET_PATH="$APP_ROOT/tmp/sockets" | ||
23 | -WEB_SERVER_PID="$PID_PATH/unicorn.pid" | ||
24 | -SIDEKIQ_PID="$PID_PATH/sidekiq.pid" | ||
25 | -STOP_SIDEKIQ="RAILS_ENV=production bundle exec rake sidekiq:stop" | ||
26 | -START_SIDEKIQ="RAILS_ENV=production bundle exec rake sidekiq:start" | ||
27 | -NAME="gitlab" | ||
28 | -DESC="GitLab service" | ||
29 | - | ||
30 | -check_pid(){ | ||
31 | - if [ -f $WEB_SERVER_PID ]; then | ||
32 | - PID=`cat $WEB_SERVER_PID` | ||
33 | - SPID=`cat $SIDEKIQ_PID` | ||
34 | - STATUS=`ps aux | grep $PID | grep -v grep | wc -l` | 21 | +# Script variable names should be lower-case not to conflict with internal |
22 | +# /bin/sh variables such as PATH, EDITOR or SHELL. | ||
23 | +app_root="/home/git/gitlab" | ||
24 | +app_user="git" | ||
25 | +unicorn_conf="$app_root/config/unicorn.rb" | ||
26 | +pid_path="$app_root/tmp/pids" | ||
27 | +socket_path="$app_root/tmp/sockets" | ||
28 | +web_server_pid_path="$pid_path/unicorn.pid" | ||
29 | +sidekiq_pid_path="$pid_path/sidekiq.pid" | ||
30 | + | ||
31 | + | ||
32 | + | ||
33 | +### Here ends user configuration ### | ||
34 | + | ||
35 | + | ||
36 | +# Switch to the app_user if it is not he/she who is running the script. | ||
37 | +if [ "$USER" != "$app_user" ]; then | ||
38 | + sudo -u "$app_user" -H $0 "$@"; exit; | ||
39 | +fi | ||
40 | + | ||
41 | +# Switch to the gitlab path, if it fails exit with an error. | ||
42 | +if ! cd "$app_root" ; then | ||
43 | + echo "Failed to cd into $app_root, exiting!"; exit 1 | ||
44 | +fi | ||
45 | + | ||
46 | +### Init Script functions | ||
47 | + | ||
48 | +check_pids(){ | ||
49 | + if ! mkdir -p "$pid_path"; then | ||
50 | + echo "Could not create the path $pid_path needed to store the pids." | ||
51 | + exit 1 | ||
52 | + fi | ||
53 | + # If there exists a file which should hold the value of the Unicorn pid: read it. | ||
54 | + if [ -f "$web_server_pid_path" ]; then | ||
55 | + wpid=$(cat "$web_server_pid_path") | ||
35 | else | 56 | else |
36 | - STATUS=0 | ||
37 | - PID=0 | 57 | + wpid=0 |
58 | + fi | ||
59 | + if [ -f "$sidekiq_pid_path" ]; then | ||
60 | + spid=$(cat "$sidekiq_pid_path") | ||
61 | + else | ||
62 | + spid=0 | ||
38 | fi | 63 | fi |
39 | } | 64 | } |
40 | 65 | ||
41 | -execute() { | ||
42 | - sudo -u $APP_USER -H bash -l -c "$1" | ||
43 | -} | 66 | +# We use the pids in so many parts of the script it makes sense to always check them. |
67 | +# Only after start() is run should the pids change. Sidekiq sets it's own pid. | ||
68 | +check_pids | ||
44 | 69 | ||
45 | -start() { | ||
46 | - cd $APP_ROOT | ||
47 | - check_pid | ||
48 | - if [ "$PID" -ne 0 -a "$STATUS" -ne 0 ]; then | ||
49 | - # Program is running, exit with error code 1. | ||
50 | - echo "Error! $DESC $NAME is currently running!" | ||
51 | - exit 1 | 70 | + |
71 | +# Checks whether the different parts of the service are already running or not. | ||
72 | +check_status(){ | ||
73 | + check_pids | ||
74 | + # If the web server is running kill -0 $wpid returns true, or rather 0. | ||
75 | + # Checks of *_status should only check for == 0 or != 0, never anything else. | ||
76 | + if [ $wpid -ne 0 ]; then | ||
77 | + kill -0 "$wpid" 2>/dev/null | ||
78 | + web_status="$?" | ||
52 | else | 79 | else |
53 | - if [ `whoami` = root ]; then | ||
54 | - execute "rm -f $SOCKET_PATH/gitlab.socket" | ||
55 | - execute "RAILS_ENV=production bundle exec unicorn_rails $DAEMON_OPTS > /dev/null 2>&1 &" | ||
56 | - execute "mkdir -p $PID_PATH && $START_SIDEKIQ > /dev/null 2>&1 &" | ||
57 | - echo "$DESC started" | 80 | + web_status="-1" |
81 | + fi | ||
82 | + if [ $spid -ne 0 ]; then | ||
83 | + kill -0 "$spid" 2>/dev/null | ||
84 | + sidekiq_status="$?" | ||
85 | + else | ||
86 | + sidekiq_status="-1" | ||
87 | + fi | ||
88 | +} | ||
89 | + | ||
90 | +# Check for stale pids and remove them if necessary | ||
91 | +check_stale_pids(){ | ||
92 | + check_status | ||
93 | + # If there is a pid it is something else than 0, the service is running if | ||
94 | + # *_status is == 0. | ||
95 | + if [ "$wpid" != "0" -a "$web_status" != "0" ]; then | ||
96 | + echo "Removing stale Unicorn web server pid. This is most likely caused by the web server crashing the last time it ran." | ||
97 | + if ! rm "$web_server_pid_path"; then | ||
98 | + echo "Unable to remove stale pid, exiting" | ||
99 | + exit 1 | ||
100 | + fi | ||
101 | + fi | ||
102 | + if [ "$spid" != "0" -a "$sidekiq_status" != "0" ]; then | ||
103 | + echo "Removing stale Sidekiq web server pid. This is most likely caused by the Sidekiq crashing the last time it ran." | ||
104 | + if ! rm "$sidekiq_pid_path"; then | ||
105 | + echo "Unable to remove stale pid, exiting" | ||
106 | + exit 1 | ||
58 | fi | 107 | fi |
59 | fi | 108 | fi |
60 | } | 109 | } |
61 | 110 | ||
62 | -stop() { | ||
63 | - cd $APP_ROOT | ||
64 | - check_pid | ||
65 | - if [ "$PID" -ne 0 -a "$STATUS" -ne 0 ]; then | ||
66 | - ## Program is running, stop it. | ||
67 | - kill -QUIT `cat $WEB_SERVER_PID` | ||
68 | - execute "mkdir -p $PID_PATH && $STOP_SIDEKIQ > /dev/null 2>&1 &" | ||
69 | - rm "$WEB_SERVER_PID" >> /dev/null | ||
70 | - echo "$DESC stopped" | 111 | +# If no parts of the service is running, bail out. |
112 | +exit_if_not_running(){ | ||
113 | + check_stale_pids | ||
114 | + if [ "$web_status" != "0" -a "$sidekiq_status" != "0" ]; then | ||
115 | + echo "GitLab is not running." | ||
116 | + exit | ||
117 | + fi | ||
118 | +} | ||
119 | + | ||
120 | +# Starts Unicorn and Sidekiq. | ||
121 | +start() { | ||
122 | + check_stale_pids | ||
123 | + | ||
124 | + # Then check if the service is running. If it is: don't start again. | ||
125 | + if [ "$web_status" = "0" ]; then | ||
126 | + echo "The Unicorn web server already running with pid $wpid, not restarting." | ||
71 | else | 127 | else |
72 | - ## Program is not running, exit with error. | ||
73 | - echo "Error! $DESC not started!" | ||
74 | - exit 1 | 128 | + echo "Starting the GitLab Unicorn web server..." |
129 | + # Remove old socket if it exists | ||
130 | + rm -f "$socket_path"/gitlab.socket 2>/dev/null | ||
131 | + # Start the webserver | ||
132 | + bundle exec unicorn_rails -D -c "$unicorn_conf" -E "$RAILS_ENV" | ||
133 | + fi | ||
134 | + | ||
135 | + # If sidekiq is already running, don't start it again. | ||
136 | + if [ "$sidekiq_status" = "0" ]; then | ||
137 | + echo "The Sidekiq job dispatcher is already running with pid $spid, not restarting" | ||
138 | + else | ||
139 | + echo "Starting the GitLab Sidekiq event dispatcher..." | ||
140 | + RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:start | ||
141 | + # We are sleeping a bit here because sidekiq is slow at writing it's pid | ||
142 | + sleep 2 | ||
75 | fi | 143 | fi |
144 | + | ||
145 | + # Finally check the status to tell wether or not GitLab is running | ||
146 | + status | ||
76 | } | 147 | } |
77 | 148 | ||
78 | -restart() { | ||
79 | - cd $APP_ROOT | ||
80 | - check_pid | ||
81 | - if [ "$PID" -ne 0 -a "$STATUS" -ne 0 ]; then | ||
82 | - echo "Restarting $DESC..." | ||
83 | - kill -USR2 `cat $WEB_SERVER_PID` | ||
84 | - execute "mkdir -p $PID_PATH && $STOP_SIDEKIQ > /dev/null 2>&1" | ||
85 | - if [ `whoami` = root ]; then | ||
86 | - execute "mkdir -p $PID_PATH && $START_SIDEKIQ > /dev/null 2>&1 &" | ||
87 | - fi | ||
88 | - echo "$DESC restarted." | 149 | +# Asks the Unicorn and the Sidekiq if they would be so kind as to stop, if not kills them. |
150 | +stop() { | ||
151 | + exit_if_not_running | ||
152 | + # If the Unicorn web server is running, tell it to stop; | ||
153 | + if [ "$web_status" = "0" ]; then | ||
154 | + kill -QUIT "$wpid" & | ||
155 | + echo "Stopping the GitLab Unicorn web server..." | ||
156 | + stopping=true | ||
89 | else | 157 | else |
90 | - echo "Error, $NAME not running!" | ||
91 | - exit 1 | 158 | + echo "The Unicorn web was not running, doing nothing." |
159 | + fi | ||
160 | + # And do the same thing for the Sidekiq. | ||
161 | + if [ "$sidekiq_status" = "0" ]; then | ||
162 | + printf "Stopping Sidekiq job dispatcher." | ||
163 | + RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:stop & | ||
164 | + stopping=true | ||
165 | + else | ||
166 | + echo "The Sidekiq was not running, must have run out of breath." | ||
92 | fi | 167 | fi |
168 | + | ||
169 | + | ||
170 | + # If something needs to be stopped, lets wait for it to stop. Never use SIGKILL in a script. | ||
171 | + while [ "$stopping" = "true" ]; do | ||
172 | + sleep 1 | ||
173 | + check_status | ||
174 | + if [ "$web_status" = "0" -o "$sidekiq_status" = "0" ]; then | ||
175 | + printf "." | ||
176 | + else | ||
177 | + printf "\n" | ||
178 | + break | ||
179 | + fi | ||
180 | + done | ||
181 | + sleep 1 | ||
182 | + # Cleaning up unused pids | ||
183 | + rm "$web_server_pid_path" 2>/dev/null | ||
184 | + # rm "$sidekiq_pid_path" # Sidekiq seems to be cleaning up it's own pid. | ||
185 | + | ||
186 | + status | ||
93 | } | 187 | } |
94 | 188 | ||
189 | +# Returns the status of GitLab and it's components | ||
95 | status() { | 190 | status() { |
96 | - cd $APP_ROOT | ||
97 | - check_pid | ||
98 | - if [ "$PID" -ne 0 -a "$STATUS" -ne 0 ]; then | ||
99 | - echo "$DESC / Unicorn with PID $PID is running." | ||
100 | - echo "$DESC / Sidekiq with PID $SPID is running." | 191 | + check_status |
192 | + if [ "$web_status" != "0" -a "$sidekiq_status" != "0" ]; then | ||
193 | + echo "GitLab is not running." | ||
194 | + return | ||
195 | + fi | ||
196 | + if [ "$web_status" = "0" ]; then | ||
197 | + echo "The GitLab Unicorn webserver with pid $wpid is running." | ||
101 | else | 198 | else |
102 | - echo "$DESC is not running." | ||
103 | - exit 1 | 199 | + printf "The GitLab Unicorn webserver is \033[31mnot running\033[0m.\n" |
200 | + fi | ||
201 | + if [ "$sidekiq_status" = "0" ]; then | ||
202 | + echo "The GitLab Sidekiq job dispatcher with pid $spid is running." | ||
203 | + else | ||
204 | + printf "The GitLab Sidekiq job dispatcher is \033[31mnot running\033[0m.\n" | ||
205 | + fi | ||
206 | + if [ "$web_status" = "0" -a "$sidekiq_status" = "0" ]; then | ||
207 | + printf "GitLab and all it's components are \033[32mup and running\033[0m.\n" | ||
104 | fi | 208 | fi |
105 | } | 209 | } |
106 | 210 | ||
107 | -## Check to see if we are running as root first. | ||
108 | -## Found at http://www.cyberciti.biz/tips/shell-root-user-check-script.html | ||
109 | -if [ "$(id -u)" != "0" ]; then | ||
110 | - echo "This script must be run as root" | 211 | +reload(){ |
212 | + exit_if_not_running | ||
213 | + if [ "$wpid" = "0" ];then | ||
214 | + echo "The GitLab Unicorn Web server is not running thus its configuration can't be reloaded." | ||
111 | exit 1 | 215 | exit 1 |
112 | -fi | 216 | + fi |
217 | + printf "Reloading GitLab Unicorn configuration... " | ||
218 | + kill -USR2 "$wpid" | ||
219 | + echo "Done." | ||
220 | + echo "Restarting GitLab Sidekiq since it isn't capable of reloading its config..." | ||
221 | + RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:stop | ||
222 | + echo "Starting Sidekiq..." | ||
223 | + RAILS_ENV=$RAILS_ENV bundle exec rake sidekiq:start | ||
224 | + # Waiting 2 seconds for sidekiq to write it. | ||
225 | + sleep 2 | ||
226 | + status | ||
227 | +} | ||
228 | + | ||
229 | +restart(){ | ||
230 | + check_status | ||
231 | + if [ "$web_status" = "0" -o "$sidekiq_status" = "0" ]; then | ||
232 | + stop | ||
233 | + fi | ||
234 | + start | ||
235 | +} | ||
236 | + | ||
237 | + | ||
238 | +## Finally the input handling. | ||
113 | 239 | ||
114 | case "$1" in | 240 | case "$1" in |
115 | start) | 241 | start) |
@@ -122,17 +248,15 @@ case "$1" in | @@ -122,17 +248,15 @@ case "$1" in | ||
122 | restart | 248 | restart |
123 | ;; | 249 | ;; |
124 | reload|force-reload) | 250 | reload|force-reload) |
125 | - echo -n "Reloading $NAME configuration: " | ||
126 | - kill -HUP `cat $PID` | ||
127 | - echo "done." | 251 | + reload |
128 | ;; | 252 | ;; |
129 | status) | 253 | status) |
130 | status | 254 | status |
131 | ;; | 255 | ;; |
132 | *) | 256 | *) |
133 | - echo "Usage: sudo service gitlab {start|stop|restart|reload}" >&2 | 257 | + echo "Usage: service gitlab {start|stop|restart|reload|status}" |
134 | exit 1 | 258 | exit 1 |
135 | ;; | 259 | ;; |
136 | esac | 260 | esac |
137 | 261 | ||
138 | -exit 0 | 262 | +exit |