我在 Python 子进程的 gnome-terminal 中运行 vim:
>>> import subprocess
>>> cmd=['gnome-terminal', '--', 'vim']
>>> p = subprocess.Popen(cmd)
可以使用p.pid
获取 gnome-terminal 的进程 ID,但是如何从 Python 脚本中获取 vim 的进程 ID?
尽管 Bash 中的pstree
将 vim 显示为 gnome-terminal 的子进程,但 psutils 没有列出它。
>>> import psutil
>>> terminal_process = psutil.Process(p.pid)
>>> terminal_process.children()
[]
此行为是由 gnome-terminal 引起的。
如果在 shell 中键入命令ps | grep <pid>
,您将看到类似于<pid> pts/0 00:00:00 gnome-terminal <defunct>
的内容。
一个进程被终止意味着它已经完成了任务并正在等待被杀死(或者行为不端,这里不是这种情况)。 这意味着你从python启动的进程已经完成了它的工作,正在等待python杀死它。
现在,如果您查看pstree
,您将看到另一个侏儒终端进程已在根级别生成。这意味着你在 Python 中启动的 gnome-terminal 进程只是在根级别启动了"真正的终端进程"并退出。 如果您进一步调查并使用ps aux | grep gnome-terminal
查找以 gnome-terminal 开头的进程,您将看到如下输出:
root 5047 0.0 0.0 0 0 pts/0 Z 10:07 0:00 [gnome-terminal] <defunct>
root 5053 0.0 0.3 595276 30468 ? Sl 10:07 0:00 /usr/lib/gnome-terminal/gnome-terminal-server
root 7147 0.0 0.0 12780 972 pts/0 S+ 10:17 0:00 grep gnome-terminal
有你现在已经不存在的过程,以及一个新的gnome-terminal-server
过程。gnome-terminal-server
是您正在寻找的过程。
长话短说pgrep -f gnome-terminal-server
将返回您想要的 pid。
我认为这很好
用
import time
import subprocess
cmd=['gnome-terminal','--', 'vim']
p = subprocess.Popen(cmd)
time.sleep(10)
a = subprocess.Popen(['ps', '-eo', 'pid,ppid,command'], stdout = subprocess.PIPE)
b = subprocess.Popen(['grep', 'vim'], stdin = a.stdout, stdout = subprocess.PIPE)
output, error = b.communicate()
output = output.decode("utf-8").split('n')
print(output)
我之所以使用time.sleep(10)
是因为由于某种原因vim
没有那么快分叉,所以我延迟了 10 秒。
在这里,我们创建 2 个进程来获取 vim 编辑器的 ID,我们使用标准输出和标准输出将进程a
的输出提供给b
。
然后我们使用.communicate()
将进程b
的标准输出放入output
。
现在我们的output
是字节的形式,所以我们使用.decode("utf-8")
将其解码为 UTF-8,然后在每个新行上拆分。
它产生输出:
rahul@RNA-HP:~$ python3 so.py
# _g_io_module_get_default: Found default implementation gvfs (GDaemonVfs) for ‘gio-vfs’
# _g_io_module_get_default: Found default implementation dconf (DConfSettingsBackend) for ‘gsettings-backend’
# watch_fast: "/org/gnome/terminal/legacy/" (establishing: 0, active: 0)
# unwatch_fast: "/org/gnome/terminal/legacy/" (active: 0, establishing: 1)
# watch_established: "/org/gnome/terminal/legacy/" (establishing: 0)
['21325 21093 vim', '21330 21318 grep vim', '']
rahul@RNA-HP:~$
要验证这一点,请执行以下操作:
rahul@RNA-HP:~$ ps aux | grep gnome-terminal
rahul 21093 1.7 2.4 978172 45096 ? Ssl 19:55 0:02 /usr/lib/gnome-terminal/gnome-terminal-server
rahul 21374 0.0 0.0 8988 840 pts/0 S+ 19:57 0:00 grep --color=auto gnome-terminal
rahul@RNA-HP:~$ ps -eo pid,ppid,command | grep vim
21325 21093 vim
21376 21104 grep --color=auto vim
rahul@RNA-HP:~$
在这里我们可以看到 vim 是从 gnome-terminal 分叉出来的,21093
是 gnome-terminal 的 id,它是 vim 的 ppid。
现在,如果我不使用time.sleep(10)
就会发生这种情况
rahul@RNA-HP:~$ python3 so.py
['21407 21406 /usr/bin/python3 /usr/bin/gnome-terminal -- vim', '21409 21406 grep vim', '']
如果我们尝试验证这些 PID 是否存在:
rahul@RNA-HP:~$ kill 21407
bash: kill: (21407) - No such process
rahul@RNA-HP:~$
由于某种原因,这些 ID 不存在。
如果有多个 vim 实例: 它产生:
['21416 21093 vim', '21736 21093 vim', '21738 21728 grep vim', '']
要获取最新的实例化 vim 的 pid,请执行以下操作:
output = output[len(output) - 3]
我们的输出按 pid 的升序排序,我们的最后一个和倒数第二个值是和 CC_22 所以我们需要倒数第三个参数来获取 vim 的 pid。
评论是否可以改进的地方。
这是我自己的 Python 唯一采取的,到目前为止效果很好。此代码有任何问题吗?
import psutil, subprocess
cmd=['gnome-terminal', '--', 'vim']
editor_cmd=cmd[-1] # vim
proc = subprocess.Popen(cmd)
proc.wait()
# find the latest editor process in the list of all running processes
editor_processes = []
for p in psutil.process_iter():
try:
process_name = p.name()
if editor_cmd in process_name:
editor_processes.append((process_name, p.pid))
except:
pass
editor_proc = psutil.Process(editor_processes[-1][1])
print(editor_proc)
这是一个解决方法。通过符号链接命名vims,并找到它们的pid:
import subprocess as sub,time,os,signal
N=5
vims= [ sub.Popen(f'ln -fs $(which vim) /dev/shm/vim{vn} && gnome-terminal -- /dev/shm/vim{vn} -c "s/$/Welcome to vim{vn}/"', shell=True) for vn in range(N) ]
time.sleep(1)
for vn in range(N):
# Get the pids of vims. Vim pid is not equal to proc.pid!
phelper= sub.Popen(f'ps -o pid= -C vim{vn}',shell=True, stdout=sub.PIPE, stderr=sub.PIPE)
try:
out,err= phelper.communicate(timeout=1)
vims[vn]= (vims[vn],int(out.decode(encoding="utf8"))) # proc_object --> (proc_object,vim pid)
except TimeoutExpired:
pass
phelper.kill()
# do something:
time.sleep(10)
for proc,vimpid in vims:
os.kill(vimpid,signal.SIGTERM)