通过屏幕获取命令的pid

2024-09-28 21:00:31 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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

我得到屏幕命令的pid,而不是启动脚本。然而,似乎pid总是位于启动脚本的pid之下,但我想这是不相关的。 如何获得java进程的pid?在

编辑: 我试过了,但是ps返回的是退出代码1,没有子pid。我想这是因为屏幕立即关闭。在

^{pr2}$

Tags: 服务器脚本管理器server屏幕dms备份pid
3条回答

您必须将java命令包装到一个获取并返回pid的shell脚本中。有关示例,请参见http://ss64.org/viewtopic.php?id=1495。在

假设您希望进程的PID在屏幕中运行,我的回答是in another question on this site。答案如下:

您可以在这里获得屏幕会话的PID,如下所示:

$ screen -ls
There are screens on:
        1934.foo_Server         (01/25/15 15:26:01)     (Detached)
        1876.foo_Webserver      (01/25/15 15:25:37)     (Detached)
        1814.foo_Monitor        (01/25/15 15:25:13)     (Detached)
3 Sockets in /var/run/screen/S-ubuntu.

假设您希望在foo_Monitor屏幕会话中在Bash中运行程序的PID。使用foo_Monitor屏幕会话的PID,通过搜索ppid(父PID)来获取在其中运行的bash会话的PID:

^{pr2}$

现在只获取bash会话的PID:

$ ps -el | grep 1814 | grep bash | awk '{print $4}'
1815

现在我们需要一个带有PID的过程。只需嵌套命令,这一次使用-v标志grep bash来获得而不是bash的进程:

echo $(ps -el | grep $(ps -el | grep 1814 | grep bash | awk '{print $4}') | grep -v bash | awk '{print $4}')
23869

只需将1814替换为实际PID或屏幕会话:

echo $(ps -el | grep $(ps -el | grep SCREEN_SESSION_PID | grep bash | awk '{print $4}') | grep -v bash | awk '{print $4}')

如果您有屏幕的进程ID(父进程,您可以使用p.pid访问,假设您使用了p = Subprocess.Popen(...)),那么您可以通过如下方式获得子进程ID

ps  ppid <SCREEN_PID>  no-headers -o pid

psutil模块中还有psutil.Process(<SCREEN_PID>).get_children(),这可能更适合解析ps的输出,因为(我认为)它直接解析/proc。在

Python的standard os module中还有一些函数允许您直接对进程id执行一些操作,但是不能获得父进程id或进程组id的子进程id


以下代码:

^{pr2}$

产生输出:

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

您可以使用cpids[0]从子pid列表访问子pid。在

该脚本只需生成具有特定名称的屏幕进程,然后查找父进程id,并从中找到子进程id。在

如果您正在使用同一个脚本运行多个实例,则会在屏幕名称后面附加随机字符。如果你没有,你可以删除所有这些,但是离开它没有任何区别。在

查找父进程id的方法(解析screen -ls的输出)可能不是最好的方法,您可以选择使用psutils.process_iter()遍历这些进程。但这似乎有效。在

相关问题 更多 >