Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

setting session variable for paramiko session

Does anyone know how to make environment variables registered for exec_command calls when using SSHClient?

I'm using a basic script that instantiates the SSHClient class, connects to another computer using the connect method, then sends out commands using the exec_command method. However, none of the environment variables seem to be registered when I try to issue commands. I can do basic things like 'ls' and see the stdout, but when trying to run installed programs, the fact that the environment variables are missing makes it impossible to run them. Using ssh in the command line to do the same thing works, as the environment variables for the user are set.

#!/usr/bin/python
import paramiko

ssh.connect('mymachine',username='myname',password='pass')    
stdin,stdout,stderr=ssh.exec_command('cd /myfolder/path')
stdin,stdout,stderr=ssh.exec_command('ls')

....

....

ssh.close()

Note: I can't change my directory in paramiko. I appended the cd command in the followup command in a single ssh.exec_command('cd /dddd/ddd;ls'). I have given ls as an example but my actual followup command is different.

like image 327
reach2arunprakash Avatar asked Feb 12 '13 13:02

reach2arunprakash


1 Answers

Since release 2.1.0 2016-12-09 , you can add an environment variable dictionary to the exec_command:

import paramiko
paramiko.util.log_to_file("paramiko.log")
ssh = paramiko.SSHClient()
k =   paramiko.RSAKey.from_private_key_file("<private_key_file>")
ssh.connect(<hostname>,username=<username>,pkey=k)
env_dict={"LC_TELEPHONE":"ET_HOME","LC_MEASUREMENT":"MILES_APART"}
stdin , stdout, stderr = ssh.exec_command('echo $LC_TELEPHONE; echo "..."; echo $LC_MEASUREMENT',environment=env_dict)
print stdout.read()

output:

ET_HOME
...
MILES_APART

But why did I choose LC_TELEPHONE and LC_MEASUREMENT? Because those are two of the few environments that the target host's ssh config allows me to set:

grep AcceptEnv /etc/ssh/sshd_config 

output:

AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL

In other words, this doesn't work:

env_dict={"HELLO":"WORLD","GOODBYE":"CRUEL_WORLD"}
stdin , stdout, stderr = ssh.exec_command("echo $HELLO; echo '...'; echo $GOODBYE")
print stdout.read()

output:

...

As the documentation warns, the environment variables are silently rejected http://docs.paramiko.org/en/2.1/api/client.html http://docs.paramiko.org/en/2.1/api/channel.html#paramiko.channel.Channel.set_environment_variable

If you cannot control the target server's sshd config, putting the environment variables into a file and sourcing it works:

stdin , stdout, stderr = ssh.exec_command("cat .set_env;source .set_env; echo $HELLO; echo '...'; echo $GOODBYE")
print stdout.read()

output:

# begin .set_env
HELLO="WORLD"
GOODBYE="CRUEL_WORLD"
# end .set_env
WORLD
...
CRUEL_WORLD
like image 177
ynux Avatar answered Oct 24 '22 18:10

ynux