我想知道在使用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-keygenargv将是

['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的情况的解决方案(但它可以工作)。

如注释中所述,代码中还存在其他与健壮性,可维护性和美观有关的问题。但是,它们都不应该阻止它正常运行。

10-08 05:12