Selenium Grid 中的 CLI 选项

所有 Grid 组件配置的 CLI 选项的详细信息。

有不同的部分可用于配置 Grid。每个部分都有可以通过命令行参数配置的选项。

组件到部分映射的完整描述如下所示。

请注意,如果某个选项被修改或添加但尚未记录,则此文档可能已过时。如果您遇到这种情况,请查看“配置帮助”部分,并随时向我们发送拉取请求以更新此页面。

章节

独立中心节点分发器路由器会话会话队列
分发器
Docker
事件
日志记录
网络
节点
路由器
中继器
服务器
会话队列
会话

分发器

选项类型值/示例描述
--healthcheck-intervalint120健康检查将为所有节点运行的频率(以秒为单位)。这确保服务器可以成功 ping 所有节点。
--distributorurihttp://localhost:5553分发器的 URL。
--distributor-hoststringlocalhost分发器正在监听的主机。
--distributor-implementationstringorg.openqa.selenium.grid.distributor.local.LocalDistributor非默认分发器实现的完整类名
--distributor-portint5553分发器正在监听的端口。
--reject-unsupported-capsbooleanfalse如果 Grid 不支持请求的功能,则允许分发器立即拒绝请求。立即拒绝请求适用于不按需启动节点的 Grid 设置。
--slot-matcherstringorg.openqa.selenium.grid.data.DefaultSlotMatcher要使用的非默认插槽匹配器的完整类名。这用于确定节点是否可以支持特定会话。
--slot-selectorstringorg.openqa.selenium.grid.distributor.selector.DefaultSlotSelector非默认插槽选择器的完整类名。这用于在匹配节点后选择节点中的插槽。
--newsession-threadpool-sizeint24分发器使用固定大小的线程池来创建新会话,因为它从队列中消耗新的会话请求。这允许配置线程池的大小。默认值为可用处理器数量 * 3。注意:如果线程数远大于可用处理器,则并不总是会提高性能。大量的线程会导致更多的上下文切换,这是一种昂贵的操作。

Docker

选项类型值/示例描述
--docker-assets-pathstring/opt/selenium/assets将存储资产的绝对路径
--docker-string[]selenium/standalone-firefox:latest '{"browserName": "firefox"}'Docker 配置,将镜像名称映射到刻板印象功能(示例 `-D selenium/standalone-firefox:latest ‘{“browserName”: “firefox”}’)
--docker-devicesstring[]/dev/kvm:/dev/kvm向容器公开设备。每个设备映射声明都必须至少包含主机和容器中设备的路径,并用冒号分隔,如本示例所示:/device/path/in/host:/device/path/in/container
--docker-hoststringlocalhostDocker 守护程序正在运行的主机名
--docker-portint2375Docker 守护程序正在运行的端口
--docker-urlstringhttp://localhost:2375用于连接 Docker 守护程序的 URL
--docker-video-imagestringselenium/video:latest启用视频录制时要使用的 Docker 镜像
--docker-host-config-keysstring[]Dns DnsOptions DnsSearch ExtraHosts Binds指定应将哪些 docker 主机配置键传递给浏览器容器。可以在 Docker API 文档中找到密钥名称,或者通过运行 `docker inspect` 节点-docker 容器找到。

事件

选项类型值/示例描述
--bind-busbooleanfalse连接字符串应绑定还是连接。
如果为 true,则组件将绑定到事件总线(就像事件总线也将由组件启动一样,通常由分发器和中心启动)。
如果为 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 规范符合性。

节点

选项类型值/示例描述
--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(通常是中心或路由器的地址)
--heartbeat-periodint60节点将向分发器发送心跳事件以告知其节点已启动的频率(以秒为单位)。
--max-sessionsint8最大并发会话数。默认值为可用处理器数。
--override-max-sessionsbooleanfalse可用处理器数是建议的最大会话值(每个处理器 1 个浏览器会话)。将此标志设置为 true 允许覆盖建议的最大值。由于主机可能会耗尽资源,因此会话的稳定性和可靠性可能会受到影响。
--register-cycleint10节点将尝试首次向分发器注册自身的频率(以秒为单位)。
--register-periodint120节点将尝试首次向分发器注册的持续时间(以秒为单位)。在此期间完成后,节点将不再尝试注册。
--session-timeoutint300设 X 为会话超时时间,单位为秒。节点将自动终止在过去 X 秒内没有任何活动的会话。这将释放插槽以供其他测试使用。
--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:4444在 Hub 和 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 连接数。这将确保一个会话不会耗尽主机的连接限制。

中继器

选项类型值/示例描述
--service-urlstringhttp://localhost:4723用于连接支持 WebDriver 命令的服务(如 Appium 服务器或云服务)的 URL。
--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 配置文件提供这种类型的配置,以提高可读性。

路由器

选项类型值/示例描述
--passwordstringmyStrongPassword客户端必须用来连接到服务器的密码。必须同时设置此密码和用户名才能使用。
--usernamestringadmin客户端必须用来连接到服务器的用户名。必须同时设置此用户名和密码才能使用。
--sub-pathstringmy_company/selenium_gridHub/路由器/独立服务器上所有面向用户的路由都应考虑的子路径。
--disable-uibooleantrue禁用 Grid UI。

服务器

选项类型值/示例描述
--external-urlstringhttp://10.0.1.1:33333组件通常可用的外部 URL。当组件位于不同的网络并且涉及代理服务器时,在复杂的网络拓扑中非常有用。
--allow-corsbooleantrueSelenium 服务器是否应允许来自任何主机的 Web 浏览器连接
--hoststringlocalhost服务器 IP 或主机名:通常会自动确定。
--bind-hostbooleantrue服务器是否应绑定到主机地址/名称,或者仅使用它来“报告其可访问的 URL”。在复杂的网络拓扑中,当服务器无法使用当前 IP/主机名而是外部 IP 或主机名(例如在 Docker 容器内部)报告自身时,这很有帮助。
--https-certificatepath/path/to/cert.pem用于 https 的服务器证书。运行“java -jar selenium-server.jar info security”以获取更详细的信息
--https-private-keypath/path/to/key.pkcs8用于 https 的私钥。运行“java -jar selenium-server.jar info security”以获取更详细的信息
--max-threadsint24最大侦听器线程数。默认值为:(可用处理器)* 3。
--portint4444要监听的端口。没有默认值,因为此参数由不同的组件使用,例如,路由器/Hub/独立服务器将使用 4444,而节点将使用 5555。

会话队列

选项类型值/示例描述
--sessionqueueurihttp://localhost:1237会话队列服务器的地址。
-sessionqueue-hoststringlocalhost会话队列服务器正在监听的主机。
--sessionqueue-portint1234会话队列服务器正在监听的端口。
--session-request-timeoutint300超时时间(秒)。新的传入会话请求将添加到队列中。在队列中等待时间超过配置时间的请求将超时。
--session-retry-intervalint5重试间隔(秒)。如果所有插槽都忙,则在给定的间隔后重试新的会话请求。

会话

选项类型值/示例描述
--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

节点,最多 4 个会话,带有调试(详细)日志,端口为 7777,并且仅使用 Firefox 和 Edge

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

分发器,设置会话映射服务器 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
启动自定义 cap 设置为 true 的节点 A
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
启动自定义 cap 设置为 false 的节点 B
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://seleniumcn.cn");
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://seleniumcn.cn/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);
		}
	}


}