获取屏幕上运行的命令的pid [英] Get pid of command ran by screen

查看:133
本文介绍了获取屏幕上运行的命令的pid的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发Minecraft(Bukkit)服务器管理器.它只是开始,停止,备份并检查其是否运行而已.最后一个导致问题. 如果我这样做是为了获取服务器的pid:

I'm developing a Minecraft (Bukkit) server manager. It's porpuse is only to start it, stop it, back it up and check if it is running. The last one causes the problem. If I do like this to get the pid of the server:

subprocess.Popen(["screen", "-dmS", "minecraft-server", "serverstart.sh"])

我得到了screen命令的pid,而不是启动脚本.但是,似乎pid始终是启动脚本的pid之下的一个,但我认为这是不可靠的. 如何获取Java进程的pid?

I get the pid of the screen command, not the startup-script. However it seems like the pid is always one underneath the pid of the startup-script, but I suppose this isn't relaiable. How can I get the pid of the java process?

我试过了,但是ps返回的退出代码为1,没有子pid.我认为这是因为屏幕突然关闭了.

I tried this, but ps returns with exit code 1 and no child pid. I think this is because screen closes down imidiately.

check_output(['ps', '--ppid', str(Popen(['screen', '-dmS', 'test']).pid), '--no-headers', '-o', 'pid'])

推荐答案

如果您具有屏幕的进程ID(父进程,假设您使用p = Subprocess.Popen(...),则可以使用p.pid访问它的父进程),则可以获得子进程的ID通过类似的方式

If you have the process ID of the screen (the parent process, which you can access with p.pid assuming you used p = Subprocess.Popen(...)), you can get the child process ids through something like

ps --ppid <SCREEN_PID> --no-headers -o pid

psutil 模块中也提供了psutil.Process(<SCREEN_PID>).get_children(),这可能是首选解析ps的输出,因为(我认为)它直接解析/proc.

There's also psutil.Process(<SCREEN_PID>).get_children() available from the psutil module which might be preferred to parsing the output of ps since (I think) it parses /proc directly.

Python的标准os模块中也有一些函数可以让您直接用进程ID做一些事情,但是什么也做不了,将获得父进程ID或进程组ID的子进程ID.

There are also some functions inside Python's standard os module that allow you to do some stuff with process IDs directly, but nothing that will get the child process IDs of a parent process id or a process group id.

以下代码:

#!/bin/env python

import subprocess, random, string, re
import psutil

SERVER_SCRIPT = "./serverstart.sh"

def get_random_key(strlen):
    return 'K'+''.join(random.choice(string.hexdigits) for x in range(strlen-1))

def find_screen_pid(name):
    ph = subprocess.Popen(["screen", "-ls"], stdout=subprocess.PIPE)
    (stdout,stderr) = ph.communicate()
    matches = re.search(r'(\d+).%s' % name, stdout, re.MULTILINE)
    if(matches): 
        pids = matches.groups()
        if(len(pids) == 1): return int(pids[0])
        else: raise Exception("Multiple matching PIDs found: %s" % pids)
    raise Exception("No matching PIDs found")

def get_child_pids(parent_pid):
    pp = psutil.Process(parent_pid)
    return [ int(cp.pid) for cp in pp.get_children()]

# Generate a random screen name, in case you're running multiple server instances
screenname = "minecraft-server-" + get_random_key(5)
print("Creating screen session named: %s" % screenname)
subprocess.Popen(["screen", "-dmS", screenname, SERVER_SCRIPT]).wait()

spid = find_screen_pid(screenname)  # Display some output
print("Screen PID: %d" % spid)
cpids = get_child_pids(spid)
print("Child PIDs: %s" % cpids)

产生输出:


./screen-pid.py
Creating screen session named: minecraft-server-K77d1
Screen PID: 2274
Child PIDs: [2276]

您可以使用cpids[0]从儿童pid列表中访问儿童pid.

You can access the child pid from the children pid list with cpids[0].

该脚本仅使用特定名称生成屏幕进程,然后找到父进程ID,并从中找到子进程ID.

The script simply spawns the screen process with a specific name, then finds the parent process id and from that, the children process ids.

如果您使用相同的脚本运行多个实例,则将在屏幕名称后附加随机字符.如果不是,则可以删除所有这些内容,但是将其保留也没关系.

The random characters appended to the screen name are there in case you're running multiple instances using the same script. If you're not, you can remove all that, but it makes no difference leaving it.

查找父进程ID(解析screen -ls的输出)的方法可能不是最佳方法,您也可以使用psutils.process_iter()遍历整个进程.但这似乎可行.

The method of finding the parent process id (parsing the output of screen -ls) probably isn't the best, you might alternatively iterate through the processes using psutils.process_iter(). But this seems to work.

这篇关于获取屏幕上运行的命令的pid的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆