Nagios集成Selenium

Nagios與Selenium結合可以執行更復雜的頁面檢查,檢測網站運行狀態、任務運行情況等。

Nagios集成Selenium步驟:

  1. 編寫一個用來調用測試用例的Java Main函數
  2. 編寫運行測試用例的shell腳本check_selenium.sh
  3. 定義Nagios Command和Service

Java測試程序

說明:Java Main函數使用了https://github.com/czunker/check_selenium 的CallSeleniumTest類,略作修改。
完整源碼可從GitHub下載。

POM

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.itrunner</groupId>
    <artifactId>nagios-selenium</artifactId>
    <version>1.0</version>
    <packaging>jar</packaging>

    <properties>
        <project.encoding>UTF-8</project.encoding>
        <jdk.version>1.8</jdk.version>
        <selenium.version>3.141.5</selenium.version>
    </properties>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-clean-plugin</artifactId>
                <version>3.1.0</version>
            </plugin>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <source>${jdk.version}</source>
                    <target>${jdk.version}</target>
                    <encoding>${project.encoding}</encoding>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-resources-plugin</artifactId>
                <version>3.1.0</version>
                <configuration>
                    <encoding>${project.encoding}</encoding>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.1.0</version>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>org.itrunner.tests.CallSeleniumTest</mainClass>
                            <addClasspath>true</addClasspath>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>3.1.0</version>
                <configuration>
                    <descriptors>
                        <descriptor>src/assembly/assembly.xml</descriptor>
                    </descriptors>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.sonarsource.scanner.maven</groupId>
                <artifactId>sonar-maven-plugin</artifactId>
                <version>3.5.0.1254</version>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-firefox-driver</artifactId>
            <version>${selenium.version}</version>
        </dependency>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-chrome-driver</artifactId>
            <version>${selenium.version}</version>
        </dependency>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-support</artifactId>
            <version>${selenium.version}</version>
        </dependency>
        <dependency>
            <groupId>com.codeborne</groupId>
            <artifactId>phantomjsdriver</artifactId>
            <version>1.4.4</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <dependency>
            <groupId>commons-cli</groupId>
            <artifactId>commons-cli</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
    </dependencies>
</project>

測試調用類

調用測試的入口類。
CallSeleniumTest

package org.itrunner.tests;

import org.apache.commons.cli.*;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.firefox.NotConnectedException;

public class CallSeleniumTest {
    private static int timeout = 30;

    private static final int NAGIOS_OK = 0;
    private static final int NAGIOS_WARNING = 1;
    private static final int NAGIOS_CRITICAL = 2;
    private static final int NAGIOS_UNKNOWN = 3;

    private static final String NAGIOS_TEXT_OK = "OK";
    private static final String NAGIOS_TEXT_WARNING = "WARNING";
    private static final String NAGIOS_TEXT_CRITICAL = "CRITICAL";
    private static final String NAGIOS_TEXT_UNKNOWN = "UNKNOWN";

    private Options options = null;

    private TestResult runTest(String className) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        Class<TestBase> seleniumTestClass = (Class<TestBase>) Class.forName(className);
        return seleniumTestClass.newInstance().run();
    }

    public static void main(String[] args) {
        CallSeleniumTest seTest = new CallSeleniumTest();

        Option optionClass = new Option("c", "class", true, "full classname of test case (required) e.g. \"org.itrunner.tests.hosts.Baidu\"");
        Option optionTimeout = new Option("t", "timeout", true, "timeout, default is 30");
        Option optionVerbose = new Option("v", "verbose", false, "show a lot of information (useful in case of problems)");
        Option optionHelp = new Option("h", "help", false, "show this help screen");

        seTest.options = new Options();
        seTest.options.addOption(optionClass);
        seTest.options.addOption(optionTimeout);
        seTest.options.addOption(optionVerbose);
        seTest.options.addOption(optionHelp);

        CommandLineParser parser = new DefaultParser();
        CommandLine cmd = null;

        String output = NAGIOS_TEXT_UNKNOWN + " - Upps";
        int nagios = NAGIOS_UNKNOWN;

        try {
            cmd = parser.parse(seTest.options, args);
            // has to be checked manually, otherwise you can't access the help message without specifying correct parameters
            if (cmd.hasOption("h") || !cmd.hasOption("c")) {
                usage(seTest.options);
                System.exit(nagios); //NOSONAR
            }

            if (cmd.hasOption("t")) {
                timeout = Integer.parseInt(cmd.getOptionValue("t"));
            }

            TestResult result = seTest.runTest(cmd.getOptionValue("c"));
            output = NAGIOS_TEXT_OK + " - " + cmd.getOptionValue("c") + " Tests passed - " + result.toString();
            nagios = NAGIOS_OK;

        } catch (ParseException e) {
            output = NAGIOS_TEXT_UNKNOWN + " - Parameter problems: " + e.getMessage();
            nagios = NAGIOS_UNKNOWN;
            usage(seTest.options);
        } catch (ClassNotFoundException e) {
            output = NAGIOS_TEXT_UNKNOWN + " - Test case class: " + e.getMessage() + " not found!";
            nagios = NAGIOS_UNKNOWN;
        } catch (TimeoutException | CriticalException e) {
            output = NAGIOS_TEXT_CRITICAL + " - Test Failures: " + e.getMessage();
            nagios = NAGIOS_CRITICAL;
        } catch (Exception e) {
            output = NAGIOS_TEXT_WARNING + " - Test Failures: " + processException(cmd, e);
            nagios = NAGIOS_WARNING;
        } finally {
            println(output);
            System.exit(nagios); //NOSONAR
        }
    }

    private static String processException(CommandLine cmd, Exception e) {
        if (cmd != null && cmd.hasOption("v")) {
            e.printStackTrace(); //NOSONAR
        }

        if (isCausedBy(e, NotConnectedException.class)) {
            return "Failed to connect to binary FirefoxBinary";
        }

        return e.getMessage();
    }

    private static void usage(Options options) {
        HelpFormatter formatter = new HelpFormatter();
        formatter.printHelp("check_selenium", options);
        println("This version of check_selenium was tested with:");
        println("  - selenium 3.14.0");
        println("  - selenium ide 3.3.1");
        println("  - test case exported as Java / JUnit 4 / WebDriver");
        println("Some example calls:");
        println(" ./check_selenium.sh -c \"org.itrunner.tests.hosts.Baidu\"");
        println(" ./check_selenium.sh --class \"org.itrunner.tests.hosts.Baidu\"");
    }

    public static int getTimeout() {
        return timeout;
    }

    private static void println(String x) {
        System.out.println(x); //NOSONAR
    }

    private static <T extends Throwable> boolean isCausedBy(final Throwable exception, Class<T> clazz) {
        Throwable cause = exception;
        while (cause != null) {
            if (clazz.isInstance(cause)) {
                return true;
            }
            cause = cause.getCause();
        }
        return false;
    }
}

Shell腳本

check_selenium.sh

#!/bin/bash

JAVA_HOME=/opt/java/jdk1.8.0_191

$JAVA_HOME/bin/java -Djava.util.logging.config.file=logging.properties -jar $(dirname $0)/lib/nagios-selenium-1.0.jar $@

基礎配置

config.ini

# drive type - chrome, firefox or phantomjs
driver.type=chrome
log.file=chrome.log
log.level=FATAL
chrome.driver=/home/nagios/chrome/chromedriver
gecko.driver=/home/nagios/gecko/geckodriver
phantomjs.binary.path=/home/nagios/phantomjs/bin/phantomjs
phantomjs.ghostdriver.path=/home/nagios/ghostdriver-master/src/main.js

proxy.host=

baidu.url=https://www.baidu.com
[email protected]
baidu.password=xxxxxx

Config

import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;

public enum Config {
    CONFIG;

    private static final String FILE_NAME = "config.ini";

    private Properties properties;

    Config() {
        properties = new Properties();
        try {
            properties.load(new FileReader(CommonUtil.getJarPath() + FILE_NAME));
        } catch (IOException e) { //NOSONAR
            e.printStackTrace(); //NOSONAR
        }
    }

    public String getDriverType() {
        return getProperty("driver.type");
    }

    public String getLogFile() {
        return getProperty("log.file");
    }

    public String getLogLevel() {
        return getProperty("log.level");
    }

    public String getChromeDriver() {
        return getProperty("chrome.driver");
    }

    public String getGeckoDriver() {
        return getProperty("gecko.driver");
    }

    public String getPhantomJsBinaryPath() {
        return getProperty("phantomjs.binary.path");
    }

    public String getPhantomJsGhostDriverPath() {
        return getProperty("phantomjs.ghostdriver.path");
    }

    public String getProxyHost() {
        return getProperty("proxy.host");
    }

    public String getBaiduUrl() {
        return getProperty("baidu.url");
    }

    public String getBaiduUsername() {
        return getProperty("baidu.username");
    }

    public String getBaiduPassword() {
        return getProperty("baidu.password");
    }

    public String getProperty(String key) {
        return properties.getProperty(key);
    }

}

測試用例

在nagios中運行Selenium測試時,爲避免浪費資源,提高性能,一般不使用圖形界面。
Selenium支持的Headless Web Driver:

  • HtmlUnitDriver

輕量級的Web Driver實現,基於HtmlUnit,純Java、支持JavScript。HtmlUnit可以模擬Chrome、Firefox或IE瀏覽器,默認爲Chrome。HtmlUnit使用了JavaScript引擎Rhino,主流瀏覽器沒有采用Rhino的,測試時可能會有JavaScript兼容性問題。

<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>htmlunit-driver</artifactId>
    <version>2.33.1</version>
</dependency>
public static WebDriver createHtmlUnitDriver() {
    HtmlUnitDriver htmlUnitDriver = new HtmlUnitDriver(true);
    if (hasProxy()) {
        htmlUnitDriver.setProxySettings(getProxy());
    }
    return htmlUnitDriver;
}
  • PhantomJSDriver

基於Headless Browser PhantomJS,對JavaScript的支持好,常用於網絡監控,但PhantomJS項目現已暫停,selenium 3.8.1以後不再支持。
使用PhantomJSDriver時,需下載PhantomJS執行文件源碼,配置“phantomjs.binary.path”和“phantomjs.ghostdriver.path”。

  • FirefoxDriver

啓用Headless模式:

FirefoxOptions options = new FirefoxOptions();
options.setHeadless(true);

Selenium 3 FirefoxDriver提供兩種DriverService:GeckoDriverService和XpiDriverService,默認使用GeckoDriverService,需安裝firefox,下載geckodriver,配置GeckoDriver路徑。
FirefoxDriver與Nagios集成,若Driver沒有正常執行quit(),會造成大量進程不能終止,臨時目錄堆積大量profile文件。

  • ChromeDriver

啓用Headless模式:

ChromeOptions options = new ChromeOptions();
options.setHeadless(true);

使用ChromeDriver,需安裝Chrome,下載ChromeDriver,配置ChromeDriver路徑。
DriverFactory
創建ChromeDriver、FirefoxDriver或PhantomJSDriver。

package org.itrunner.tests;

import org.openqa.selenium.Proxy;
import org.openqa.selenium.chrome.ChromeDriverService;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.firefox.FirefoxDriverLogLevel;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.firefox.GeckoDriverService;
import org.openqa.selenium.phantomjs.PhantomJSDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.remote.service.DriverService;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import static org.itrunner.tests.utils.Config.CONFIG;
import static org.openqa.selenium.phantomjs.PhantomJSDriverService.*;

public class DriverFactory {
    private static DriverService service;
    private static RemoteWebDriver driver;

    private DriverFactory() {
    }

    public static RemoteWebDriver createDriver() {
        String driverType = CONFIG.getDriverType();

        if (driverType.equals("phantomjs")) {
            return createPhantomJSDriver();
        }

        if (driverType.equals("firefox")) {
            return createFirefoxDriver();
        }

        return createChromeDriver();
    }

    public static RemoteWebDriver createChromeDriver() {
        try {
            service = new ChromeDriverService.Builder()
                    .usingDriverExecutable(new File(CONFIG.getChromeDriver()))
                    .usingAnyFreePort()
                    .withSilent(true)
                    .withVerbose(false)
                    .withLogFile(new File(CONFIG.getLogFile()))
                    .build();
            service.start();

            ChromeOptions options = new ChromeOptions();
            options.setHeadless(true);

            if (hasProxy()) {
                options.setProxy(getProxy());
            }

            driver = new RemoteWebDriver(service.getUrl(), options);
        } catch (Exception e) {
            // do nothing
        }
        return driver;
    }

    public static RemoteWebDriver createFirefoxDriver() {
        try {
            service = new GeckoDriverService.Builder()
                    .usingDriverExecutable(new File(CONFIG.getGeckoDriver()))
                    .usingAnyFreePort()
                    .withLogFile(new File(CONFIG.getLogFile()))
                    .build();
            service.start();

            FirefoxOptions options = new FirefoxOptions();
            options.setHeadless(true);
            options.setLogLevel(FirefoxDriverLogLevel.fromString(CONFIG.getLogLevel()));

            if (hasProxy()) {
                options.setProxy(getProxy());
            }

            driver = new RemoteWebDriver(service.getUrl(), options);
        } catch (Exception e) {
            // do nothing
        }
        return driver;
    }

    public static RemoteWebDriver createPhantomJSDriver() {
        DesiredCapabilities capabilities = new DesiredCapabilities();
        capabilities.setJavascriptEnabled(true);
        capabilities.setCapability(PHANTOMJS_EXECUTABLE_PATH_PROPERTY, CONFIG.getPhantomJsBinaryPath());
        capabilities.setCapability(PHANTOMJS_GHOSTDRIVER_PATH_PROPERTY, CONFIG.getPhantomJsGhostDriverPath());

        List<String> cliArgs = new ArrayList<>();
        cliArgs.add("--web-security=false");
        cliArgs.add("--ssl-protocol=any");
        cliArgs.add("--ignore-ssl-errors=true");
        capabilities.setCapability(PHANTOMJS_CLI_ARGS, cliArgs);

        // Control LogLevel for GhostDriver, via CLI arguments
        String[] ghostDriverCliArgs = {"--logFile=" + CONFIG.getLogFile(), "--logLevel=" + CONFIG.getLogLevel()};
        capabilities.setCapability(PHANTOMJS_GHOSTDRIVER_CLI_ARGS, ghostDriverCliArgs);
        if (hasProxy()) {
            capabilities.setCapability("proxy", getProxy());
        }
        driver = new PhantomJSDriver(capabilities);
        return driver;
    }

    public static void quit() {
        if (driver != null) {
            driver.quit();
        }
        if (service != null) {
            service.stop();
        }
        driver = null;
        service = null;
    }

    private static Proxy getProxy() {
        Proxy proxy = new Proxy();
        proxy.setHttpProxy(CONFIG.getProxyHost());
        return proxy;
    }

    private static boolean hasProxy() {
        return CONFIG.getProxyHost() != null && !CONFIG.getProxyHost().equals("");
    }
}

說明:

  1. 使用DriverService + RemoteWebDriver方式創建FirefoxDriver和ChromeDriver,退出時分別執行driver.quit()和service.stop(),這樣可以避免單獨使用driver.quit()時不能正常退出的問題。爲了提高性能,也可以通過shell啓動DriverService。
  2. 要禁用firefox日誌,設置logfile路徑爲/dev/null
  3. 如未配置phantomjs.ghostdriver.path,則使用PhantomJS內部的GhostDriver。
  4. 如配置PhantomJS logLevel,必須設置phantomjs.ghostdriver.path才能啓作用。

TestBase
測試基類

package org.itrunner.tests;

import org.apache.commons.io.FileUtils;
import org.junit.After;
import org.junit.Before;
import org.openqa.selenium.By;
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;

import static java.lang.System.currentTimeMillis;
import static org.openqa.selenium.OutputType.BYTES;
import static org.openqa.selenium.support.ui.ExpectedConditions.titleIs;
import static org.openqa.selenium.support.ui.ExpectedConditions.visibilityOfElementLocated;

public abstract class TestBase {
    protected RemoteWebDriver driver;

    private long startTime;

    private TestResult result = new TestResult();

    @Before
    public void setup() {
        startTime = currentTimeMillis();
        nextStep(this::createDriver, "init");
        setTimeout();
        addShutdownHook();
    }

    TestResult run() {
        setup();
        test();
        tearDown();
        setTotalTime();
        return result;
    }

    @After
    public void tearDown() {
        nextStep(() -> DriverFactory.quit(), "destroy");
    }

    private void createDriver() {
        driver = DriverFactory.createDriver();
    }

    public abstract void test();

    protected void savePageSource(String host) {
        try {
            File sourceFile = new File("reports/" + host + ".html");
            FileUtils.writeStringToFile(sourceFile, driver.getPageSource(), Charset.defaultCharset());
        } catch (IOException e) { //NOSONAR
            // do nothing
        }
    }

    protected void takeScreenshot(String host) {
        File imageFile = new File("reports/" + host + ".png");
        try {
            FileUtils.writeByteArrayToFile(imageFile, driver.getScreenshotAs(BYTES));
        } catch (IOException e) { //NOSONAR
            // do nothing
        }
    }

    protected void nextStep(TestStep step, String stepName) {
        long beginTime = currentTimeMillis();

        try {
            step.run();
        } catch (TimeoutException | NoSuchElementException e) {
            throw new CriticalException(stepName + " failed: " + e.getMessage(), e);
        }

        result.putStepTime(stepName, currentTimeMillis() - beginTime);
    }

    public boolean isElementPresent(By by) {
        try {
            return waitForElementPresent(by);
        } catch (TimeoutException e) { //NOSONAR
            return false;
        }
    }

    protected void open(final String url) {
        nextStep(() -> driver.get(url), "loading page");
    }

    public void click(final By by, String stepName) {
        nextStep(() -> driver.findElement(by).click(), stepName);
    }

    protected void waitForTitlePresent(final String title) {
        nextStep(() -> waitForCondition(titleIs(title)), "finding title");
    }

    private boolean waitForElementPresent(By by) {
        return waitForCondition(visibilityOfElementLocated(by)).isDisplayed();
    }

    private <T> T waitForCondition(ExpectedCondition<T> condition) {
        return (new WebDriverWait(driver, CallSeleniumTest.getTimeout())).until(condition);
    }

    private void setTimeout() {
        driver.manage().timeouts().implicitlyWait(CallSeleniumTest.getTimeout(), TimeUnit.SECONDS);
    }

    private void setTotalTime() {
        result.setTotalTime(currentTimeMillis() - startTime);
    }

    private void addShutdownHook() {
        Runtime.getRuntime().addShutdownHook(new Thread("Selenium Quit Hook") {
            @Override
            public void run() {
                DriverFactory.quit();
            }
        });
    }
}

示例代碼記錄了每步執行的時間。
網站測試

package org.itrunner.tests.hosts;

import org.itrunner.tests.TestBase;
import org.junit.Test;
import org.openqa.selenium.By;

import static org.itrunner.tests.utils.Config.CONFIG;

public class Baidu extends TestBase {

    @Override
    @Test
    public void test() {
        open(CONFIG.getBaiduUrl());

        waitForTitlePresent("百度一下,你就知道");

        nextStep(() -> {
            driver.findElement(By.linkText("登錄")).click();
            driver.findElement(By.id("TANGRAM__PSP_10__footerULoginBtn")).click();
            driver.findElement(By.id("TANGRAM__PSP_10__userName")).sendKeys(CONFIG.getBaiduUsername());
            driver.findElement(By.id("TANGRAM__PSP_10__password")).sendKeys(CONFIG.getBaiduPassword());
            driver.findElement(By.id("TANGRAM__PSP_10__submit")).click();
        }, "login");
    }
}

log配置

在nagios中運行是不需要selenium日誌的,將其關閉。
logging.properties

org.openqa.selenium.level=OFF

打包裝配

使用maven assembly打包,爲便於隨時調整配置,將配置文件放在Jar外。

<assembly>
    <id>bin</id>
    <formats>
        <!--<format>zip</format>-->
        <format>dir</format>
    </formats>
    <baseDirectory>libexec</baseDirectory>
    <dependencySets>
        <dependencySet>
            <useProjectArtifact>true</useProjectArtifact>
            <outputDirectory>lib</outputDirectory>
        </dependencySet>
    </dependencySets>
    <fileSets>
        <fileSet>
            <directory>src/main/resources</directory>
            <outputDirectory>.</outputDirectory>
            <includes>
                <include>check_selenium.sh</include>
            </includes>
        </fileSet>
        <fileSet>
            <directory>target/classes</directory>
            <outputDirectory>lib</outputDirectory>
            <includes>
                <include>config.ini</include>
            </includes>
        </fileSet>
    </fileSets>
</assembly>

打包後的結構如下:
Nagios集成Selenium
部署時將libexec目錄下的內容拷貝到nagios/libexec目錄即可。

配置Command和Service

Command

define command {  
  command_name  check_selenium  
  command_line  $USER1$/check_selenium.sh -c $ARG1$  
}

Service

define service {  
  service_description  selenium_baidu 
  use                  service-check-05min  
  host_name            www.baidu.com  
  check_command        check_selenium!org.itrunner.tests.hosts.Baidu
} 

常見問題

  1. Error: Package: perl-Net-SNMP-6.0.1-7.el7.noarch (epel) Requires: perl(Crypt::DES)
    在RHEL 7安裝perl-Net-SNMP時,報這個錯誤,請先到rpmfind下載安裝perl-Crypt-DES-2.05-20.el7.x86_64.rpm

  2. CHECK_NRPE: Received 0 bytes from daemon. Check the remote server logs for error messages
    Install nrpe:
    ./configure --enable-command-args

  3. NRPE installation error: configure: error: Cannot find ssl headers
    yum install openssl-devel

  4. (Service check timed out after 60.01 seconds)
    在nagios.cfg配置中service_check_timeout=60,如果頁面檢查超時,nagios將停止檢查,根據實際情況調整參數

附錄

安裝Chrome

  1. 啓用Google YUM repository

創建文件/etc/yum.repos.d/google-chrome.repo,內容如下:

[google-chrome]
name=google-chrome
baseurl=http://dl.google.com/linux/chrome/rpm/stable/$basearch
enabled=1
gpgcheck=1
gpgkey=https://dl-ssl.google.com/linux/linux_signing_key.pub
  1. 安裝Signing Key
$ wget https://dl.google.com/linux/linux_signing_key.pub
$ sudo rpm --import linux_signing_key.pub
  1. 安裝Chrome
$ sudo yum install google-chrome-stable

參考資料

Nagios - The Industry Standard In IT Infrastructure Monitoring
Nagios Core
Nagios Core Quickstart Installation Guides
Nagios NRPE Documentation
Zabbix - The Enterprise-Class Open Source Network Monitoring Solution
SeleniumHQ
HtmlUnit
geckodriver
PhantomJS

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章