From 476524c0c19af0edd0b579c42e3c9d7811de547d Mon Sep 17 00:00:00 2001 From: Alex Vandiver Date: Fri, 16 Apr 2021 05:46:05 +0000 Subject: [PATCH] scripts: Add a script to stop the server. Using `supervisorctl stop all` to stop the server is not terribly discoverable, and may stop services which are not part of Zulip proper. Add an explicit tool which only stops the relevant services. It also more carefully controls the order in which services are stopped to minimize lost requests, and maximally quiesce the server. Locations which may be stopping _older_ versions of Zulip (without this script) are left with using `supervisorctl stop all`. Fixes #14959. --- docs/production/export-and-import.md | 6 +-- docs/production/troubleshooting.md | 3 ++ docs/production/upgrade-or-modify.md | 1 - scripts/setup/postgresql-init-db | 2 +- scripts/stop-server | 50 +++++++++++++++++++ templates/zerver/help/import-from-gitter.md | 2 +- .../zerver/help/import-from-mattermost.md | 2 +- templates/zerver/help/import-from-slack.md | 2 +- tools/ci/production-upgrade-pg | 6 +-- 9 files changed, 63 insertions(+), 11 deletions(-) create mode 100755 scripts/stop-server diff --git a/docs/production/export-and-import.md b/docs/production/export-and-import.md index 38c6e565b6..08386be4cf 100644 --- a/docs/production/export-and-import.md +++ b/docs/production/export-and-import.md @@ -257,7 +257,7 @@ For best results, you'll want to shut down access to the organization before exporting; so that nobody can send new messages (etc.) while you're exporting data. There are two ways to do this: -1. `supervisorctl stop all`, which stops the whole server. This is +1. `./scripts/stop-server`, which stops the whole server. This is preferred if you're not hosting multiple organizations, because it has no side effects other than disabling the Zulip server for the duration. @@ -282,7 +282,7 @@ following commands: ``` cd /home/zulip/deployments/current -# supervisorctl stop all # Stops the Zulip server +# ./scripts/stop-server # export DEACTIVATE_FLAG="--deactivate" # Deactivates the organization ./manage.py export -r '' $DEACTIVATE_FLAG # Exports the data ``` @@ -316,7 +316,7 @@ archive of all the organization's uploaded files. several months of development ahead of the latest release. * Note that if your server has limited free RAM, you'll want to - shut down the Zulip server with `supervisorctl stop all` while + shut down the Zulip server with `./scripts/stop-server` while you run the import, since our minimal system requirements do not budget extra RAM for running the data import tool. diff --git a/docs/production/troubleshooting.md b/docs/production/troubleshooting.md index b2d25e8e05..21733d9d93 100644 --- a/docs/production/troubleshooting.md +++ b/docs/production/troubleshooting.md @@ -87,6 +87,9 @@ Similarly, you can stop Zulip using: supervisorctl stop all ``` +If you're looking to shut down the server, it is often better to run +`./scripts/stop-server`. + ## Troubleshooting services The Zulip application uses several major open source services to store diff --git a/docs/production/upgrade-or-modify.md b/docs/production/upgrade-or-modify.md index b2d1730ad1..04acfbbf36 100644 --- a/docs/production/upgrade-or-modify.md +++ b/docs/production/upgrade-or-modify.md @@ -415,7 +415,6 @@ To upgrade the version of PostgreSQL on the Zulip server: 2. Stop the server and take a backup: ``` - sudo -i # Or otherwise get a root shell supervisorctl stop all /home/zulip/deployments/current/manage.py backup --output=/home/zulip/postgresql-upgrade.backup.tar.gz ``` diff --git a/scripts/setup/postgresql-init-db b/scripts/setup/postgresql-init-db index 5a06229c1a..230c077fbe 100755 --- a/scripts/setup/postgresql-init-db +++ b/scripts/setup/postgresql-init-db @@ -28,7 +28,7 @@ fi # Shut down all services to ensure a quiescent state. if [ -e "/var/run/supervisor.sock" ]; then - supervisorctl stop all + su zulip -c "$(dirname "$(dirname "$0")")/stop-server" fi # Drop any open connections to any old database. diff --git a/scripts/stop-server b/scripts/stop-server new file mode 100755 index 0000000000..accc150f06 --- /dev/null +++ b/scripts/stop-server @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +import logging +import os +import pwd +import subprocess +import sys +import time + +sys.path.append(os.path.join(os.path.dirname(__file__), "..")) +from scripts.lib.zulip_tools import ENDC, OKGREEN, WARNING + +deploy_path = os.path.realpath(os.path.join(os.path.dirname(__file__), "..")) +os.chdir(deploy_path) + +if pwd.getpwuid(os.getuid()).pw_name != "zulip": + logging.error("Must be run as user 'zulip'.") + sys.exit(1) + +logging.Formatter.converter = time.gmtime +logging.basicConfig(format="%(asctime)s stop-server: %(message)s", level=logging.INFO) + +services = [] + +# Start with the least-critical services: +if os.path.exists("/etc/supervisor/conf.d/zulip/zulip_db.conf"): + services.append("process-fts-updates") + +if os.path.exists("/etc/supervisor/conf.d/zulip/thumbor.conf"): + services.append("zulip-thumbor") + +# Contrary to the order in (re)start-server, we stop django before the +# workers, to increase the chance that we finish processing any work +# that may have been enqueued by the Django, leaving the final state +# closer to "empty." We stop Django before Tornado so it doesn't try +# to make requests to make queues with a down'd Tornado. +services.append("zulip-django") +services.extend(["zulip-tornado", "zulip-tornado:*"]) +services.append("zulip-workers:*") + +subprocess.check_call(["supervisorctl", "stop", *services]) + +print() +print(OKGREEN + "Zulip stopped successfully!" + ENDC) + +using_sso = subprocess.check_output(["./scripts/get-django-setting", "USING_APACHE_SSO"]) +if using_sso.strip() == b"True": + print() + print(WARNING + "Apache2 needs to be shut down; as root, run:" + ENDC) + print(" service apache2 stop") + print() diff --git a/templates/zerver/help/import-from-gitter.md b/templates/zerver/help/import-from-gitter.md index dd44c19d79..01e61f4560 100644 --- a/templates/zerver/help/import-from-gitter.md +++ b/templates/zerver/help/import-from-gitter.md @@ -49,7 +49,7 @@ the most common configuration, run the following commands: ``` cd /home/zulip/deployments/current -supervisorctl stop all # Stop the Zulip server +./scripts/stop-server ./manage.py convert_gitter_data gitter_data.json --output converted_gitter_data ./manage.py import '' converted_gitter_data ./scripts/restart-server diff --git a/templates/zerver/help/import-from-mattermost.md b/templates/zerver/help/import-from-mattermost.md index 67848d41f7..bfe109196f 100644 --- a/templates/zerver/help/import-from-mattermost.md +++ b/templates/zerver/help/import-from-mattermost.md @@ -149,7 +149,7 @@ the most common configuration, run the following commands, replacing cd /home/zulip tar -xzvf export.tar.gz cd /home/zulip/deployments/current -supervisorctl stop all # Stop the Zulip server +./scripts/stop-server ./manage.py convert_mattermost_data /home/zulip/mattermost --output /home/zulip/converted_mattermost_data ./manage.py import "" /home/zulip/converted_mattermost_data/ ./scripts/restart-server diff --git a/templates/zerver/help/import-from-slack.md b/templates/zerver/help/import-from-slack.md index 2493905e6a..bb385cbd47 100644 --- a/templates/zerver/help/import-from-slack.md +++ b/templates/zerver/help/import-from-slack.md @@ -79,7 +79,7 @@ the most common configuration, run the following commands, replacing ``` cd /home/zulip/deployments/current -supervisorctl stop all # Stop the Zulip server +./scripts/stop-server ./manage.py convert_slack_data slack_data.zip --token --output converted_slack_data ./manage.py import '' converted_slack_data ./scripts/restart-server diff --git a/tools/ci/production-upgrade-pg b/tools/ci/production-upgrade-pg index b59b74ad47..91234a10f7 100755 --- a/tools/ci/production-upgrade-pg +++ b/tools/ci/production-upgrade-pg @@ -3,10 +3,10 @@ set -e set -x -ZULIP_PATH=/home/github/zulip +cd /home/github/zulip -supervisorctl stop all -"$ZULIP_PATH"/scripts/setup/upgrade-postgresql +su zulip -c ./scripts/stop-server +./scripts/setup/upgrade-postgresql supervisorctl start all echo "Upgrade of PostgreSQL complete!"