Python: запустить процесс sudo (в новом терминале), дождаться завершения

Изменить: мой окончательный код выглядит примерно так:

#WARNING: all " in command need to be escaped: \\"
def spawnInNewTerminal(command):
    #creates lock file
    lock = open(lockPath, 'w')
    lock.write("Currently performing task in separate terminal.")
    lock.close()

    #adds line to command to remove lock file
    command += ";rm " + lockPath

    #executes the command in a new terminal
    process = subprocess.Popen (
        ['x-terminal-emulator', '-e',  'sh -c "{0}"'.format(command) ]
        , stdout=subprocess.PIPE )
    process.wait()

    #doesn't let us proceed until the lock file has been removed by the bash command
    while os.path.exists(lockPath):
        time.sleep(0.1)

Оригинальный вопрос:

Я пишу простую оболочку, которая устанавливает все отсутствующие пакеты «на лету» перед окончательным запуском LuaLaTeX. В основном это работает, но ближе к концу мне нужно запустить команду

sudo tlmgr install [string of packages]

и, кроме того, поскольку нет никакой гарантии, что редактор LaTeX позволит пользователю вводить данные, мне нужно вызвать новый терминал, чтобы сделать это, чтобы они могли ввести свой пароль sudo.

Я в основном понял это: либо

process = subprocess.Popen(
    shlex.split('''x-terminal-emulator -t \'Installing new packages\' -e \'sudo tlmgr install ''' + packagesString + '''\''''), stdout=subprocess.PIPE)
retcode = process.wait()

or

os.system('''x-terminal-emulator -t \'Installing new packages\' -e \'sudo tlmgr install ''' + packagesString + '''\'''')

Единственная проблема заключается в том, что эта строка не ожидает завершения порожденного терминального процесса. На самом деле, он сразу же переходит к следующей строке (запускает реальный LuaLaTeX), прежде чем пользователь сможет даже ввести свой пароль или загрузить пакеты!

Насколько я понимаю, это потому, что дочерний процесс sudo завершается сразу. Есть ли способ убедиться, что процесс tlmgr завершится, прежде чем продолжить?


person scarlet    schedule 17.09.2011    source источник


Ответы (1)


Причина в том, что x-terminal-emulator порождает новый процесс и завершает работу, поэтому вы не можете знать, когда на самом деле завершится выполнение выполняемой команды. Чтобы обойти это, решением было бы изменить вашу команду, чтобы добавить другую команду, которая уведомляет вас. Поскольку очевидно, что x-terminal-emulator выполняет только одну команду, мы можем использовать оболочку для их объединения. Вероятно, это не лучший способ сделать, но один из них:

os.system('x-terminal-emulator -t "Installing new packages" -e "sh -c \\"sudo tlmgr install %s; touch /tmp/install_completed\\""' % packagesString)
while not os.path.exists("/tmp/install_completed"):
    time.sleep(0.1)
os.remove("/tmp/install_completed")
person rumpel    schedule 17.09.2011
comment
Я пытаюсь что-то подобное, но кажется, что при таком вызове выполняется только первая команда. Это случается и с вами? - person scarlet; 18.09.2011