2018年4月

 title=

我目前正在参加一个机器学习班,虽然工作量很疯狂,但我非常喜欢。我最初计划使用 R) 来训练我的数据库,但老师建议我使用一个 FOSS 机器学习框架 H2o

起初我有点怀疑,因为我已经对 R 掌握得不错了,但后来我发现你可以简单地将 H2o 作为 R 库导入。H2o 将大多数 R 函数替换为其自己的并行化函数,以减少处理时间(不再需要 doParallel 调用),并且使用“外部”服务端来运行,而不是直接调用 R。

 title=

直到我真正在实际中开始在 H2o 中使用 R 时,我对这种情况都非常满意。我在使用非常大的数据库时,库变得笨重,我几乎不能做任何有用得事情。大多数时候,我最后只是得到一个很长的 Java 回溯调用。

我相信正确地将 H2o 作为一个库使用将非常强大,但可惜的是,它似乎在我的 R 技能中无效。

 title=

我生了一整天的气 —— 无法实现我想做的事 —— 直到我意识到 H2o 有一个名为 Flow 的 WebUI。我通常不喜欢使用 web 来完成重要的工作,比如编写代码,但是 Flow 简直太不可思议了。

自动绘图功能,运行资源密集模型时集成 ETA(预计剩余时间),每个模型参数的描述(这些参数甚至会根据您熟悉的统计模型分成不同部分),Flow 似乎拥有所有功能。我很快就能够运行 3 种基本的机器学习模型并获得实际可解释的结果。

所以,如果你一直渴望使用最先进的机器学习模型分析非常大的数据库,我会推荐使用 H2o。首先尝试使用 Flow,而不是 Python 或 R 的钩子,来看看它能做什么。

唯一缺点是,H2o 是用 Java 编写的,并依赖 Java 1.7 来运行。并且需要警告的是:它需要非常强大的处理器和大量的内存。即使有 10 个可用的内核和 10Gb 的 RAM,我可怜的服务器也苦苦挣扎了一段时间。


via: https://veronneau.org/playing-with-water.html

作者:Louis-Philippe Véronneau 译者:geekpi 校对:wxy

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

如何下载并使用运行在 Ubuntu Linux 服务器上的 KVM 云镜像?如何在 Ubuntu Linux 16.04 LTS 服务器上无需完整安装即可创建虚拟机?如何在 Ubuntu Linux 上使用 KVM 云镜像?

基于内核的虚拟机(KVM)是 Linux 内核的虚拟化模块,可将其转变为虚拟机管理程序。你可以在命令行使用 Ubuntu 为 libvirt 和 KVM 提供的虚拟化前端通过 KVM 创建 Ubuntu 云镜像。

这个快速教程展示了如何安装和使用 uvtool,它为 Ubuntu 云镜像下载,libvirt 和 clout\_int 提供了统一的集成虚拟机前端。

步骤 1 - 安装 KVM

你必须安装并配置 KVM。使用 apt 命令/apt-get 命令,如下所示:

$ sudo apt install qemu-kvm libvirt-bin virtinst bridge-utils cpu-checker
$ kvm-ok
## [configure bridged networking as described here][3]
$ sudo vi /etc/network/interfaces
$ sudo systemctl restart networking
$ sudo brctl show

参阅如何在 Ubuntu 16.04 LTS Headless 服务器上安装 KVM 以获得更多信息。(LCTT 译注:Headless 服务器是指没有本地接口的计算设备,专用于向其他计算机及其用户提供服务。)

步骤 2 - 安装 uvtool

键入以下 apt 命令/apt-get 命令

$ sudo apt install uvtool

示例输出:

[sudo] password for vivek: 
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following packages were automatically installed and are no longer required:
  gksu libgksu2-0 libqt5designer5 libqt5help5 libqt5printsupport5 libqt5sql5 libqt5sql5-sqlite libqt5xml5 python3-dbus.mainloop.pyqt5 python3-notify2 python3-pyqt5 python3-sip
Use 'sudo apt autoremove' to remove them.
The following additional packages will be installed:
  cloud-image-utils distro-info python-boto python-pyinotify python-simplestreams socat ubuntu-cloudimage-keyring uvtool-libvirt
Suggested packages:
  cloud-utils-euca shunit2 python-pyinotify-doc
The following NEW packages will be installed:
  cloud-image-utils distro-info python-boto python-pyinotify python-simplestreams socat ubuntu-cloudimage-keyring uvtool uvtool-libvirt
0 upgraded, 9 newly installed, 0 to remove and 0 not upgraded.
Need to get 1,211 kB of archives.
After this operation, 6,876 kB of additional disk space will be used.
Get:1 http://in.archive.ubuntu.com/ubuntu artful/main amd64 distro-info amd64 0.17 [20.3 kB]
Get:2 http://in.archive.ubuntu.com/ubuntu artful/universe amd64 python-boto all 2.44.0-1ubuntu2 [740 kB]
Get:3 http://in.archive.ubuntu.com/ubuntu artful/main amd64 python-pyinotify all 0.9.6-1 [24.6 kB]
Get:4 http://in.archive.ubuntu.com/ubuntu artful/main amd64 ubuntu-cloudimage-keyring all 2013.11.11 [4,504 B]
Get:5 http://in.archive.ubuntu.com/ubuntu artful/main amd64 cloud-image-utils all 0.30-0ubuntu2 [17.2 kB]
Get:6 http://in.archive.ubuntu.com/ubuntu artful/universe amd64 python-simplestreams all 0.1.0~bzr450-0ubuntu1 [29.7 kB]
Get:7 http://in.archive.ubuntu.com/ubuntu artful/universe amd64 socat amd64 1.7.3.2-1 [342 kB]
Get:8 http://in.archive.ubuntu.com/ubuntu artful/universe amd64 uvtool all 0~git122-0ubuntu1 [6,498 B]
Get:9 http://in.archive.ubuntu.com/ubuntu artful/universe amd64 uvtool-libvirt all 0~git122-0ubuntu1 [26.9 kB]
Fetched 1,211 kB in 3s (393 kB/s)        
Selecting previously unselected package distro-info.
(Reading database ... 199933 files and directories currently installed.)
Preparing to unpack .../0-distro-info_0.17_amd64.deb ...
Unpacking distro-info (0.17) ...
Selecting previously unselected package python-boto.
Preparing to unpack .../1-python-boto_2.44.0-1ubuntu2_all.deb ...
Unpacking python-boto (2.44.0-1ubuntu2) ...
Selecting previously unselected package python-pyinotify.
Preparing to unpack .../2-python-pyinotify_0.9.6-1_all.deb ...
Unpacking python-pyinotify (0.9.6-1) ...
Selecting previously unselected package ubuntu-cloudimage-keyring.
Preparing to unpack .../3-ubuntu-cloudimage-keyring_2013.11.11_all.deb ...
Unpacking ubuntu-cloudimage-keyring (2013.11.11) ...
Selecting previously unselected package cloud-image-utils.
Preparing to unpack .../4-cloud-image-utils_0.30-0ubuntu2_all.deb ...
Unpacking cloud-image-utils (0.30-0ubuntu2) ...
Selecting previously unselected package python-simplestreams.
Preparing to unpack .../5-python-simplestreams_0.1.0~bzr450-0ubuntu1_all.deb ...
Unpacking python-simplestreams (0.1.0~bzr450-0ubuntu1) ...
Selecting previously unselected package socat.
Preparing to unpack .../6-socat_1.7.3.2-1_amd64.deb ...
Unpacking socat (1.7.3.2-1) ...
Selecting previously unselected package uvtool.
Preparing to unpack .../7-uvtool_0~git122-0ubuntu1_all.deb ...
Unpacking uvtool (0~git122-0ubuntu1) ...
Selecting previously unselected package uvtool-libvirt.
Preparing to unpack .../8-uvtool-libvirt_0~git122-0ubuntu1_all.deb ...
Unpacking uvtool-libvirt (0~git122-0ubuntu1) ...
Setting up distro-info (0.17) ...
Setting up ubuntu-cloudimage-keyring (2013.11.11) ...
Setting up cloud-image-utils (0.30-0ubuntu2) ...
Setting up socat (1.7.3.2-1) ...
Setting up python-pyinotify (0.9.6-1) ...
Setting up python-boto (2.44.0-1ubuntu2) ...
Setting up python-simplestreams (0.1.0~bzr450-0ubuntu1) ...
Processing triggers for doc-base (0.10.7) ...
Processing 1 added doc-base file...
Setting up uvtool (0~git122-0ubuntu1) ...
Processing triggers for man-db (2.7.6.1-2) ...
Setting up uvtool-libvirt (0~git122-0ubuntu1) ...

步骤 3 - 下载 Ubuntu 云镜像

你需要使用 uvt-simplestreams-libvirt 命令。它维护一个 libvirt 容量存储池,作为一个 简单流 simplestreams 源的镜像子集的本地镜像,比如 Ubuntu 云镜像。要使用当前所有 amd64 镜像更新 uvtool 的 libvirt 容量存储池,运行:

$ uvt-simplestreams-libvirt sync arch=amd64

要更新/获取 Ubuntu 16.04 LTS (xenial/amd64) 镜像,运行:

$ uvt-simplestreams-libvirt --verbose sync release=xenial arch=amd64

示例输出:

Adding: com.ubuntu.cloud:server:16.04:amd64 20171121.1

通过 query 选项查询本地镜像:

$ uvt-simplestreams-libvirt query

示例输出:

release=xenial arch=amd64 label=release (20171121.1)

现在,我为 Ubuntu xenial 创建了一个镜像,接下来我会创建虚拟机。

步骤 4 - 创建 SSH 密钥

你需要使用 SSH 密钥才能登录到 KVM 虚拟机。如果你根本没有任何密钥,请使用 ssh-keygen 命令创建一个新的密钥。

$ ssh-keygen

参阅“如何在 Linux / Unix 系统上设置 SSH 密钥” 和 “Linux / UNIX: 生成 SSH 密钥” 以获取更多信息。

步骤 5 - 创建 VM

是时候创建虚拟机了,它叫 vm1,即创建一个 Ubuntu Linux 16.04 LTS 虚拟机:

$ uvt-kvm create vm1

默认情况下 vm1 使用以下配置创建:

  1. 内存:512M
  2. 磁盘大小:8GiB
  3. CPU:1 vCPU core

要控制内存、磁盘、CPU 和其他配置,使用以下语法:

$ uvt-kvm create vm1 \
--memory MEMORY \
--cpu CPU \
--disk DISK \
--bridge BRIDGE \
--ssh-public-key-file /path/to/your/SSH_PUBLIC_KEY_FILE \
--packages PACKAGES1, PACKAGES2, .. \
--run-script-once RUN_SCRIPT_ONCE \
--password PASSWORD

其中

  1. --password PASSWORD:设置 ubuntu 用户的密码和允许使用 ubuntu 的用户登录(不推荐,使用 ssh 密钥)。
  2. --run-script-once RUN_SCRIPT_ONCE : 第一次启动时,在虚拟机上以 root 身份运行 RUN_SCRIPT_ONCE 脚本,但再也不会运行。这里给出完整的路径。这对于在虚拟机上运行自定义任务时非常有用,例如设置安全性或其他内容。
  3. --packages PACKAGES1, PACKAGES2, .. : 在第一次启动时安装以逗号分隔的软件包。

要获取帮助,运行:

$ uvt-kvm -h
$ uvt-kvm create -h

如何删除虚拟机?

要销毁/删除名为 vm1 的虚拟机,运行(请小心使用以下命令,因为没有确认框):

$ uvt-kvm destroy vm1

获取 vm1 的 IP 地址,运行:

$ uvt-kvm ip vm1
192.168.122.52

列出所有运行的虚拟机

$ uvt-kvm list

示例输出:

vm1
freebsd11.1

步骤 6 - 如何登录 vm1

语法是:

$ uvt-kvm ssh vm1

示例输出:

Welcome to Ubuntu 16.04.3 LTS (GNU/Linux 4.4.0-101-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud

0 packages can be updated.
0 updates are security updates.


Last login: Thu Dec  7 09:55:06 2017 from 192.168.122.1

另一个选择是从 macOS/Linux/Unix/Windows 客户端使用常规的 ssh 命令:

$ ssh [email protected]
$ ssh -i ~/.ssh/id_rsa [email protected]

示例输出:

Connect to the running VM using ssh

一旦创建了 vim,你可以照常使用 virsh 命令:

$ virsh list

via: https://www.cyberciti.biz/faq/how-to-use-kvm-cloud-images-on-ubuntu-linux/

作者:Vivek Gite 译者:MjSeven 校对:wxy

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

在一本叫做 《高效思考的 5 要素》 的书中,作者 Burger 和 Starbird 讲述了一个关于他们如何研究 Tony Plog 的故事,他是一位举世闻名的交响曲名家,为一些有才华的演奏者开创了一个大师班。这些学生一开始演奏复杂的乐曲,他们演奏的非常好。然后他们被要求演奏非常基础简单的乐曲。当他们演奏这些乐曲时,与之前所演奏的相比,听起来非常幼稚。在他们结束演奏后,老师也演奏了同样的乐曲,但是听上去非常娴熟。差别令人震惊。Tony 解释道,精通简单音符可以让人更好的掌握复杂的部分。这个例子很清晰 —— 要成为真正的名家,必须要掌握简单基础的思想。

故事中的例子明显不仅仅适用于音乐,而且适用于软件开发。这个故事告诉我们不要忽视繁琐工作中简单基础的概念的重要性,哪怕有时候这让人感觉是一种倒退。尽管熟练掌握一门工具或者框架非常重要,了解它们背后的原理也是极其重要的。正如 Palph Waldo Emerson 所说:

“如果你只学习方法,你就会被方法束缚。但如果你知道原理,就可以发明自己的方法。”

有鉴于此,让我们再次深入了解解释器和编译器。

今天我会向你们展示一个全新的计算器,与 第一部分 相比,它可以做到:

  1. 处理输入字符串任意位置的空白符
  2. 识别输入字符串中的多位整数
  3. 做两个整数之间的减法(目前它仅能加减整数)

新版本计算器的源代码在这里,它可以做到上述的所有事情:

# 标记类型
# EOF (end-of-file 文件末尾)标记是用来表示所有输入都解析完成
INTEGER, PLUS, MINUS, EOF = 'INTEGER', 'PLUS', 'MINUS', 'EOF'


class Token(object):
    def __init__(self, type, value):
        # token 类型: INTEGER, PLUS, MINUS, or EOF
        self.type = type
        # token 值: 非负整数值, '+', '-', 或无
        self.value = value

    def __str__(self):
        """String representation of the class instance.

        Examples:
            Token(INTEGER, 3)
            Token(PLUS '+')
        """
        return 'Token({type}, {value})'.format(
            type=self.type,
            value=repr(self.value)
        )

    def __repr__(self):
        return self.__str__()


class Interpreter(object):
    def __init__(self, text):
        # 客户端字符输入, 例如. "3 + 5", "12 - 5", 
        self.text = text
        # self.pos 是 self.text 的索引
        self.pos = 0
        # 当前标记实例
        self.current_token = None
        self.current_char = self.text[self.pos]

    def error(self):
        raise Exception('Error parsing input')

    def advance(self):
        """Advance the 'pos' pointer and set the 'current_char' variable."""
        self.pos += 1
        if self.pos > len(self.text) - 1:
            self.current_char = None  # Indicates end of input
        else:
            self.current_char = self.text[self.pos]

    def skip_whitespace(self):
        while self.current_char is not None and self.current_char.isspace():
            self.advance()

    def integer(self):
        """Return a (multidigit) integer consumed from the input."""
        result = ''
        while self.current_char is not None and self.current_char.isdigit():
            result += self.current_char
            self.advance()
        return int(result)

    def get_next_token(self):
        """Lexical analyzer (also known as scanner or tokenizer)

        This method is responsible for breaking a sentence
        apart into tokens.
        """
        while self.current_char is not None:

            if self.current_char.isspace():
                self.skip_whitespace()
                continue

            if self.current_char.isdigit():
                return Token(INTEGER, self.integer())

            if self.current_char == '+':
                self.advance()
                return Token(PLUS, '+')

            if self.current_char == '-':
                self.advance()
                return Token(MINUS, '-')

            self.error()

        return Token(EOF, None)

    def eat(self, token_type):
        # 将当前的标记类型与传入的标记类型作比较,如果他们相匹配,就
        # “eat” 掉当前的标记并将下一个标记赋给 self.current_token,
        # 否则抛出一个异常
        if self.current_token.type == token_type:
            self.current_token = self.get_next_token()
        else:
            self.error()

    def expr(self):
        """Parser / Interpreter

        expr -> INTEGER PLUS INTEGER
        expr -> INTEGER MINUS INTEGER
        """
        # 将输入中的第一个标记设置成当前标记
        self.current_token = self.get_next_token()

        # 当前标记应该是一个整数
        left = self.current_token
        self.eat(INTEGER)

        # 当前标记应该是 ‘+’ 或 ‘-’
        op = self.current_token
        if op.type == PLUS:
            self.eat(PLUS)
        else:
            self.eat(MINUS)

        # 当前标记应该是一个整数
        right = self.current_token
        self.eat(INTEGER)
        # 在上述函数调用后,self.current_token 就被设为 EOF 标记

        # 这时要么是成功地找到 INTEGER PLUS INTEGER,要么是 INTEGER MINUS INTEGER
        # 序列的标记,并且这个方法可以仅仅返回两个整数的加或减的结果,就能高效解释客户端的输入
        if op.type == PLUS:
            result = left.value + right.value
        else:
            result = left.value - right.value
        return result


def main():
    while True:
        try:
            # To run under Python3 replace 'raw_input' call
            # with 'input'
            text = raw_input('calc> ')
        except EOFError:
            break
        if not text:
            continue
        interpreter = Interpreter(text)
        result = interpreter.expr()
        print(result)


if __name__ == '__main__':
    main()

把上面的代码保存到 calc2.py 文件中,或者直接从 GitHub 上下载。试着运行它。看看它是不是正常工作:它应该能够处理输入中任意位置的空白符;能够接受多位的整数,并且能够对两个整数做减法和加法。

这是我在自己的笔记本上运行的示例:

$ python calc2.py
calc> 27 + 3
30
calc> 27 - 7
20
calc>

第一部分 的版本相比,主要的代码改动有:

  1. get_next_token 方法重写了很多。增加指针位置的逻辑之前是放在一个单独的方法中。
  2. 增加了一些方法:skip_whitespace 用于忽略空白字符,integer 用于处理输入字符的多位整数。
  3. expr 方法修改成了可以识别 “整数 -> 减号 -> 整数” 词组和 “整数 -> 加号 -> 整数” 词组。在成功识别相应的词组后,这个方法现在可以解释加法和减法。

第一部分 中你学到了两个重要的概念,叫做 标记 token 词法分析 lexical analyzer 。现在我想谈一谈 词法 lexeme 解析 parsing 解析器 parser

你已经知道了标记。但是为了让我详细的讨论标记,我需要谈一谈词法。词法是什么? 词法 lexeme 是一个 标记 token 中的字符序列。在下图中你可以看到一些关于标记的例子,这可以让它们之间的关系变得清晰:

现在还记得我们的朋友,expr 方法吗?我之前说过,这是数学表达式实际被解释的地方。但是你要先识别这个表达式有哪些词组才能解释它,比如它是加法还是减法。expr 方法最重要的工作是:它从 get_next_token 方法中得到流,并找出该标记流的结构,然后解释已经识别出的词组,产生数学表达式的结果。

在标记流中找出结构的过程,或者换种说法,识别标记流中的词组的过程就叫 解析 parsing 。解释器或者编译器中执行这个任务的部分就叫做 解析器 parser

现在你知道 expr 方法就是你的解释器的部分, 解析 parsing 解释 interpreting 都在这里发生 —— expr 方法首先尝试识别(解析)标记流里的 “整数 -> 加法 -> 整数” 或者 “整数 -> 减法 -> 整数” 词组,成功识别后 (解析了) 其中一个词组,这个方法就开始解释它,返回两个整数的和或差。

又到了练习的时间。

  1. 扩展这个计算器,让它能够计算两个整数的乘法
  2. 扩展这个计算器,让它能够计算两个整数的除法
  3. 修改代码,让它能够解释包含了任意数量的加法和减法的表达式,比如 “9 - 5 + 3 + 11”

检验你的理解:

  1. 词法是什么?
  2. 找出标记流结构的过程叫什么,或者换种说法,识别标记流中一个词组的过程叫什么?
  3. 解释器(编译器)执行解析的部分叫什么?

希望你喜欢今天的内容。在该系列的下一篇文章里你就能扩展计算器从而处理更多复杂的算术表达式。敬请期待。


via: https://ruslanspivak.com/lsbasi-part2/

作者:Ruslan Spivak 译者:BriFuture 校对:wxy

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

type 命令用于查找 Linux 命令的信息。顾名思义,你可以使用 type 命令轻松找出给定的命令是否是别名、shell 内置命令、文件、函数或关键字。另外,你也可以找到命令的实际路径。为什么有人需要找到命令类型?例如,如果你经常在共享的计算机上工作,则某些人可能会故意或意外地为特定的 Linux 命令创建别名来执行不需要的操作,例如 alias ls = rm -rf /。因此,在发生更糟糕的事情之前检查它们总是一个好主意。这是 type 命令有用的地方。

让我给你看一些例子。

不带任何选项运行 type 命令。

$ type ls
ls is aliased to `ls --color=auto'

正如你在上面的输出中看到的那样,ls 命令已被别名为 ls -color-auto。但是,它是无害的。但只要想想 ls 如果被别名为了其他一些危险的命令。你不想那样,是吗?

你可以使用 -t 选项仅找出 Linux 命令的类型。例如:

$ type -t ls
alias

$ type -t mkdir
file

$ type -t pwd
builtin

$ type -t if
keyword

$ type -t rvm
function

该命令仅显示命令的类型,例如别名。它不显示被别名的内容。如果该命令找不到,你将在终端中看不到任何内容。

type 命令的另一个有用的地方是我们可以很容易地找出给定 Linux 命令的绝对路径。为此,请使用 -p 选项,如下所示。

$ type -p cal
/usr/bin/cal

这与 which ls 命令类似。如果给定的命令是别名,则不会打印任何内容。

要显示命令的所有信息,请使用 -a 选项。

$ type -a ls
ls is aliased to `ls --color=auto'
ls is /usr/bin/ls
ls is /bin/ls

如你所见,-a 标志显示给定命令的类型及其绝对路径。有关更多详细信息,请参阅手册页。

$ man type

希望这有帮助。会有更多的好东西。请继续访问!

干杯!


via: https://www.ostechnix.com/the-type-command-tutorial-with-examples-for-beginners/

作者:SK 译者:geekpi 校对:wxy

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

Linux/Unix 系统管理员对服务器的系统运行时间有一种奇怪的痴迷。这里有一个关于这个主题的 xkcd 漫画,一个好的系统管理员是一股不可阻挡的力量,他伫立在你家猫咪博客的服务器之前,对抗黑暗势力。

Fig.01: Devotion to Duty https://xkcd.com/705/

我们可以使用 uptime 命令或 w 命令top 命令来判断 Linux 系统运行了多久。我可以使用 tuptime 工具保留每次重新启动的运行时间,以获得系统运行时间的历史和统计报告

这就像 uptime 命令一样,但输出结果更令人印象深刻。最近我发现了另一种称为 uptimed 的工具,用于记录关于机器的系统运行时间和统计信息。让我们看看如何使用 Linux 操作系统上的 uptimeduprecords 来获得运行时间的记录统计信息。

查找系统运行时间非常简单,只需在基于 Linux 的系统上键入以下命令即可:

$ uptime -p
up 2 weeks, 4 days, 7 hours, 28 minutes

要保留有关 uptime 的历史统计信息,请使用 tuptimeuptimed 工具。

安装 uptimed

安装 uptimed 的最简单的方式是通过你的软件包管理器,比如 apt/apt-get/yum 这些你的 Linux 发行版的朋友。

在 Debian/Ubuntu Linux 上安装 uptimed

键入以下 apt 命令/apt-get 命令

$ sudo apt-get install uptimed

示例输出:

Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  libuptimed0
The following NEW packages will be installed:
  libuptimed0 uptimed
0 upgraded, 2 newly installed, 0 to remove and 3 not upgraded.
Need to get 40.7 kB of archives.
After this operation, 228 kB of additional disk space will be used.
Do you want to continue? [Y/n] y
Get:1 http://mirrors.linode.com/ubuntu xenial/universe amd64 libuptimed0 amd64 1:0.3.17-4 [9,050 B]
Get:2 http://mirrors.linode.com/ubuntu xenial/universe amd64 uptimed amd64 1:0.3.17-4 [31.6 kB]
Fetched 40.7 kB in 0s (2,738 kB/s)  
Preconfiguring packages ...
Selecting previously unselected package libuptimed0.
(Reading database ... 39163 files and directories currently installed.)
Preparing to unpack .../libuptimed0_1%3a0.3.17-4_amd64.deb ...
Unpacking libuptimed0 (1:0.3.17-4) ...
Selecting previously unselected package uptimed.
Preparing to unpack .../uptimed_1%3a0.3.17-4_amd64.deb ...
Unpacking uptimed (1:0.3.17-4) ...
Processing triggers for systemd (229-4ubuntu21) ...
Processing triggers for ureadahead (0.100.0-19) ...
Processing triggers for man-db (2.7.5-1) ...
Setting up libuptimed0 (1:0.3.17-4) ...
Setting up uptimed (1:0.3.17-4) ...
Processing triggers for libc-bin (2.23-0ubuntu9) ...
Processing triggers for systemd (229-4ubuntu21) ...
Processing triggers for ureadahead (0.100.0-19) ...

在 CentOS/RHEL/Fedora/Oracle/Scientific Linux 上安装 uptimed

首先 在 CentOS/RHEL 使用 EPEL 仓库

$ sudo yum -y install epel-release

然后,键入以下 yum 命令

$ sudo yum install uptimed

示例输出:

Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: centos.excellmedia.net
 * epel: ftp.cuhk.edu.hk
 * extras: centos.excellmedia.net
 * updates: centos.excellmedia.net
Resolving Dependencies
--> Running transaction check
---> Package uptimed.x86_64 0:0.4.0-6.el7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

===============================================================================
 Package           Arch             Version               Repository      Size
===============================================================================
Installing:
 uptimed           x86_64           0.4.0-6.el7           epel            47 k

Transaction Summary
===============================================================================
Install  1 Package

Total download size: 47 k
Installed size: 98 k
Is this ok [y/d/N]: y
Downloading packages:
uptimed-0.4.0-6.el7.x86_64.rpm                            |  47 kB   00:01     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : uptimed-0.4.0-6.el7.x86_64                                  1/1 
  Verifying  : uptimed-0.4.0-6.el7.x86_64                                  1/1 

Installed:
  uptimed.x86_64 0:0.4.0-6.el7                                                 

Complete!

如果你正在使用 Fedora Linux,运行以下 dnf 命令:

$ sudo dnf install uptimed

在 Arch Linux 上安装 uptimed

键入以下 pacman 命令:

$ sudo pacman -S uptimed

在 Gentoo Linux 上安装 uptimed

键入以下 emerge 命令:

$ sudo emerge --ask uptimed

如何配置 uptimed

使用文本编辑器编辑 /etc/uptimed.conf 文件,例如 vim 命令:

$ sudo vim /etc/uptimed.conf

最少设置一个 email 地址来发送记录。假定有个兼容 sendmail 的 MTA 安装在 /usr/lib/sendmail

[email protected]

保存并关闭文件。

如何在系统启动时启动 uptimed 服务?

使用 systemctl 命令启动 uptimed 服务:

$ sudo systemctl enable uptimed

我该如何 启动/停止/重启 或者查看 uptimed 服务的状态?

$ sudo systemctl start uptimed ## start it ##
$ sudo systemctl stop uptimed ## stop it ##
$ sudo systemctl restart uptimed ## restart it ##
$ sudo systemctl status uptimed ## view status ##

示例输出:

● uptimed.service - uptime record daemon
   Loaded: loaded (/lib/systemd/system/uptimed.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2017-11-09 17:49:14 UTC; 18min ago
 Main PID: 11137 (uptimed)
   CGroup: /system.slice/uptimed.service
           └─11137 /usr/sbin/uptimed -f

Nov 09 17:49:14 gfs04 systemd[1]: Started uptime record daemon.

如何查看 uptime 记录

只需键入以下命令即可查看 uptimed(8) 程序的统计信息:

$ uprecords

示例输出:

Fig.02: uprecords in action

uprecords 有一些选项:

$ uprecords -?

示例输出:

usage: uprecords [OPTION]...

  -?             this help
  -a             do not print ansi codes
  -b             sort by boottime
  -B             reverse sort by boottime
  -k             sort by sysinfo
  -K             reverse sort by sysinfo
  -d             print downtime seen before every uptimes instead of system
  -c             do not show current entry if not in top entries
  -f             run continously in a loop
  -s             do not print extra statistics
  -w             wide output (more than 80 cols per line)
  -i INTERVAL    use INTERVAL seconds for loop instead of 5, implies -f
  -m COUNT       show a maximum of top COUNT entries instead of 10
  -M             show next milestone
  -v             version information

结论

这是一个极好的小工具,可以显示服务器正常运行时间的记录,以证明机器正常运行时间和你的业务连续性。在相关说明中,你可以看到官方的 XKCD 系统管理员 T恤 因为漫画被制作成衬衫,其中包括背面的新插图。

Fig.03: Sysadmin XKCD shirt features the original comic on the front and a new illustration on the back.


via: https://www.cyberciti.biz/hardware/see-records-statistics-about-a-linux-servers-uptime/

作者:Vivek Gite 译者:MjSeven 校对:wxy

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

本系列的第一篇文章 开始使用 Git 时,我们创建了一个简单的 Git 仓库,并用我们的计算机连接到它,向其中添加一个文件。在本文中,我们将学习一些关于 Git 的其他内容,即如何克隆(下载)、修改、添加和删除 Git 仓库中的文件。

让我们来克隆一下

假设你在 GitHub 上已经有一个 Git 仓库,并且想从它那里获取你的文件——也许你在你的计算机上丢失了本地副本,或者你正在另一台计算机上工作,但是想访问仓库中的文件,你该怎么办?从 GitHub 下载你的文件?没错!在 Git 术语中我们称之为“ 克隆 clone ”。(你也可以将仓库作为 ZIP 文件下载,但我们将在本文中探讨克隆方式。)

让我们克隆在上一篇文章中创建的名为 Demo 的仓库。(如果你还没有创建 Demo 仓库,请跳回到那篇文章并在继续之前执行那些步骤)要克隆文件,只需打开浏览器并导航到 https://github.com/<your_username>/Demo (其中 <your_username> 是你仓库的名称。例如,我的仓库是 https://github.com/kedark3/Demo)。一旦你导航到该 URL,点击“ 克隆或下载 Clone or download ”按钮,你的浏览器看起来应该是这样的:

正如你在上面看到的,“ 使用 HTTPS 克隆 Clone with HTTPS ”选项已打开。从该下拉框中复制你的仓库地址(https://github.com/<your_username>/Demo.git),打开终端并输入以下命令将 GitHub 仓库克隆到你的计算机:

git clone https://github.com/<your_username>/Demo.git

然后,要查看 Demo 目录中的文件列表,请输入以下命令:

ls Demo/

终端看起来应该是这样的:

修改文件

现在我们已经克隆了仓库,让我们修改文件并在 GitHub 上更新它们。首先,逐个输入下面的命令,将目录更改为 Demo/,检查 README.md 中的内容,添加新的(附加的)内容到 README.md,然后使用 git status 检查状态:

cd Demo/
ls
cat README.md
echo "Added another line to REAMD.md" >> README.md
cat README.md
git status

如果你逐一运行这些命令,终端看起开将会是这样:

让我们看一下 git status 的输出,并了解它的意思。不要担心这样的语句:

On branch master
Your branch is up-to-date with 'origin/master'.".

因为我们还没有学习这些。(LCTT 译注:学了你就知道了)下一行说:Changes not staged for commit(变化未筹划提交);这是告诉你,它下面列出的文件没有被标记准备(“ 筹划 stage ”)提交。如果你运行 git add,Git 会把这些文件标记为 Ready for commit(准备提交);换句话说就是 Changes staged for commit(变化筹划提交)。在我们这样做之前,让我们用 git diff 命令来检查我们添加了什么到 Git 中,然后运行 git add

这里是终端输出:

我们来分析一下:

  • diff --git a/README.md b/README.md 是 Git 比较的内容(在这个例子中是 README.md)。
  • --- a/README.md 会显示从文件中删除的任何东西。
  • +++ b/README.md 会显示从文件中添加的任何东西。
  • 任何添加到文件中的内容都以绿色文本打印,并在该行的开头加上 + 号。
  • 如果我们删除了任何内容,它将以红色文本打印,并在该行的开头加上 - 号。
  • 现在 git status 显示 Changes to be committed:(变化将被提交),并列出文件名(即 README.md)以及该文件发生了什么(即它已经被 modified 并准备提交)。

提示:如果你已经运行了 git add,现在你想看看文件有什么不同,通常 git diff 不会输出任何东西,因为你已经添加了文件。相反,你必须使用 git diff --cached。它会告诉你 Git 添加的当前版本和以前版本文件之间的差别。你的终端输出看起来会是这样:

上传文件到你的仓库

我们用一些新内容修改了 README.md 文件,现在是时候将它上传到 GitHub。

让我们提交更改并将其推送到 GitHub。运行:

git commit -m "Updated Readme file"

这告诉 Git 你正在“提交”已经“添加”的更改,你可能还记得,从本系列的第一部分中,添加一条消息来解释你在提交中所做的操作是非常重要的,以便你在稍后回顾 Git 日志时了解当时的目的。(我们将在下一篇文章中更多地关注这个话题。)Updated Readme file 是这个提交的消息——如果你认为这没有合理解释你所做的事情,那么请根据需要写下你的提交消息。

运行 git push -u origin master,这会提示你输入用户名和密码,然后将文件上传到你的 GitHub 仓库。刷新你的 GitHub 页面,你应该会看到刚刚对 README.md 所做的更改。

终端的右下角显示我提交了更改,检查了 Git 状态,并将更改推送到了 GitHub。git status 显示:

Your branch is ahead of 'origin/master' by 1 commit
  (use "git push" to publish your local commits)

第一行表示在本地仓库中有一个提交,但不在 origin/master 中(即在 GitHub 上)。下一行指示我们将这些更改推送到 origin/master 中,这就是我们所做的。(在本例中,请参阅本系列的第一篇文章,以唤醒你对 origin 含义的记忆。我将在下一篇文章中讨论分支的时候,解释 master 的含义。)

添加新文件到 Git

现在我们修改了一个文件并在 GitHub 上更新了它,让我们创建一个新文件,将它添加到 Git,然后将其上传到 GitHub。 运行:

echo "This is a new file" >> file.txt

这将会创建一个名为 file.txt 的新文件。

如果使用 cat 查看它:

cat file.txt

你将看到文件的内容。现在继续运行:

git status

Git 报告说你的仓库中有一个未跟踪的文件(名为 file.txt)。这是 Git 告诉你说在你的计算机中的仓库目录下有一个新文件,然而你并没有告诉 Git,Git 也没有跟踪你所做的任何修改。

我们需要告诉 Git 跟踪这个文件,以便我们可以提交并上传文件到我们的仓库。以下是执行该操作的命令:

git add file.txt
git status

终端输出如下:

git status 告诉你有 file.txt 被修改,对于 Git 来说它是一个 new file,Git 在此之前并不知道。现在我们已经为 Git 添加了 file.txt,我们可以提交更改并将其推送到 origin/master

Git 现在已经将这个新文件上传到 GitHub;如果刷新 GitHub 页面,则应该在 GitHub 上的仓库中看到新文件 file.txt

通过这些步骤,你可以创建尽可能多的文件,将它们添加到 Git 中,然后提交并将它们推送到 GitHub。

从 Git 中删除文件

如果我们发现我们犯了一个错误,并且需要从我们的仓库中删除 file.txt,该怎么办?一种方法是使用以下命令从本地副本中删除文件:

rm file.txt

如果你现在做 git status,Git 就会说有一个文件 not staged for commit(未筹划提交),并且它已经从仓库的本地拷贝中删除了。如果我们现在运行:

git add file.txt
git status

我知道我们正在删除这个文件,但是我们仍然运行 git add,因为我们需要告诉 Git 我们正在做的更改git add 可以用于我们添加新文件、修改一个已存在文件的内容、或者从仓库中删除文件时。实际上,git add 将所有更改考虑在内,并将这些筹划提交这些更改。如果有疑问,请仔细查看下面终端屏幕截图中每个命令的输出。

Git 会告诉我们已删除的文件正在进行提交。只要你提交此更改并将其推送到 GitHub,该文件也将从 GitHub 的仓库中删除。运行以下命令:

git commit -m "Delete file.txt"
git push -u origin master

现在你的终端看起来像这样:

你的 GitHub 看起来像这样:

现在你知道如何从你的仓库克隆、添加、修改和删除 Git 文件。本系列的下一篇文章将检查 Git 分支。


via: https://opensource.com/article/18/2/how-clone-modify-add-delete-git-files

作者:Kedar Vijay Kulkarni 译者:MjSeven 校对:wxy

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