It seems as though Ben has a good approach (in the separate thread).

But to follow up on questions from others, let me be a bit more
detailed about the problem setting:

We deploy python based web-sites and web applications (Django, Twisted
or -- shudder --Plone) to various *nix servers.  Could be Linux.
Could be some BSD.  Maybe even something else.  We usually have the
ability to install general stuff on these boxes, even if we don't have
full root privileges, but sometimes we are limited to a sampling.

I can count on Python because it has to be there for the deployed
product (or we wouldn't be deploying there).  I can almost certainly
count on bash, sh for sure.  The deployed code is a checkout from a
revision control system (usually mercurial, in the past subversion,
now we're seeing a requirement to use git, with a github repository),
so I can count on the VCS tool suite.  And I can count on being able
to ssh into the box, though I can't be assured of being able to tweak
the sshd configuration.

Several developers, including some potentially non-programmer
developers, work on these products.  While I generally try to edit on
my personal machine, commit and push to the central repository, then
pull from it onto the deployment server in an ssh session, I
sometimes, and other even more frequently, do editing on the
deployment server, and need to commit and push from there.  We
generally want the commits credited to the correct developer for all
the obvious reasons.  But we typically only get one account on these
boxes, so even if several of us are connected, it is always as the
same user.

We can certainly have scripts to run or source that arrange for the
VCS credentials to be set, with the problem of having to remember to
run them.  Thus I typically adjust ~/.bash_profile to (source a file
to) define a shell function and to invoke the function.  The function
prompts the user to enter a number, choosing from a displayed menu,
indicating who he is, which, for mercurial, is used to set a single
environment variable, HGUSER, which mercurial uses to identify the
committer.  Thus the problem of remembering to set your credentials is
gone.

Not having a lot of shell-fu, it took me a long time to get that
script right.  Now I want to do something similar for a site where we
must use git.  While one could use the approach of modifying the
.git/config file (either the user's or the repository clone's), and
git even provides a tool to do this, that leads, when several
developers are ssh'ed in, to a case of last to connect wins.  Git is
also willing to listen to environment variables (if you haven't done
the other stuff), so that seems the better choice (though folks should
still coordinate what they're committing when, do they don't do
overlapping "git add" commands before one of them commits).

But I have to provide two different values, for four different
environment variables to get the job done.  I was thinking about how
to pack two values into one table (displayed in the menu), and doing
the splitting of stuff in bash, when I said to myself "why should I
struggle with this in bash when python is there?".

Except, of course, the environment variables need to be set in the
login shell, the shell sourcing ~/.bash_profile, if subsequent
invocations of git over the terminal are going to see them.

I can't count on any X client tools being installed on the deployment
server, and anyway I can't count on the developers to invoke ssh with
-X or -Y (it's hard enough to get them to use ssh-add before
connecting).  I can't even count on an X server at the developer end.
So there is no magically available other means of displaying a UI.
Thus the approach of printing a selection list and accepting a number
from stdin seems the most bullet proof.



I'll be looking harder at Ben's work, but what I've been thinking
about most recently is as follows.

1. During the time I care about (logging in) it's pretty certain that
both fd 1 and fd 2 are open for writing on /dev/tty (or whatever the
OS calls the generic for the session's controlling terminal) and fd 0
is open for input on same.

2. When the shell runs a sub command, it opens any files specified by
simple redirections and creates any pipes needed for chaining the
commands of a pipe (all of which appear on fds between 3 and 10, which
is probably why the {NAME}> syntax specifies an fd above 10) -
including that used for capturing output with back tick or $()
notation, and then it forks.
2a. The child process, if there was any redirection, does suitable
dup2 operations to place the files open on some of those 3 to 10 fds
onto fd 0, 1, and/or 2, then closes the fds they came from, and also
the other end of any pipes, so, normally, only 0, 1, and 2 are open,
then execs the sub command, which inherits the child shell's fds.
2b. The parent shell closes the fds for the files used in redirection
and the child's ends of the pipes.  If a pipeline is being built the
output end of one of those pipes will be used for execing the next
subcommand instead of opening a new pipe for the next subcommand's
stdin.  In the case of back ticked or $()ed commands (pipelines?) the
(final) output pipe is kept, and the shell reads from it until the
command exits and the pipe is empty.

3. Redirecting stdout does not redirect stderr, including stderr from
a command in back ticks or $() leaves stderr connected to the tty.

4. Therefore, if my python script gets invoked in back ticks or $(), I
should be able to count on:
4a. stdin (fd 0) and stderr (fd 2) have the tty open for reading and
writing respectively.
4b. stdout (fd 1) will be the input end of a pip back to the parent shell.

Thus I can either be sure to send all UI output to fd 2 (be careful
not to redirect it to a log or something in the shell), or I can dup2
to make a copy of fd1 on, say, fd3 (for my pipe back to the parent
shell) and then dup2 to make a copy of fd2 on fd1, so stdout of the
child python is now the tty (and I can use, say, python-dialog,
without worrying about finding all the places in which it might assume
that it should talk to the user on stdout).

Probably that last set of redirections could be done inside the back ticks.
_______________________________________________
gnhlug-discuss mailing list
gnhlug-discuss@mail.gnhlug.org
http://mail.gnhlug.org/mailman/listinfo/gnhlug-discuss/

Reply via email to