分类 技术 下的文章

Selenium 是浏览器自动化的绝佳工具。使用 Selenium IDE,你可以录制命令序列(如单击、拖动和输入),验证结果并最终存储此自动化测试供日后使用。这非常适合在浏览器中进行活跃开发。但是当你想要将这些测试与 CI/CD 流集成时,是时候使用 Selenium WebDriver 了。

WebDriver 公开了一个绑定了许多编程语言的 API,它允许你将浏览器测试与其他测试集成。这篇文章向你展示了如何在容器中运行 WebDriver 并将其与 Python 程序一起使用。

使用 Podman 运行 Selenium

Podman 是下面例子的容器运行时。有关如何开始使用 Podman 的信息,请参见此前文章

此例使用了 Selenium 的独立容器,其中包含 WebDriver 服务器和浏览器本身。要在后台启动服务器容器,请运行以下命令:

$ podman run -d --network host --privileged --name server docker.io/selenium/standalone-firefox

当你使用特权标志和主机网络运行容器时,你可以稍后从在 Python 中连接到此容器。你不需要使用 sudo

在 Python 中使用 Selenium

现在你可以提供一个使用此服务器的简单程序。这个程序很小,但应该会让你知道可以做什么:

from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

server ="http://127.0.0.1:4444/wd/hub"

driver = webdriver.Remote(command_executor=server,
    desired_capabilities=DesiredCapabilities.FIREFOX)

print("Loading page...")
driver.get("https://fedoramagazine.org/")
print("Loaded")
assert "Fedora" in driver.title

driver.quit()
print("Done.")

首先,程序连接到你已经启动的容器。然后它加载 Fedora Magazine 网页并判断 “Fedora” 是页面标题的一部分。最后,它退出会话。

需要 Python 绑定才能运行此程序。既然你已经在使用容器了,为什么不在容器中这样做呢?将以下内容保存到 Dockerfile 中:

FROM fedora:29
RUN dnf -y install python3
RUN pip3 install selenium

然后使用 Podman 在与 Dockerfile 相同的文件夹中构建容器镜像:

$ podman build -t selenium-python .

要在容器中运行程序,在运行容器时将包含 Python 代码的文件作为卷挂载:

$ podman run -t --rm --network host \
 -v $(pwd)/browser-test.py:/browser-test.py:z \
 selenium-python python3 browser-test.py

输出看上去像这样:

Loading page...
Loaded
Done.

接下来做什么

上面的示例程序是最小的,也许没那么有用。但这仅仅是最表面的东西!查看 SeleniumPython 绑定 的文档。在那里,你将找到有关如何在页面中查找元素、处理弹出窗口或填写表单的示例。拖放也是可能的,当然还有等待事件。

在实现一些不错的测试后,你可能希望将它们包含在 CI/CD 流程中。幸运的是,这是相当直接的,因为一切都是容器化的。

你可能也有兴趣设置 grid 来并行运行测试。这不仅有助于加快速度,还允许你同时测试多个不同的浏览器。

清理

当你容器使用完后,可以使用以下命令停止并删除独立容器:

$ podman stop server
$ podman rm server

如果你还想释放磁盘空间,请运行以下命令删除镜像:

$ podman rmi docker.io/selenium/standalone-firefox
$ podman rmi selenium-python fedora:29

总结

在本篇中,你已经看到使用容器技术开始使用 Selenium 是多么容易。它允许你自动化与网站的交互,以及测试交互。Podman 允许你在没有超级用户权限或 Docker 守护程序的情况下运行所需的容器。最后,Python 绑定允许你使用普通的 Python 代码与浏览器进行交互。


via: https://fedoramagazine.org/automate-web-browser-selenium/

作者:Lennart Jern 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

这里有所有你想知道的关于设置存储器而又不敢问的一切。

在大多数的计算机系统上,Linux 或者是其它,当你插入一个 USB 设备时,你会注意到一个提示驱动器存在的警告。如果该驱动器已经按你想要的进行分区和格式化,你只需要你的计算机在文件管理器或桌面上的某个地方列出驱动器。这是一个简单的要求,而且通常计算机都能满足。

然而,有时候,驱动器并没有按你想要的方式进行格式化。对于这些,你必须知道如何查找准备连接到您计算机上的存储设备。

什么是块设备?

硬盘驱动器通常被称为“块设备”,因为硬盘驱动器以固定大小的块进行读写。这就可以区分硬盘驱动器和其它可能插入到您计算机的一些设备,如打印机、游戏手柄、麦克风,或相机。一个简单的方法用来列出连接到你 Linux 系统上的块设备就是使用 lsblk (list block devices)命令:

NAME                  MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT
sda                    8:0    0 238.5G  0 disk  
├─sda1                 8:1    0     1G  0 part  /boot
└─sda2                 8:2    0 237.5G  0 part  
  └─luks-e2bb...e9f8 253:0    0 237.5G  0 crypt 
        ├─fedora-root    253:1    0    50G  0 lvm   /
        ├─fedora-swap    253:2    0   5.8G  0 lvm   [SWAP]
        └─fedora-home    253:3    0 181.7G  0 lvm   /home
sdb                   8:16    1  14.6G  0 disk  
└─sdb1                8:17    1  14.6G  0 part

最左列是设备标识符,每个都是以 sd 开头,并以一个字母结尾,字母从 a 开始。每个块设备上的分区分配一个数字,从 1 开始。例如,第一个设备上的第二个分区用 sda2 表示。如果你不确定到底是哪个分区,那也不要紧,只需接着往下读。

lsblk 命令是无损的,仅仅用于检测,所以你可以放心的使用而不用担心破坏你驱动器上的数据。

使用 dmesg 进行测试

如果你有疑问,你可以通过在 dmesg 命令的最后几行查看驱动器的卷标,这个命令显示了操作系统最近的日志(比如说插入或移除一个驱动器)。一句话,如果你想确认你插入的设备是不是 /dev/sdc ,那么,把设备插到你的计算机上,然后运行这个 dmesg 命令:

$ sudo dmesg | tail

显示中列出的最新的驱动器就是你刚刚插入的那个。如果你拔掉它,并再运行这个命令一次,你可以看到,这个设备已经被移除。如果你再插上它再运行命令,这个设备又会出现在那里。换句话说,你可以监控内核对驱动器的识别。

理解文件系统

如果你只需要设备卷标,那么你的工作就完成了。但是如果你的目的是想创建一个可用的驱动器,那你还必须给这个驱动器做一个文件系统。

如果你还不知道什么是文件系统,那么通过了解当没有文件系统时会发生什么可能会更容易理解这个概念。如果你有多余的设备驱动器,并且上面没有什么重要的数据资料,你可以跟着做一下下面的这个实验。否则,请不要尝试,因为根据其设计目的,这个肯定会删除您的资料。

当一个驱动器没有文件系统时也是可以使用的。一旦你已经肯定,正确识别了一个驱动器,并且已经确定上面没有任何重要的资料,那就可以把它插到你的计算机上 —— 但是不要挂载它,如果它被自动挂载上了,那就请手动卸载掉它。

$ su -
# umount /dev/sdx{,1}

为了防止灾难性的复制 —— 粘贴错误,下面的例子将使用不太可能出现的 sdx 来作为驱动器的卷标。

现在,这个驱动器已经被卸载了,尝试使用下面的命令:

# echo 'hello world' > /dev/sdx

你已经可以将数据写入到块设备中,而无需将其挂载到你的操作系统上,也不需要一个文件系统。

再把刚写入的数据取出来,你可以看到驱动器上的原始数据:

# head -n 1 /dev/sdx
hello world

这看起来工作得很好,但是想象一下如果 “hello world” 这个短语是一个文件,如果你想要用这种方法写入一个新的文件,则必须:

  1. 知道第 1 行已经存在一个文件了
  2. 知道已经存在的文件只占用了 1 行
  3. 创建一种新的方法来在后面添加数据,或者在写第 2 行的时候重写第 1 行

例如:

# echo 'hello world
> this is a second file' >> /dev/sdx

获取第 1 个文件,没有任何改变。

# head -n 1 /dev/sdx
hello world

但是,获取第 2 个文件的时候就显得有点复杂了。

# head -n 2 /dev/sdx | tail -n 1
this is a second file

显然,通过这种方式读写数据并不实用,因此,开发人员创建了一个系统来跟踪文件的组成,并标识一个文件的开始和结束,等等。

大多数的文件系统都需要一个分区。

创建分区

分区是硬盘驱动器的一种边界,用来告诉文件系统它可以占用哪些空间。举例来说,你有一个 4GB 的 USB 驱动器,你可以只分一个分区占用一个驱动器 (4GB),或两个分区,每个 2GB (又或者是一个 1GB,一个 3GB,只要你愿意),或者三个不同的尺寸大小,等等。这种组合将是无穷无尽的。

假设你的驱动器是 4GB,你可以使用 GNU parted 命令来创建一个大的分区。

# parted /dev/sdx --align opt mklabel msdos 0 4G

parted 命令的要求,首先指定了驱动器的路径。

--align 选项让 parted 命令自动选择一个最佳的开始点和结束点。

mklabel 命令在驱动器上创建了一个分区表 (称为磁盘卷标)。这个例子使用了 msdos 磁盘卷标,因为它是一个非常兼容和流行的卷标,虽然 gpt 正变得越来越普遍。

最后定义了分区所需的起点和终点。因为使用了 --align opt 标志,所以 parted 将根据需要调整大小以优化驱动器的性能,但这些数字仍然可以做为参考。

接下来,创建实际的分区。如果你开始点和结束点的选择并不是最优的, parted 会向您发出警告并让您做出调整。

# parted /dev/sdx -a opt mkpart primary 0 4G

Warning: The resulting partition is not properly aligned for best performance: 1s % 2048s != 0s
Ignore/Cancel? C                                                          
# parted /dev/sdx -a opt mkpart primary 2048s 4G

如果你再次运行 lsblk 命令,(你可能必须要拔掉驱动器,并把它再插回去),你就可以看到你的驱动器上现在已经有一个分区了。

手动创建一个文件系统

我们有很多文件系统可以使用。有些是开源和免费的,另外的一些并不是。一些公司拒绝支持开源文件系统,所以他们的用户无法使用开源的文件系统读取,而开源的用户也无法在不对其进行逆向工程的情况下从封闭的文件系统中读取。

尽管有这种特殊的情况存在,还是仍然有很多文件系统可以使用,选择哪个取决于驱动器的用途。如果你希望你的驱动器兼容多个系统,那么你唯一的选择是 exFAT 文件系统。然而微软尚未向任何开源内核提交 exFAT 的代码,因此你可能必须在软件包管理器中安装 exFAT 支持,但是 Windows 和 MacOS 都支持 exFAT 文件系统。

一旦你安装了 exFAT 支持,你可以在驱动器上你创建好的分区中创建一个 exFAT 文件系统。

# mkfs.exfat -n myExFatDrive /dev/sdx1

现在你的驱动器可由封闭系统和其它开源的系统(尚未经过微软批准)内核模块进行读写了。

Linux 中常见的文件系统是 ext4。但对于便携式的设备来说,这可能是一个麻烦的文件系统,因为它保留了用户的权限,这些权限通常因为计算机而异,但是它通常是一个可靠而灵活的文件系统。只要你熟悉管理权限,那 ext4 对于便携式的设备来说就是一个很棒的文件系统。

# mkfs.ext4 -L myExt4Drive /dev/sdx1

拔掉你的驱动器,再把它插回去。对于 ext4 文件系统的便携设备来说,使用 sudo 创建一个目录,并将该目录的权限授予用户和系统中通用的组。如果你不确定使用哪个用户和组,也可以使用 sudoroot 来修改出现问题的设备的读写权限。

使用桌面工具

很高兴知道了在只有一个 Linux shell 的时候如何操作和处理你的块设备,但是,有时候你仅仅是想让一个驱动器可用,而不需要进行那么多的检测。 GNOME 的 KDE 的开发者们提供了这样的一些优秀的工具让这个过程变得简单。

GNOME 磁盘KDE 分区管理器 是一个图形化的工具,为本文到目前为止提到的一切提供了一个一体化的解决方案。启动其中的任何一个,来查看所有连接的设备(在左侧列表中),创建和调整分区大小,和创建文件系统。

 title=

KDE 分区管理器

可以预见的是,GNOME 版本会比 KDE 版本更加简单,因此,我将使用复杂的版本进行演示——如果你愿意动手的话,很容易弄清楚 GNOME 磁盘工具的使用。

启动 KDE 分区管理工具,然后输入你的 root 密码。

在最左边的一列,选择你想要格式化的驱动器。如果你的驱动器并没有列出来,确认下是否已经插好,然后选择 “Tools > Refresh devices” (或使用键盘上的 F5 键)。

除非你想销毁驱动器已经存在的分区表,否则请勿继续。选择好驱动器后,单击顶部工具栏中的 “New Partition Table” 。系统会提示你为该分区选择一种卷标:gpt 或 msdos 。前者更加灵活可以处理更大的驱动器,而后者像很多微软的技术一样,是占据大量市场份额的事实上的标准。

现在您有了一个新的分区表,在右侧的面板中右键单击你的设备,然后选择 “New” 来创建新的分区,按照提示设置分区的类型和大小。此操作包括了分区步骤和创建文件系统。

 title=

创建一个新分区

要将更改应用于你的驱动器,单击窗口左上角的 “Apply” 按钮。

硬盘驱动器,轻松驱动

在 Linux 上处理硬盘驱动器很容易,甚至如果你理解硬盘驱动器的语言就更容易了。自从切换到 Linux 系统以来,我已经能够以任何我想要的方式来处理我的硬盘驱动器了。由于 Linux 在处理存储提供的透明性,因此恢复数据也变得更加容易了。

如果你想实验并了解有关硬盘驱动器的更多的信息,请参考下面的几个提示:

  1. 备份您的数据,而不仅仅是你在实验的驱动器上。仅仅需要一个小小的错误操作来破坏一个重要驱动器的分区。(这是一个用来学习重建丢失分区的很好的方法,但并不是很有趣)。
  2. 反复确认你所定位的驱动器是正确的驱动器。我经常使用 lsblk 来确定我并没有移动驱动器。(因为从两个独立的 USB 端口移除两个驱动器很容易,然后以不同的顺序重新连接它们,就会很容易导致它们获得了新的驱动器标签。)
  3. 花点时间“销毁”你测试的驱动器,看看你是否可以把数据恢复。在删除文件系统后,重新创建分区表或尝试恢复数据是一个很好的学习体验。

还有一些更好玩的东西,如果你身边有一个封闭的操作系统,在上面尝试使用一个开源的文件系统。有一些项目致力于解决这种兼容性,并且尝试让它们以一种可靠稳定的方式工作是一个很好的业余项目。


via: https://opensource.com/article/18/11/partition-format-drive-linux

作者:Seth Kenlon 选题:lujun9972 译者:Jamskr 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

继续 systemd 教程,这些特殊的例子可以展示给你如何更好的利用 systemd 定时器单元。

在这个 systemd 系列教程中,我们已经在某种程度上讨论了 systemd 定时器单元。不过,在我们开始讨论 sockets 之前,我们先来看三个例子,这些例子展示了如何最佳化利用这些单元。

简单的类 cron 行为

我每周都要去收集 Debian popcon 数据,如果每次都能在同一时间收集更好,这样我就能看到某些应用程序的下载趋势。这是一个可以使用 cron 任务来完成的典型事例,但 systemd 定时器同样能做到:

# 类 cron 的 popcon.timer

[Unit]
Description= 这里描述了下载并处理 popcon 数据的时刻

[Timer]
OnCalendar= Thu *-*-* 05:32:07
Unit= popcon.service

[Install]
WantedBy= basic.target

实际的 popcon.service 会执行一个常规的 wget 任务,并没有什么特别之处。这里的新内容是 OnCalendar= 指令。这个指令可以让你在一个特定日期的特定时刻来运行某个服务。在这个例子中,Thu 表示 “在周四运行”,*-*-* 表示“具体年份、月份和日期无关紧要”,这些可以翻译成 “不管年月日,只在每周四运行”。

这样,你就设置了这个服务的运行时间。我选择在欧洲中部夏令时区的上午 5:30 左右运行,那个时候服务器不是很忙。

如果你的服务器关闭了,而且刚好错过了每周的截止时间,你还可以在同一个计时器中使用像 anacron 一样的功能。

# 具备类似 anacron 功能的 popcon.timer

[Unit]
Description= 这里描述了下载并处理 popcon 数据的时刻

[Timer]
Unit=popcon.service
OnCalendar=Thu *-*-* 05:32:07
Persistent=true

[Install]
WantedBy=basic.target

当你将 Persistent= 指令设为真值时,它会告诉 systemd,如果服务器在本该它运行的时候关闭了,那么在启动后就要立刻运行服务。这意味着,如果机器在周四凌晨停机了(比如说维护),一旦它再次启动后,popcon.service 将会立刻执行。在这之后,它的运行时间将会回到例行性的每周四早上 5:32.

到目前为止,就是这么简单直白。

延迟执行

但是,我们提升一个档次,来“改进”这个基于 systemd 的监控系统。你应该记得,当你接入摄像头的时候,系统就会开始拍照。假设你并不希望它在你安装摄像头的时候拍下你的脸。你希望将拍照服务的启动时间向后推迟一两分钟,这样你就有时间接入摄像头,然后走到画框外面。

为了完成这件事,首先你要更改 Udev 规则,将它指向一个定时器:

ACTION=="add", SUBSYSTEM=="video4linux", ATTRS{idVendor}=="03f0", 
ATTRS{idProduct}=="e207", TAG+="systemd", ENV{SYSTEMD_WANTS}="picchanged.timer", 
SYMLINK+="mywebcam", MODE="0666"

这个定时器看起来像这样:

# picchanged.timer

[Unit]
Description= 在摄像头接入的一分钟后,开始运行 picchanged

[Timer]
OnActiveSec= 1 m
Unit= picchanged.path

[Install]
WantedBy= basic.target

在你接入摄像头后,Udev 规则被触发,它会调用定时器。这个定时器启动后会等上一分钟(OnActiveSec= 1 m),然后运行 picchanged.path,它会监视主图片的变化picchanged.path 还会负责接触 webcan.service,这个实际用来拍照的服务。

在每天的特定时刻启停 Minetest 服务器

在最后一个例子中,我们认为你决定用 systemd 作为唯一的依赖。讲真,不管怎么样,systemd 差不多要接管你的生活了。为什么不拥抱这个必然性呢?

你有个为你的孩子设置的 Minetest 服务。不过,你还想要假装关心一下他们的教育和成长,要让他们做作业和家务活。所以你要确保 Minetest 只在每天晚上的一段时间内可用,比如五点到七点。

这个跟之前的“在特定时间启动服务”不太一样。写个定时器在下午五点启动服务很简单…:

# minetest.timer

[Unit]
Description= 在每天下午五点运行 minetest.service

[Timer]
OnCalendar= *-*-* 17:00:00
Unit= minetest.service

[Install]
WantedBy= basic.target

…可是编写一个对应的定时器,让它在特定时刻关闭服务,则需要更大剂量的横向思维。

我们从最明显的东西开始 —— 设置定时器:

# stopminetest.timer

[Unit]
Description= 每天晚上七点停止 minetest.service

[Timer]
OnCalendar= *-*-* 19:05:00
Unit= stopminetest.service

[Install]
WantedBy= basic.target

这里棘手的部分是如何去告诉 stopminetest.service 去 —— 你知道的 —— 停止 Minetest. 我们无法从 minetest.service 中传递 Minetest 服务器的 PID. 而且 systemd 的单元词汇表中也没有明显的命令来停止或禁用正在运行的服务。

我们的诀窍是使用 systemd 的 Conflicts= 指令。它和 systemd 的 Wants= 指令类似,不过它所做的事情正相反。如果你有一个 b.service 单元,其中包含一个 Wants=a.service 指令,在这个单元启动时,如果 a.service 没有运行,则 b.service 会运行它。同样,如果你的 b.service 单元中有一行写着 Conflicts= a.service,那么在 b.service 启动时,systemd 会停止 a.service.

这种机制用于两个服务在尝试同时控制同一资源时会发生冲突的场景,例如当两个服务要同时访问打印机的时候。通过在首选服务中设置 Conflicts=,你就可以确保它会覆盖掉最不重要的服务。

不过,你会在一个稍微不同的场景中来使用 Conflicts=. 你将使用 Conflicts= 来干净地关闭 minetest.service

# stopminetest.service

[Unit]
Description= 关闭 Minetest 服务
Conflicts= minetest.service

[Service]
Type= oneshot
ExecStart= /bin/echo "Closing down minetest.service"

stopminetest.service 并不会做特别的东西。事实上,它什么都不会做。不过因为它包含那行 Conflicts=,所以在它启动时,systemd 会关掉 minetest.service.

在你完美的 Minetest 设置中,还有最后一点涟漪:你下班晚了,错过了服务器的开机时间,可当你开机的时候游戏时间还没结束,这该怎么办?Persistent= 指令(如上所述)在错过开始时间后仍然可以运行服务,但这个方案还是不行。如果你在早上十一点把服务器打开,它就会启动 Minetest,而这不是你想要的。你真正需要的是一个确保 systemd 只在晚上五到七点启动 Minetest 的方法:

# minetest.timer

[Unit]
Description= 在下午五到七点内的每分钟都运行 minetest.service

[Timer]
OnCalendar= *-*-* 17..19:*:00
Unit= minetest.service

[Install]
WantedBy= basic.target

OnCalendar= *-*-* 17..19:*:00 这一行有两个有趣的地方:(1) 17..19 并不是一个时间点,而是一个时间段,在这个场景中是 17 到 19 点;以及,(2) 分钟字段中的 * 表示服务每分钟都要运行。因此,你会把它读做 “在下午五到七点间的每分钟,运行 minetest.service”

不过还有一个问题:一旦 minetest.service 启动并运行,你会希望 minetest.timer 不要再次尝试运行它。你可以在 minetest.service 中包含一条 Conflicts= 指令:

# minetest.service

[Unit]
Description= 运行 Minetest 服务器
Conflicts= minetest.timer

[Service]
Type= simple
User= <your user name>

ExecStart= /usr/bin/minetest --server
ExecStop= /bin/kill -2 $MAINPID

[Install]
WantedBy= multi-user.targe

上面的 Conflicts= 指令会保证在 minstest.service 成功运行后,minetest.timer 就会立即停止。

现在,启用并启动 minetest.timer

systemctl enable minetest.timer
systemctl start minetest.timer

而且,如果你在六点钟启动了服务器,minetest.timer 会启用;到了五到七点,minetest.timer 每分钟都会尝试启动 minetest.service。不过,一旦 minetest.service 开始运行,systemd 会停止 minetest.timer,因为它会与 minetest.service “冲突”,从而避免计时器在服务已经运行的情况下还会不断尝试启动服务。

在首先启动某个服务时杀死启动它的计时器,这么做有点反直觉,但它是有效的。

总结

你可能会认为,有更好的方式来做上面这些事。我在很多文章中看到过“过度设计”这个术语,尤其是在用 systemd 定时器来代替 cron 的时候。

但是,这个系列文章的目的不是为任何具体问题提供最佳解决方案。它的目的是为了尽可能多地使用 systemd 来解决问题,甚至会到荒唐的程度。它的目的是展示大量的例子,来说明如何利用不同类型的单位及其包含的指令。我们的读者,也就是你,可以从这篇文章中找到所有这些的可实践范例。

尽管如此,我们还有一件事要做:下回中,我们会关注 sockets 和 targets,然后我们将完成对 systemd 单元的介绍。

你可以在 Linux 基金会和 edX 中,通过免费的 Linux 介绍课程中,学到更多关于 Linux 的知识。


via: https://www.linux.com/blog/intro-to-linux/2018/8/systemd-timers-two-use-cases-0

作者:Paul Brown 选题:lujun9972 译者:StdioA 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

用这个有用工具从 Markdown 文件创建一个基础的网站。

有很多理由喜欢 Markdown,这是一门简单的语言,有易于学习的语法,它可以与任何文本编辑器一起使用。使用像 Pandoc 这样的工具,你可以将 Markdown 文本转换为各种流行格式,包括 HTML。你还可以在 Web 服务器中自动执行转换过程。由 TimoDörr 创建的名为 MDwiki 的 HTML5 和 JavaScript 应用可以将一堆 Markdown 文件在浏览器请求它们时转换为网站。MDwiki 网站包含一个操作指南和其他信息可帮助你入门:

 title=

Mdwiki 网站的样子。

在 Web 服务器内部,基本的 MDwiki 站点如下所示:

 title=

该站点的 web 服务器文件夹的样子

我将此项目的 MDwiki HTML 文件重命名为 START.HTML。还有一个处理导航的 Markdown 文件和一个 JSON 文件来保存一些配置设置。其他的都是网站内容。

虽然整个网站设计被 MDwiki 固定了,但内容、样式和页面数量却没有。你可以在 MDwiki 站点查看由 MDwiki 生成的一系列不同站点。公平地说,MDwiki 网站缺乏网页设计师可以实现的视觉吸引力 —— 但它们是功能性的,用户应该平衡其简单的外观与创建和编辑它们的速度和简易性。

Markdown 有不同的风格,可以针对不同的特定目的扩展稳定的核心功能。MDwiki 使用 GitHub 风格 Markdown,它为流行的编程语言添加了格式化代码块和语法高亮等功能,使其非常适合生成程序文档和教程。

MDwiki 还支持 “gimmick”,它增加了如嵌入 YouTube 视频和显示数学公式等额外功能。如果在某些项目中需要它们,这些值得探索。我发现 MDwiki 是创建技术文档和教育资源的理想工具。我还发现了一些可能不会立即显现出来的技巧和 hack。

当部署在 Web 服务器中时,MDwiki 可与任何现代 Web 浏览器一起使用。但是,如果你使用 Mozilla Firefox 访问 MDwiki,那么就不需要 Web 服务器。大多数 MDwiki 用户会选择在 Web 服务器上部署完整的项目,以避免排除潜在用户,但只需使用文本编辑器和 Firefox 即可完成开发和测试。任何现代浏览器都可以读取加载到 Moodle 虚拟学习环境(VLE)中的完整的 MDwiki 项目,这在教育环境中非常有用。 (对于其他 VLE 软件,这可能也是如此,但你应该测试它。)

MDwiki 的默认配色方案并非适用于所有项目,但你可以将其替换为从 Bootswatch.com 下载的其他主题。为此,只需在编辑器中打开 MDwiki HTML 文件,找到 extlib/css/bootstrap-3.0.0.min.css,然后插入下载的 Bootswatch 主题。还有一个 MDwiki gimmick,让用户在浏览器中载入 MDwiki 后,选择 Bootswatch 主题来替换默认值。我经常与有视力障碍的用户一起工作,他们倾向于喜欢高对比度的主题,在深色背景上使用白色文字。

 title=

MDwiki 页面使用 Bootswatch Superhero 主题

MDwiki、Markdown 文件和静态图像可以用于许多目的。但是,你有时可能希望包含 JavaScript 幻灯片或反馈表单。Markdown 文件可以包含 HTML 代码,但将 Markdown 与 HTML 混合会让人感到困惑。一种解决方案是在单独的 HTML 文件中创建所需的功能,并将其显示在带有 iframe 标记的 Markdown 文件中。我从 Twine Cookbook 知道了这个想法,它是 Twine 交互式小说引擎的支持站点。Twine Cookbook 实际上并没有使用 MDwiki,但结合 Markdown 和 iframe 标签开辟了广泛的创作可能性。

这是一个例子:

此 HTML 将显示由 Markdown 文件中的 Twine 交互式小说引擎创建的 HTML 页面。

<iframe height="400" src="sugarcube_dungeonmoving_example.html" width="90%"></iframe>

MDwiki 生成的站点结果如下所示:

简而言之,MDwiki 是一个出色的小应用,可以很好地实现其目的。


via: https://opensource.com/article/18/8/markdown-html-publishing

作者:Peter Cheer 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

均衡网络流量的常用技术,它们的优势和利弊权衡。

大型的多站点互联网系统,包括内容分发网络(CDN)和云服务提供商,用一些方法来均衡来访的流量。这篇文章我们讲一下常见的流量均衡设计,包括它们的技术手段和利弊权衡。

早期的云计算服务提供商,可以提供单一一台客户 Web 服务器,分配一个 IP 地址,然后用一个便于人读的域名配置一个 DNS 记录指向这个 IP 地址,再将 IP 地址通过边界网关协议(BGP)宣告出去,BGP 是在不同网络之间交换路由信息的标准方式。

这本身并不是负载均衡,但是能在冗余的多条网络路径中进行流量分发,而且可以利用网络技术让流量绕过不可用的网络,从而提高了可用性(也引起了非对称路由的现象)。

简单的 DNS 负载均衡

随着来自客户的流量变大,老板希望服务是高可用的。你上线第二台 web 服务器,它有自己独立的公网 IP 地址,然后你更新了 DNS 记录,把用户流量引到两台服务器上(内心希望它们均衡地提供服务)。在其中一台服务器出故障之前,这样做一直是没有问题的。假设你能很快地监测到故障,可以更新一下 DNS 配置(手动更新或者通过软件)删除解析到故障机器的记录。

不幸的是,因为 DNS 记录会被缓存,在客户端缓存和它们依赖的 DNS 服务器上的缓存失效之前,大约一半的请求会失败。DNS 记录都有一个几分钟或更长的生命周期(TTL),所以这种方式会对系统可用性造成严重的影响。

更糟糕的是,部分客户端会完全忽略 TTL,所以有一些请求会持续被引导到你的故障机器上。设置很短的 TTL 也不是个好办法,因为这意味着更高的 DNS 服务负载,还有更长的访问时延,因为客户端要做更多的 DNS 查询。如果 DNS 服务由于某种原因不可用了,那设置更短的 TTL 会让服务的访问量更快地下降,因为没那么多客户端有你网站 IP 地址的缓存了。

增加网络负载均衡

要解决上述问题,可以增加一对相互冗余的四层(L4)网络负载均衡器,配置一样的虚拟 IP 地址(VIP)。均衡器可以是硬件的,也可以是像 HAProxy 这样的软件。域名的 DNS 记录指向 VIP,不再承担负载均衡的功能。

 title=

四层负载均衡器能够均衡用户和两台 web 服务器的连接

四层均衡器将网络流量均衡地引导至后端服务器。通常这是基于对 IP 数据包的五元组做散列(数学函数)来完成的,五元组包括:源地址、源端口、目的地址、目的端口、协议(比如 TCP 或 UDP)。这种方法是快速和高效的(还维持了 TCP 的基本属性),而且不需要均衡器维持每个连接的状态。(更多信息请阅读谷歌发表的 Maglev 论文,这篇论文详细讨论了四层软件负载均衡器的实现细节。)

四层均衡器可以对后端服务做健康检查,只把流量分发到健康的机器上。和使用 DNS 做负载均衡不同的是,在某个后端 web 服务故障的时候,它可以很快地把流量重新分发到其他机器上,虽然故障机器的已有连接会被重置。

当后端服务器的能力不同时,四层均衡器可以根据权重做流量分发。它为运维人员提供了强大的能力和灵活性,而且硬件成本相对较小。

扩展到多站点

系统规模在持续增长。你的客户希望能一直使用服务,即使是数据中心发生故障的时候。所以你建设了一个新的数据中心,另外独立部署了一套服务和四层负载均衡器集群,仍然使用同样的 VIP。DNS 的设置不变。

两个站点的边缘路由器都把自己的地址空间宣告出去,包括 VIP 地址。发往该 VIP 的请求可能到达任何一个站点,取决于用户和系统之间的网络是如何连接的,以及各个网络的路由策略是如何配置的。这就是泛播。大部分时候这种机制可以很好的工作。如果一个站点出问题了,你可以停止通过 BGP 宣告 VIP 地址,客户的请求就会迅速地转移到另外一个站点去。

 title=

多个站点使用泛播提供服务

这种设置有一些问题。最大的问题是,不能控制请求流向哪个站点,或者限制某个站点的流量。也没有一个明确的方式把用户的请求转到距离他最近的站点(为了降低网络延迟),不过,网络协议和路由选路配置在大部分情况下应该能把用户请求路由到最近的站点。

控制多站点系统中的入站请求

为了维持稳定性,需要能够控制每个站点的流量大小。要实现这种控制,可以给每个站点分配不同的 VIP 地址,然后用简单的或者有权重的 DNS 轮询来做负载均衡。

 title=

多站点提供服务,每个站点使用一个主 VIP,另外一个站点作为备份。基于能感知地理位置的 DNS。

现在有两个问题。

第一、使用 DNS 均衡意味着会有被缓存的记录,如果你要快速重定向流量的话就麻烦了。

第二、用户每次做新的 DNS 查询,都可能连上任意一个站点,可能不是距离最近的。如果你的服务运行在分布广泛的很多站点上,用户会感受到响应时间有明显的变化,取决于用户和提供服务的站点之间有多大的网络延迟。

让每个站点都配置上其他所有站点的 VIP 地址,并宣告出去(因此也会包含故障的站点),这样可以解决第一个问题。有一些网络上的小技巧,比如备份站点宣告路由时,不像主站点使用那么具体的目的地址,这样可以保证每个 VIP 的主站点只要可用就会优先提供服务。这是通过 BGP 来实现的,所以我们应该可以看到,流量在 BGP 更新后的一两分钟内就开始转移了。

即使离用户最近的站点是健康而且有服务能力的,但是用户真正访问到的却不一定是这个站点,这个问题还没有很好的解决方案。很多大型的互联网服务利用 DNS 给不同地域的用户返回不同的解析结果,也能有一定的效果。不过,因为网络地址的结构和地理位置无关,一个地址段也可能会改变所在位置(例如,当一个公司重新规划网络时),而且很多用户可能使用了同一个 DNS 缓存服务器。所以这种方案有一定的复杂度,而且容易出错。

增加七层负载均衡

又过了一段时间,你的客户开始要更多的高级功能。

虽然四层负载均衡可以高效地在多个 web 服务器之间分发流量,但是它们只针对源地址、目标地址、协议和端口来操作,请求的内容是什么就不得而知了,所以很多高级功能在四层负载均衡上实现不了。而七层(L7)负载均衡知道请求的内容和结构,所以能做更多的事情。

七层负载均衡可以实现缓存、限速、错误注入,做负载均衡时可以感知到请求的代价(有些请求需要服务器花更多的时间去处理)。

七层负载均衡还可以基于请求的属性(比如 HTTP cookies)来分发流量,可以终结 SSL 连接,还可以帮助防御应用层的拒绝服务(DoS)攻击。规模大的 L7 负载均衡的缺点是成本 —— 处理请求需要更多的计算,而且每个活跃的请求都占用一些系统资源。在一个或者多个 L7 均衡器前面运行 L4 均衡器集群,对扩展规模有帮助。

结论

负载均衡是一个复杂的难题。除了上面说过的策略,还有不同的负载均衡算法,用来实现负载均衡器的高可用技术、客户端负载均衡技术,以及最近兴起的服务网络等等。

核心的负载均衡模式随着云计算的发展而不断发展,而且,随着大型 web 服务商致力于让负载均衡技术更可控和更灵活,这项技术会持续发展下去。


via: https://opensource.com/article/18/10/internet-scale-load-balancing

作者:Laura Nolan 选题:lujun9972 译者:BeliteX 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

一篇了解如何在 SUSE 12 Linux 服务器中进入单用户模式的简短文章。

How to enter single user mode in SUSE 12 Linux

在这篇简短的文章中,我们将向你介绍在 SUSE 12 Linux 中进入单用户模式的步骤。在排除系统主要问题时,单用户模式始终是首选。单用户模式禁用网络并且没有其他用户登录,你可以排除许多多用户系统的情况,可以帮助你快速排除故障。单用户模式最常见的一种用处是重置忘记的 root 密码

1、暂停启动过程

首先,你需要拥有机器的控制台才能进入单用户模式。如果它是虚拟机那就是虚拟机控制台,如果它是物理机那么你需要连接它的 iLO/串口控制台。重启系统并在 GRUB 启动菜单中按任意键停止内核的自动启动。

Kernel selection menu at boot in SUSE 12

2、编辑内核的启动选项

进入上面的页面后,在所选内核(通常是你首选的最新内核)上按 e 更新其启动选项。你会看到下面的页面。

grub2 edits in SUSE 12

现在,向下滚动到内核引导行,并在行尾添加 init=/bin/bash,如下所示。

Edit to boot in single user shell

3、引导编辑后的内核

现在按 Ctrl-xF10 来启动这个编辑过的内核。内核将以单用户模式启动,你将看到 # 号提示符,即有服务器的 root 访问权限。此时,根文件系统以只读模式挂载。因此,你对系统所做的任何更改都不会被保存。

运行以下命令以将根文件系统重新挂载为可重写入的。

kerneltalks:/ # mount -o remount,rw /

这就完成了!继续在单用户模式中做你必要的事情吧。完成后不要忘了重启服务器引导到普通多用户模式。


via: https://kerneltalks.com/howto/how-to-enter-single-user-mode-in-suse-12-linux/

作者:kerneltalks 选题:lujun9972 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出