温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Python中如何查看当前的进程在干什么

发布时间:2021-08-12 14:41:34 来源:亿速云 阅读:190 作者:小新 栏目:开发技术

这篇文章主要介绍Python中如何查看当前的进程在干什么,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

signal

在代码中,我们可以使用 signal 为进程预先注册一个信号接收器,在进程接收到特定信号的时候,可以打印方法栈:

import traceback, signal
class Debugger():
  def __init__(self, logger):
    self._logger = logger
  def log_stack_trace(self, sig, frame):
    d={'_frame':frame}
    d.update(frame.f_globals)
    d.update(frame.f_locals)
    messages = "Signal received. Stack trace:\n"
    messages += ''.join(traceback.format_stack(frame))
    self._logger.warn(messages)
  def listen(self):
    signal.signal(signal.SIGUSR1, self.log_stack_trace)

通过调用上面的 listen 方法(比如 new Debug(logger).listen()),就将一个可以接收 SIGUSR1 并打印方法栈的接收器注册到当前进程了。这里是打印方法栈,但是实际上可以做任何事,因为方法执行的当前,上下文已经跑到进程里面了。

那么怎么向进程发送信号呢?和 JVM 的方法类似,可以通过操作系统命令来发送:

kill -30 pid

这里的信号为什么是 30?这是因为 SIGUSR1 被当前操作系统定义成 30(请注意不同的操作系统这个映射表是可能不同的),这点可以通过 man signal 查看:

No Name Default Action Description
 SIGHUP terminate process terminal line hangup
 SIGINT terminate process interrupt program
 SIGQUIT create core image quit program
 SIGILL create core image illegal instruction
 SIGTRAP create core image trace trap
 SIGABRT create core image abort program (formerly SIGIOT)
 SIGEMT create core image emulate instruction executed
 SIGFPE create core image floating-point exception
 SIGKILL terminate process kill program
 SIGBUS create core image bus error
 SIGSEGV create core image segmentation violation
 SIGSYS create core image non-existent system call invoked
 SIGPIPE terminate process write on a pipe with no reader
 SIGALRM terminate process real-time timer expired
 SIGTERM terminate process software termination signal
 SIGURG discard signal urgent condition present on socket
 SIGSTOP stop process stop (cannot be caught or ignored)
 SIGTSTP stop process stop signal generated from keyboard
 SIGCONT discard signal continue after stop
 SIGCHLD discard signal child status has changed
 SIGTTIN stop process background read attempted from control terminal
 SIGTTOU stop process background write attempted to control terminal
 SIGIO discard signal I/O is possible on a descriptor (see fcntl(2))
 SIGXCPU terminate process cpu time limit exceeded (see setrlimit(2))
 SIGXFSZ terminate process file size limit exceeded (see setrlimit(2))
 SIGVTALRM terminate process virtual time alarm (see setitimer(2))
 SIGPROF terminate process profiling timer alarm (see setitimer(2))
 SIGWINCH discard signal Window size change
 SIGINFO discard signal status request from keyboard
 SIGUSR1 terminate process User defined signal 1
 SIGUSR2 terminate process User defined signal 2

当然,也可以写一点点 python 脚本来发送这个信号:

import os, signal
os.kill($PID, signal.SIGUSR1)

原理是一样的。

strace

如果进程已经无响应了,或者上面的信号接收器没有注册,那么就要考虑别的方法来或者“进程在干什么”这件事情了。其中,一个有用的命令是 strace:

strace -p pid

比如,我自己写了一个测试脚本 t.py,使用 python 执行,然后调用 sleep,再给它发送一个 SIGUSR1 的消息,它打印方法栈并退出。这整个过程,我使用 strace 可以得到这样的结果:

strace -p 9157
strace: Process 9157 attached
select(0, NULL, NULL, NULL, {9999943, 62231}) = ? ERESTARTNOHAND (To be restarted if no handler)
--- SIGUSR1 {si_signo=SIGUSR1, si_code=SI_USER, si_pid=9273, si_uid=9007} ---
rt_sigreturn({mask=[]})         = -1 EINTR (Interrupted system call)
stat("t.py", {st_mode=S_IFREG|0644, st_size=1281, ...}) = 0
open("t.py", O_RDONLY)         = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=1281, ...}) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=1281, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f631e866000
read(3, "import traceback, signal, time\n "..., 8192) = 1281
read(3, "", 4096)            = 0
close(3)                = 0
munmap(0x7f631e866000, 4096)      = 0
stat("t.py", {st_mode=S_IFREG|0644, st_size=1281, ...}) = 0
write(1, "Signal received. Stack trace:\n "..., 134) = 134
write(1, "\n", 1)            = 1
rt_sigaction(SIGINT, {SIG_DFL, [], SA_RESTORER, 0x7f631e06f5d0}, {0x7f631e392680, [], SA_RESTORER, 0x7f631e06f5d0}, 8) = 0
rt_sigaction(SIGUSR1, {SIG_DFL, [], SA_RESTORER, 0x7f631e06f5d0}, {0x7f631e392680, [], SA_RESTORER, 0x7f631e06f5d0}, 8) = 0
exit_group(0)              = ?
+++ exited with 0 +++

可以看到从 strace attached 开始,到进程退出,所有重要的调用都被打印出来了。

在 iOS 下,没有 strace,但是可以使用类似的(更好的)命令 dtruss。

lsof

lsof 可以打印某进程打开的文件,而 Linux 下面一切都是文件,因此查看打开的文件列表有时可以获取很多额外的信息。比如,打开前面提到的这个测试进程:

lsof -p 16872
COMMAND  PID USER  FD  TYPE DEVICE  SIZE/OFF   NODE NAME
Python 16872 xxx cwd  DIR  1,5    2688 1113586 /Users/xxx
Python 16872 xxx txt  REG  1,5   51744 10627527 /System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python
Python 16872 xxx txt  REG  1,5   52768 10631046 /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload/_locale.so
Python 16872 xxx txt  REG  1,5   65952 10631134 /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload/time.so
Python 16872 xxx txt  REG  1,5   841440 10690598 /usr/lib/dyld
Python 16872 xxx txt  REG  1,5 1170079744 10705794 /private/var/db/dyld/dyld_shared_cache_x86_64h
Python 16872 xxx  0u  CHR  16,2  0t39990   649 /dev/ttys002
Python 16872 xxx  1u  CHR  16,2  0t39990   649 /dev/ttys002
Python 16872 xxx  2u  CHR  16,2  0t39990   649 /dev/ttys002

它有几个参数很常用,比如-i,用来指定网络文件(如果是“-i: 端口号”这样的形式还可以指定端口)。

以上是“Python中如何查看当前的进程在干什么”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注亿速云行业资讯频道!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI