Reputation: 613
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
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
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 restrictedAcceptEnv
setting (which is the common default).
Upvotes: 1
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
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
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