Rob Mecham
Rob Mecham

Reputation: 613

Environment Variables in Fabric2

I’m using Python 3.6 and Fabric 2.4. I’m using Fabric to SSH into a server and run some commands. I need to set an environment variable for the commands being run on the remote server. The documentation indicates that something like this should work:

from fabric import task

@task(hosts=["servername"])
def do_things(c):
    c.run("command_to_execute", env={"KEY": "VALUE"})

But that doesn’t work. Something like this should also be possible:

from fabric import task

@task(hosts=["servername"])
def do_things(c):
    c.config.run.env = {"KEY": "VALUE"}
    c.run("command_to_execute")

But that doesn’t work either. I feel like I’m missing something. Can anyone help?

Upvotes: 5

Views: 5710

Answers (5)

Preethi Vaidyanathan
Preethi Vaidyanathan

Reputation: 1322

I was able to do it by setting inline_ssh_env=True, and then explicitly setting the env variable, ex:

with Connection(host=hostname, user=username, inline_ssh_env=True) as c:
    c.config.run.env = {"MY_VAR": "this worked"}
    c.run('echo $MY_VAR')

Upvotes: 4

Nicholas Bishop
Nicholas Bishop

Reputation: 1141

When creating the Connection object, try adding inline_ssh_env=True.

Quoting the documentation:

Whether to send environment variables “inline” as prefixes in front of command strings (export VARNAME=value && mycommand here), instead of trying to submit them through the SSH protocol itself (which is the default behavior). This is necessary if the remote server has a restricted AcceptEnv setting (which is the common default).

Upvotes: 1

MikeL
MikeL

Reputation: 5621

You can try that:

@task
def qa(ctx):
  ctx.config.run.env['counter'] = 22
  ctx.config.run.env['conn'] = Connection('qa_host')

@task
def sign(ctx):
  print(ctx.config.run.env['counter'])
  conn = ctx.config.run.env['conn']
  conn.run('touch mike_was_here.txt')

And run:

fab2 qa sign

Upvotes: 1

Peshmerge
Peshmerge

Reputation: 1060

As stated on the site of Fabric:

The root cause of this is typically because the SSH server runs non-interactive commands via a very limited shell call: /path/to/shell -c "command" (for example, OpenSSH). Most shells, when run this way, are not considered to be either interactive or login shells; and this then impacts which startup files get loaded.

You read more on this page link

So what you try to do won't work, and the solution is to pass the environment variable you want to set explicitly:

from fabric import task

    @task(hosts=["servername"])
    def do_things(c):
        c.config.run.env = {"KEY": "VALUE"}
        c.run('echo export %s >> ~/.bashrc ' % 'ENV_VAR=VALUE' )
        c.run('source ~/.bashrc' )
        c.run('echo $ENV_VAR') # to verify if it's set or not! 
        c.run("command_to_execute")

Upvotes: 2

Ismaïl Mourtada
Ismaïl Mourtada

Reputation: 472

According to that part of the official doc, the connect_kwargs attribute of the Connection object is intended to replace the env dict. I use it, and it works as expected.

Upvotes: 0

Related Questions