为paramiko会话设置会话变量

8 投票
4 回答
12515 浏览
提问于 2025-04-17 15:37

有没有人知道在使用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 个回答

1

你可以这样做:client.exec_command(..., get_pty=True)

这样做会让paramiko分配一个伪终端,这个效果和使用ssh时是类似的。

1
#!/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')

你试过类似的做法吗?

10

自从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

撰写回答