在docker中使用selenium 或者pyppeteer,browser退出后,会产生僵尸进程。
处理方法一:
脚本内部加入信号处理的方法,参照文章https://www.jianshu.com/p/160a401eabb4
在Linux下可以简单地将SIGCHLD信号的操作设为SIG_IGN,这样,内核在子进程结束时不会产生僵尸进程。python 可以调用singal包来处理。
signal包的核心是使用signal.signal()函数来预设(register)信号处理函数:
参照:1. Python模块之信号(signal)2.Python Signal(信号) 异步系统事件
singnal.signal(signalnum, handler)
signalnum为某个信号,handler为该信号的处理函数。我们在信号基础里提到,进程可以无视信号,可以采取默认操作,还可以自定义操作。当handler为signal.SIG_IGN时,信号被无视(ignore)。当handler为singal.SIG_DFL,进程采取默认操作(default)。当handler为一个函数名时,进程采取函数中定义的操作。
优化后的代码如下:
# python3
# 开头加入如下代码,告诉此进程 SIGCLD的信号用SIG_IGN方法处理
import signal
signal.signal(signal.SIGCLD, signal.SIG_IGN)
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("//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()
if __name__=='__main__':
url='https://www.baidu.com'
screenshot(url)
处理方法二:
别人写好的程序,下载启动,参照:防止产生僵尸进程的dumb-init程序
dumb-init runs as PID 1, acting like a simple init system. It launches a single process and then proxies all received signals to a session rooted at that child process.
Since your actual process is no longer PID 1, when it receives signals from dumb-init, the default signal handlers will be applied, and your process will behave as you would expect. If your process dies, dumb-init will also die, taking care to clean up any other processes that might still remain.
制作Dockerfile时可加上此程序,参考docker 中 browserless/chrome 的制作
# It's a good idea to use dumb-init to help prevent zombie chrome processes.
ADD https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64 /usr/local/bin/dumb-init
RUN chmod +x /usr/local/bin/dumb-init
或者启动命令时
docker run my_container dumb-init python -c 'while True: pass'
参考https://www.infoq.cn/article/2016/01/dumb-init-Docker