2 LOG_FILE
="/tmp/discourse-debug.txt"
3 WORKING_DIR
="$( cd "$
( dirname "${BASH_SOURCE[0]}" )" && pwd )"
9 echo -e "$*" |
tee -a "$LOG_FILE"
11 echo "$*" |
tee -a "$LOG_FILE"
16 if [[ $EUID -ne 0 ]]; then
17 log
"This script must be run as root. Please sudo or log in as root first." 1>&2
23 ## Check whether a connection to HOSTNAME ($1) on PORT ($2) is possible
28 VERIFY
=$
(date +%s | sha256sum | base64 |
head -c 20)
29 echo -e "HTTP/1.1 200 OK\n\n $VERIFY" | nc
-w 4 -l -p $PORT >/dev
/null
2>&1 &
30 if curl
--proto =http
-s $HOST:$PORT --connect-timeout 3 |
grep $VERIFY >/dev
/null
2>&1 &
41 log Checking your domain name . . .
42 if connect_to_port
$HOST 443
45 log
"Connection to $HOST succeeded."
47 log WARNING
:: This server does not appear to be accessible
at $HOST:443.
49 if connect_to_port
$HOST 80
51 log A connection to port
80 succeeds
, however.
52 log This suggests that your DNS settings are correct
,
53 log but something is keeping traffic to port
443 from getting to your server.
54 log Check your networking configuration to see that connections to port
443 are allowed.
56 log
"A connection to http://$HOST (port 80) also fails."
58 log This suggests that
$HOST resolves to the wrong IP address
59 log or that traffic is not being routed to your server.
62 log Google
: \"open ports YOUR CLOUD SERVICE
\" for information
for resolving this problem.
64 log This
test might not work
for all situations
,
65 log so
if you can access Discourse
at http
://$HOST, this might not indicate a problem.
70 check_docker_is_installed
() {
71 log
-e "\n==================== DOCKER INFO ===================="
72 docker_path
="$(which docker.io || which docker)"
73 if [ -z $docker_path ]; then
74 log
"Docker is not installed. Have you installed Discourse at all?"
75 log
"Perhaps you're looking for ./discourse-setup ."
76 log
"There is no point in continuing."
79 log
-e "DOCKER VERSION: $(docker --version)"
80 log
-e "\nDOCKER PROCESSES (docker ps -a)\n\n$(sudo docker ps -a)\n"
85 log
-e "OS: $(uname -s)"
88 check_disk_and_memory
() {
89 log
-e "\n\n==================== MEMORY INFORMATION ===================="
91 if [ "$os_type" == "Darwin" ]; then
92 log
-e "RAM: $( free -m | awk '/Mem:/ {print $2}' ) \n"
94 log
-e "RAM (MB): $( free -m --si | awk ' /Mem:/ {print $2} ')\n"
98 log
-e "\n==================== DISK SPACE CHECK ===================="
99 log
"---------- OS Disk Space ----------"
100 log
"$(df -h / /var/discourse /var/lib/docker /var/lib/docker/* | uniq)"
102 if [ "$version" != "NOT FOUND" ]
105 log
"---------- Container Disk Space ----------"
106 log
"$(sudo docker exec -w /var/www/discourse -i $app_name df -h / /shared/ /shared/postgres_data /shared/redis_data /shared/backups /var/log | uniq)"
109 log
-e "\n==================== DISK INFORMATION ===================="
111 log
-e "\n==================== END DISK INFORMATION ===================="
113 free_disk
="$(df /var | tail -n 1 | awk '{print $4}')"
114 # Arguably ./launcher is doing this so discourse-doctor does not need to . . .
115 if [ "$free_disk" -lt 5000 ]; then
116 log
"\n\n==================== DISK SPACE PROBLEM ===================="
117 log
"WARNING: you appear to have very low disk space."
118 log
"This could be the cause of problems running your site."
119 log
"Please free up some space, or expand your disk, before continuing."
121 log
"Run \'apt-get autoremove && apt-get autoclean\' to clean up unused"
122 log
"packages and \'./launcher cleanup\' to remove stale Docker containers."
127 get_discourse_version
() {
129 version
=$
(wget
-q --timeout=3 https
://$VERSION_HOSTNAME/privacy
-O -|
grep generator|
head -1 |cut
-d "=" -f 3|cut
-d '-' -f 1 |cut
-d '"' -f 2) &> /dev
/null
130 if ! echo $version |
grep Discourse
132 version
=$
(wget
-q --timeout=3 http
://$VERSION_HOSTNAME/privacy
-O -|
grep generator|
head -1 |cut
-d "=" -f 3|cut
-d '-' -f 1 |cut
-d '"' -f 2) &> /dev
/null
138 log
"Discourse version at $VERSION_HOSTNAME: $version"
141 check_if_hostname_resolves_here
() {
142 log
"========================================"
143 VERSION_HOSTNAME
=$DISCOURSE_HOSTNAME
144 get_discourse_version
145 DISCOURSE_VERSION
="$version"
146 VERSION_HOSTNAME
=localhost
147 get_discourse_version
148 LOCALHOST_VERSION
="$version"
149 if [ "$DISCOURSE_VERSION" != "$LOCALHOST_VERSION" ]
151 log
"==================== DNS PROBLEM ===================="
152 log
"This server reports $LOCALHOST_VERSION, but $DISCOURSE_HOSTNAME reports $DISCOURSE_VERSION."
153 log
"This suggests that you have a DNS problem or that an intermediate proxy is to blame."
154 log
"If you are using Cloudflare, or a CDN, it may be improperly configured."
159 ## get discourse configuration values from YML file
161 get_discourse_config
() {
162 log
-e "\n==================== YML SETTINGS ===================="
163 read_config
"DISCOURSE_HOSTNAME"
164 DISCOURSE_HOSTNAME
=$read_config_result
165 log DISCOURSE_HOSTNAME
=$DISCOURSE_HOSTNAME
166 read_config
"DISCOURSE_SMTP_ADDRESS"
167 SMTP_ADDRESS
=$read_config_result
168 log SMTP_ADDRESS
=$SMTP_ADDRESS
169 read_config
"DISCOURSE_DEVELOPER_EMAILS"
170 DEVELOPER_EMAILS
=$read_config_result
171 log DEVELOPER_EMAILS
=$DEVELOPER_EMAILS
172 read_config
"DISCOURSE_SMTP_PASSWORD"
173 SMTP_PASSWORD
=$read_config_result
174 log SMTP_PASSWORD
=$read_config_result
175 read_config
"DISCOURSE_SMTP_PORT"
176 SMTP_PORT
=$read_config_result
177 log SMTP_PORT
=$read_config_result
178 read_config
"DISCOURSE_SMTP_USER_NAME"
179 SMTP_USER_NAME
=$read_config_result
180 log SMTP_USER_NAME
=$read_config_result
181 read_config
"LETSENCRYPT_ACCOUNT_EMAIL"
182 letsencrypt_account_email
=$read_config_result
183 log
"LETSENCRYPT_ACCOUNT_EMAIL=$letsencrypt_account_email"
187 log
-e "\n\n==================== PLUGINS ===================="
188 log
-e "$(grep 'git clone' containers/$app_name.yml)"
189 grep git containers
/$app_name.yml
> /tmp
/$PPID.
grep
191 if grep -cv "github.com/discourse" /tmp
/$PPID.
grep > /dev
/null
194 log You have what appear to be non-official plugins.
195 log
"If you are having trouble, you should disable them and try rebuilding again."
197 log
-e "\nNo non-official plugins detected."
199 log
-e "\nSee https://github.com/discourse/discourse/blob/master/lib/plugin/metadata.rb for the official list.\n"
203 log
-e "\n\n==================== YML DUMP ===================="
204 log Dumping
$app_name.yml
209 ## read a variable from the config file and stick it in read_config_result
212 config_line
=$
(egrep "^ #?$1:" $web_file)
213 read_config_result
=$
(echo $config_line |
awk --field-separator=":" '{print $2}')
214 read_config_result
=$
(echo $read_config_result |
sed "s/^\([\"']\)\(.*\)\1\$/\2/g")
218 ## call rake emails:test inside the container
221 log
-e "\n==================== MAIL TEST ===================="
222 log
"For a robust test, get an address from http://www.mail-tester.com/"
223 echo "Or just send a test message to yourself."
224 EMAIL
=$
(echo $DEVELOPER_EMAILS |cut
-d , -f 1)
225 read -p "Email address for mail test? ('n' to skip) [$EMAIL]: " new_value
226 if [ ! -z "$new_value" ]
230 if [ "$new_value" != "n" ] && [ "$new_value" != "N" ]
232 log
"Sending mail to $EMAIL. . . "
233 log
"$(sudo docker exec -w /var/www/discourse -i $app_name rake emails:test[$EMAIL])"
235 log
"Mail test skipped."
241 if [ -f containers
/app.yml
]
244 web_file
=containers
/$app_name.yml
245 log
"Found $web_file"
246 elif [ -f containers
/web_only.yml
]
248 log
"YML=web_only.yml"
250 web_file
=containers
/$app_name.yml
251 log
"Found $web_file"
253 log
"Can't find app.yml or web_only.yml."
260 docker ps |
tail -n +2 > /tmp
/$UUID-docker.txt
262 if grep $app_name /tmp
/$UUID-docker.txt
264 log
-e "\nDiscourse container $app_name is running"
266 log
"==================== SERIOUS PROBLEM!!!! ===================="
267 log
"$app_name not running!"
268 log
"Attempting to rebuild"
269 log
"==================== REBUILD LOG ===================="
270 # too hard to pass STDERR of ./launcher to log()
271 .
/launcher rebuild
$app_name 2>&1 |
tee -a $LOG_FILE
272 log
"==================== END REBUILD LOG ===================="
273 docker ps |
tail -n +2 > /tmp
/$UUID-docker.txt
274 if grep $app_name /tmp
/$UUID-docker.txt
276 log
-e "\nDiscourse container $app_name is now running."
277 log
". . . waiting 30 seconds for container to crank up. . . "
280 log
"Failed to rebuild $app_name."
281 # check_ip_match checks if curl to $DISCOURSE_HOSTNAME gets to this server
282 # It works only if ports 80 and 443 are free
283 check_ip_match
$DISCOURSE_HOSTNAME
284 log
"You should probably remove any non-standard plugins and rebuild."
286 log
"Attempting to restart existing container. . . "
287 .
/launcher start
$app_name 2>&1 |
tee -a $LOG_FILE
288 docker ps |
tail -n +2 > /tmp
/$UUID-docker.txt
289 if grep $app_name /tmp
/$UUID-docker.txt
291 log
"Restarted the container."
294 log
"Failed to restart the container."
301 ## redact passwords and email addresses from log file
303 clean_up_log_file
() {
305 in SMTP_PASSWORD LETSENCRYPT_ACCOUNT_EMAIL DEVELOPER_EMAILS DISCOURSE_DB_PASSWORD
'Sending mail to'
307 echo "Replacing: $VAR"
308 sed -i -e 's/'"$VAR"'\([=: ]\)\S*/'"$VAR"'\1REDACTED /g' $LOG_FILE
314 log
"==================== DONE! ===================="
315 DOCTOR_FILE
=$
(date +%s | sha256sum | base64 |
head -c 20).txt
317 if [ $app_name == 'app' ] && [ "$NO_CONTAINER" != 'y' ]
319 read -p "Would you like to serve a publicly available version of this file? (Y/n)" serve
322 cp $LOG_FILE shared
/standalone
/log
/var-log
/$DOCTOR_FILE
323 sudo docker
exec -w /var
/www
/discourse
-i $app_name cp /var
/log
/$DOCTOR_FILE public
324 log
"The output of this program may be available at http://$DISCOURSE_HOSTNAME/$DOCTOR_FILE"
325 log
"You should inspect that file carefully before sharing the URL."
327 log
"Publicly available log not generated."
330 # The following is not in the web log file since it was copied above, which seems corect
332 log
"You can examine the output of this script with "
333 log
"LESS=-Ri less $LOG_FILE"
335 log
"BUT FIRST, make sure that you know the first three commands below!!!"
337 log
"Commands to know when viewing the file with the above command (called 'less'): "
339 log
"/error<ENTER> -- search for the word 'error'"
340 log
"n -- search for the next occurrence"
341 log
"g -- go to the beginning of the file"
342 log
"f -- go forward a page"
343 log
"b -- go back a page"
344 log
"G -- go to the end of the file"
347 initialize_log_file
() {
350 log DISCOURSE DOCTOR $
(date)
351 log
-e "OS: $(uname -a)\n\n"
355 ## END FUNCTION DECLARATION
359 cd $WORKING_DIR ||
exit
363 check_docker_is_installed
366 check_if_hostname_resolves_here
367 check_disk_and_memory