为paramiko会话设置会话变量
有没有人知道在使用SSHClient时,如何让环境变量在exec_command调用中生效?
我在用一个简单的脚本,先创建了SSHClient这个类,然后用connect方法连接到另一台电脑,接着用exec_command方法发送命令。不过,当我尝试执行命令时,发现环境变量似乎没有生效。我可以执行一些基本的命令,比如'ls',并看到输出,但当我尝试运行已安装的程序时,由于缺少环境变量,导致这些程序无法运行。而如果我在命令行中用ssh做同样的事情,就没问题,因为用户的环境变量已经设置好了。
#!/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()
注意:我不能在paramiko中更改目录。我把cd
命令加到了后续命令中,像这样ssh.exec_command('cd /dddd/ddd;ls')
。我用ls
作为例子,但我实际的后续命令是不同的。
4 个回答
你可以这样做:client.exec_command(..., get_pty=True)
。
这样做会让paramiko分配一个伪终端,这个效果和使用ssh
时是类似的。
#!/usr/bin/python
import paramiko
client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.WarningPolicy)
client.connect(myhostname, theport, myuser, thepass)
stdin,stdout,stderr = client.exec_command('cd /tmp;pwd;ls -al')
#returns your output
print stdout.read()
这一切对我来说都运行得很好。如果你有特别的环境变量,可能需要在远程命令提示符下设置它们。也许你可以把这些变量写进一个叫做 myENV 的文件里,然后执行下面的命令:
stdin,stdout,stderr = client.exec_command('source ./myEnv')
你试过类似的做法吗?
自从2016年12月9日发布的2.1.0版本以来,你可以在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()
输出:
ET_HOME
...
MILES_APART
那么我为什么选择LC_TELEPHONE和LC_MEASUREMENT呢?因为这两个环境变量是目标主机的ssh配置允许我设置的少数几个变量之一:
grep AcceptEnv /etc/ssh/sshd_config
输出:
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
换句话说,这样做是行不通的:
env_dict={"HELLO":"WORLD","GOODBYE":"CRUEL_WORLD"}
stdin , stdout, stderr = ssh.exec_command("echo $HELLO; echo '...'; echo $GOODBYE")
print stdout.read()
输出:
...
正如文档所警告的,环境变量会被默默地拒绝 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
如果你无法控制目标服务器的sshd配置,把环境变量放到一个文件里并执行它是可行的:
stdin , stdout, stderr = ssh.exec_command("cat .set_env;source .set_env; echo $HELLO; echo '...'; echo $GOODBYE")
print stdout.read()
输出:
# begin .set_env
HELLO="WORLD"
GOODBYE="CRUEL_WORLD"
# end .set_env
WORLD
...
CRUEL_WORLD