Stopping bench in a Multi-bench setup

I have a Production and Development bench setup on my server

I started bench using bench start and accessed my site on localhost:8001
My ssh connection cut, I’m still able to access the site but can not redo bench start, it says

redis_queue.1 - 127.0.0.1:11001: bind: Address already in use

How do I stop this without disturbing my other bench?

  • I can’t CTRL + C
  • fg command says there’s nothing in the background
  • sudo service supervisor stop - will only affect my production
  • Is my only option so far is hunting down and killing the processes using these ports?
    sudo kill `sudo lsof -t -i:port` OR something similar How to stop bench
    – This works but it can’t be the best option, I see so many memory leak errors

Hi Adam - Yes, your only option is hunting down and killing processes using the ports.

I agree with you, it’s not a great option. But there’s nothing else better.

There should be a bench command that does this. But we need to convince/pay someone to write the code.

1 Like

Too bad.

I’ll give a shot at automating “the hunt” with a python script when I can make time. The ERPNext setup file install.py is a great reference for this.

I’ll update this thread when done.

Ok, I took like 5 minutes to put down this script (edit: much more than 5 minutes by now). It’s far from perfect but will help simplify what is yet to become bench stop.

Setup

  • Create stop.py in your development bench directory. e.g sudo nano ~/my-bench/stop.py
  • Paste the code below
  • Test the script by bench start then break your ssh connection. Login and execute python stop.py in your bench directory.
  • Improvement contributions are welcome :wink:

The code

""" stop.py is an attempt at creating an easy 'bench stop' command

    Expected improvements:
    - refactor
    - merge with bench 
            - check for production where stop command will use existing supervisor
            - check for non-ubuntu platforms

"""


import os, socket, errno

# Getting port suffix from current  redis config.
ports = [1100, 1200, 1300, 900, 800]
lines = {}
port_suffix = 0;
sockets = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

with open("./config/redis_cache.conf") as config_file:
    for line in config_file:
        key, value = line.partition(" ")[::2]
        lines[key.strip()] = value.strip()
    port_suffix =  lines["port"][-1:]
config_file.close()

for port in ports:
  port = int("".join([str(port), str(port_suffix)]))
  try:
    sockets.bind(("127.0.0.1", port))
  except socket.error as e:
    if e.errno == errno.EADDRINUSE:
      os.system("echo 'shutdown' | redis-cli -h 127.0.0.1 -p %d" % port)
      print 'Port %d' % port, 'closed'

sockets.close()
print 'bench stopped'

Happy Frappe-ing!


Edit: Another improvement to mitigate this issue has been making my ssh more resilient to disconnections by increasing my **ServerAliveInterval** duration as below.

sudo nano ~/.ssh/config

Host *
    ServerAliveInterval 240
    ServerAliveCountMax 10
2 Likes

I like it!

I worry a little about immediately going with the kill command. What you do think of this, Adam?

  1. Try to shutdown Redis gracefully
  2. After that’s been done (all 3 ports), then execute the kill commands, in case there’s something still running.
1 Like

@brian_pond

Thank for that contribution, its so graceful now. Works like a charm, everytime!

:sunglasses:

I’ve updated the code above. Next update will probably go to github, with a link back here.

Here goes:

Installation

$ cd frappe-bench #or whatever your bench directory is
$ git clone https://github.com/proenterprise/bench-stop
$ mv ./bench-stop/stop.py .
$ sudo rm -r ./bench-stop

Usage

$ python stop.py

4 Likes

Fantastic. Adding more people to this conversation.

TL;DR - Adam’s code basically does a “bench stop” command. Even when your terminal is closed or missing.

@codingCoffee @saurabh6790 --> You are the Bench module maintainers. Any objection to Adam’s code becoming part of Bench repository?

I am tagging other people below, because they previously discussed this topic on the forums. I want them to know you’ve created a solution, Adam.

@pratu16x7
@ManasSolanki
@vrms
@revant_one
@Ahmad_Mardianto

2 Likes

Thanks!

1 Like

I submitted a pull request for a tiny improvement:

It adds the following as the first line in stop.py:

#!/usr/bin/env python3

If you are in older versions or have a symlink from P3 to P, you’ll prefer:

#!/usr/bin/env python

Also run:

chmod +x stop.py

Having made those two changes, you can simply do…

./stop.py

… instead of …

python stop.py

Having said all that, I actually just have to type …

bnrst

… because I set up a shell alias …

alias bnrst="cd /home/erpdev/frappe-bench/; sudo -A supervisorctl stop all; ./stop.py; bench start;"

… which is enabled automatically on log in because it is stored in the file …

${HOME}/.bash_aliases

Never forget…

The Three Heavenly Sins of Programmers

Sloth: The quality that makes you go to great effort to reduce overall energy expenditure. It makes you write labor-saving programs that other people will find useful and document what you wrote so you don’t have to answer so many questions about it.

Impatience: The anger you feel when the computer is being lazy. This makes you write programs that don’t just react to your needs, but actually anticipate them. Or at least pretend to.

Hubris: The quality that makes you write (and maintain) programs that other people won’t want to say bad things about.

3 Likes