2018年11月

越来越多的开发人员使用容器开发和部署他们的应用。这意味着可以轻松地测试容器也变得很重要。Conu (container utilities 的简写) 是一个 Python 库,让你编写容器测试变得简单。本文向你介绍如何使用它测试容器。

开始吧

首先,你需要一个容器程序来测试。为此,以下命令创建一个包含一个容器的 Dockerfile 和一个被容器伺服的 Flask 应用程序的文件夹。

$ mkdir container_test
$ cd container_test
$ touch Dockerfile
$ touch app.py

将以下代码复制到 app.py 文件中。这是惯常的基本 Flask 应用,它返回字符串 “Hello Container World!”。

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello Container World!'

if __name__ == '__main__':
    app.run(debug=True,host='0.0.0.0')

创建和构建测试容器

为了构建测试容器,将以下指令添加到 Dockerfile。

FROM registry.fedoraproject.org/fedora-minimal:latest
RUN microdnf -y install python3-flask && microdnf clean all
ADD ./app.py /srv
CMD ["python3", "/srv/app.py"]

然后使用 Docker CLI 工具构建容器。

$ sudo dnf -y install docker
$ sudo systemctl start docker
$ sudo docker build . -t flaskapp_container

提示:只有在系统上未安装 Docker 时才需要前两个命令。

构建之后使用以下命令运行容器。

$ sudo docker run -p 5000:5000 --rm flaskapp_container
* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 473-505-51

最后,使用 curl 检查 Flask 应用程序是否在容器内正确运行:

$ curl http://127.0.0.1:5000
Hello Container World!

现在,flaskapp\_container 正在运行并准备好进行测试,你可以使用 Ctrl+C 将其停止。

创建测试脚本

在编写测试脚本之前,必须安装 conu。在先前创建的 container_test 目录中,运行以下命令。

$ python3 -m venv .venv
$ source .venv/bin/activate
(.venv)$ pip install --upgrade pip
(.venv)$ pip install conu
$ touch test_container.py

然后将以下脚本复制并保存在 test_container.py 文件中。

import conu

PORT = 5000

with conu.DockerBackend() as backend:
  image = backend.ImageClass("flaskapp_container")
  options = ["-p", "5000:5000"]
  container = image.run_via_binary(additional_opts=options)
  
  try:
    # Check that the container is running and wait for the flask application to start.
    assert container.is_running()
    container.wait_for_port(PORT)
    
    # Run a GET request on / port 5000.
    http_response = container.http_request(path="/", port=PORT)
    
    # Check the response status code is 200
    assert http_response.ok
    
    # Get the response content
    response_content = http_response.content.decode("utf-8")

    # Check that the "Hello Container World!" string is served.
    assert "Hello Container World!" in response_content

    # Get the logs from the container
    logs = [line for line in container.logs()]
    # Check the the Flask application saw the GET request.
    assert b'"GET / HTTP/1.1" 200 -' in logs[-1]

  finally:
    container.stop()
    container.delete()

测试设置

这个脚本首先设置 conu 使用 Docker 作为后端来运行容器。然后它设置容器镜像以使用你在本教程第一部分中构建的 flaskapp\_container。

下一步是配置运行容器所需的选项。在此示例中,Flask 应用在端口5000上提供内容。于是你需要暴露此端口并将其映射到主机上的同一端口。

最后,用这个脚本启动容器,现在可以测试了。

测试方法

在测试容器之前,检查容器是否正在运行并准备就绪。示范脚本使用 container.is_runningcontainer.wait_for_port。这些方法可确保容器正在运行,并且服务在预设端口上可用。

container.http_requestrequest 库的包装器,可以方便地在测试期间发送 HTTP 请求。这个方法返回requests.Responseobject,因此可以轻松地访问响应的内容以进行测试。

conu 还可以访问容器日志。又一次,这在测试期间非常有用。在上面的示例中,container.logs 方法返回容器日志。你可以使用它们断言打印了特定日志,或者,例如在测试期间没有异常被引发。

conu 提供了许多与容器接合的有用方法。文档中提供了完整的 API 列表。你还可以参考 GitHub 上提供的示例。

运行本教程所需的所有代码和文件也可以在 GitHub 上获得。 对于想要进一步采用这个例子的读者,你可以看看使用 pytest 来运行测试并构建一个容器测试套件。


via: https://fedoramagazine.org/test-containers-python-conu/

作者:Clément Verna 选题:lujun9972 译者:GraveAccent 校对:wxy

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

想要建立一个积极,富有成效的工作环境? 在招聘过程中要专注于寻找契合点。

聘请一个不合适的人代价是很高的。根据 Link 人力资源的首席执行官 Jörgen Sundberg 的统计,招聘、雇佣一名新员工将会花费公司$240,000 之多,当你进行了一次不合适的招聘:

  • 你失去了他们的知识技能。
  • 你失去了他们的人脉。
  • 你的团队将可能进入到一个组织发展的震荡阶段
  • 你的公司将会面临组织破裂的风险

当你失去一名员工的时候,你就像丢失了公司版图中的一块。同样值得一提的是另一端的痛苦。应聘到一个错误工作岗位的员工会感受到很大的压力以及整个身心的不满意,甚至是健康问题。

另外一方面,当你招聘到合适的人时,新的员工将会:

  • 丰富公司现有的文化,使你的组织成为一个更好的工作场所。研究表明一个积极的工作文化能够帮助更长久推动财务业绩增长,而且如果你在一个欢快的环境中工作,你更有可能在生活中做的更好。
  • 热爱和你的组织在一起工作。当人们热爱他们所在做的,他们会趋向于做的更好。

招聘以适合或加强现有的文化在 DevOps 和敏捷团多中是必不可少的。也就是说雇佣到一个能够鼓励积极合作的人,以便来自不同背景,有着不同目标和工作方式的团队能够在一起有效的工作。你新雇佣的员工应该能够帮助团队合作来充分发挥放大他们的价值,同时也能够增加员工的满意度以及平衡组织目标的冲突。他或者她应该能够通过明智的选择工具和工作流来促进你的组织,文化就是一切。

作为我们 2017 年 11 月发布的一篇文章 DevOps 的招聘经理应该准备回答的 20 个问题 的回应,这篇文章将会重点关注在如何招聘最适合的人。

为什么招聘走错了方向

很多公司现在用的典型的雇佣策略是基于人才过剩的基础上:

  • 在职位公告栏发布招聘。
  • 关注具有所需才能的应聘者。
  • 尽可能找多的候选者。
  • 通过面试淘汰弱者。
  • 通过正式的面试淘汰更多的弱者。
  • 评估,投票,选择。
  • 渐渐接近补偿。

职位公告栏是有成千上万失业者人才过剩的经济大萧条时期发明的。在今天的求职市场上已经没有人才过剩了,然而我们仍然在使用基于此的招聘策略。

雇佣最合适的人员:运用文化和情感

在人才过剩雇佣策略背后的思想是设计工作岗位然后将人员安排进去。

反而应该反过来:寻找将会积极融入你的商业文化的人才,然后为他们寻找他们热爱的最合适的岗位。要想实现这样的目标,你必须能够围绕他们热情为他们创造工作岗位。

谁正在寻找一份工作? 根据一份 2016 年对美国 50000 名开发者的调查显示,85.7% 的受访对象要么对新的机会不感兴趣,要么对于寻找新工作没有积极性。在寻找工作的那部分中,有将近 28.3% 的求职者来自于朋友的推荐。如果你只是在那些在找工作的人中寻找人才,你将会错过高端的人才。

运用团队力量去发现和寻找潜力的雇员。例如,戴安娜是你的团队中的一名开发者,她所能提供的机会是,她已经从事编程很多年而且在期间已经结识了很多从事热爱他们所从事的工作的人。难道你不认为她所推荐的潜在员工在技能、知识和智慧上要比 HR 所寻找的要优秀吗?在要求戴安娜分享她同伴之前,通知她即将到来的使命任务,向她阐明你要雇佣潜在有探索精神的团队,描述在将来会需要的知识领域。

雇员想要什么?一份来自千禧年婴儿潮时期出生的人的对比综合性研究显示,20% 的人所想要的是相同的:

  1. 对组织产生积极的影响
  2. 帮助解决社交或者环境上的挑战
  3. 和一群有动力的人一起工作

面试的挑战

面试应该是招聘者和应聘者双方为了寻找最合适的人才进行的一次双方之间的对话。将面试聚焦在企业文化和情感对话两个问题上:这个应聘者将会丰富你的企业文化并且会热爱和你在一起工作吗?你能够在工作中帮他们取得成功吗?

对于招聘经理来说: 每一次的面试都是你学习如何将自己的组织变得对未来的团队成员更有吸引力,并且每次积极的面试都可能是你发现人才(即使你不会雇佣)的机会。每个人都将会记得积极有效的面试的经历。即使他们不会被雇佣,他们将会和他们的朋友谈论这次经历,你会得到一个被推荐的机会。这有很大的好处:如果你无法吸引到这个人才,你也将会从中学习吸取经验并且改善。

对面试者来说:每次的面试都是你释放激情的机会。

助你释放潜在雇员激情的 20 个问题

  1. 你热爱什么?
  2. “今天早晨我已经迫不及待的要去工作”,你怎么看待这句话?
  3. 你曾经最快乐的是什么?
  4. 你曾经解决问题的最典型的例子是什么,你是如何解决的?
  5. 你如何看待配对学习?
  6. 你到达办公室和离开办公室心里最先想到的是什么?
  7. 你如果你有一次改变你之前或者现在的工作中的一件事的机会,将会是什么事?
  8. 当你在工作的时候,你最乐于去学习什么?
  9. 你的梦想是什么,你如何去实现?
  10. 你在学会如何去实现你的追求的时候想要或者需要什么?
  11. 你的价值观是什么?
  12. 你是如何坚守自己的价值观的?
  13. 在你的生活中平衡意味着什么?
  14. 你最引以为傲的工作交流能力是什么?为什么?
  15. 你最喜欢营造什么样的环境?
  16. 你喜欢别人怎样对待你?
  17. 你信任我们什么,如何验证?
  18. 告诉我们你在最近的一个项目中学习到什么?
  19. 我们还能知道你的其他方面的什么?
  20. 如果你正在雇佣我,你将会问我什么问题?

via: https://opensource.com/article/18/3/questions-devops-employees-should-answer

作者:Catherine Louis 译者:FelixYFZ 校对:wxy

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

在严重的故障发生之前,找到引起问题的异常事件,并修复它。

黑天鹅 Black swan 用来比喻造成严重影响的小概率事件(比如 2008 年的金融危机)。在生产环境的系统中,黑天鹅是指这样的事情:它引发了你不知道的问题,造成了重大影响,不能快速修复或回滚,也不能用值班说明书上的其他标准响应来解决。它是事发几年后你还在给新人说起的事件。

从定义上看,黑天鹅是不可预测的,不过有时候我们能找到其中的一些模式,针对有关联的某一类问题准备防御措施。

例如,大部分故障的直接原因是变更(代码、环境或配置)。虽然这种方式触发的 bug 是独特的、不可预测的,但是常见的金丝雀发布对避免这类问题有一定的作用,而且自动回滚已经成了一种标准止损策略。

随着我们的专业性不断成熟,一些其他的问题也正逐渐变得容易理解,被归类到某种风险并有普适的预防策略。

公布出来的黑天鹅事件

所有科技公司都有生产环境的故障,只不过并不是所有公司都会分享他们的事故分析。那些公开讨论事故的公司帮了我们的忙。下列事故都描述了某一类问题,但它们绝对不是只一个孤例。我们的系统中都有黑天鹅在潜伏着,只是有些人还不知道而已。

达到上限

达到任何类型的限制都会引发严重事故。这类问题的一个典型例子是 2017 年 2 月 Instapaper 的一次服务中断。我把这份事故报告给任何一个运维工作者看,他们读完都会脊背发凉。Instapaper 生产环境的数据库所在的文件系统有 2 TB 的大小限制,但是数据库服务团队并不知情。在没有任何报错的情况下,数据库不再接受任何写入了。完全恢复需要好几天,而且还得迁移数据库。

资源限制有各式各样的触发场景。Sentry 遇到了 Postgres 的最大事务 ID 限制。Platform.sh 遇到了管道缓冲区大小限制。SparkPost 触发了 AWS 的 DDoS 保护。Foursquare 在他们的一个 MongoDB 耗尽内存时遭遇了性能骤降。

提前了解系统限制的一个办法是定期做测试。好的压力测试(在生产环境的副本上做)应该包含写入事务,并且应该把每一种数据存储都写到超过当前生产环境的容量。压力测试时很容易忽略的是次要存储(比如 Zookeeper)。如果你是在测试时遇到了资源限制,那么你还有时间去解决问题。鉴于这种资源限制问题的解决方案可能涉及重大的变更(比如数据存储拆分),所以时间是非常宝贵的。

说到云产品的使用,如果你的服务产生了异常的负载,或者你用的产品或功能还没有被广泛使用(比如老旧的或者新兴的),那么你遇到资源上限的风险很大。对这些云产品做一下压力测试是值得的。不过,做之前要提醒一下你的云服务提供商。

最后,知道了哪里有限制之后,要增加监控(和对应文档),这样你才能知道系统在什么时候接近了资源上限。不要寄希望于那些还在维护服务的人会记得。

扩散的慢请求

“这个世界的关联性远比我们想象中更大。所以我们看到了更多 Nassim Taleb 所说的‘黑天鹅事件’ —— 即罕见事件以更高的频率离谱地发生了,因为世界是相互关联的” —— Richard Thaler

HostedGraphite 的负载均衡器并没有托管在 AWS 上,却被 AWS 的服务中断给搞垮了,他们关于这次事故原因的分析报告很好地诠释了分布式计算系统之间存在多么大的关联。在这个事件里,负载均衡器的连接池被来自 AWS 上的客户访问占满了,因为这些连接很耗时。同样的现象还会发生在应用的线程、锁、数据库连接上 —— 任何能被慢操作占满的资源。

这个 HostedGraphite 的例子中,慢速连接是外部系统施加的,不过慢速连接经常是由内部某个系统的饱和所引起的,饱和与慢操作的级联,拖慢了系统中的其他部分。Spotify 的一个事故就说明了这样的传播 —— 流媒体服务的前端被另一个微服务的饱和所影响,造成健康检查失败。强制给所有请求设置超时时间,以及限制请求队列的长度,可以预防这一类故障传播。这样即使有问题,至少你的服务还能承担一些流量,而且因为整体上你的系统里故障的部分更少了,恢复起来也会更快。

重试的间隔应该用指数退避来限制一下,并加入一些时间抖动。Square 有一次服务中断是 Redis 存储的过载,原因是有一段代码对失败的事务重试了 500 次,没有任何重试退避的方案,也说明了过度重试的潜在风险。另外,针对这种情况,断路器设计模式也是有用的。

应该设计出监控仪表盘来清晰地展示所有资源的使用率、饱和度和报错,这样才能快速发现问题。

突发的高负载

系统在异常高的负载下经常会发生故障。用户天然会引发高负载,不过也常常是由系统引发的。午夜突发的 cron 定时任务是老生常谈了。如果程序让移动客户端同时去获取更新,这些客户端也会造成突发的大流量(当然,给这种请求加入时间抖动会好很多)。

在预定时刻同时发生的事件并不是突发大流量的唯一原因。Slack 经历过一次短时间内的多次服务中断,原因是非常多的客户端断开连接后立即重连,造成了突发的大负载。 CircleCI 也经历过一次严重的服务中断,当时 Gitlab 从故障中恢复了,所以数据库里积累了大量的构建任务队列,服务变得饱和而且缓慢。

几乎所有的服务都会受突发的高负载所影响。所以对这类可能出现的事情做应急预案 —— 并测试一下预案能否正常工作 —— 是必须的。客户端退避和减载通常是这些方案的核心。

如果你的系统必须不间断地接收数据,并且数据不能被丢掉,关键是用可伸缩的方式把数据缓冲到队列中,后续再处理。

自动化系统是复杂的系统

“复杂的系统本身就是有风险的系统”
—— Richard Cook, MD

过去几年里软件的运维操作趋势是更加自动化。任何可能降低系统容量的自动化操作(比如擦除磁盘、退役设备、关闭服务)都应该谨慎操作。这类自动化操作的故障(由于系统有 bug 或者有不正确的调用)能很快地搞垮你的系统,而且可能很难恢复。

谷歌的 Christina Schulman 和 Etienne Perot 在用安全规约协助保护你的数据中心的演讲中给了一些例子。其中一次事故是将谷歌整个内部的内容分发网络(CDN)提交给了擦除磁盘的自动化系统。

Schulman 和 Perot 建议使用一个中心服务来管理规约,限制破坏性自动化操作的速度,并能感知到系统状态(比如避免在最近有告警的服务上执行破坏性的操作)。

自动化系统在与运维人员(或其他自动化系统)交互时,也可能造成严重事故。Reddit 遭遇过一次严重的服务中断,当时他们的自动化系统重启了一个服务,但是这个服务是运维人员停掉做维护的。一旦有了多个自动化系统,它们之间潜在的交互就变得异常复杂和不可预测。

所有的自动化系统都把日志输出到一个容易搜索的中心存储上,能帮助到对这类不可避免的意外情况的处理。自动化系统总是应该具备这样一种机制,即允许快速地关掉它们(完全关掉或者只关掉其中一部分操作或一部分目标)。

防止黑天鹅事件

可能在等着击垮系统的黑天鹅可不止上面这些。有很多其他的严重问题是能通过一些技术来避免的,像金丝雀发布、压力测试、混沌工程、灾难测试和模糊测试 —— 当然还有冗余性和弹性的设计。但是即使用了这些技术,有时候你的系统还是会有故障。

为了确保你的组织能有效地响应,在服务中断期间,请保证关键技术人员和领导层有办法沟通协调。例如,有一种你可能需要处理的烦人的事情,那就是网络完全中断。拥有故障时仍然可用的通信通道非常重要,这个通信通道要完全独立于你们自己的基础设施及对其的依赖。举个例子,假如你使用 AWS,那么把故障时可用的通信服务部署在 AWS 上就不明智了。在和你的主系统无关的地方,运行电话网桥或 IRC 服务器是比较好的方案。确保每个人都知道这个通信平台,并练习使用它。

另一个原则是,确保监控和运维工具对生产环境系统的依赖尽可能的少。将控制平面和数据平面分开,你才能在系统不健康的时候做变更。不要让数据处理和配置变更或监控使用同一个消息队列,比如,应该使用不同的消息队列实例。在 SparkPost: DNS 挂掉的那一天 这个演讲中,Jeremy Blosser 讲了一个这类例子,很关键的工具依赖了生产环境的 DNS 配置,但是生产环境的 DNS 出了问题。

对抗黑天鹅的心理学

处理生产环境的重大事故时会产生很大的压力。为这些场景制定结构化的事故管理流程确实是有帮助的。很多科技公司(包括谷歌)成功地使用了联邦应急管理局事故指挥系统的某个版本。对于每一个值班的人,遇到了他们无法独立解决的重大问题时,都应该有一个明确的寻求协助的方法。

对于那些持续很长时间的事故,有一点很重要,要确保工程师不会连续工作到不合理的时长,确保他们不会不吃不睡(没有报警打扰的睡觉)。疲惫不堪的工程师很容易犯错或者漏掉了可能更快解决故障的信息。

了解更多

关于黑天鹅(或者以前的黑天鹅)事件以及应对策略,还有很多其他的事情可以说。如果你想了解更多,我强烈推荐你去看这两本书,它们是关于生产环境中的弹性和稳定性的:Susan Fowler 写的《生产微服务》,还有 Michael T. Nygard 的 《Release It!》。


via: https://opensource.com/article/18/10/taxonomy-black-swans

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

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

熟悉你的环境对高效率的开发和调试来说是至关重要的。本文将为你简单概述一下 JOS 环境和非常有用的 GDB 和 QEMU 命令。话虽如此,但你仍然应该去阅读 GDB 和 QEMU 手册,来理解这些强大的工具如何使用。

调试小贴士

内核

GDB 是你的朋友。使用 qemu-gdb target(或它的变体 qemu-gdb-nox)使 QEMU 等待 GDB 去绑定。下面在调试内核时用到的一些命令,可以去查看 GDB 的资料。

如果你遭遇意外的中断、异常、或三重故障,你可以使用 -d 参数要求 QEMU 去产生一个详细的中断日志。

调试虚拟内存问题时,尝试 QEMU 的监视命令 info mem(提供内存高级概述)或 info pg(提供更多细节内容)。注意,这些命令仅显示当前页表。

(在实验 4 以后)去调试多个 CPU 时,使用 GDB 的线程相关命令,比如 threadinfo threads

用户环境(在实验 3 以后)

GDB 也可以去调试用户环境,但是有些事情需要注意,因为 GDB 无法区分开多个用户环境或区分开用户环境与内核环境。

你可以使用 make run-name(或编辑 kern/init.c 目录)来指定 JOS 启动的用户环境,为使 QEMU 等待 GDB 去绑定,使用 run-name-gdb 的变体。

你可以符号化调试用户代码,就像调试内核代码一样,但是你要告诉 GDB,哪个符号表用到符号文件命令上,因为它一次仅能够使用一个符号表。提供的 .gdbinit 用于加载内核符号表 obj/kern/kernel。对于一个用户环境,这个符号表在它的 ELF 二进制文件中,因此你可以使用 symbol-file obj/user/name 去加载它。不要从任何 .o 文件中加载符号,因为它们不会被链接器迁移进去(库是静态链接进 JOS 用户二进制文件中的,因此这些符号已经包含在每个用户二进制文件中了)。确保你得到了正确的用户二进制文件;在不同的二进制文件中,库函数被链接为不同的 EIP,而 GDB 并不知道更多的内容!

(在实验 4 以后)因为 GDB 绑定了整个虚拟机,所以它可以将时钟中断看作为一种控制转移。这使得从底层上不可能实现步进用户代码,因为一个时钟中断无形中保证了片刻之后虚拟机可以再次运行。因此可以使用 stepi 命令,因为它阻止了中断,但它仅可以步进一个汇编指令。断点一般来说可以正常工作,但要注意,因为你可能在不同的环境(完全不同的一个二进制文件)上遇到同一个 EIP。

参考

JOS makefile

JOS 的 GNUmakefile 包含了在各种方式中运行的 JOS 的许多假目标。所有这些目标都配置 QEMU 去监听 GDB 连接(*-gdb 目标也等待这个连接)。要在运行中的 QEMU 上启动它,只需要在你的实验目录中简单地运行 gdb 即可。我们提供了一个 .gdbinit 文件,它可以在 QEMU 中自动指向到 GDB、加载内核符号文件、以及在 16 位和 32 位模式之间切换。退出 GDB 将关闭 QEMU。

  • make qemu

在一个新窗口中构建所有的东西并使用 VGA 控制台和你的终端中的串行控制台启动 QEMU。想退出时,既可以关闭 VGA 窗口,也可以在你的终端中按 Ctrl-cCtrl-a x

  • make qemu-nox

make qemu 一样,但仅使用串行控制台来运行。想退出时,按下 Ctrl-a x。这种方式在通过 SSH 拨号连接到 Athena 上时非常有用,因为 VGA 窗口会占用许多带宽。

  • make qemu-gdb

make qemu 一样,但它与任意时间被动接受 GDB 不同,而是暂停第一个机器指令并等待一个 GDB 连接。

  • make qemu-nox-gdb

它是 qemu-noxqemu-gdb 目标的组合。

  • make run-nam

(在实验 3 以后)运行用户程序 name。例如,make run-hello 运行 user/hello.c

  • make run-name-nox,run-name-gdb, run-name-gdb-nox

(在实验 3 以后)与 qemu 目标变量对应的 run-name 的变体。

makefile 也接受几个非常有用的变量:

  • make V=1 …

详细模式。输出正在运行的每个命令,包括参数。

  • make V=1 grade

在评级测试失败后停止,并将 QEMU 的输出放入 jos.out 文件中以备检查。

  • make QEMUEXTRA=' _args_ ' …

指定传递给 QEMU 的额外参数。

JOS obj/

在构建 JOS 时,makefile 也产生一些额外的输出文件,这些文件在调试时非常有用:

  • obj/boot/boot.asmobj/kern/kernel.asmobj/user/hello.asm、等等。

引导加载器、内核、和用户程序的汇编代码列表。

  • obj/kern/kernel.symobj/user/hello.sym、等等。

内核和用户程序的符号表。

  • obj/boot/boot.outobj/kern/kernelobj/user/hello、等等。

内核和用户程序链接的 ELF 镜像。它们包含了 GDB 用到的符号信息。

GDB

完整的 GDB 命令指南请查看 GDB 手册。下面是一些在 6.828 课程中非常有用的命令,它们中的一些在操作系统开发之外的领域几乎用不到。

  • Ctrl-c

在当前指令处停止机器并打断进入到 GDB。如果 QEMU 有多个虚拟的 CPU,所有的 CPU 都会停止。

  • c(或 continue

继续运行,直到下一个断点或 Ctrl-c

  • si(或 stepi

运行一个机器指令。

  • b functionb file:line(或 breakpoint

在给定的函数或行上设置一个断点。

  • b * addr(或 breakpoint

在 EIP 的 addr 处设置一个断点。

  • set print pretty

启用数组和结构的美化输出。

  • info registers

输出通用寄存器 eipeflags、和段选择器。更多更全的机器寄存器状态转储,查看 QEMU 自己的 info registers 命令。

  • x/ N x addr

以十六进制显示虚拟地址 addr 处开始的 N 个词的转储。如果 N 省略,默认为 1。addr 可以是任何表达式。

  • x/ N i addr

显示从 addr 处开始的 N 个汇编指令。使用 $eip 作为 addr 将显示当前指令指针寄存器中的指令。

  • symbol-file file

(在实验 3 以后)切换到符号文件 file 上。当 GDB 绑定到 QEMU 后,它并不是虚拟机中进程边界内的一部分,因此我们要去告诉它去使用哪个符号。默认情况下,我们配置 GDB 去使用内核符号文件 obj/kern/kernel。如果机器正在运行用户代码,比如是 hello.c,你就需要使用 symbol-file obj/user/hello 去切换到 hello 的符号文件。

QEMU 将每个虚拟 CPU 表示为 GDB 中的一个线程,因此你可以使用 GDB 中所有的线程相关的命令去查看或维护 QEMU 的虚拟 CPU。

  • thread n

GDB 在一个时刻只关注于一个线程(即:CPU)。这个命令将关注的线程切换到 n,n 是从 0 开始编号的。

  • info threads

列出所有的线程(即:CPU),包括它们的状态(活动还是停止)和它们在什么函数中。

QEMU

QEMU 包含一个内置的监视器,它能够有效地检查和修改机器状态。想进入到监视器中,在运行 QEMU 的终端中按入 Ctrl-a c 即可。再次按下 Ctrl-a c 将切换回串行控制台。

监视器命令的完整参考资料,请查看 QEMU 手册。下面是 6.828 课程中用到的一些有用的命令:

  • xp/ N x paddr

显示从物理地址 paddr 处开始的 N 个词的十六进制转储。如果 N 省略,默认为 1。这是 GDB 的 x 命令模拟的物理内存。

  • info registers

显示机器内部寄存器状态的一个完整转储。实践中,对于段选择器,这将包含机器的 隐藏 段状态和局部、全局、和中断描述符表加任务状态寄存器。隐藏状态是在加载段选择器后,虚拟的 CPU 从 GDT/LDT 中读取的信息。下面是实验 1 中 JOS 内核处于运行中时的 CS 信息和每个字段的含义:

CS =0008 10000000 ffffffff 10cf9a00 DPL=0 CS32 [-R-]
  • CS =0008

代码选择器可见部分。我们使用段 0x8。这也告诉我们参考全局描述符表(0x8&4=0),并且我们的 CPL(当前权限级别)是 0x8&3=0。

  • 10000000

这是段基址。线性地址 = 逻辑地址 + 0x10000000。

  • ffffffff

这是段限制。访问线性地址 0xffffffff 以上将返回段违规异常。

  • 10cf9a00

段的原始标志,QEMU 将在接下来的几个字段中解码这些对我们有用的标志。

  • DPL=0

段的权限级别。一旦代码以权限 0 运行,它将就能够加载这个段。

  • CS32

这是一个 32 位代码段。对于数据段(不要与 DS 寄存器混淆了),另外的值还包括 DS,而对于本地描述符表是 LDT

  • [-R-]

这个段是只读的。

  • info mem

(在实验 2 以后)显示映射的虚拟内存和权限。比如:

ef7c0000-ef800000 00040000 urw
efbf8000-efc00000 00008000 -rw

这告诉我们从 0xef7c0000 到 0xef800000 的 0x00040000 字节的内存被映射为读取/写入/用户可访问,而映射在 0xefbf8000 到 0xefc00000 之间的内存权限是读取/写入,但是仅限于内核可访问。

  • info pg

(在实验 2 以后)显示当前页表结构。它的输出类似于 info mem,但与页目录条目和页表条目是有区别的,并且为每个条目给了单独的权限。重复的 PTE 和整个页表被折叠为一个单行。例如:

VPN range     Entry         Flags        Physical page
[00000-003ff]  PDE[000]     -------UWP
  [00200-00233]  PTE[200-233] -------U-P 00380 0037e 0037d 0037c 0037b 0037a ..
[00800-00bff]  PDE[002]     ----A--UWP
  [00800-00801]  PTE[000-001] ----A--U-P 0034b 00349
  [00802-00802]  PTE[002]     -------U-P 00348

这里各自显示了两个页目录条目、虚拟地址范围 0x00000000 到 0x003fffff 以及 0x00800000 到 0x00bfffff。 所有的 PDE 都存在于内存中、可写入、并且用户可访问,而第二个 PDE 也是可访问的。这些页表中的第二个映射了三个页、虚拟地址范围 0x00800000 到 0x00802fff,其中前两个页是存在于内存中的、可写入、并且用户可访问的,而第三个仅存在于内存中,并且用户可访问。这些 PTE 的第一个条目映射在物理页 0x34b 处。

QEMU 也有一些非常有用的命令行参数,使用 QEMUEXTRA 变量可以将参数传递给 JOS 的 makefile。

  • make QEMUEXTRA='-d int' ...

记录所有的中断和一个完整的寄存器转储到 qemu.log 文件中。你可以忽略前两个日志条目、“SMM: enter” 和 “SMM: after RMS”,因为这些是在进入引导加载器之前生成的。在这之后的日志条目看起来像下面这样:

     4: v=30 e=0000 i=1 cpl=3 IP=001b:00800e2e pc=00800e2e SP=0023:eebfdf28 EAX=00000005
EAX=00000005 EBX=00001002 ECX=00200000 EDX=00000000
ESI=00000805 EDI=00200000 EBP=eebfdf60 ESP=eebfdf28
...

第一行描述了中断。4: 只是一个日志记录计数器。v 提供了十六进程的向量号。e 提供了错误代码。i=1 表示它是由一个 int 指令(相对一个硬件产生的中断而言)产生的。剩下的行的意思很明显。对于一个寄存器转储而言,接下来看到的就是寄存器信息。

注意:如果你运行的是一个 0.15 版本之前的 QEMU,日志将写入到 /tmp 目录,而不是当前目录下。


via: https://pdos.csail.mit.edu/6.828/2018/labguide.html

作者:csail.mit 选题:lujun9972 译者:qhwdw 校对:wxy

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

记录笔记是我们每个人必备的重要技能,它可以帮助我们把自己听到、读到、学到的内容长期地保留下来,也有很多的应用和工具都能让我们更好地记录笔记。下面我要介绍一个叫做 ProtectedText 的应用,这是一个可以将你的笔记在线上保存起来的免费的加密笔记。它是一个免费的 web 服务,在上面记录文本以后,它将会对文本进行加密,只需要一台支持连接到互联网并且拥有 web 浏览器的设备,就可以访问到记录的内容。

ProtectedText 不会向你询问任何个人信息,也不会保存任何密码,没有广告,没有 Cookies,更没有用户跟踪和注册流程。除了拥有密码能够解密文本的人,任何人都无法查看到笔记的内容。而且,使用前不需要在网站上注册账号,写完笔记之后,直接关闭浏览器,你的笔记也就保存好了。

在加密笔记本上记录笔记

访问 https://www.protectedtext.com/这个链接,就可以打开ProtectedText页面了(LCTT译注:如果访问不了,你知道的)。这个时候你将进入网站主页,接下来需要在页面上的输入框输入一个你想用的名称,或者在地址栏后面直接加上想用的名称。这个名称是一个自定义的名称(例如https://www.protectedtext.com/mysite),是你查看自己保存的笔记的专有入口。

如果你选用的名称还没有被占用,你就会看到下图中的提示信息。点击 “Create” 键就可以创建你的个人笔记页了。

至此你已经创建好了你自己的笔记页面,可以开始记录笔记了。目前每个笔记页的最大容量是每页 750000+ 个字符。

ProtectedText 使用 AES 算法对你的笔记内容进行加密和解密,而计算散列则使用了 SHA512 算法。

笔记记录完毕以后,点击顶部的 “Save” 键保存。

按下保存键之后,ProtectedText 会提示你输入密码以加密你的笔记内容。按照它的要求输入两次密码,然后点击 “Save” 键。

尽管 ProtectedText 对你使用的密码没有太多要求,但毕竟密码总是一寸长一寸强,所以还是最好使用长且复杂的密码(用到数字和特殊字符)以避免暴力破解。由于 ProtectedText 不会保存你的密码,一旦密码丢失,密码和笔记内容就都找不回来了。因此,请牢记你的密码,或者使用诸如 ButtercupKeeWeb 这样的密码管理器来存储你的密码。

在使用其它设备时,可以通过访问之前创建的 URL 就可以访问你的笔记了。届时会出现如下的提示信息,只需要输入正确的密码,就可以查看和编辑你的笔记。

一般情况下,只有知道密码的人才能正常访问笔记的内容。如果你希望将自己的笔记公开,只需要以 https://www.protectedtext.com/yourSite?yourPassword 的形式访问就可以了,ProtectedText 将会自动使用 yourPassword 字符串解密你的笔记。

ProtectedText 还有配套的 Android 应用 可以让你在移动设备上进行同步笔记、离线工作、备份笔记、锁定/解锁笔记等等操作。

优点

  • 简单、易用、快速、免费
  • ProtectedText.com 的客户端代码可以在这里免费获取,如果你想了解它的底层实现,可以自行学习它的源代码
  • 存储的内容没有到期时间,只要你愿意,笔记内容可以一直保存在服务器上
  • 可以让你的数据限制为私有或公开开放

缺点

  • 尽管客户端代码是公开的,但服务端代码并没有公开,因此你无法自行搭建一个类似的服务。如果你不信任这个网站,请不要使用。
  • 由于网站不存储你的任何个人信息,包括你的密码,因此如果你丢失了密码,数据将永远无法恢复。网站方还声称他们并不清楚谁拥有了哪些数据,所以一定要牢记密码。

如果你想通过一种简单的方式将笔记保存到线上,并且需要在不需要安装任何工具的情况下访问,那么 ProtectedText 会是一个好的选择。如果你还知道其它类似的应用程序,欢迎在评论区留言!


via: https://www.ostechnix.com/protectedtext-a-free-encrypted-notepad-to-save-your-notes-online/

作者:SK 选题:lujun9972 译者:HankChow 校对:wxy

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

之前,Steam 宣布要给 Steam Play 增加一个新组件,用于支持在 Linux 平台上使用 Proton 来玩 Windows 的游戏,这个组件是 WINE 的一个分支。这个功能仍然处于测试阶段,且并非对所有游戏都有效。这里有一些关于 Steam 和 Proton 的细节。

据 Steam 网站称,测试版本中有以下这些新功能:

  • 现在没有 Linux 版本的 Windows 游戏可以直接从 Linux 上的 Steam 客户端进行安装和运行,并且有完整、原生的 Steamworks 和 OpenVR 的支持。
  • 现在 DirectX 11 和 12 的实现都基于 Vulkan,它可以提高游戏的兼容性并减小游戏性能收到的影响。
  • 全屏支持已经得到了改进,全屏游戏时可以无缝扩展到所需的显示程度,而不会干扰到显示屏本身的分辨率或者说需要使用虚拟桌面。
  • 改进了对游戏控制器的支持,游戏自动识别所有 Steam 支持的控制器,比起游戏的原始版本,能够获得更多开箱即用的控制器兼容性。
  • 和 vanilla WINE 比起来,游戏的多线程性能得到了极大的提高。

安装

如果你有兴趣,想尝试一下 Steam 和 Proton。请按照下面这些简单的步骤进行操作。(请注意,如果你已经安装了最新版本的 Steam,可以忽略启用 Steam 测试版这个第一步。在这种情况下,你不再需要通过 Steam 测试版来使用 Proton。)

打开 Steam 并登陆到你的帐户,这个截屏示例显示的是在使用 Proton 之前仅支持 22 个游戏。

现在点击客户端顶部的 “Steam” 选项,这会显示一个下拉菜单。然后选择“设置”。

现在弹出了设置窗口,选择“账户”选项,并在 “参与 Beta 测试” 旁边,点击“更改”。

现在将 “None” 更改为 “Steam Beta Update”。

点击“确定”,然后系统会提示你重新启动。

让 Steam 下载更新,这会需要一段时间,具体需要多久这要取决于你的网络速度和电脑配置。

在重新启动之后,返回到上面的设置窗口。这次你会看到一个新选项。确定勾选了“为提供支持的游戏使用 Stream Play” 、“让所有的游戏都使用 Steam Play 运行”,“使用这个工具替代 Steam 中游戏特定的选项”。这个兼容性工具应该就是 Proton。

Steam 客户端会要求你重新启动,照做,然后重新登录你的 Steam 账户,你的 Linux 的游戏库就能得到扩展了。

使用 Steam Play 来安装一个 Windows 游戏

现在你已经启用 Proton,开始安装游戏,选择你想要安装的游戏,然后你会发现这个安装过程类似于在 Steam 上安装一个普通游戏,如下面这些截图所示。

在下载和安装完游戏后,你就可以开始玩了。

一些游戏可能会受到 Proton 测试性质的影响,在这个叫 Chantelise 游戏中,没有了声音并且帧率很低。请记住这个功能仍然在测试阶段,Fedora 不会对结果负责。如果你想要了解更多,社区已经创建了一个 Google 文档,这个文档里有已经测试过的游戏的列表。


via: https://fedoramagazine.org/play-windows-games-steam-play-proton/

作者:Francisco J. Vergara Torres 选题:lujun9972 译者:hopefully2333 校对:wxy

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