1

我想知道当我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 "mail@gmail.com" -q -N ""

bashCommand.split()也应该如此:

['ssh-keygen', '-t', 'rsa', '-f', '/home/pi/.ssh/id_rsa', '-C', '"mail@gmail.com"', '-q', '-N', '""']

非常奇怪的是,当我bashCommand在 shell 中运行它时,没有出现任何问题:

ssh-keygen -t rsa -f /home/pi/.ssh/id_rsa -C "mail@gmail.com" -q -N ""

但是在我的日志文件中我仍然有这个错误:

Saving key "/home/pi/.ssh/id_rsa" failed: passphrase is too short (minimum five characters)

问题出在哪里?

4

1 回答 1

2

我假设您正在一个类 Unix 环境中运行,它带有类似bash或类似的 shell(正如变量bashCommand所暗示的那样)。Windows 中的工作方式非常不同。

当您运行在 shell 中显示的命令时,传递给ssh-keygenas的参数argv是(在 Python 语法中):

['ssh-keygen', '-t', 'rsa', '-f', '/home/pi/.ssh/id_rsa', '-C', 'mail@gmail.com', '-q', '-N', '']

shell 扩展了字符串,并去掉了任何引号。当您拆分命令时,参数按原样传递,因为您没有指定shell=Trueto Popen。这意味着ssh-keygen'sargv将是

['ssh-keygen', '-t', 'rsa', '-f', '/home/pi/.ssh/id_rsa', '-C', '"mail@gmail.com"', '-q', '-N', '""']

希望你能看到区别。to 的参数-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 那样传递给程序。相反,程序负责解析自己的命令行字符串,因此必须使用引号。使用通常不受欢迎,因此我不建议将其用作类 Unix 案例的解决方案(但它会起作用)。argvshell=True

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

于 2019-07-23T16:01:56.383 回答