I have a fabric task set up like this:
@task
def cli():
command = [
os.path.join(env.servers_path, "bin", "redis-cli"),
]
run(" ".join(command))
Running it gives me a prompt, but no interactivity:
$ fab cli
[server] Executing task 'cli'
[server] Executing task 'redis.cli'
[server] run: /path/to/bin/redis-cli
[server] out: redis 127.0.0.1:6379> help
<no output produced>
Typing further produces an “out: ” prompt that I type onto, but at no point do I get anything back from redis.
However, if I change to some other interactive prompt, I do get interactivity:
@task
def cli():
command = [
"python"
]
run(" ".join(command))
produces:
$ fab cli
[server] Executing task 'cli'
[server] run: python
[server] out: Python 2.4.3 (#1, Sep 3 2009, 15:37:37)
[server] out: [GCC 4.1.2 20080704 (Red Hat 4.1.2-46)] on linux2
[server] out: Type "help", "copyright", "credits" or "license" for more information.
[server] out: >>> a = 1
[server] out: >>> a
[server] out: 1
[server] out: >>>
Can anyone offer me any hints as to why redis-cli doesn’t behave nicely? I’d like to open a bug with that project, but I’d like to understand it better first.
I think this is due to the fact redis-cli in interactive mode is really designed to work with a terminal, while fabric probably runs redis-cli redirecting standard input/output file descriptors.
For instance, the following command works fine:
while the following one does not:
redis-cli and the linenoise library providing readline-like facilities do not flush correctly the output with a non terminal file descriptor. A possible workaround which I have not tried with fabric, is to deactivate linenoise:
By defining the TERM variable to dumb, linenoise defaults on a very basic code path which happens to use a simple printf to deal with the prompt and flush the output just after its display. It may solve your issue with fabric provided you can set this variable in the process environment.