Fabric - Is there any way to capture run stdout?

2020-06-06 20:06发布

问题:

I'm trying to do the following:

output = run("ls -l backups")
for line in output.split("/n"):
    do_stuff(line)

Any way of having the stdout of ls sent to output?


To be more specific I'm using a CLI app called s3cmd which does something similar to ls, but with remote Amazon S3 buckets.

So a replacement for ls won't help unfortunately.


回答1:

Exactly what you are asking for should be happening. From the docs:

run will return the result of the remote program’s stdout as a single (likely multiline) string.

run(), and related commands like local() and sudo(), return an _AttributeString object that is just a wrapper around stdout with attribute access to additional information like failure/success booleans, stderr, the command run, etc. The result object also has a stdout attribute, which is just more explicit.

To troubleshoot, print type(output), output to be sure the response is what you expect. Examine output.failed and output.stderr. It could be the command isn't doing what you expect, there is no "backups" directory, etc.



回答2:

Try as below using String IO

from fabric.api import *
from StringIO import StringIO

fh = StringIO()
run("ls -l backups", stdout=fh)

fh.seek(0)
for line in fh.readlines():
    do_stuff(line)


回答3:

In case you need to use run(), you can do it like this:

with settings(
    hide('warnings', 'running', 'stdout', 'stderr'),
    warn_only=True
):
    command = 'ls -l backups'
    output = run(command)
    for line in output.splitlines():
        do_stuff(line)

For local() there is a bit more simple solution:

command = 'ls -l backups'
output = local(command, capture=True)
for line in output.splitlines():
    do_stuff(line)

I hope it helps.



回答4:

You can also use this if you are using the local() api, by setting the capture=True

@task
def login_ecr_docker():
    ecr_login = local("aws ecr get-login --region us-west-2", capture=True)
    docker_login = ecr_login.stdout
    status = local(docker_login, capture=True)
    print (status.stdout)


回答5:

Try split using "\r\n":

output = run("ls -l backups")
output_stdout = output.stdout.split("\r\n")


回答6:

Just simply return it:

def output():
    return run("ls -l backups")
a = execute(output, host=hostname)
print a

a will be dictionary of results.



标签: python fabric