Python:在新终端中启动sudo进程,并等待其完成

1 投票
1 回答
1333 浏览
提问于 2025-04-17 02:30

编辑:我的最终代码大致如下:

#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()

要么

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

唯一的问题是,这行代码并不会等到新开的终端进程完成。实际上,它会立即继续到下一行(运行真正的LuaLaTeX),甚至在用户输入密码或下载包之前就开始了!

根据我的理解,这是因为sudo的子进程很快就结束了。有没有办法确保tlmgr进程完成后再继续?

1 个回答

3

原因是,x-terminal-emulator会启动一个新进程然后退出,所以你无法知道你执行的命令到底什么时候完成。为了绕过这个问题,可以修改你的命令,添加一个可以通知你的其他命令。因为x-terminal-emulator似乎只执行一个命令,所以我们可以用一个shell来把它们连接起来。这样做可能不是最好的方法,但可以这样做:

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")

撰写回答