国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

使用pyrasite進(jìn)行python進(jìn)程調(diào)試,改變運(yùn)行中進(jìn)程的代碼

Y3G / 3575人閱讀

摘要:反之,如果是使用并通過進(jìn)行調(diào)用,那么就應(yīng)當(dāng)進(jìn)行修改如果一個(gè)函數(shù)內(nèi)部有阻塞式的,那么改變這個(gè)函數(shù)是沒有用的,顯然要應(yīng)用改變的對象需要對象下一次被調(diào)用,這個(gè)不難理解但是容易漏想到

后端開發(fā)中有時(shí)會(huì)遇到這種情況:進(jìn)程運(yùn)行中偶現(xiàn),重啟進(jìn)程問題就消失;或者是,進(jìn)程一定要運(yùn)行一段時(shí)間才會(huì)出現(xiàn)問題;又或是,極難復(fù)現(xiàn)的問題出現(xiàn)了,然而已有的log不足以定位

對于這些情況,盡管大部分時(shí)候,我們可以通過在可能的地方加log,然后重啟進(jìn)程等待問題復(fù)現(xiàn),但這樣相對被動(dòng)。我們都知道如果要調(diào)試C/C++程序,gdb attach上進(jìn)程就可以,而python雖然有相似的工具pdb,但它無法附加到一個(gè)進(jìn)程上,必須要用pdb啟動(dòng)進(jìn)程,在實(shí)際環(huán)境中顯然不管用,那么python是否有類似的辦法來改變運(yùn)行中進(jìn)程的代碼呢?這樣我們就可以通過實(shí)時(shí)加log來定位問題,這樣幾乎可以解決python層面的任何問題

可以參考兩篇文章:

https://mozillazg.com/2018/07...
https://mozillazg.com/2017/07...

簡單來說,可以直接用gdb使用類似調(diào)試c程序的方式,但要求python進(jìn)程是使用python-debug這種版本的python,同樣不夠?qū)嵱谩_@里介紹博客中提到的“純gdb”的方式,通過github上一個(gè)開源python包pyrasite,本質(zhì)上是通過gdb的-eval-command和它的PyRun_SimpleString來向進(jìn)程注入代碼。

這個(gè)庫有一些附加功能,可以通過它的文檔去了解。這里只說實(shí)現(xiàn)進(jìn)程注入的核心,是其中一個(gè)很短的文件injector.py,這里去掉了原文件中用于windows平臺(tái)的一段代碼,我們這里只考慮linux,核心代碼如下:

import os
import subprocess
import platform

def inject(pid, filename, verbose=False, gdb_prefix=""):
    """Executes a file in a running Python process."""
    filename = os.path.abspath(filename)
    gdb_cmds = [
        "PyGILState_Ensure()",
        "PyRun_SimpleString(""
            "import sys; sys.path.insert(0, "%s"); "
            "sys.path.insert(0, "%s"); "
            "exec(open("%s").read())")" %
                (os.path.dirname(filename),
                os.path.abspath(os.path.join(os.path.dirname(__file__), "..")),
                filename),
        "PyGILState_Release($1)",
        ]
    p = subprocess.Popen("%sgdb -p %d -batch %s" % (gdb_prefix, pid,
        " ".join(["-eval-command="call %s"" % cmd for cmd in gdb_cmds])),
        shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out, err = p.communicate()
    if verbose:
        print(out)
        print(err)
        

這個(gè)函數(shù)做的事很簡單,不難看懂,所以,我們需要做的就是調(diào)用這個(gè)函數(shù),傳入pid和文件名,文件是一個(gè)你要對這個(gè)進(jìn)程執(zhí)行的python代碼。現(xiàn)在我們運(yùn)行一個(gè)很簡單的python進(jìn)程test.py

import time
def b():
  print("b")

while 1:
  b()
  time.sleep(1)
  

然后創(chuàng)建一個(gè)文件patch.py

print("injecting")
def newb():
  print("new b")
b = newb

injector.py的末尾加上一段,以便接收命令行調(diào)用:

import sys
pid = sys.argv[1]
filename = sys.argv[2]

inject(int(pid), filename)

通過ps aux|grep test.py查看上面進(jìn)程的pid,然后執(zhí)行python injector.py pid patch.py,為方便反復(fù)測試可以這樣:

pid=`ps aux | grep test.py | grep -v grep | awk "{print $2}"`;python injector.py $pid patch.py;echo $pid injected

輸出如下:

至此就實(shí)現(xiàn)了進(jìn)程注入。

注意點(diǎn):

修改類或類方法和函數(shù)同理,改變類的方法時(shí),直接使用類名classA.method = new_method會(huì)將變化應(yīng)用到所有實(shí)例,注意對類方法來說在patch.py中定義時(shí)也要加上self參數(shù)

patch.py中,我們可以直接對b賦值,因?yàn)槲覀僩db進(jìn)入一個(gè)進(jìn)程后,所在的上下文環(huán)境就是該進(jìn)程的入口模塊,可以通過打印globals()來看到有哪些全局變量,這些就是可以直接訪問的對象。如果是在一個(gè)普通的業(yè)務(wù)進(jìn)程中,必然有大量import,這種情況下你需要import相應(yīng)模塊再對該模塊的函數(shù)或類進(jìn)行修改,如import x.y.z as z; z.b = newb

特別需要注意的是,如果一個(gè)模塊A使用了from B import func,那么如果你想改變A中運(yùn)行的func,需要import A; A.func = newfunc,像這樣改變B是沒有用的:import B; B.func = newfunc,因?yàn)?b>from .. import ..會(huì)將對象復(fù)制一份到本地命名空間。反之,如果A是使用import B并通過B.func進(jìn)行調(diào)用,那么就應(yīng)當(dāng)import B進(jìn)行修改

如果一個(gè)函數(shù)內(nèi)部有阻塞式的while True,那么改變這個(gè)函數(shù)是沒有用的,顯然要應(yīng)用改變的對象需要對象下一次被調(diào)用,這個(gè)不難理解但是容易漏想到

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/43988.html

相關(guān)文章

  • 將任意Bytecode注入運(yùn)行Python進(jìn)程

    摘要:在調(diào)試程序的時(shí)候,一般我們只能通過以下幾種方式進(jìn)行調(diào)試程序中已經(jīng)有的日志在代碼中插入但是以上的方法也有不方便的地方,比如對于已經(jīng)在運(yùn)行中的程序,就不可能停止程序后加入調(diào)試代碼和增加新的日志從的項(xiàng)目得到靈感,嘗試對正在運(yùn)行的進(jìn)程插入代碼,在程 在調(diào)試 Python 程序的時(shí)候,一般我們只能通過以下幾種方式進(jìn)行調(diào)試: 程序中已經(jīng)有的日志 在代碼中插入 import pdb; pdb.s...

    endiat 評(píng)論0 收藏0
  • Python 調(diào)試方法

    摘要:背景這幾天一直在查一個(gè)線上程序住的問題這個(gè)程序總是在運(yùn)行分鐘后住通過以下的一些調(diào)試手段發(fā)現(xiàn)是打日志的時(shí)候因?yàn)闈M被了日志是默認(rèn)打到的無論日志級(jí)別而我這個(gè)程序是被另一個(gè)程序調(diào)起的父進(jìn)程沒有接收子進(jìn)程的導(dǎo)致了被打滿在調(diào)試的過程中用到了以下幾種調(diào)試 FROM http://kamushin.github.io/debug/python.html 背景 這幾天一直在查一個(gè)線上程序 hang 住的...

    klivitamJ 評(píng)論0 收藏0
  • 【openQPA】教你DIY進(jìn)程流量捕獲工具

    摘要:開源項(xiàng)目起因最近做病毒分析的時(shí)候遇到遠(yuǎn)控馬,需要記錄連接的遠(yuǎn)程地址用火絨劍或者可以看到一部分,但是我想要更全面的信息,于是搗鼓了和。使用比較簡單,但是只能看到的流量,雖然能捕獲所有流量,但沒法過濾特定進(jìn)程的包,而且過濾規(guī)則對我來說太復(fù)雜了。 開源項(xiàng)目QPA 起因最近做病毒分析的時(shí)候遇到遠(yuǎn)控馬,需要記錄連接的遠(yuǎn)程地址!用火絨劍或者ProcessMonitr可以看到一部分,但是我想要更全面...

    SimonMa 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<