我想知道在使用ssh-keygen
或不使用脚本调用subprocess
时是否需要做其他事情。
我在Linux环境中运行。
这是我的代码:
cfg_r = configparser.ConfigParser()
cfg_r.read('ssh_config.cfg')
p_mail=cfg_r.get('Company', 'mail')
bashCo m mand="ssh-keygen -t rsa -f /home/pi/.ssh/id_rsa - C \"{}\" -q -N \"\"".format(p_mail)
print(bashCommand.split())
proc = subprocess.Popen(bashCommand.split(),
stdout=subprocess.PIPE,
stderr=open('logfile_Get_conf.log', 'a'),
preexec_fn=os.setpgrp
)
outpu.stdout.read().decode('utf-8')
除此以外,我使用
configparser
来阅读电子邮件,没什么特别的。bashCommand
应为:ssh-keygen -t rsa -f /home/pi/.ssh/id_rsa -C "[email protected]" -q -N ""
bashCommand.split()
应该也是:['ssh-keygen', '-t', 'rsa', '-f', '/home/pi/.ssh/id_rsa', '-C', '"[email protected]"', '-q', '-N', '""']
非常奇怪的是,当我在外壳中运行此
bashCommand
时,没有出现任何问题:ssh-keygen -t rsa -f /home/pi/.ssh/id_rsa -C "[email protected]" -q -N ""
但是在我的日志文件中,我仍然有此错误:
Saving key "/home/pi/.ssh/id_rsa" failed: passphrase is too short (minimum five characters)
问题出在哪里?
最佳答案
我假设您正在类似Unix的环境中运行,并且外壳像bash
或类似的外壳(如变量bashCommand
所暗示)。 Windows中的工作原理大不相同。
运行在外壳程序中显示的命令时,以ssh-keygen
传递给argv
的参数是(使用Python语法):
['ssh-keygen', '-t', 'rsa', '-f', '/home/pi/.ssh/id_rsa', '-C', '[email protected]', '-q', '-N', '']
外壳将字符串展开,并去除所有引号。拆分命令时,由于未在
shell=True
中指定Popen
,因此参数按原样传递。这意味着ssh-keygen
的argv
将是['ssh-keygen', '-t', 'rsa', '-f', '/home/pi/.ssh/id_rsa', '-C', '"[email protected]"', '-q', '-N', '""']
希望您能看到区别。
-N
的参数不再为空。它是一个两个字符的字符串""
,显然少于五个字符。您不需要字符串
bashCommand
。使用列表,并将其直接传递给Popen
更加方便:bashCommand = ['ssh-keygen', '-t', 'rsa', '-f', '/home/pi/.ssh/id_rsa', '-C', p_mail, '-q', '-N', '']
proc = subprocess.Popen(bashCommand, ...)
注意,通过这种方式,您不需要对命令行进行任何字符串内插,花式拆分,引用,转义或其他修改。
我已经提到过,Windows上的工作方式大不相同。这是因为在Windows上始终设置
shell=True
,您对此无能为力。 Windows不会像Unix那样将argv
传递给程序。相反,程序负责解析自己的命令行字符串,因此必须使用引号。通常不赞成使用shell=True
,因此,我不建议将它用作类似Unix的情况的解决方案(但它可以工作)。如注释中所述,代码中还存在其他与健壮性,可维护性和美观有关的问题。但是,它们都不应该阻止它正常运行。