在docker里,使用selenium啟動(dòng)chrome做截圖的時(shí)候挂据,webdriver quit后以清,會(huì)產(chǎn)生很多僵尸進(jìn)程。
def screenshot(url):
current_path = os.path.join(os.path.dirname(__file__)) # 文件的暫存路徑
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')
browser_exe_path = os.path.join(current_path, "chromedriver")
browser = webdriver.Chrome(executable_path=browser_exe_path,
chrome_options=chrome_options)
browser.get(url)
time.sleep(5)
size = browser.find_element_by_xpath("http://main").size
browser.set_window_size(1200, size.get("height"))
pic_path = os.path.join(current_path, "screenshot.png")
browser.save_screenshot(pic_path)
browser.quit()
在調(diào)查了進(jìn)程樹之后崎逃,終于發(fā)現(xiàn):chromedriver fork出了多個(gè)子進(jìn)程和一個(gè)孫進(jìn)程掷倔,而調(diào)用quit后,chrome driver正常退出个绍,而它的子孫們變成了孤兒進(jìn)程勒葱,被托管給了docker的1號(hào)進(jìn)程浪汪,也就是docker的啟動(dòng)進(jìn)程。這些孤兒進(jìn)程退出后凛虽,根據(jù)孤兒進(jìn)程托管的優(yōu)先級(jí)死遭,最終由1號(hào)進(jìn)程托管,而1號(hào)進(jìn)程沒(méi)有處理(wait/waitpid)涩维,這些進(jìn)程就變成了僵尸進(jìn)程殃姓。
但是!M卟蜗侈!這個(gè)1號(hào)進(jìn)程和宿主機(jī)的init進(jìn)程有著本質(zhì)的區(qū)別,這個(gè)1號(hào)進(jìn)程睡蟋,并沒(méi)有能力處理子進(jìn)程退出的信號(hào)踏幻,所以導(dǎo)致僵尸進(jìn)程沒(méi)有人“收尸”。
僵尸進(jìn)程是kill不掉的戳杀。最終该面,解決辦法是,在1號(hào)進(jìn)程加了一行代碼:
signal.signal(signal.SIGCLD, signal.SIG_IGN)
在Linux下可以簡(jiǎn)單地將SIGCHLD信號(hào)的操作設(shè)為SIG_IGN信卡,這樣隔缀,內(nèi)核在子進(jìn)程結(jié)束時(shí)不會(huì)產(chǎn)生僵尸進(jìn)程。這一點(diǎn)與BSD4不同傍菇,BSD4下必須顯式等待子進(jìn)程結(jié)束才能釋放僵尸進(jìn)程猾瘸。