LoginSignup
55
45

More than 5 years have passed since last update.

[Ruby]Selenium::WebDriverでHeadless Chromeを起動したときのChromeのオプション設定

Last updated at Posted at 2019-01-19

Selenium::WebDriverを使ってHeadless Chromeを起動したときのオプション設定について調べてみました。

Selenium::WebDriverでHeadless Chromeを起動するには

通常のChromeとの違いは、オプション設定に--headlessを渡すことだけです。

require 'selenium-webdriver'

options = Selenium::WebDriver::Chrome::Options.new
options.add_argument('--headless')
@driver = Selenium::WebDriver.for :chrome, options: options
@driver.navigate.to "https://www.google.com/"

Selenium::WebDriverからHeadless Chromeを起動するとどんなプロセスが生成されているか?

上記のコードを実行すると、

  • chromedriver
  • google-chrome webdriver
  • chrome zygote x2
  • chrome gpu-process
  • chrome broker
  • chrome renderer

という6種類7つのプロセスが生成されます。(zygoteプロセスは2つ生成されていました)
PID値を見る限り、この順番で生成されているようです。

各プロセス生成時のオプション設定

chromedriver

chromedriverは以下のコマンドで起動されています。

chromedriver --port=9515

オプション設定はポート指定のみです。

google-chrome webdriver

google-chromechromeのラッパーとのこと。

Difference between “/opt/google/chrome/chrome” and “/opt/google/chrome/google-chrome” on Fedora 22
https://superuser.com/questions/975050/difference-between-opt-google-chrome-chrome-and-opt-google-chrome-google-ch

以下のようにgoogle-chromeコマンドに大量のオプションが渡されています。

/opt/google/chrome/google-chrome --disable-background-networking --disable-client-side-phishing-detection --disable-default-apps --disable-hang-monitor --disable-popup-blocking --disable-prompt-on-repost --disable-sync --disable-web-resources --enable-automation --enable-logging --force-fieldtrials=SiteIsolationExtensions/Control --headless --ignore-certificate-errors --load-extension=/tmp/.org.chromium.Chromium.YZWaub/internal --log-level=0 --metrics-recording-only --no-first-run --password-store=basic --remote-debugging-port=0 --test-type=webdriver --use-mock-keychain --user-data-dir=/tmp/.org.chromium.Chromium.tVOWvT data:,

オプション設定の内容を表にまとめました。
実に23個のオプションが設定されています。

options 内容
disable-background-networking 複数のサブシステムの動作オフ
disable-client-side-phishing-detection フィッシング検知機能オフ
disable-default-apps デフォルトアプリ設定オフ
disable-hang-monitor ページの停止監視機能オフ
disable-popup-blocking ポップアップブロック機能オフ
disable-prompt-on-repost POSTリクエストの結果確認機能オフ
disable-sync ブラウザデータとGoogleアカウントの同期オフ
disable-web-resources Webリソースのためのバックエンド機能オフ
enable-automation 自動テスト中であることの通知機能オン
enable-logging コンソールログ機能オン
force-fieldtrials=SiteIsolationExtensions/Control fieldtrialsオプションの設定
headless ヘッドレスChromeとして起動
ignore-certificate-errors 認証関連エラー無視
load-extension=/tmp/.org.chromium.Chromium.YZWaub/internal 拡張機能へのパス設定
log-level=0 ログレベルをINFOに設定
metrics-recording-only メトリックスの通知オフ、記録のみオン
no-first-run First runタスク オフ
password-store=basic パスワード用暗号化ストレージをbasicに指定
remote-debugging-port=0 ポート0のリモートデバッグ オン
test-type=webdriver テストに使うツールをwebdriverに設定
use-mock-keychain macOS用の必須設定(詳細不明)
user-data-dir=/tmp/.org.chromium.Chromium.tVOWvT ユーザープロフィールの保存場所指定
data:, user-data-dirのオプション?

test-type=webdriverとあるので、このプロセスと勝手にwebdriverと呼ぶことにしました。
主にテストを実施する際に邪魔な機能をオフする目的のオプション設定になっていると思います。

chrome zygote

webdriverのプロセス生成に続いてChromeの一部であるzygoteというプロセスが2つ立て続けに生成されています。

chromeコマンドのオプションを見ると--headlessオプションが重複していました。わざわざ渡さなくても良かった、というわけではないでしょうが、理由はわかりません。

/opt/google/chrome/chrome --type=zygote --enable-logging --headless --log-level=0 --headless --enable-crash-reporter
options 内容
type=zygote プロセスのタイプ表示のための名前設定
enable-logging コンソールログ機能オン
headless ヘッドレスChromeとして起動
log-level=0 ログレベルをINFOに設定
enable-crash-reporter ヘッドレスのためのクラッシュ通知オン

A zygote process is one that listens for spawn requests from a master process and forks itself in response. Generally they are used because forking a process after some expensive setup has been performed can save time and share extra memory pages.

zygoteプロセスは時間短縮や省メモリを実現するための仕組みとして使われているとのこと。またChrome起動中に一部のライブラリがアップデートされたときの泣き別れ対策としても動作しているようです。
Selenium関連というより、Chromeの動作に必要なプロセスということでしょう。

chrome gpu-process

次はgpu-processというプロセスが生成されます。

/opt/google/chrome/chrome --type=gpu-process --enable-logging --headless --log-level=0 --headless --enable-crash-reporter --gpu-preferences=KAAAAAAAAACAAABAAQAAAAAAAAAAAGAAAAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAA --use-gl=swiftshader-webgl --override-use-software-gl-for-tests --headless --enable-crash-reporter --enable-logging --log-level=0 --service-request-channel-token=10264762006126535026
options 内容
type=gpu-process プロセスのタイプ表示のための名前設定
enable-logging コンソールログ機能オン
headless ヘッドレスChromeとして起動
log-level=0 ログレベルをINFOに設定
enable-crash-reporter ヘッドレスのためのクラッシュ通知オン
gpu-preferences=KAAAAAAAAACAAABAA... GPU情報の設定?
use-gl=swiftshader-webgl GPUが使うGLをSwiftShaderに設定
override-use-software-gl-for-tests ソフトウェアGLを使用するよう強制的に設定
service-request-channel-token=1026476200612... 子プロセスでのメッセージパイプのためのトークン

chromeコマンドを見ると14個のオプションが設定されていますが、重複が多く、実際には上記表のように9種類のオプションが渡されています。

内容はgpu-processという名前から推測される通り、GPU関連の設定を行っています。というより、GPUを使わずにソフトウェアGLを使うように強制的に設定しています。

chrome broker

brokerプロセスはタイプの指定を行っているだけで、それ以外のオプションはありません。

/opt/google/chrome/chrome --type=-broker

Chromiumのプロセス構成と Worker/SharedWorker/ServiceWorkerのうごき
https://qiita.com/amiq11/items/61cf100e5f9fac8533b6

「ブラウザ」、「GPUプロセス」という2つのプロセスに加え、おおよそそれぞれのタブが別のプロセスに割り振られていることがわかります。このタブごとのプロセスを「レンダラプロセス」といいます。
たとえばa.comを開いたとすると、ブラウザプロセスがレンダラプロセスをつくり、ネットワークリクエストがブラウザプロセスへ投げられ(1)、ブラウザプロセスがネットワークにリクエストを投げ(2)、レスポンスがブラウザプロセスに帰ってきて(3)、それをレンダラになげる(4)、という手順になります。

In Chromium, the broker is always the browser process. The broker, is in broad terms, a privileged controller/supervisor of the activities of the sandboxed processes.

brokerプロセスはブラウザプロセスとしてレンダラプロセスを作るコントローラの役目を果たしているとのこと。

chrome renderer

最後にrendererプロセスが生成されます。rendererプロセスはいわゆるタブに相当するものなので、タブが3つあれば3つのrendererプロセスが生成されます。

chromeコマンドは以下の通り。これも大量のオプションが渡されています。

/opt/google/chrome/chrome --type=renderer --enable-automation --enable-logging --log-level=0 --test-type=webdriver --use-gl=swiftshader-webgl --disable-gpu-compositing --service-pipe-token=4567683379984847303 --lang=en-US --headless --enable-crash-reporter --num-raster-threads=1 --service-request-channel-token=4567683379984847303 --renderer-client-id=4 --shared-files=v8_context_snapshot_data:100,v8_natives_data:101
options 内容
type=renderer プロセスのタイプ表示のための名前設定
enable-automation 自動テスト中であることの通知機能オン
enable-logging コンソールログ機能オン
log-level=0 ログレベルをINFOに設定
test-type=webdriver テストに使うツールをwebdriverに設定
use-gl=swiftshader-webgl GPUが使うGLをSwiftShaderに設定
disable-gpu-compositing GPUの使用をオフ
service-pipe-token=4567683379984847303 メッセージパイプを使うためのトークン
lang=en-US 言語をen-USに設定
headless ヘッドレスChromeとして起動
enable-crash-reporter ヘッドレスのためのクラッシュ通知オン
num-raster-threads=1 ラスタ変換に使うスレッド数を1に設定
service-request-channel-token=4567683379984847303 メッセージパイプを作るためのトークン
renderer-client-id=4 ???
shared-files=v8_context_snapshot_data:100,v8_natives_data:101 子プロセスへ渡すファイル記述子の設定

重複なく15個のオプションが設定されています。子プロセスとのやりとりに必要となるオプションがいくつか設定されていることが特徴的です。そしてこのプロセスが最も多くのメモリを使います。

まとめ

以上がSelenium::WebDriverを使ってHeadless Chromeを起動した際に生成されるプロセスとそのプロセスに設定されるオプションです。
ブラウザの動作は奥が深いですが、なんとなく各プロセスの役割分担がオプション設定の内容を通してイメージできてきたように思います。

おまけ 各プロセス生成とSelenium::WebDriverのコードとの対応関係について

各プロセスとそれを生成しているSelenium::WebDriverのコードの対応関係を以下のようになっていると思われます。

PID %MEM RSS type codes
046 1.0 10664 chromedriver @driver = Selenium::WebDriver.for :chrome, options: options
055 9.2 93320 webdriver @driver = Selenium::WebDriver.for :chrome, options: options
063 4.2 43152 zygote @driver = Selenium::WebDriver.for :chrome, options: options
065 1.0 11088 zygote @driver = Selenium::WebDriver.for :chrome, options: options
084 5.4 54848 gpu-process @driver = Selenium::WebDriver.for :chrome, options: options
092 1.2 12712 broker @driver = Selenium::WebDriver.for :chrome, options: options
101 13.8 139744 renderer @driver.navigate.to "https://www.google.com/"

メモリ使用量はrendererが最も多く、次がwebdriverとなっていました。

余談

Headless Chromeを起動させる処理を繰り返しているうちにメモリエラーを起こしてサーバーがダウンしてしまい、メモリ容量を圧迫している原因を探っている過程で今回のオプション設定の調査を行いました。

メモリエラーの原因は@driver.quitが抜けていたという初歩的ミスでした。
Selenium::WebDriverを正常に終了させないまま繰り返しHeadless Chromeを起動していたため、上記のプロセスがひたすら重複して生成されてメモリを使いまくっていました。反省。

55
45
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
55
45