<div dir="ltr">Doesn't the equivalent of ^A ^D (from screen) also work to just disconnect all sessions? (<a href="http://www.dayid.org/comp/tm.html">http://www.dayid.org/comp/tm.html</a> says it would be ^B d). Or switching to session 0 and exiting that one first?<div><br>I thought we had a quick way to disconnect, but its possible you have to exit 2x and that fast firing hooks always catch a new window before you can exit a second time.</div><div><br>John</div><div>=:-></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Jun 4, 2017 at 5:56 PM, Dmitrii Shcherbakov <span dir="ltr"><<a href="mailto:dmitrii.shcherbakov@canonical.com" target="_blank">dmitrii.shcherbakov@canonical.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi everybody,<br>
<br>
Currently if you do<br>
<br>
juju debug-hooks <unit-name> # no event (hook) in particular<br>
<br>
each time there is a new event you will get a new tmux window open and<br>
this will be done serially as there is no parallelism in hook<br>
execution on a given logical machine. This is all good and intentional<br>
but when you've observed the charm behavior and want to let it work<br>
without your interference again, you need to end your tmux session.<br>
This can be hard via `exit [status]` shell builtin when you get a lot<br>
of events (think of an OpenStack HA deployment) - each time you do<br>
<br>
./hooks/$JUJU_HOOK_NAME && exit<br>
<br>
you are dropped into a session '0' and a new session is created for a<br>
queued event for which you have to manually execute a hook and exit<br>
again until you process the backlog.<br>
<br>
tmux list-windows<br>
0: bash- (1 panes) [239x62] [layout bbde,239x62,0,0,1] @1 # <---<br>
dropping here after `exit`<br>
1: update-status* (1 panes) [239x62] [layout bbe0,239x62,0,0,3] @3 (active)<br>
<br>
<a href="https://jujucharms.com/docs/stable/authors-hook-debug#running-a-debug-session" rel="noreferrer" target="_blank">https://jujucharms.com/docs/<wbr>stable/authors-hook-debug#<wbr>running-a-debug-session</a><br>
"Note: To allow Juju to continue processing events normally, you must<br>
exit the hook execution with a zero return code (using the exit<br>
command), otherwise all further events on that unit may be blocked<br>
indefinitely."<br>
<br>
My initial thought was something like this - send SIGTERM to a child<br>
of sshd which will terminate your ssh session:<br>
unset n ; p=`pgrep -f 'tmux attach-session.*'$JUJU_UNIT_<wbr>NAME` ; while<br>
[ "$n" != "sshd" ] ; do pc=$p ; p=$(ps -o ppid= $p | tr -d ' ') ; echo<br>
$p ; n=`basename $(readlink /proc/$p/exe || echo -n none)` ; done &&<br>
kill $pc<br>
<br>
as an agent waits for an SSH client to exit:<br>
<a href="https://github.com/juju/juju/blob/develop/worker/uniter/runner/debug/server.go#L53" rel="noreferrer" target="_blank">https://github.com/juju/juju/<wbr>blob/develop/worker/uniter/<wbr>runner/debug/server.go#L53</a><br>
<br>
After thinking about it some more, I thought it would be cleaner to<br>
just kill a specific tmux session:<br>
<br>
tmux list-sessions<br>
gluster/0: 2 windows (created Fri JunĀ  2 20:22:30 2017) [239x62] (attached)<br>
<br>
./hooks/$JUJU_HOOK_NAME && tmux kill-session -t $JUJU_UNIT_NAME<br>
[exited]<br>
Cleaning up the debug session<br>
no server running on /tmp/tmux-0/default<br>
Connection to 10.10.101.77 closed.<br>
<br>
The cleanup message comes from debugHooksClientScript that simply sets<br>
up a bash trap on EXIT:<br>
<a href="https://github.com/juju/juju/blob/develop/worker/uniter/runner/debug/client.go#L51" rel="noreferrer" target="_blank">https://github.com/juju/juju/<wbr>blob/develop/worker/uniter/<wbr>runner/debug/client.go#L51</a><br>
<br>
Judging by the code, it should be pretty safe to do so - unless there<br>
is a debug session in a debug context for a particular unit, other<br>
hooks will be executed regularly by an agent instead of creating a new<br>
tmux window:<br>
<a href="https://github.com/juju/juju/blob/develop/worker/uniter/runner/runner.go#L225" rel="noreferrer" target="_blank">https://github.com/juju/juju/<wbr>blob/develop/worker/uniter/<wbr>runner/runner.go#L225</a><br>
debugctx := debug.NewHooksContext(runner.<wbr>context.UnitName())<br>
if session, _ := debugctx.FindSession(); session != nil &&<br>
session.MatchHook(hookName) {<br>
logger.Infof("executing %s via debug-hooks", hookName)<br>
err = session.RunHook(hookName, runner.paths.GetCharmDir(), env)<br>
} else {<br>
err = runner.runCharmHook(hookName, env, charmLocation)<br>
}<br>
return runner.context.Flush(hookName, err)<br>
<br>
There are two scripts:<br>
<br>
- a client script executed via an ssh client when you run juju debug-hooks<br>
- a server script which is executed in the `RunHook` function by an<br>
agent and creates a new window for an existing tmux session.<br>
<br>
client side:<br>
<a href="https://github.com/juju/juju/blob/develop/cmd/juju/commands/debughooks.go#L137" rel="noreferrer" target="_blank">https://github.com/juju/juju/<wbr>blob/develop/cmd/juju/<wbr>commands/debughooks.go#L137</a><br>
script := base64.StdEncoding.<wbr>EncodeToString([]byte(<wbr>unitdebug.ClientScript(<wbr>debugctx,<br>
c.hooks)))<br>
innercmd := fmt.Sprintf(`F=$(mktemp); echo %s | base64 -d > $F; . $F`, script)<br>
args := []string{fmt.Sprintf("sudo /bin/bash -c '%s'", innercmd)}<br>
c.Args = args<br>
return c.sshCommand.Run(ctx)<br>
<br>
Server script:<br>
<a href="https://github.com/juju/juju/blob/develop/worker/uniter/runner/debug/server.go#L90" rel="noreferrer" target="_blank">https://github.com/juju/juju/<wbr>blob/develop/worker/uniter/<wbr>runner/debug/server.go#L90</a><br>
Client script:<br>
<a href="https://github.com/juju/juju/blob/develop/worker/uniter/runner/debug/client.go#L49" rel="noreferrer" target="_blank">https://github.com/juju/juju/<wbr>blob/develop/worker/uniter/<wbr>runner/debug/client.go#L49</a><br>
<br>
A worker waits until a client exists by monitoring a file lock at<br>
ClientExitFileLock:<br>
<a href="https://github.com/juju/juju/blob/develop/worker/uniter/runner/debug/server.go#L34" rel="noreferrer" target="_blank">https://github.com/juju/juju/<wbr>blob/develop/worker/uniter/<wbr>runner/debug/server.go#L34</a><br>
<a href="https://github.com/juju/juju/blob/develop/worker/uniter/runner/debug/server.go#L53" rel="noreferrer" target="_blank">https://github.com/juju/juju/<wbr>blob/develop/worker/uniter/<wbr>runner/debug/server.go#L53</a><br>
A path of a lock itself for a particular session:<br>
<a href="https://github.com/juju/juju/blob/develop/worker/uniter/runner/debug/common.go#L24" rel="noreferrer" target="_blank">https://github.com/juju/juju/<wbr>blob/develop/worker/uniter/<wbr>runner/debug/common.go#L24</a><br>
<br>
---<br>
<br>
If this approach with killing a tmux session is fine then I could<br>
create a PR for the doc repo and for the description in the<br>
debugHooksServerScript to explicitly mention it.<br>
<br>
I doubt it deserves a helper command but rather a more verbose explanation.<br>
<br>
Have anybody else encountered the need to do the same?<br>
<br>
Best Regards,<br>
Dmitrii Shcherbakov<br>
<br>
Field Software Engineer<br>
IRC (freenode): Dmitrii-Sh<br>
<span class="HOEnZb"><font color="#888888"><br>
--<br>
Juju-dev mailing list<br>
<a href="mailto:Juju-dev@lists.ubuntu.com">Juju-dev@lists.ubuntu.com</a><br>
Modify settings or unsubscribe at: <a href="https://lists.ubuntu.com/mailman/listinfo/juju-dev" rel="noreferrer" target="_blank">https://lists.ubuntu.com/<wbr>mailman/listinfo/juju-dev</a><br>
</font></span></blockquote></div><br></div>