Giter Club home page Giter Club logo

pgctl's People

Contributors

0xngold avatar asottile avatar benbariteau avatar bukzor avatar chriskuehl avatar kaisen avatar kentwills avatar struys avatar yalinhuang avatar ymilki avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pgctl's Issues

colorize output

If we added just a little color to the output, it would be much more readable.
colorama seems to be the go-to library for this.

rename "up" to "starting" ?

"up" is actually an intermediate state.
Any service that stays in this state long has something wrong with it.
I don't think "up" denotes this.

Confusing pgctl status output when service is starting

If I see this:

(virtualenv_run)ckuehl@dev4-uswest1cdevc:~/pg/yelp-main$ pgctl status
memcached: down
watch-templates: down
apache: down
haproxy: down
relode: down

Then I expect pgctl stop to be a no-op. However it isn't in this case:

(virtualenv_run)ckuehl@dev4-uswest1cdevc:~/pg/yelp-main$ pgctl stop
[pgctl] Stopping: memcached, watch-templates, apache, haproxy, relode
[pgctl] Stopped: memcached
[pgctl] Stopped: watch-templates
[pgctl] Stopped: haproxy
[pgctl] Stopped: relode
[pgctl] ERROR: service 'apache' failed to stop after 30 seconds, these runaway processes did not stop:
UID         PID   PPID   PGID    SID  C STIME TTY      STAT   TIME CMD
ckuehl   125867      1  82930  82930  0 Aug24 ?        S      0:01 apache2 -DFOREGROUND -f /nail/home/ckuehl/.pgconf-ckuehl/apache2/httpd-webapp.conf -k start
ckuehl   125802      1  82930  82930  0 Aug24 ?        S      0:02 apache2 -DFOREGROUND -f /nail/home/ckuehl/.pgconf-ckuehl/apache2/httpd-webapp.conf -k start
ckuehl   122718      1  82930  82930  0 Aug24 ?        S      0:20 apache2 -DFOREGROUND -f /nail/home/ckuehl/.pgconf-ckuehl/apache2/httpd-webapp.conf -k start
ckuehl   121655      1  82930  82930  0 Aug24 ?        S      0:21 apache2 -DFOREGROUND -f /nail/home/ckuehl/.pgconf-ckuehl/apache2/httpd-webapp.conf -k start
ckuehl   121561      1  82930  82930  0 Aug24 ?        S      0:22 apache2 -DFOREGROUND -f /nail/home/ckuehl/.pgconf-ckuehl/apache2/httpd-webapp.conf -k start

There are two ways you can fix this:
  * temporarily: lsof -t /nail/home/ckuehl/.pgconf-ckuehl/playground/apache | xargs kill -9
  * permanently: http://pgctl.readthedocs.org/en/latest/user/quickstart.html#writing-playground-services

==> /nail/home/ckuehl/.pgconf-ckuehl/playground/apache/log <==
[...log of apache trying to start...]
[pgctl]
[pgctl] There might be useful information further up in the log; you can view it by running:
[pgctl]     less +G /nail/home/ckuehl/.pgconf-ckuehl/playground/apache/log
[pgctl] ERROR: Some services failed to stop: apache

The current belief is that this happens because I ran pgctl start successfully in the past, then later the service dies and repeatedly tries to come back up, and while it's trying to start, the status is down and pgctl stop fails.

I think we need two new states: starting and stopping. Alternatively, desired state: ready, but I think that is less obvious.

An invariant that we should have:

  • pgctl stop a down service is a no-op
  • pgctl start an up or ready service is a no-op

debug spams stdout

when I ctrl^c the debug process I get:

^C
SIGINT/SIGQUIT received...killing workers...
gateway "uWSGI http 1" has been buried (pid: 4022375)
subprocess 4016589 exited by signal 2
(virtualenv_run)user@localhost:~/pg/project (master) $ subprocess 4016550 exited with code 130
worker 1 buried after 1 seconds
worker 2 buried after 1 seconds
goodbye to uWSGI.

cd'ing from home directory results in pgctl not knowing where the playground dir is

(virtualenv_run)(www_pages/master) rkwills@dev24-devc:~/trees/yelp/www_pages 
[Mon 08-17 05:03:17PM]$ cd assets
(virtualenv_run)(www_pages/master) rkwills@dev24-devc:~/trees/yelp/www_pages/assets 
[Wed 08-19 09:19:43AM]$ pgctl-2015 start
Starting: 
Traceback (most recent call last):
  File "/nail/home/rkwills/trees/yelp/www_pages/virtualenv_run/bin/pgctl-2015", line 9, in <module>
    load_entry_point('pgctl==0.0.2', 'console_scripts', 'pgctl-2015')()
  File "/nail/home/rkwills/trees/yelp/pgctl/pgctl/cli.py", line 259, in main
    return app()
  File "/nail/home/rkwills/trees/yelp/pgctl/pgctl/cli.py", line 74, in __call__
    return command()
  File "/nail/home/rkwills/trees/yelp/pgctl/pgctl/cli.py", line 97, in start
    return self.__change_state('-u', 'up', 'Starting:', 'Started:')
  File "/nail/home/rkwills/trees/yelp/pgctl/pgctl/cli.py", line 79, in __change_state
    with self.pgdir.as_cwd():
  File "/usr/lib64/python2.7/contextlib.py", line 17, in __enter__
    return self.gen.next()
  File "/nail/home/rkwills/trees/yelp/www_pages/virtualenv_run/lib/python2.7/site-packages/py/_path/local.py", line 562, in as_cwd
    old = self.chdir()
  File "/nail/home/rkwills/trees/yelp/www_pages/virtualenv_run/lib/python2.7/site-packages/py/_path/local.py", line 553, in chdir
    py.error.checked_call(os.chdir, self.strpath)
  File "/nail/home/rkwills/trees/yelp/www_pages/virtualenv_run/lib/python2.7/site-packages/py/_error.py", line 84, in checked_call
    raise cls("%s%r" % (func.__name__, args))
py.error.ENOENT: [No such file or directory]: chdir(u'/nail/home/rkwills/trees/yelp/www_pages/assets/playground',)

Bad file descriptor when running pgctl-in-pgctl under python3

Naively you end up with output that looks like this if you try and make sub-playgrounds within a pgctl service:

$ pgctl debug scrapers
[pgctl] Stopping: scrapers
[pgctl] Stopped: scrapers
[pgctl] Stopping: scraper_pscrp1, scraper_pscrp2, scraper_pscrp3
[pgctl] Stopped: scraper_pscrp1
[pgctl] Stopped: scraper_pscrp2
[pgctl] Stopped: scraper_pscrp3
Traceback (most recent call last):
  File "/home/asottile/workspace/PokemonGo-Map-dev/venv/bin/pgctl", line 11, in <module>
    sys.exit(main())
  File "/home/asottile/workspace/PokemonGo-Map-dev/venv/lib/python3.5/site-packages/pgctl/cli.py", line 436, in main
    return app()
  File "/home/asottile/workspace/PokemonGo-Map-dev/venv/lib/python3.5/site-packages/pgctl/cli.py", line 142, in __call__
    result = command()
  File "/home/asottile/workspace/PokemonGo-Map-dev/venv/lib/python3.5/site-packages/pgctl/cli.py", line 265, in stop
    failed = self.__change_state(stop)
  File "/home/asottile/workspace/PokemonGo-Map-dev/venv/lib/python3.5/site-packages/pgctl/cli.py", line 183, in __change_state
    return self.__locked_change_state(state)
  File "/home/asottile/workspace/PokemonGo-Map-dev/venv/lib/python3.5/site-packages/contextlib2.py", line 414, in __exit__
    _reraise_with_existing_context(exc_details)
  File "/home/asottile/workspace/PokemonGo-Map-dev/venv/lib/python3.5/site-packages/contextlib2.py", line 276, in _reraise_with_existing_context
    raise exc_details[1]
  File "/home/asottile/workspace/PokemonGo-Map-dev/venv/lib/python3.5/site-packages/contextlib2.py", line 403, in __exit__
    if cb(*exc_details):
  File "/home/asottile/workspace/PokemonGo-Map-dev/venv/lib/python3.5/site-packages/contextlib2.py", line 331, in _exit_wrapper
    return cm_exit(cm, *exc_details)
  File "/usr/lib/python3.5/contextlib.py", line 66, in __exit__
    next(self.gen)
  File "/home/asottile/workspace/PokemonGo-Map-dev/venv/lib/python3.5/site-packages/pgctl/flock.py", line 84, in flock
    os.close(fd)
OSError: [Errno 9] Bad file descriptor
[pgctl] Stopping: scraper_pscrp1, scraper_pscrp2, scraper_pscrp3
[pgctl] Stopped: scraper_pscrp1
[pgctl] Stopped: scraper_pscrp2
[pgctl] Stopped: scraper_pscrp3
Traceback (most recent call last):
  File "/home/asottile/workspace/PokemonGo-Map-dev/venv/bin/pgctl", line 11, in <module>
    sys.exit(main())
  File "/home/asottile/workspace/PokemonGo-Map-dev/venv/lib/python3.5/site-packages/pgctl/cli.py", line 436, in main
    return app()
  File "/home/asottile/workspace/PokemonGo-Map-dev/venv/lib/python3.5/site-packages/pgctl/cli.py", line 142, in __call__
    result = command()
  File "/home/asottile/workspace/PokemonGo-Map-dev/venv/lib/python3.5/site-packages/pgctl/cli.py", line 265, in stop
    failed = self.__change_state(stop)
  File "/home/asottile/workspace/PokemonGo-Map-dev/venv/lib/python3.5/site-packages/pgctl/cli.py", line 183, in __change_state
    return self.__locked_change_state(state)
  File "/home/asottile/workspace/PokemonGo-Map-dev/venv/lib/python3.5/site-packages/contextlib2.py", line 414, in __exit__
    _reraise_with_existing_context(exc_details)
  File "/home/asottile/workspace/PokemonGo-Map-dev/venv/lib/python3.5/site-packages/contextlib2.py", line 276, in _reraise_with_existing_context
    raise exc_details[1]
  File "/home/asottile/workspace/PokemonGo-Map-dev/venv/lib/python3.5/site-packages/contextlib2.py", line 403, in __exit__
    if cb(*exc_details):
  File "/home/asottile/workspace/PokemonGo-Map-dev/venv/lib/python3.5/site-packages/contextlib2.py", line 331, in _exit_wrapper
    return cm_exit(cm, *exc_details)
  File "/usr/lib/python3.5/contextlib.py", line 66, in __exit__
    next(self.gen)
  File "/home/asottile/workspace/PokemonGo-Map-dev/venv/lib/python3.5/site-packages/pgctl/flock.py", line 84, in flock
    os.close(fd)
OSError: [Errno 9] Bad file descriptor
Traceback (most recent call last):
  File "/home/asottile/workspace/PokemonGo-Map-dev/playground/scrapers/run", line 58, in main
    remove_old_scrapers()
  File "/home/asottile/workspace/PokemonGo-Map-dev/playground/scrapers/run", line 29, in remove_old_scrapers
    subprocess.check_call(('pgctl', 'stop'))
  File "/usr/lib/python3.5/subprocess.py", line 581, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '('pgctl', 'stop')' returned non-zero exit status 1

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/asottile/workspace/PokemonGo-Map-dev/playground/scrapers/run", line 68, in <module>
    exit(main())
  File "/home/asottile/workspace/PokemonGo-Map-dev/playground/scrapers/run", line 64, in main
    remove_old_scrapers()
  File "/home/asottile/workspace/PokemonGo-Map-dev/playground/scrapers/run", line 29, in remove_old_scrapers
    subprocess.check_call(('pgctl', 'stop'))
  File "/usr/lib/python3.5/subprocess.py", line 581, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '('pgctl', 'stop')' returned non-zero exit status 1

Here's a workaround:

def no_pgctl_environ():
    # We're using pgctl-in-pgctl, clear all pgctl related variables
    for k in tuple(os.environ):
        if k.startswith('PGCTL_'):
            del os.environ[k]

Print out an actionable stack trace on called process error

For example, this error only shows that the service failed to start, but does not show the stack associated with the service. For debugging this is pretty useless and for those less familiar with pgctl, they paste this trace expecting a dev to know how to fix the problem.

15:42:50.184     def check_call(*popenargs, **kwargs):
15:42:50.185         """Run command with arguments.  Wait for command to complete.  If
15:42:50.185         the exit code was zero then return, otherwise raise
15:42:50.186         CalledProcessError.  The CalledProcessError object will have the
15:42:50.188         return code in the returncode attribute.
15:42:50.188     
15:42:50.189         The arguments are the same as for the call function.  Example:
15:42:50.190     
15:42:50.190         check_call(["ls", "-l"])
15:42:50.191         """
15:42:50.191         retcode = call(*popenargs, **kwargs)
15:42:50.192         if retcode:
15:42:50.193             cmd = kwargs.get("args")
15:42:50.193             if cmd is None:
15:42:50.194                 cmd = popenargs[0]
15:42:50.194 >           raise CalledProcessError(retcode, cmd)
15:42:50.195 E           subprocess.CalledProcessError: Command '('pgctl', 'start', 'service')' returned non-zero exit status 1
15:42:50.195 
15:42:50.196 /usr/lib/python3.5/subprocess.py:584: CalledProcessError

pre-commit cmd_output seems to have a nice way to give a better printout, but all of the extra code to support windows seems unnecessary for our use case.

@bukzor @chriskuehl

pgctl-poll-ready has no help

$ pgctl-poll-ready  --help
Traceback (most recent call last):
  File "/nail/home/buck/pg/master/virtualenv_run/bin/pgctl-poll-ready", line 9, in <module>
    load_entry_point('pgctl==1.4.0rc1', 'console_scripts', 'pgctl-poll-ready')()
  File "/nail/home/buck/pg/master/virtualenv_run/lib/python2.7/site-packages/pgctl/poll_ready.py", line 76, in main
    notification_fd = int(floatfile('notification-fd'))
  File "/nail/home/buck/pg/master/virtualenv_run/lib/python2.7/site-packages/pgctl/poll_ready.py", line 19, in floatfile
    with open(filename) as f:
IOError: [Errno 2] No such file or directory: u'notification-fd'

how to tag releases file

Suggested content

  1. git checkout upstream/master -b {{branch}}
  2. bump setup.py
  3. bump doc versions in docs/source/conf.py
  4. git commit -m "{{version}}"
  5. git tag {{version}}
  6. git push --tags (push tags to upstream)
  7. git push origin HEAD
  8. Create a pull request

improve the upgrade/downgrade story

Currently if we change the design between versions, the old and new pgctl don't cooperate in any natural way. Since pgctl has some state, the playground can get into a completely weird irrecoverable state.

We need to figure out a strategy that allows pgctl to make major design changes between versions without harming users.

Possibly, we should record the version and do a deep-clean when we see the version has changed.

Stop asserting entire output of argparse --help

We shouldn't be testing the standard library; and this particular instance makes maintenance more challenging.

We can probably find a way to test that the help is being displayed without asserting the entire body of it.

pgctl sometimes tells you to kill your own processes

I am not quite sure how I got into this state, but if I follow the lsof | xargs kill instructions, I'll kill tmux without thinking too much about it, which might be really disruptive.

I was able to fix this by just killing the two s6 processes. Maybe there's a better command we can suggest? Unsure.

(virtualenv_run)ckuehl@dev4-uswest1cdevc:~/proj/www_pages$ pgctl stop yelp-main
[pgctl] Stopping: yelp-main
[pgctl] ERROR: service 'yelp-main' failed to stop after 40.02 seconds, these runaway processes did not stop:
UID         PID   PPID   PGID    SID  C STIME TTY      STAT   TIME CMD
ckuehl    43601      1  14852 124554  0 04:34 pts/5    S      0:00 s6-ftrig-wait event d
ckuehl    43602  43601  14852 124554  0 04:34 pts/5    S      0:00  \_ s6-ftrigrd
ckuehl   122700      1 122700 122700  0 Aug31 ?        Ss     2:07 tmux

There are two ways you can fix this:
  * temporarily: lsof -t playground/yelp-main | xargs kill -9
  * permanently: http://pgctl.readthedocs.org/en/latest/user/quickstart.html#writing-playground-services

==> playground/yelp-main/log <==
[pgctl]
[pgctl] There might be useful information further up in the log; you can view it by running:
[pgctl]     less +G playground/yelp-main/log
[pgctl] ERROR: Some services failed to stop: yelp-main

Add "pgctl status --json"

We currently use pidfiles to signal services (e.g. we have a service which watches Python files and sends HUP to apache when a file is changed).

pidfiles suck; it'd be great if we could use pgctl to get the PID.

We discussed adding a "kill" or "signal" command to pgctl, but a nice start would just be adding JSON output to pgctl status --json.

Logging a service which does not exist

$ pgctl-2015 log i-dont-exist
==> playground/i-dont-exist/log <==

And then afterwards:

$ pgctl-2015 start
[pgctl] Starting: i-dont-exist, scraper, server
[pgctl] Started: i-dont-exist
[pgctl] Started: scraper
[pgctl] Started: server

wompwomp

pgctl-poll-ready error messaging

This seems incomprehensible.

$ echo 3 > notification-fd
$ pgctl-poll-ready /dev/null
Traceback (most recent call last):
  File "/nail/home/buck/trees/yelp/pgctl/.tox/pgctl/bin/pgctl-poll-ready", line 9, in <module>
    load_entry_point('pgctl==1.0.1', 'console_scripts', 'pgctl-poll-ready')()
  File "/nail/home/buck/trees/yelp/pgctl/pgctl/poll_ready.py", line 77, in main
    exec_(argv[1:])  # never returns
  File "/nail/home/buck/trees/yelp/pgctl/pgctl/functions.py", line 23, in exec_
    atexit._run_exitfuncs()  # pylint:disable=protected-access
  File "/nail/home/buck/trees/yelp/pgctl/.tox/pgctl/lib/python2.7/os.py", line 353, in execvpe
    _execvpe(file, args, env)
  File "/nail/home/buck/trees/yelp/pgctl/.tox/pgctl/lib/python2.7/os.py", line 368, in _execvpe
    func(file, *argrest)
OSError: [Errno 13] Permission denied

pgctl debug only says "stopping"

For example:

$ pgctl debug relode
[pgctl] Stopping: relode
[pgctl] Stopped: relode
INFO:relode:base watch is on /nail/home/rkwills/trees/yelp id 1

It obviously started the service named 'relode' in debug mode, but the messages only say that it stopped it.

Poor user error message for incorrect yaml file

Example:

aliases:
    default:
        - watch-templates
    test:
        -

Traceback:

[Mon 08-31 11:48:54AM]$ pgctl-2015 start test
Traceback (most recent call last):
  File "/nail/home/rkwills/pg/yelp-main/virtualenv_run/bin/pgctl-2015", line 11, in <module>
    sys.exit(main())
  File "/nail/home/rkwills/pg/yelp-main/virtualenv_run/lib/python2.7/site-packages/pgctl/cli.py", line 261, in main
    return app()
  File "/nail/home/rkwills/pg/yelp-main/virtualenv_run/lib/python2.7/site-packages/pgctl/cli.py", line 66, in __call__
    return command()
  File "/nail/home/rkwills/pg/yelp-main/virtualenv_run/lib/python2.7/site-packages/pgctl/cli.py", line 89, in start
    return self.__change_state('-u', 'up', 'Starting:', 'Started:')
  File "/nail/home/rkwills/pg/yelp-main/virtualenv_run/lib/python2.7/site-packages/pgctl/cli.py", line 70, in __change_state
    print(xing, self.service_names_string, file=stderr)
  File "/nail/home/rkwills/pg/yelp-main/virtualenv_run/lib/python2.7/site-packages/cached_property.py", line 26, in __get__
    value = obj.__dict__[self.func.__name__] = self.func(obj)
  File "/nail/home/rkwills/pg/yelp-main/virtualenv_run/lib/python2.7/site-packages/pgctl/cli.py", line 221, in service_names_string
    return ', '.join(self.service_names)
  File "/nail/home/rkwills/pg/yelp-main/virtualenv_run/lib/python2.7/site-packages/cached_property.py", line 26, in __get__
    value = obj.__dict__[self.func.__name__] = self.func(obj)
  File "/nail/home/rkwills/pg/yelp-main/virtualenv_run/lib/python2.7/site-packages/pgctl/cli.py", line 225, in service_names
    return tuple([service.name for service in self.services])
  File "/nail/home/rkwills/pg/yelp-main/virtualenv_run/lib/python2.7/site-packages/cached_property.py", line 26, in __get__
    value = obj.__dict__[self.func.__name__] = self.func(obj)
  File "/nail/home/rkwills/pg/yelp-main/virtualenv_run/lib/python2.7/site-packages/pgctl/cli.py", line 176, in services
    for service_name in self._expand_aliases(alias)
  File "/nail/home/rkwills/pg/yelp-main/virtualenv_run/lib/python2.7/site-packages/pgctl/cli.py", line 161, in service_by_name
    path = self.pgdir.join(service_name)
  File "/nail/home/rkwills/pg/yelp-main/virtualenv_run/lib/python2.7/site-packages/py/_path/local.py", line 334, in join
    arg = arg.strip(sep)
AttributeError: 'NoneType' object has no attribute 'strip'

Example:

aliases:
    default:
        - watch-templates
    test:

Traceback:

[Mon 08-31 11:48:55AM]$ pgctl-2015 start test
Traceback (most recent call last):
  File "/nail/home/rkwills/pg/yelp-main/virtualenv_run/bin/pgctl-2015", line 11, in <module>
    sys.exit(main())
  File "/nail/home/rkwills/pg/yelp-main/virtualenv_run/lib/python2.7/site-packages/pgctl/cli.py", line 261, in main
    return app()
  File "/nail/home/rkwills/pg/yelp-main/virtualenv_run/lib/python2.7/site-packages/pgctl/cli.py", line 66, in __call__
    return command()
  File "/nail/home/rkwills/pg/yelp-main/virtualenv_run/lib/python2.7/site-packages/pgctl/cli.py", line 89, in start
    return self.__change_state('-u', 'up', 'Starting:', 'Started:')
  File "/nail/home/rkwills/pg/yelp-main/virtualenv_run/lib/python2.7/site-packages/pgctl/cli.py", line 70, in __change_state
    print(xing, self.service_names_string, file=stderr)
  File "/nail/home/rkwills/pg/yelp-main/virtualenv_run/lib/python2.7/site-packages/cached_property.py", line 26, in __get__
    value = obj.__dict__[self.func.__name__] = self.func(obj)
  File "/nail/home/rkwills/pg/yelp-main/virtualenv_run/lib/python2.7/site-packages/pgctl/cli.py", line 221, in service_names_string
    return ', '.join(self.service_names)
  File "/nail/home/rkwills/pg/yelp-main/virtualenv_run/lib/python2.7/site-packages/cached_property.py", line 26, in __get__
    value = obj.__dict__[self.func.__name__] = self.func(obj)
  File "/nail/home/rkwills/pg/yelp-main/virtualenv_run/lib/python2.7/site-packages/pgctl/cli.py", line 225, in service_names
    return tuple([service.name for service in self.services])
  File "/nail/home/rkwills/pg/yelp-main/virtualenv_run/lib/python2.7/site-packages/cached_property.py", line 26, in __get__
    value = obj.__dict__[self.func.__name__] = self.func(obj)
  File "/nail/home/rkwills/pg/yelp-main/virtualenv_run/lib/python2.7/site-packages/pgctl/cli.py", line 176, in services
    for service_name in self._expand_aliases(alias)
  File "/nail/home/rkwills/pg/yelp-main/virtualenv_run/lib/python2.7/site-packages/pgctl/cli.py", line 195, in _expand_aliases
    stack.extend(reversed(aliases[name]))
TypeError: argument to reversed() must be a sequence

Please don't create the virtualenv in .activate.sh

Same reason as venv-update which @bukzor reverted:

  • Making a virtualenv when you cd into a directory is totally unexpected
  • It takes a long time and is difficult to stop (^C works but then it keeps trying to rebuild it every time you do something)
  • It's annoying enough that I disabled aactivator for this repo

Please don't do this, this is not expected behavior for changing a directory.

status -v: show the processes

For each (listed) service, show the various processes involved.
fuser -v playground/myservice gets pretty close, but doesn't indicate the tree structure.

`pgctl debug service1 service2 service3`

Only the first will be in the foreground.

This enables a no-argument pgctl debug to be meaningful in real-world scenarios.

Of coures the documentation / --help will need to be updated to reflect this.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.