为什么我无法通过fabric与redis-cli交互?

3 投票
2 回答
1058 浏览
提问于 2025-04-17 10:12

我设置了一个fabric任务,内容如下:

@task
def cli():
    command = [
        os.path.join(env.servers_path, "bin", "redis-cli"),
    ]

    run(" ".join(command))

运行这个任务后,我得到了一个提示,但没有互动:

$ 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>

继续输入后出现了一个“out: ”的提示,我在上面输入,但我始终没有从redis那里得到任何反馈。

不过,如果我换成其他的互动提示,我就能进行互动:

@task
def cli():
    command = [
        "python"
    ]

    run(" ".join(command))

这会产生:

$ 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: >>> 

有没有人能告诉我为什么redis-cli的表现不好?我想向这个项目提交一个bug,但我想先更好地理解这个问题。

2 个回答

3

我刚发现一个简单又酷的方法;你可以通过echo和管道发送任何你想要的命令:

  • echo "keys *" | redis-cli
  • 或者针对你的情况:run("echo 'keys *' | redis-cli")
5

我觉得这个问题是因为redis-cli在交互模式下其实是为了在终端上使用而设计的,而fabric可能是通过重定向标准输入/输出的方式来运行redis-cli。

比如,下面这个命令可以正常工作:

python | cat

而下面这个命令就不行:

redis-cli | cat

redis-cli和linenoise库提供的类似readline的功能在非终端的文件描述符上输出时不能正确刷新。有一个可能的解决办法,我还没在fabric上试过,就是关闭linenoise:

TERM=dumb redis-cli | cat

通过把TERM变量设置为dumb,linenoise就会使用一个非常基础的代码路径,这个路径会用简单的printf来处理提示符,并在显示后立即刷新输出。如果你能在进程环境中设置这个变量,这可能会解决你在fabric上遇到的问题。

撰写回答