Сделайте так, чтобы программа python3 нажимала «ввод» несколько раз

Я использую OpenVPN в своей компании и пытаюсь автоматизировать процесс создания пользователей. Возникла проблема на этапе генерации сертификата, с которой я столкнулся сейчас. При попытке построить ключ для пользователя (все параметры предопределены) программа должна несколько раз нажать Enter и в конце 2 раза "y" и "Enter". Я пытался использовать Popen и PIPE, но пока безуспешно. Был бы признателен за любую информацию.

import sys, os
from subprocess import Popen, PIPE
# Generate an .ovpn file

try:
    username = sys.argv[1]
except:
    print "Error. Supply a username!"
    sys.exit()

print("Adding user")
os.system("useradd" + " -m" + " -s" + " /bin/bash" + username)
print("Sourcing vars")
os.system('source + /home/myuser/openvpn-ca/vars')
enter = Popen(['/home/myuser/openvpn-ca/build-key {}'.format(username)]), 
stdin=PIPE, shell=True)
enter.communicate(input='\n')

Редактировать:

Это отличается от того, для чего он был помечен как [дубликат]. Вот почему:

Мне не нужно генерировать пользовательский сертификат, изменять какие-либо значения и т. д. Мне просто нужно нажать «Ввод» несколько раз и ввести «да» и «Ввод» 2 раза.

🤔 А знаете ли вы, что...
Python подходит для начинающих программистов благодаря своей простоте и читаемости кода.


1
248
1

Ответ:

Вы не можете source скрипт оболочки из Python; точнее, вы можете, но он просто запустит новый подпроцесс, который sources что-то и затем исчезнет, ​​ничего не изменив в вашей среде Python или последующих подпроцессах.

Вместо этого попробуйте что-то вроде этого:

import sys
import logging   # to get diagnostics on standard error instead
import subprocess

# Maybe switch to level=logging.WARNING once you are confident this works
logging.basicConfig(level=logging.INFO, format='%(module)s:%(asctime)s:%(message)s')

try:
    username = sys.argv[1]
except:
    logging.error("Error. Supply a username!")
    sys.exit()

logging.info("Adding user")
subprocess.run(["useradd", "-m", "-s", "/bin/bash", username],
    check=True, universal_newlines=True)
logging.info("Building key")
subprocess.run('''
        source /home/myuser/openvpn-ca/vars
        /home/myuser/openvpn-ca/build-key {}'''.format(username),
    shell=True, check=True, input='\n\n', universal_newlines=True)

Для переключения на subprocess.run() требуется достаточно новая версия Python 3. В более старых версиях subprocess.check_call() делала примерно то же самое, но не имела аргумента input=, так что вам действительно приходилось использовать для этого базовый Popen().

Дополнительные примечания:

  • Знак плюс после source явно был синтаксической ошибкой.
  • Мы везде используем check=True, чтобы убедиться, что Python проверяет успешность выполнения команд.
  • Смешивание os.system() с subprocess — это не ошибка, а подозрительный запах кода.

(Намного) больше об использовании subprocess на U*x здесь: https://stackoverflow.com/a/51950538/874188