[英]Get process ID of command executed inside terminal in Python subprocess
I run vim inside gnome-terminal in a Python subprocess:我在 Python 子进程中的 gnome-terminal 内运行 vim:
>>> import subprocess
>>> cmd=['gnome-terminal', '--', 'vim']
>>> p = subprocess.Popen(cmd)
It is possible to get the process ID for gnome-terminal with p.pid
, but how can I get the process ID for vim from within the Python script?可以使用
p.pid
获取 gnome-terminal 的进程 ID,但是如何从 Python 脚本中获取 vim 的进程 ID?
Even though pstree
in Bash shows vim as a child process of gnome-terminal, psutils does not list it.尽管 Bash 中的
pstree
vim 显示为 gnome-terminal 的子进程,但 psutils 并未列出它。
>>> import psutil
>>> terminal_process = psutil.Process(p.pid)
>>> terminal_process.children()
[]
This behavior is caused by gnome-terminal.此行为是由 gnome-terminal 引起的。
If you type the command ps | grep <pid>
如果您键入命令
ps | grep <pid>
ps | grep <pid>
inside your shell, you will see something similar to <pid> pts/0 00:00:00 gnome-terminal <defunct>
. ps | grep <pid>
在你的 shell 中,你会看到类似于<pid> pts/0 00:00:00 gnome-terminal <defunct>
。
A process being defunct means it has finished its task and is waiting to get killed (or is misbehaving which isn't the case here).一个进程被取消意味着它已经完成了它的任务并正在等待被杀死(或者行为不端,这里不是这种情况)。 This means the process you launched from python has completed its job and is waiting for python to kill it.
这意味着你从 python 启动的进程已经完成了它的工作,正在等待 python 杀死它。
Now if you look at pstree
, you will see that another gnome-terminal process has been spawn at the root level.现在,如果您查看
pstree
,您将看到另一个 gnome-terminal 进程已在根级别生成。 This means that the gnome-terminal process you launched in Python simply launched the "real terminal process" at the root level and exited.这意味着您在 Python 中启动的 gnome-terminal 进程只是在根级别启动了“真正的终端进程”并退出。 If you further investigate and look for processes starting with gnome-terminal using
ps aux | grep gnome-terminal
如果您进一步调查并使用
ps aux | grep gnome-terminal
查找以 gnome-terminal 开头的进程ps aux | grep gnome-terminal
, you will see output like : ps aux | grep 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
There is your now defunct process, and a new gnome-terminal-server
process.有你现在已经不复存在的进程,以及一个新的
gnome-terminal-server
进程。 gnome-terminal-server
is the process you are looking for. gnome-terminal-server
是您正在寻找的进程。
Long story short pgrep -f gnome-terminal-server
will return the pid you want.长话短说
pgrep -f gnome-terminal-server
将返回您想要的 pid。
I think this works fine我认为这很好用
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)
The reason I used time.sleep(10)
is because for some reason vim
was not getting forked that fast so, I delayed it for 10 seconds.我使用
time.sleep(10)
原因是由于某种原因vim
没有被分叉那么快,所以我延迟了 10 秒。
Here we create 2 process for getting the ID of vim editor, we give the output of process a
to b
using stdout and stdin.这里我们创建了 2 个获取 vim 编辑器 ID 的进程,我们使用 stdout 和 stdin 将进程
a
的输出a
给b
。
Then we use .communicate()
to get stdout of process b
into output
.然后我们使用
.communicate()
将进程b
stdout 输出到output
。
Now our output
is in form of bytes so we decode it to UTF-8 using .decode("utf-8")
and then split on every new line.现在我们的
output
是字节的形式,所以我们使用.decode("utf-8")
将其解码为 UTF-8,然后在每个新行上拆分。
It produces the output:它产生输出:
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:~$
To verify this:要验证这一点:
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:~$
Here we can see that vim is forked from gnome-terminal 21093
is the id of gnome-terminal which is the ppid of vim.在这里我们可以看到 vim 是从 gnome-terminal 分叉出来的
21093
是 gnome-terminal 的 id,它是 vim 的 ppid。
Now, this happened if I didn't use time.sleep(10)
现在,如果我不使用
time.sleep(10)
发生这种情况
rahul@RNA-HP:~$ python3 so.py
['21407 21406 /usr/bin/python3 /usr/bin/gnome-terminal -- vim', '21409 21406 grep vim', '']
If we try to verify if those PID exist:如果我们尝试验证这些 PID 是否存在:
rahul@RNA-HP:~$ kill 21407
bash: kill: (21407) - No such process
rahul@RNA-HP:~$
Those ID dont exist for some reason.由于某种原因,这些 ID 不存在。
If there are multiple instances of vim: It produces:如果有多个 vim 实例:它会产生:
['21416 21093 vim', '21736 21093 vim', '21738 21728 grep vim', '']
To get the latest instantiated vim's pid:要获取最新实例化的 vim pid:
output = output[len(output) - 3]
Our output is sorted in ascending order of pid's and our last and second last values are我们的输出按 pid 的升序排序,我们的最后一个和倒数第二个值是
and
grep vim
so we need the third last argument for getting the pid of vim.和
grep vim
所以我们需要最后第三个参数来获取 vim 的 pid。
Comment if something can be improved.评论是否可以改进。
Here is a workaround.这是一个解决方法。 Name the vims by symbolic links, and find their pids:
通过符号链接命名 vim,并找到它们的 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)
Here is my own Python only take, which works well so far.这是我自己的 Python 唯一版本,到目前为止效果很好。 Any issues with this code?
这段代码有什么问题吗?
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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.