Selenium Grid 的 CLI 選項

所有 Grid 組件組態 CLI 選項的詳細資訊。

不同的章節可用於組態 Grid。每個章節都有可透過命令列引數組態的選項。

組件到章節對應的完整說明如下所示。

請注意,如果選項已修改或新增但尚未記錄,則此文件可能已過時。如果您遇到這種情況,請查看「組態說明」章節,並隨時向我們發送提取請求以更新此頁面。

章節

獨立模式HubNodeDistributorRouterSessionsSessionQueue
Distributor
Docker
Events
記錄
網路
Node
Router
Relay
Server
SessionQueue
Sessions

Distributor

選項類型值/範例描述
--healthcheck-intervalint120節點健康檢查的執行頻率(秒)。這可確保伺服器可以成功 ping 所有節點。
--distributorurihttp://localhost:5553Distributor 的 URL。
--distributor-hoststringlocalhostDistributor 正在監聽的主機。
--distributor-implementationstringorg.openqa.selenium.grid.distributor.local.LocalDistributor非預設 Distributor 實作的完整類別名稱
--distributor-portint5553Distributor 正在監聽的埠。
--reject-unsupported-capsbooleanfalse如果 Grid 不支援請求的功能,則允許 Distributor 立即拒絕請求。立即拒絕請求適用於不會按需啟動節點的 Grid 設定。
--slot-matcherstringorg.openqa.selenium.grid.data.DefaultSlotMatcher要使用的非預設 slot matcher 的完整類別名稱。這用於確定節點是否可以支援特定的會話。
--slot-selectorstringorg.openqa.selenium.grid.distributor.selector.DefaultSlotSelector非預設 slot selector 的完整類別名稱。這用於在節點匹配後選擇節點中的 slot。
--newsession-threadpool-sizeint24Distributor 使用固定大小的執行緒池來建立新會話,因為它會從佇列中消耗新的會話請求。這允許組態執行緒池的大小。預設值是可用處理器數量 * 3。注意:如果執行緒數量遠大於可用處理器,則不一定會提高效能。大量的執行緒會導致更多的上下文切換,這是一個昂貴的操作。

Docker

選項類型值/範例描述
--docker-assets-pathstring/opt/selenium/assets資產將儲存的絕對路徑
--docker-string[]selenium/standalone-firefox:latest '{"browserName": "firefox"}'Docker 組態,將映像名稱對應到 stereotype 功能 (範例 `-D selenium/standalone-firefox:latest ‘{“browserName”: “firefox”}’`)
--docker-devicesstring[]/dev/kvm:/dev/kvm將裝置暴露給容器。每個裝置映射聲明必須至少具有主機和容器中以冒號分隔的裝置路徑,如本例所示:/device/path/in/host:/device/path/in/container
--docker-hoststringlocalhost執行 Docker daemon 的主機名稱
--docker-portint2375Docker daemon 正在執行的埠
--docker-urlstringhttp://localhost:2375用於連線到 Docker daemon 的 URL
--docker-video-imagestringselenium/video:latest啟用錄影時要使用的 Docker 映像
--docker-host-config-keysstring[]Dns DnsOptions DnsSearch ExtraHosts Binds指定應將哪些 docker 主機組態金鑰傳遞給瀏覽器容器。金鑰名稱可以在 Docker API 文件中找到,或執行 docker inspect node-docker 容器。

Events

選項類型值/範例描述
--bind-busbooleanfalse連線字串應該是綁定還是連線。
如果為 true,組件將綁定到事件總線(如同事件總線也將由組件啟動,通常由 Distributor 和 Hub 啟動)。
如果為 false,組件將連線到事件總線。
--events-implementationstringorg.openqa.selenium.events.zeromq.ZeroMqEventBus非預設事件總線實作的完整類別名稱
--publish-eventsstringtcp://*:4442用於將事件發布到事件總線的連線字串
--subscribe-eventsstringtcp://*:4443用於從事件總線訂閱事件的連線字串

記錄

選項類型值/範例描述
--http-logsbooleanfalse啟用 http 日誌記錄。應啟用追蹤以記錄 http 日誌。
--log-encodingstringUTF-8日誌編碼
--logstringWindows 路徑範例
'\path\to\file\gridlog.log'

'C:\path\path\to\file\gridlog.log'

Linux/Unix/MacOS 路徑範例
'/path/to/file/gridlog.log'
用於寫出日誌的檔案。確保檔案路徑與作業系統的檔案路徑相容。
--log-levelstring“INFO”日誌級別。預設日誌級別為 INFO。日誌級別在此處描述 https://docs.oracle.com/javase/7/docs/api/java/util/logging/Level.html
--plain-logsbooleantrue使用純文字日誌行
--structured-logsbooleanfalse使用結構化日誌
--tracingbooleantrue啟用追蹤收集
--log-timestamp-formatstringHH:mm:ss.SSS允許組態日誌時間戳記格式

網路

選項類型值/範例描述
--relax-checksbooleanfalse放寬對傳入請求的來源標頭和內容類型的檢查,違反嚴格的 W3C 規範合規性。

Node

選項類型值/範例描述
--detect-driversbooleantrue自動偵測目前系統上可用的驅動程式,並將其新增至節點。
--driver-configurationstring[]display-name="Firefox Nightly" max-sessions=2 webdriver-path="/usr/local/bin/geckodriver" stereotype="{\"browserName\": \"firefox\", \"browserVersion\": \"86\", \"moz:firefoxOptions\": {\"binary\":\"/Applications/Firefox Nightly.app/Contents/MacOS/firefox-bin\"}}"節點支援的已組態驅動程式列表。建議透過 toml 組態檔案提供此類組態,以提高可讀性
--driver-factorystring[]org.openqa.selenium.example.LynxDriverFactory '{"browserName": "lynx"}'完整類別名稱到此名稱符合的瀏覽器組態的映射。
--driver-implementationstring[]"firefox"應檢查的驅動程式。如果指定,將跳過自動組態。
--node-implementationstring"org.openqa.selenium.grid.node.local.LocalNodeFactory"非預設節點實作的完整類別名稱。這用於管理會話的生命週期。
--grid-urlstringhttps://grid.example.com整個 Grid 的公用 URL(通常是 Hub 或 Router 的位址)
--heartbeat-periodint60節點向 Distributor 發送心跳事件以告知其節點已啟動的頻率(秒)。
--max-sessionsint8並行會話的最大數量。預設值是可用處理器的數量。
--override-max-sessionsbooleanfalse可用處理器的數量是建議的最大會話值(每個處理器 1 個瀏覽器會話)。將此標記設定為 true 可覆寫建議的最大值。由於主機可能會耗盡資源,因此會話穩定性和可靠性可能會受到影響。
--register-cycleint10節點首次嘗試向 Distributor 註冊自身的頻率(秒)。
--register-periodint120節點首次嘗試向 Distributor 註冊的時間長度(秒)。在此期間完成後,節點將不會再次嘗試註冊。
--session-timeoutint300令 X 為會話逾時時間(秒)。節點將自動終止在過去 X 秒內沒有任何活動的會話。這將釋放 slot 以用於其他測試。
--vnc-env-varstring[]SE_START_XVFB SE_START_VNC SE_START_NO_VNC要檢查的環境變數,以確定 vnc 串流是否可用。
--no-vnc-portint7900如果 VNC 可用,則設定可取得本機 noVNC 串流的埠
--drain-after-session-countint1在執行 X 個會話後,排空並關閉節點。適用於 Kubernetes 等環境。大於零的值啟用此功能。
--hubstringhttp://localhost:4444Hub-and-Node 組態中 Hub 的位址。可以是主機名稱或 IP 位址 (hostname),在這種情況下,Hub 將假定為 http://hostname:4444--grid-url 將相同,--publish-events 將為 tcp://hostname:4442,而 --subscribe-events 將為 tcp://hostname:4443。如果 hostname 包含埠號,則該埠號將用於 --grid-url,但事件總線的 URI 將保持不變。任何這些預設值都可以被覆寫,但需要設定正確的標記。如果主機名稱具有協定(例如 https),也將使用該協定。
--enable-cdpbooleantrue在 Grid 中啟用 CDP 代理。如果網路不允許 websocket,Grid 管理員可以停用 CDP。預設為 True。
--enable-managed-downloadsbooleanfalse這會導致節點自動管理在節點上為給定會話下載的檔案。
--selenium-managerbooleanfalse當驅動程式在目前系統上不可用時,請使用 Selenium Manager。預設為 False。
--connection-limit-per-sessionint10令 X 為每個會話的最大 websocket 連線數。這將確保一個會話無法耗盡主機的連線限制。

Relay

選項類型值/範例描述
--service-urlstringhttp://localhost:4723用於連線到支援 WebDriver 命令的服務的 URL,例如 Appium 伺服器或雲端服務。
--service-hoststringlocalhost支援 WebDriver 命令的服務正在執行的主機名稱
--service-portint4723支援 WebDriver 命令的服務正在執行的埠
--service-status-endpointstring/status選用,用於查詢 WebDriver 服務狀態的端點,預期會收到 HTTP 200 回應
--service-protocol-versionstringHTTP/1.1選用,在與端點服務狀態通訊時,在 HttpClient 中強制執行特定的協定版本
--service-configurationstring[]max-sessions=2 stereotype='{"browserName": "safari", "platformName": "iOS", "appium:platformVersion": "14.5"}}'將呼叫轉發到的服務的組態。建議透過 toml 組態檔案提供此類組態,以提高可讀性。

Router

選項類型值/範例描述
--passwordstringmyStrongPassword用戶端必須用於連線到伺服器的密碼。必須同時設定此密碼和使用者名稱才能使用。
--usernamestringadmin用戶端必須用於連線到伺服器的使用者名稱。必須同時設定此名稱和密碼才能使用。
--sub-pathstringmy_company/selenium_grid應針對 Hub/Router/Standalone 上的所有面向使用者的路由考慮的子路徑。
--disable-uibooleantrue停用 Grid UI。

Server

選項類型值/範例描述
--external-urlstringhttp://10.0.1.1:33333組件通常可用的外部 URL。在組件位於不同網路且涉及代理伺服器的複雜網路拓撲中很有用。
--allow-corsbooleantrueSelenium 伺服器是否應允許來自任何主機的 Web 瀏覽器連線
--hoststringlocalhost伺服器 IP 或主機名稱:通常自動確定。
--bind-hostbooleantrue伺服器是否應綁定到主機位址/名稱,還是僅使用它來報告其可連線的 URL。在伺服器無法使用目前的 IP/主機名稱報告自身,而是外部 IP 或主機名稱(例如,在 Docker 容器內)的複雜網路拓撲中很有用
--https-certificatepath/path/to/cert.pemhttps 的伺服器憑證。執行 "java -jar selenium-server.jar info security" 以取得更詳細的資訊
--https-private-keypath/path/to/key.pkcs8https 的私密金鑰。執行 "java -jar selenium-server.jar info security" 以取得更詳細的資訊
--max-threadsint24監聽器執行緒的最大數量。預設值為:(可用處理器) * 3。
--portint4444要監聽的埠。沒有預設值,因為此參數由不同的組件使用,例如,Router/Hub/Standalone 將使用 4444,而 Node 將使用 5555。

SessionQueue

選項類型值/範例描述
--sessionqueueurihttp://localhost:1237會話佇列伺服器的位址。
-sessionqueue-hoststringlocalhost會話佇列伺服器正在監聽的主機。
--sessionqueue-portint1234會話佇列伺服器正在監聽的埠。
--session-request-timeoutint300逾時時間(秒)。新的傳入會話請求會新增到佇列。在佇列中等待時間超過組態時間的請求將會逾時。
--session-retry-intervalint5重試間隔(秒)。如果所有 slot 都忙碌,則會在給定間隔後重試新的會話請求。

Sessions

選項類型值/範例描述
--sessionsurihttp://localhost:1234會話映射伺服器的位址。
--sessions-hoststringlocalhost會話映射伺服器正在監聽的主機。
--sessions-portint1234會話映射伺服器正在監聽的埠。

組態範例

上述所有選項都可以在啟動 Grid 組件時使用。它們是探索 Grid 選項和嘗試尋找合適組態的值的好方法。

我們建議使用 Toml 檔案來組態 Grid。組態檔案提高了可讀性,您也可以在原始碼控制中檢查它們。

在需要時,您可以將 Toml 檔案組態與 CLI 引數結合使用。

命令列標記

若要以命令列標記傳遞組態選項,請識別組件的有效選項,並遵循以下範本。

java -jar selenium-server-<version>.jar <component> --<option> value

獨立模式,設定最大會話數和主埠

java -jar selenium-server-<version>.jar standalone --max-sessions 4 --port 4444

Hub,設定新的會話請求逾時時間、主埠,並停用追蹤

java -jar selenium-server-<version>.jar hub --session-request-timeout 500 --port 3333 --tracing false

Node,具有 4 個最大會話數、具有 debug(fine) 日誌、7777 作為埠,並且僅具有 Firefox 和 Edge

java -jar selenium-server-<version>.jar node --max-sessions 4 --log-level "fine" --port 7777 --driver-implementation "firefox" --driver-implementation "edge"

Distributor,設定會話映射伺服器 URL、會話佇列伺服器 URL,並停用總線

java -jar selenium-server-<version>.jar distributor --sessions http://localhost:5556 --sessionqueue http://localhost:5559 --bind-bus false

設定自訂功能以匹配特定節點

重要提示: 自訂功能需要在所有節點的組態中設定。它們也需要始終包含在每個會話請求中。

啟動 Hub
java -jar selenium-server-<version>.jar hub
啟動節點 A,其中自訂功能設定為 true
java -jar selenium-server-<version>.jar node --detect-drivers false --driver-configuration display-name="Chrome (custom capability true)" max-sessions=1 stereotype='{"browserName":"chrome","gsg:customcap":true}' --port 6161
啟動節點 B,其中自訂功能設定為 false
java -jar selenium-server-<version>.jar node --detect-drivers false --driver-configuration display-name="Chrome (custom capability true)" max-sessions=1 stereotype='{"browserName":"chrome","gsg:customcap":false}' --port 6262
匹配節點 A
ChromeOptions options = new ChromeOptions();
options.setCapability("gsg:customcap", true);
WebDriver driver = new RemoteWebDriver(new URL("http://localhost:4444"), options);
driver.get("https://selenium.dev.org.tw");
driver.quit();

將自訂功能設定為 false 以匹配節點 B。

啟用節點管理的下載

有時測試可能需要存取由其在節點上下載的檔案。若要檢索此類檔案,可以執行以下操作。

啟動 Hub
java -jar selenium-server-<version>.jar hub
啟動啟用管理下載的節點
java -jar selenium-server-<version>.jar node --enable-managed-downloads true
在測試層級設定功能

想要使用此功能的測試應將功能 "se:downloadsEnabled" 設定為 true

options.setCapability("se:downloadsEnabled", true);
這如何運作
  • Grid 基礎架構將嘗試將具有 "se:downloadsEnabled" 的會話請求與僅使用 --enable-managed-downloads true 啟動的節點進行匹配
  • 如果會話匹配,則節點會自動設定所需的功能,以讓瀏覽器知道檔案應下載到何處。
  • 節點現在允許使用者執行以下操作
    • 列出特定會話下載的所有檔案,以及
    • 從檔案列表中檢索特定檔案。
  • 當會話結束(或)由於不活動而逾時時,會自動清除檔案下載到特定會話的目錄。

注意:目前此功能僅在以下瀏覽器上受支援

  • Edge
  • Firefox
  • Chrome 瀏覽器
列出可以為當前會話下載的檔案
  • GET 的端點是 /session/<sessionId>/se/files
  • 會話需要處於活動狀態,命令才能運作。
  • 原始回應如下所示
{
  "value": {
    "names": [
      "Red-blue-green-channel.jpg"
    ]
  }
}

在回應中,檔案名稱列表會出現在金鑰 names 下。

下載檔案
  • 要從中 POST 的端點是 /session/<sessionId>/se/files,其有效負載形式為 {"name": "fileNameGoesHere}
  • 會話需要處於活動狀態,命令才能運作。
  • 原始回應如下所示
{
	"value": {
		"filename": "Red-blue-green-channel.jpg",
		"contents": "Base64EncodedStringContentsOfDownloadedFileAsZipGoesHere"
	}
}
  • 回應 blob 包含兩個金鑰,
    • filename - 已下載的檔案名稱。
    • contents - Base64 編碼的檔案壓縮內容。
  • 檔案內容是 Base64 編碼的,需要解壓縮。
列出可以下載的檔案

以下提及的 curl 範例可用於列出目前會話在節點中下載的所有檔案,這些檔案可以在本機檢索。

curl -X GET "http://localhost:4444/session/90c0149a-2e75-424d-857a-e78734943d4c/se/files"

範例回應如下所示

{
  "value": {
    "names": [
      "Red-blue-green-channel.jpg"
    ]
  }
}
檢索已下載的檔案

假設下載的檔案名為 Red-blue-green-channel.jpg,並使用 curl,可以使用以下命令下載檔案

curl -H "Accept: application/json" \
-H "Content-Type: application/json; charset=utf-8" \
-X POST -d '{"name":"Red-blue-green-channel.jpg"}' \
"http://localhost:4444/session/18033434-fa4f-4d11-a7df-9e6d75920e19/se/files"

範例回應如下所示

{
  "value": {
    "filename": "Red-blue-green-channel.jpg",
    "contents": "UEsDBBQACAgIAJpagVYAAAAAAAAAAAAAAAAaAAAAUmVkLWJsAAAAAAAAAAAAUmVkLWJsdWUtZ3JlZW4tY2hhbm5lbC5qcGdQSwUGAAAAAAEAAQBIAAAAcNkAAAAA"
  }
}
Java 中的完整範例程式碼

以下是 Java 中的範例,它執行以下操作

  • 設定功能以指示測試需要自動管理下載的檔案。
  • 透過瀏覽器觸發檔案下載。
  • 列出可從遠端節點檢索的檔案(這些基本上是在目前會話中下載的檔案)
  • 選取一個檔案,並將檔案從遠端節點下載到本機電腦。
import com.google.common.collect.ImmutableMap;

import org.openqa.selenium.By;
import org.openqa.selenium.io.Zip;
import org.openqa.selenium.json.Json;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.remote.http.HttpClient;
import org.openqa.selenium.remote.http.HttpRequest;
import org.openqa.selenium.remote.http.HttpResponse;

import java.io.File;
import java.net.URL;
import java.nio.file.Files;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

import static org.openqa.selenium.remote.http.Contents.asJson;
import static org.openqa.selenium.remote.http.Contents.string;
import static org.openqa.selenium.remote.http.HttpMethod.GET;
import static org.openqa.selenium.remote.http.HttpMethod.POST;

public class DownloadsSample {

  public static void main(String[] args) throws Exception {
    // Assuming the Grid is running locally.
    URL gridUrl = new URL("http://localhost:4444");
    ChromeOptions options = new ChromeOptions();
    options.setCapability("se:downloadsEnabled", true);
    RemoteWebDriver driver = new RemoteWebDriver(gridUrl, options);
    try {
      demoFileDownloads(driver, gridUrl);
    } finally {
      driver.quit();
    }
  }

	private static void demoFileDownloads(RemoteWebDriver driver, URL gridUrl) throws Exception {
		driver.get("https://selenium.dev.org.tw/selenium/web/downloads/download.html");
		// Download the two available files on the page
		driver.findElement(By.id("file-1")).click();
		driver.findElement(By.id("file-2")).click();

		// The download happens in a remote Node, which makes it difficult to know when the file
		// has been completely downloaded. For demonstration purposes, this example uses a
		// 10-second sleep which should be enough time for a file to be downloaded.
		// We strongly recommend to avoid hardcoded sleeps, and ideally, to modify your
		// application under test, so it offers a way to know when the file has been completely
		// downloaded.
		TimeUnit.SECONDS.sleep(10);

		//This is the endpoint which will provide us with list of files to download and also to
		//let us download a specific file.
		String downloadsEndpoint = String.format("/session/%s/se/files", driver.getSessionId());

		String fileToDownload;

		try (HttpClient client = HttpClient.Factory.createDefault().createClient(gridUrl)) {
			// To list all files that are were downloaded on the remote node for the current session
			// we trigger GET request.
			HttpRequest request = new HttpRequest(GET, downloadsEndpoint);
			HttpResponse response = client.execute(request);
			Map<String, Object> jsonResponse = new Json().toType(string(response), Json.MAP_TYPE);
			@SuppressWarnings("unchecked")
			Map<String, Object> value = (Map<String, Object>) jsonResponse.get("value");
			@SuppressWarnings("unchecked")
			List<String> names = (List<String>) value.get("names");
			// Let's say there were "n" files downloaded for the current session, we would like
			// to retrieve ONLY the first file.
			fileToDownload = names.get(0);
		}

		// Now, let's download the file
		try (HttpClient client = HttpClient.Factory.createDefault().createClient(gridUrl)) {
			// To retrieve a specific file from one or more files that were downloaded by the current session
			// on a remote node, we use a POST request.
			HttpRequest request = new HttpRequest(POST, downloadsEndpoint);
			request.setContent(asJson(ImmutableMap.of("name", fileToDownload)));
			HttpResponse response = client.execute(request);
			Map<String, Object> jsonResponse = new Json().toType(string(response), Json.MAP_TYPE);
			@SuppressWarnings("unchecked")
			Map<String, Object> value = (Map<String, Object>) jsonResponse.get("value");
			// The returned map would contain 2 keys,
			// filename - This represents the name of the file (same as what was provided by the test)
			// contents - Base64 encoded String which contains the zipped file.
			String zippedContents = value.get("contents").toString();
			// The file contents would always be a zip file and has to be unzipped.
			File downloadDir = Zip.unzipToTempDir(zippedContents, "download", "");
			// Read the file contents
			File downloadedFile = Optional.ofNullable(downloadDir.listFiles()).orElse(new File[]{})[0];
			String fileContent = String.join("", Files.readAllLines(downloadedFile.toPath()));
			System.out.println("The file which was "
					+ "downloaded in the node is now available in the directory: "
					+ downloadDir.getAbsolutePath() + " and has the contents: " + fileContent);
		}
	}


}