分类 技术 下的文章

每个来到这里的人都会对许多系统中默认 Bash shell 有所了解(无论多少)。过去这些年已经有一些新的 shell 出现来解决 Bash 中的一些缺点。Elvish 就是其中之一,我们将在今天讨论它。

什么是 Elvish Shell?

Pipelines In Elvish

Elvish 不仅仅是一个 shell。它也是“一种表达性编程语言”。它有许多有趣的特性,包括:

  • 它是由 Go 语言编写的
  • 内置文件管理器,灵感来自 Ranger 文件管理器Ctrl + N
  • 可搜索的命令历史记录(Ctrl + R
  • 访问的目录的历史记录(Ctrl + L
  • 支持结构化数据,例如列表、字典和函数的强大的管道
  • 包含“一组标准的控制结构:有 if 条件控制、forwhile 循环,还有 try 的异常处理”
  • 通过包管理器支持第三方模块扩展 Elvish
  • BSD 两句版许可证

你肯定在喊,“为什么叫 Elvish?”。好吧,根据他们的网站,他们之所以选择当前的名字,是因为:

在 Roguelike 游戏中,精灵制造的物品质量很高。它们通常被称为“精灵物品”。但是之所以选择 “elvish” 是因为它以 “sh” 结尾,这是 Unix shell 的久远传统。这个与 fish 押韵,它是影响 Elvish 哲学的 shell 之一。

如何安装 Elvish Shell

Elvish 在几种主流发行版中都有。

请注意,该软件还很年轻。最新版本是 0.12。根据该项目的 GitHub 页面:“尽管还处在 1.0 之前,但它已经适合大多数日常交互使用。”

Elvish Control Structures

Debian 和 Ubuntu

Elvish 包已引入 Debian Buster 和 Ubuntu 17.10。不幸的是,这些包已经过时,你需要使用 PPA 安装最新版本。你需要使用以下命令:

sudo add-apt-repository ppa:zhsj/elvish
sudo apt update
sudo apt install elvish

Fedora

Elvish 在 Fedora 的主仓库中没有。你需要添加 FZUG 仓库安装 Evlish。为此,你需要使用以下命令:

sudo dnf config-manager --add-repo=http://repo.fdzh.org/FZUG/FZUG.repol
sudo dnf install elvish

Arch

Elvish 在 Arch 用户仓库中可用。

我相信你知道该如何在 Linux 中更改 Shell,因此安装后可以切换到 Elvish 来使用它。

对 Elvish Shell 的想法

就个人而言,我没有理由在任何系统上安装 Elvish。我可以通过安装几个小的命令行程序或使用已经安装的程序来获得它的大多数功能。

例如,Bash 中已经存在“搜索历史命令”功能,并且效果很好。如果要提高历史命令的能力,我建议安装 fzffzf 使用模糊搜索,因此你无需记住要查找的确切命令。fzf 还允许你预览和打开文件。

我认为 Elvish 作为一种编程语言是不错的,但是我会坚持使用 Bash shell 脚本,直到 Elvish 变得更成熟。

你们都有用过 Elvish 么?你认为安装 Elvish 是否值得?你最喜欢的 Bash 替代品是什么?请在下面的评论中告诉我们。

如果你发现这篇文章有趣,请花一点时间在社交媒体、Hacker News 或 Reddit 上分享它。


via: https://itsfoss.com/elvish-shell/

作者:John Paul 选题:lujun9972 译者:geekpi 校对:wxy

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

在 Linux 服务器上工作时,在网卡/以太网卡上分配静态 IP 地址是每个 Linux 工程师的常见任务之一。如果一个人在 Linux 服务器上正确配置了静态地址,那么他/她就可以通过网络远程访问它。在本文中,我们将演示在 RHEL 8 服务器网卡上配置静态 IP 地址的不同方法。

以下是在网卡上配置静态IP的方法:

  • nmcli(命令行工具)
  • 网络脚本文件(ifcfg-*
  • nmtui(基于文本的用户界面)

使用 nmcli 命令行工具配置静态 IP 地址

每当我们安装 RHEL 8 服务器时,就会自动安装命令行工具 nmcli,它是由网络管理器使用的,可以让我们在以太网卡上配置静态 IP 地址。

运行下面的 ip addr 命令,列出 RHEL 8 服务器上的以太网卡

[root@linuxtechi ~]# ip addr

正如我们在上面的命令输出中看到的,我们有两个网卡 enp0s3enp0s8。当前分配给网卡的 IP 地址是通过 DHCP 服务器获得的。

假设我们希望在第一个网卡 (enp0s3) 上分配静态 IP 地址,具体内容如下:

  • IP 地址 = 192.168.1.4
  • 网络掩码 = 255.255.255.0
  • 网关 = 192.168.1.1
  • DNS = 8.8.8.8

依次运行以下 nmcli 命令来配置静态 IP,

使用 nmcli connection 命令列出当前活动的以太网卡,

[root@linuxtechi ~]# nmcli connection
NAME    UUID                                  TYPE      DEVICE
enp0s3  7c1b8444-cb65-440d-9bf6-ea0ad5e60bae  ethernet  enp0s3
virbr0  3020c41f-6b21-4d80-a1a6-7c1bd5867e6c  bridge    virbr0
[root@linuxtechi ~]#

使用下面的 nmcli 给 enp0s3 分配静态 IP。

命令语法:

# nmcli connection modify <interface_name> ipv4.address  <ip/prefix>

注意: 为了简化语句,在 nmcli 命令中,我们通常用 con 关键字替换 connection,并用 mod 关键字替换 modify

将 IPv4 地址 (192.168.1.4) 分配给 enp0s3 网卡上,

[root@linuxtechi ~]# nmcli con mod enp0s3 ipv4.addresses 192.168.1.4/24

使用下面的 nmcli 命令设置网关,

[root@linuxtechi ~]# nmcli con mod enp0s3 ipv4.gateway 192.168.1.1

设置手动配置(从 dhcp 到 static),

[root@linuxtechi ~]# nmcli con mod enp0s3 ipv4.method manual

设置 DNS 值为 “8.8.8.8”,

[root@linuxtechi ~]# nmcli con mod enp0s3 ipv4.dns "8.8.8.8"
[root@linuxtechi ~]#

要保存上述更改并重新加载,请执行如下 nmcli 命令,

[root@linuxtechi ~]# nmcli con up enp0s3
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/4)

以上命令显示网卡 enp0s3 已成功配置。我们使用 nmcli 命令做的那些更改都将永久保存在文件 etc/sysconfig/network-scripts/ifcfg-enp0s3 里。

[root@linuxtechi ~]# cat /etc/sysconfig/network-scripts/ifcfg-enp0s3

要确认 IP 地址是否分配给了 enp0s3 网卡了,请使用以下 IP 命令查看,

[root@linuxtechi ~]#ip addr show enp0s3

使用网络脚本文件(ifcfg-*)手动配置静态 IP 地址

我们可以使用配置以太网卡的网络脚本或 ifcfg-* 文件来配置以太网卡的静态 IP 地址。假设我们想在第二个以太网卡 enp0s8 上分配静态 IP 地址:

  • IP 地址 = 192.168.1.91
  • 前缀 = 24
  • 网关 =192.168.1.1
  • DNS1 =4.2.2.2

转到目录 /etc/sysconfig/network-scripts,查找文件 ifcfg-enp0s8,如果它不存在,则使用以下内容创建它,

[root@linuxtechi ~]# cd /etc/sysconfig/network-scripts/
[root@linuxtechi network-scripts]# vi ifcfg-enp0s8
TYPE="Ethernet"
DEVICE="enp0s8"
BOOTPROTO="static"
ONBOOT="yes"
NAME="enp0s8"
IPADDR="192.168.1.91"
PREFIX="24"
GATEWAY="192.168.1.1"
DNS1="4.2.2.2"

保存并退出文件,然后重新启动网络管理器服务以使上述更改生效,

[root@linuxtechi network-scripts]# systemctl restart NetworkManager

现在使用下面的 ip 命令来验证 IP 地址是否分配给网卡,

[root@linuxtechi ~]# ip add show enp0s8
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:7c:bb:cb brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.91/24 brd 192.168.1.255 scope global noprefixroute enp0s8
       valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:fe7c:bbcb/64 scope link
       valid_lft forever preferred_lft forever
[root@linuxtechi ~]#

以上输出内容确认静态 IP 地址已在网卡 enp0s8 上成功配置了。

使用 nmtui 实用程序配置静态 IP 地址

nmtui 是一个基于文本用户界面的,用于控制网络的管理器,当我们执行 nmtui 时,它将打开一个基于文本的用户界面,通过它我们可以添加、修改和删除连接。除此之外,nmtui 还可以用来设置系统的主机名。

假设我们希望通过以下细节将静态 IP 地址分配给网卡 enp0s3

  • IP 地址 = 10.20.0.72
  • 前缀 = 24
  • 网关 = 10.20.0.1
  • DNS1 =4.2.2.2

运行 nmtui 并按照屏幕说明操作,示例如下所示,

[root@linuxtechi ~]# nmtui

选择第一个选项 “Edit a connection”,然后选择接口为 “enp0s3”,

选择 “Edit”,然后指定 IP 地址、前缀、网关和域名系统服务器 IP,

选择确定,然后点击回车。在下一个窗口中,选择 “Activate a connection”,

选择 “enp0s3”,选择 “Deactivate” 并点击回车,

现在选择 “Activate” 并点击回车,

选择 “Back”,然后选择 “Quit”,

使用下面的 ip 命令验证 IP 地址是否已分配给接口 enp0s3

[root@linuxtechi ~]# ip add show enp0s3
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:53:39:4d brd ff:ff:ff:ff:ff:ff
    inet 10.20.0.72/24 brd 10.20.0.255 scope global noprefixroute enp0s3
       valid_lft forever preferred_lft forever
    inet6 fe80::421d:5abf:58bd:c47e/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
[root@linuxtechi ~]#

以上输出内容显示我们已经使用 nmtui 实用程序成功地将静态 IP 地址分配给接口 enp0s3

以上就是本教程的全部内容,我们已经介绍了在 RHEL 8 系统上为以太网卡配置 IPv4 地址的三种不同方法。请在下面的评论部分分享反馈和评论。


via: https://www.linuxtechi.com/configure-static-ip-address-rhel8/

作者:Pradeep Kumar 选题:lujun9972 译者:heguangzhi 校对:wxy

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

当回车字符(Ctrl+M)让你紧张时,别担心。有几种简单的方法消除它们。

“回车”字符可以往回追溯很长一段时间 —— 早在打字机上就有一个机械装置或杠杆将承载纸滚筒的机架移到右边,以便可以重新在左侧输入字母。他们在 Windows 上的文本文件上保留了它,但从未在 Linux 系统上使用过。当你尝试在 Linux 上处理在 Windows 上创建的文件时,这种不兼容性有时会导致问题,但这是一个非常容易解决的问题。

如果你使用 od 八进制转储 octal dump )命令查看文件,那么回车(也用 Ctrl+M 代表)字符将显示为八进制的 15。字符 CRLF 通常用于表示 Windows 文本文件中的一行结束的回车符和换行符序列。那些注意看八进制转储的会看到 `
`。相比之下,Linux 文本仅以换行符结束。

这有一个 od 输出的示例,高亮显示了行中的 CRLF 字符,以及它的八进制。

$ od -bc testfile.txt
0000000 124 150 151 163 040 151 163 040 141 040 164 145 163 164 040 146
          T   h   i   s       i   s       a       t   e   s   t       f
0000020 151 154 145 040 146 162 157 155 040 127 151 156 144 157 167 163
          i   l   e       f   r   o   m       W   i   n   d   o   w   s
0000040 056 015 012 111 164 047 163 040 144 151 146 146 145 162 145 156  <==
          .  \r  \n   I   t   '   s       d   i   f   f   e   r   e   n  <==
0000060 164 040 164 150 141 156 040 141 040 125 156 151 170 040 164 145
          t       t   h   a   n       a       U   n   i   x       t   e
0000100 170 164 040 146 151 154 145 015 012 167 157 165 154 144 040 142  <==
          x   t       f   i   l   e  \r  \n   w   o   u   l   d       b  <==

虽然这些字符不是大问题,但是当你想要以某种方式解析文本,并且不希望就它们是否存在进行编码时,这有时候会产生干扰。

3 种从文本中删除回车符的方法

幸运的是,有几种方法可以轻松删除回车符。这有三个选择:

dos2unix

你可能会在安装时遇到麻烦,但 dos2unix 可能是将 Windows 文本转换为 Unix/Linux 文本的最简单方法。一个命令带上一个参数就行了。不需要第二个文件名。该文件会被直接更改。

$ dos2unix testfile.txt
dos2unix: converting file testfile.txt to Unix format...

你应该会发现文件长度减少,具体取决于它包含的行数。包含 100 行的文件可能会缩小 99 个字符,因为只有最后一行不会以 CRLF 字符结尾。

之前:

-rw-rw-r--   1 shs  shs        121 Sep 14 19:11 testfile.txt

之后:

-rw-rw-r--   1 shs  shs        118 Sep 14 19:12 testfile.txt

如果你需要转换大量文件,不用每次修复一个。相反,将它们全部放在一个目录中并运行如下命令:

$ find . -type f -exec dos2unix {} \;

在此命令中,我们使用 find 查找常规文件,然后运行 dos2unix 命令一次转换一个。命令中的 {} 将被替换为文件名。运行时,你应该处于包含文件的目录中。此命令可能会损坏其他类型的文件,例如除了文本文件外在上下文中包含八进制 15 的文件(如,镜像文件中的字节)。

sed

你还可以使用流编辑器 sed 来删除回车符。但是,你必须提供第二个文件名。以下是例子:

$ sed -e “s/^M//” before.txt > after.txt

一件需要注意的重要的事情是,请不要输入你看到的字符。你必须按下 Ctrl+V 后跟 Ctrl+M 来输入 ^Ms 是替换命令。斜杠将我们要查找的文本(Ctrl + M)和要替换的文本(这里为空)分开。

vi

你甚至可以使用 vi 删除回车符(Ctrl+M),但这里假设你没有打开数百个文件,或许也在做一些其他的修改。你可以键入 : 进入命令行,然后输入下面的字符串。与 sed 一样,命令中 ^M 需要通过 Ctrl+V 输入 ^,然后 Ctrl+M 插入 M%s 是替换操作,斜杠再次将我们要删除的字符和我们想要替换它的文本(空)分开。 g(全局)意味在所有行上执行。

:%s/^M//g

总结

dos2unix 命令可能是最容易记住的,也是从文本中删除回车的最可靠的方法。其他选择使用起来有点困难,但它们提供相同的基本功能。


via: https://www.networkworld.com/article/3438857/how-to-remove-carriage-returns-from-text-files-on-linux.html

作者:Sandra Henry-Stocker 选题:lujun9972 译者:geekpi 校对:wxy

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

Linux 发行版提供了几个度量磁盘活动的有用命令。让我们了解一下其中的几个。

Linux 系统提供了一套方便的命令,帮助你查看磁盘有多忙,而不仅仅是磁盘有多满。在本文中,我们将研究五个非常有用的命令,用于查看磁盘活动。其中两个命令(iostatioping)可能必须添加到你的系统中,这两个命令一样要求你使用 sudo 特权,所有这五个命令都提供了查看磁盘活动的有用方法。

这些命令中最简单、最直观的一个可能是 dstat 了。

dtstat

尽管 dstat 命令以字母 “d” 开头,但它提供的统计信息远远不止磁盘活动。如果你只想查看磁盘活动,可以使用 -d 选项。如下所示,你将得到一个磁盘读/写测量值的连续列表,直到使用 CTRL-c 停止显示为止。注意,在第一个报告信息之后,显示中的每个后续行将在接下来的时间间隔内报告磁盘活动,缺省值仅为一秒。

$ dstat -d
-dsk/total-
 read  writ
 949B   73k
  65k     0    <== first second
   0    24k    <== second second
   0    16k
   0    0 ^C

-d 选项后面包含一个数字将把间隔设置为该秒数。

$ dstat -d 10
-dsk/total-
 read  writ
 949B   73k
  65k   81M    <== first five seconds
   0    21k    <== second five second
   0  9011B ^C

请注意,报告的数据可能以许多不同的单位显示——例如,M(Mb)、K(Kb)和 B(字节)。

如果没有选项,dstat 命令还将显示许多其他信息——指示 CPU 如何使用时间、显示网络和分页活动、报告中断和上下文切换。

$ dstat
You did not select any stats, using -cdngy by default.
--total-cpu-usage-- -dsk/total- -net/total- ---paging-- ---system--
usr sys idl wai stl| read  writ| recv  send|  in   out | int   csw
  0   0 100   0   0| 949B   73k|   0     0 |   0     3B|  38    65
  0   0 100   0   0|   0     0 | 218B  932B|   0     0 |  53    68
  0   1  99   0   0|   0    16k|  64B  468B|   0     0 |  64    81 ^C

dstat 命令提供了关于整个 Linux 系统性能的有价值的见解,几乎可以用它灵活而功能强大的命令来代替 vmstatnetstatiostatifstat 等较旧的工具集合,该命令结合了这些旧工具的功能。要深入了解 dstat 命令可以提供的其它信息,请参阅这篇关于 dstat 命令的文章。

iostat

iostat 命令通过观察设备活动的时间与其平均传输速率之间的关系,帮助监视系统输入/输出设备的加载情况。它有时用于评估磁盘之间的活动平衡。

$ iostat
Linux 4.18.0-041800-generic (butterfly)         12/26/2018      _x86_64_       (2 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.07    0.01    0.03    0.05    0.00   99.85

Device             tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
loop0             0.00         0.00         0.00       1048          0
loop1             0.00         0.00         0.00        365          0
loop2             0.00         0.00         0.00       1056          0
loop3             0.00         0.01         0.00      16169          0
loop4             0.00         0.00         0.00        413          0
loop5             0.00         0.00         0.00       1184          0
loop6             0.00         0.00         0.00       1062          0
loop7             0.00         0.00         0.00       5261          0
sda               1.06         0.89        72.66    2837453  232735080
sdb               0.00         0.02         0.00      48669         40
loop8             0.00         0.00         0.00       1053          0
loop9             0.01         0.01         0.00      18949          0
loop10            0.00         0.00         0.00         56          0
loop11            0.00         0.00         0.00       7090          0
loop12            0.00         0.00         0.00       1160          0
loop13            0.00         0.00         0.00        108          0
loop14            0.00         0.00         0.00       3572          0
loop15            0.01         0.01         0.00      20026          0
loop16            0.00         0.00         0.00         24          0

当然,当你只想关注磁盘时,Linux 回环设备上提供的所有统计信息都会使结果显得杂乱无章。不过,该命令也确实提供了 -p 选项,该选项使你可以仅查看磁盘——如以下命令所示。

$ iostat -p sda
Linux 4.18.0-041800-generic (butterfly)         12/26/2018      _x86_64_        (2 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.07    0.01    0.03    0.05    0.00   99.85

Device             tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda               1.06         0.89        72.54    2843737  232815784
sda1              1.04         0.88        72.54    2821733  232815784

请注意 tps 是指每秒的传输量。

你还可以让 iostat 提供重复的报告。在下面的示例中,我们使用 -d 选项每五秒钟进行一次测量。

$ iostat -p sda -d 5
Linux 4.18.0-041800-generic (butterfly)         12/26/2018      _x86_64_        (2 CPU)

Device             tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda               1.06         0.89        72.51    2843749  232834048
sda1              1.04         0.88        72.51    2821745  232834048

Device             tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda               0.80         0.00        11.20          0         56
sda1              0.80         0.00        11.20          0         56

如果你希望省略第一个(自启动以来的统计信息)报告,请在命令中添加 -y

$ iostat -p sda -d 5 -y
Linux 4.18.0-041800-generic (butterfly)         12/26/2018      _x86_64_        (2 CPU)

Device             tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda               0.80         0.00        11.20          0         56
sda1              0.80         0.00        11.20          0         56

接下来,我们看第二个磁盘驱动器。

$ iostat -p sdb
Linux 4.18.0-041800-generic (butterfly)         12/26/2018      _x86_64_        (2 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.07    0.01    0.03    0.05    0.00   99.85

Device             tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sdb               0.00         0.02         0.00      48669         40
sdb2              0.00         0.00         0.00       4861         40
sdb1              0.00         0.01         0.00      35344          0

iotop

iotop 命令是类似 top 的实用程序,用于查看磁盘 I/O。它收集 Linux 内核提供的 I/O 使用信息,以便你了解哪些进程在磁盘 I/O 方面的要求最高。在下面的示例中,循环时间被设置为 5 秒。显示将自动更新,覆盖前面的输出。

$ sudo iotop -d 5
Total DISK READ:         0.00 B/s | Total DISK WRITE:      1585.31 B/s
Current DISK READ:       0.00 B/s | Current DISK WRITE:      12.39 K/s
  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND
32492 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.12 % [kworker/u8:1-ev~_power_efficient]
  208 be/3 root        0.00 B/s 1585.31 B/s  0.00 %  0.11 % [jbd2/sda1-8]
    1 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % init splash
    2 be/4 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [kthreadd]
    3 be/0 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [rcu_gp]
    4 be/0 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [rcu_par_gp]
    8 be/0 root        0.00 B/s    0.00 B/s  0.00 %  0.00 % [mm_percpu_wq]

ioping

ioping 命令是一种完全不同的工具,但是它可以报告磁盘延迟——也就是磁盘响应请求需要多长时间,而这有助于诊断磁盘问题。

$ sudo ioping /dev/sda1
4 KiB <<< /dev/sda1 (block device 111.8 GiB): request=1 time=960.2 us (warmup)
4 KiB <<< /dev/sda1 (block device 111.8 GiB): request=2 time=841.5 us
4 KiB <<< /dev/sda1 (block device 111.8 GiB): request=3 time=831.0 us
4 KiB <<< /dev/sda1 (block device 111.8 GiB): request=4 time=1.17 ms
^C
--- /dev/sda1 (block device 111.8 GiB) ioping statistics ---
3 requests completed in 2.84 ms, 12 KiB read, 1.05 k iops, 4.12 MiB/s
generated 4 requests in 3.37 s, 16 KiB, 1 iops, 4.75 KiB/s
min/avg/max/mdev = 831.0 us / 947.9 us / 1.17 ms / 158.0 us

atop

atop 命令,像 top 一样提供了大量有关系统性能的信息,包括有关磁盘活动的一些统计信息。

ATOP - butterfly      2018/12/26  17:24:19      37d3h13m------ 10ed
PRC | sys    0.03s | user   0.01s | #proc    179 | #zombie    0 | #exit      6 |
CPU | sys       1% | user      0% | irq       0% | idle    199% | wait      0% |
cpu | sys       1% | user      0% | irq       0% | idle     99% | cpu000 w  0% |
CPL | avg1    0.00 | avg5    0.00 | avg15   0.00 | csw      677 | intr     470 |
MEM | tot     5.8G | free  223.4M | cache   4.6G | buff  253.2M | slab  394.4M |
SWP | tot     2.0G | free    2.0G |              | vmcom   1.9G | vmlim   4.9G |
DSK |          sda | busy      0% | read       0 | write      7 | avio 1.14 ms |
NET | transport    | tcpi 4 | tcpo  stall      8 | udpi 1 | udpo 0swout   2255 |
NET | network      | ipi       10 | ipo 7 | ipfrw      0 | deliv      60.67 ms |
NET | enp0s25   0% | pcki      10 | pcko 8 | si    1 Kbps | so    3 Kbp0.73 ms |

  PID SYSCPU  USRCPU  VGROW   RGROW  ST EXC   THR  S CPUNR   CPU  CMD 1/1673e4 |
 3357  0.01s   0.00s   672K    824K  --   -     1  R     0    0%  atop
 3359  0.01s   0.00s     0K      0K  NE   0     0  E     -    0%  <ps>
 3361  0.00s   0.01s     0K      0K  NE   0     0  E     -    0%  <ps>
 3363  0.01s   0.00s     0K      0K  NE   0     0  E     -    0%  <ps>
31357  0.00s   0.00s     0K      0K  --   -     1  S     1    0%  bash
 3364  0.00s   0.00s  8032K    756K  N-   -     1  S     1    0%  sleep
 2931  0.00s   0.00s     0K      0K  --   -     1  I     1    0%  kworker/u8:2-e
 3356  0.00s   0.00s     0K      0K  -E   0     0  E     -    0%  <sleep>
 3360  0.00s   0.00s     0K      0K  NE   0     0  E     -    0%  <sleep>
 3362  0.00s   0.00s     0K      0K  NE   0     0  E     -    0%  <sleep>

如果你想查看磁盘统计信息,则可以使用以下命令轻松进行管理:

$ atop | grep DSK
DSK |          sda | busy      0% | read  122901 | write 3318e3 | avio 0.67 ms |
DSK |          sdb | busy      0% | read    1168 | write    103 | avio 0.73 ms |
DSK |          sda | busy      2% | read       0 | write     92 | avio 2.39 ms |
DSK |          sda | busy      2% | read       0 | write     94 | avio 2.47 ms |
DSK |          sda | busy      2% | read       0 | write     99 | avio 2.26 ms |
DSK |          sda | busy      2% | read       0 | write     94 | avio 2.43 ms |
DSK |          sda | busy      2% | read       0 | write     94 | avio 2.43 ms |
DSK |          sda | busy      2% | read       0 | write     92 | avio 2.43 ms |
^C

了解磁盘 I/O

Linux 提供了足够的命令,可以让你很好地了解磁盘的工作强度,并帮助你关注潜在的问题或减缓。希望这些命令中的一个可以告诉你何时需要质疑磁盘性能。偶尔使用这些命令将有助于确保当你需要检查磁盘,特别是忙碌或缓慢的磁盘时可以显而易见地发现它们。


via: https://www.networkworld.com/article/3330497/linux/linux-commands-for-measuring-disk-activity.html

作者:Sandra Henry-Stocker 选题:lujun9972 译者:laingke 校对:wxy

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

冻结终端窗口并锁定屏幕意味着什么 - 以及如何在 Linux 系统上管理这些活动。

如何在 Linux 系统上冻结和“解冻”屏幕,很大程度上取决于这些术语的含义。有时“冻结屏幕”可能意味着冻结终端窗口,以便该窗口内的活动停止。有时它意味着锁定屏幕,这样就没人可以在你去拿一杯咖啡时,走到你的系统旁边代替你输入命令了。

在这篇文章中,我们将研究如何使用和控制这些操作。

如何在 Linux 上冻结终端窗口

你可以输入 Ctrl+S(按住 Ctrl 键和 s 键)冻结 Linux 系统上的终端窗口。把 s 想象成“ 开始冻结 start the freeze ”。如果在此操作后继续输入命令,那么你不会看到输入的命令或你希望看到的输出。实际上,命令将堆积在一个队列中,并且只有在通过输入 Ctrl+Q 解冻时才会运行。把它想象成“ 退出冻结 quit the freeze ”。

查看其工作的一种简单方式是使用 date 命令,然后输入 Ctrl+S。接着再次输入 date 命令并等待几分钟后再次输入 Ctrl+Q。你会看到这样的情景:

$ date
Mon 16 Sep 2019 06:47:34 PM EDT
$ date
Mon 16 Sep 2019 06:49:49 PM EDT

这两次时间显示的差距表示第二次的 date 命令直到你解冻窗口时才运行。

无论你是坐在计算机屏幕前还是使用 PuTTY 等工具远程运行,终端窗口都可以冻结和解冻。

这有一个可以派上用场的小技巧。如果你发现终端窗口似乎处于非活动状态,那么可能是你或其他人无意中输入了 Ctrl+S。那么,输入 Ctrl+Q 来尝试解决不妨是个不错的办法。

如何锁定屏幕

要在离开办公桌前锁定屏幕,请按住 Ctrl+Alt+LSuper+L(即按住 Windows 键和 L 键)。屏幕锁定后,你必须输入密码才能重新登录。

Linux 系统上的自动屏幕锁定

虽然最佳做法建议你在即将离开办公桌时锁定屏幕,但 Linux 系统通常会在一段时间没有活动后自动锁定。 “消隐”屏幕(使其变暗)并实际锁定屏幕(需要登录才能再次使用)的时间取决于你个人首选项中的设置。

要更改使用 GNOME 屏幕保护程序时屏幕变暗所需的时间,请打开设置窗口并选择 “Power” 然后 “Blank screen”。你可以选择 1 到 15 分钟或从不变暗。要选择屏幕变暗后锁定所需时间,请进入设置,选择 “Privacy”,然后选择 “Blank screen”。设置应包括 1、2、3、5 和 30 分钟或一小时。

如何在命令行锁定屏幕

如果你使用的是 GNOME 屏幕保护程序,你还可以使用以下命令从命令行锁定屏幕:

gnome-screensaver-command -l

这里是小写的 L,代表“锁定”。

如何检查锁屏状态

你还可以使用 gnome-screensaver 命令检查屏幕是否已锁定。使用 --query 选项,该命令会告诉你屏幕当前是否已锁定(即处于活动状态)。使用 --time 选项,它会告诉你锁定生效的时间。这是一个示例脚本:

#!/bin/bash

gnome-screensaver-command --query
gnome-screensaver-command --time

运行脚本将会输出:

$ ./check_lockscreen
The screensaver is active
The screensaver has been active for 1013 seconds.

总结

如果你记住了正确的控制方式,那么锁定终端窗口是很简单的。对于屏幕锁定,它的效果取决于你自己的设置,或者你是否习惯使用默认设置。


via: https://www.networkworld.com/article/3438818/how-to-freeze-and-lock-your-linux-system-and-why-you-would-want-to.html

作者:Sandra Henry-Stocker 选题:lujun9972 译者:geekpi 校对:wxy

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

Go 语言,能在多低下的配置上运行并发挥作用呢?

我最近购买了一个特别便宜的开发板:

STM32F030F4P6

我购买它的理由有三个。首先,我(作为程序员)从未接触过 STM320 系列的开发板。其次,STM32F10x 系列使用也有点少了。STM320 系列的 MCU 很便宜,有更新一些的外设,对系列产品进行了改进,问题修复也做得更好了。最后,为了这篇文章,我选用了这一系列中最低配置的开发板,整件事情就变得有趣起来了。

硬件部分

STM32F030F4P6 给人留下了很深的印象:

  • CPU: Cortex M0 48 MHz(最低配置,只有 12000 个逻辑门电路)
  • RAM: 4 KB,
  • Flash: 16 KB,
  • ADC、SPI、I2C、USART 和几个定时器

以上这些采用了 TSSOP20 封装。正如你所见,这是一个很小的 32 位系统。

软件部分

如果你想知道如何在这块开发板上使用 Go 编程,你需要反复阅读硬件规范手册。你必须面对这样的真实情况:在 Go 编译器中给 Cortex-M0 提供支持的可能性很小。而且,这还仅仅只是第一个要解决的问题。

我会使用 Emgo,但别担心,之后你会看到,它如何让 Go 在如此小的系统上尽可能发挥作用。

在我拿到这块开发板之前,对 stm32/hal 系列下的 F0 MCU 没有任何支持。在简单研究参考手册后,我发现 STM32F0 系列是 STM32F3 削减版,这让在新端口上开发的工作变得容易了一些。

如果你想接着本文的步骤做下去,需要先安装 Emgo

cd $HOME
git clone https://github.com/ziutek/emgo/
cd emgo/egc
go install

然后设置一下环境变量

export EGCC=path_to_arm_gcc      # eg. /usr/local/arm/bin/arm-none-eabi-gcc
export EGLD=path_to_arm_linker   # eg. /usr/local/arm/bin/arm-none-eabi-ld
export EGAR=path_to_arm_archiver # eg. /usr/local/arm/bin/arm-none-eabi-ar

export EGROOT=$HOME/emgo/egroot
export EGPATH=$HOME/emgo/egpath

export EGARCH=cortexm0
export EGOS=noos
export EGTARGET=f030x6

更详细的说明可以在 Emgo 官网上找到。

要确保 egc 在你的 PATH 中。 你可以使用 go build 来代替 go install,然后把 egc 复制到你的 $HOME/bin/usr/local/bin 中。

现在,为你的第一个 Emgo 程序创建一个新文件夹,随后把示例中链接器脚本复制过来:

mkdir $HOME/firstemgo
cd $HOME/firstemgo
cp $EGPATH/src/stm32/examples/f030-demo-board/blinky/script.ld .

最基本程序

main.go 文件中创建一个最基本的程序:

package main

func main() {
}

文件编译没有出现任何问题:

$ egc
$ arm-none-eabi-size cortexm0.elf
   text    data     bss     dec     hex filename
   7452     172     104    7728    1e30 cortexm0.elf

第一次编译可能会花点时间。编译后产生的二进制占用了 7624 个字节的 Flash 空间(文本 + 数据)。对于一个什么都没做的程序来说,占用的空间有些大。还剩下 8760 字节,可以用来做些有用的事。

不妨试试传统的 “Hello, World!” 程序:

package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}

不幸的是,这次结果有些糟糕:

$ egc
/usr/local/arm/bin/arm-none-eabi-ld: /home/michal/P/go/src/github.com/ziutek/emgo/egpath/src/stm32/examples/f030-demo-board/blog/cortexm0.elf section `.text' will not fit in region `Flash'
/usr/local/arm/bin/arm-none-eabi-ld: region `Flash' overflowed by 10880 bytes
exit status 1

“Hello, World!” 需要 STM32F030x6 上至少 32KB 的 Flash 空间。

fmt 包强制包含整个 strconvreflect 包。这三个包,即使在精简版本中的 Emgo 中,占用空间也很大。我们不能使用这个例子了。有很多的应用不需要好看的文本输出。通常,一个或多个 LED,或者七段数码管显示就足够了。不过,在第二部分,我会尝试使用 strconv 包来格式化,并在 UART 上显示一些数字和文本。

闪烁

我们的开发板上有一个与 PA4 引脚和 VCC 相连的 LED。这次我们的代码稍稍长了一些:

package main

import (
    "delay"

    "stm32/hal/gpio"
    "stm32/hal/system"
    "stm32/hal/system/timer/systick"
)

var led gpio.Pin

func init() {
    system.SetupPLL(8, 1, 48/8)
    systick.Setup(2e6)

    gpio.A.EnableClock(false)
    led = gpio.A.Pin(4)

    cfg := &gpio.Config{Mode: gpio.Out, Driver: gpio.OpenDrain}
    led.Setup(cfg)
}

func main() {
    for {
        led.Clear()
        delay.Millisec(100)
        led.Set()
        delay.Millisec(900)
    }
}

按照惯例,init 函数用来初始化和配置外设。

system.SetupPLL(8, 1, 48/8) 用来配置 RCC,将外部的 8 MHz 振荡器的 PLL 作为系统时钟源。PLL 分频器设置为 1,倍频数设置为 48/8 =6,这样系统时钟频率为 48MHz。

systick.Setup(2e6) 将 Cortex-M SYSTICK 时钟作为系统时钟,每隔 2e6 次纳秒运行一次(每秒钟 500 次)。

gpio.A.EnableClock(false) 开启了 GPIO A 口的时钟。False 意味着这一时钟在低功耗模式下会被禁用,但在 STM32F0 系列中并未实现这一功能。

led.Setup(cfg) 设置 PA4 引脚为开漏输出。

led.Clear() 将 PA4 引脚设为低,在开漏设置中,打开 LED。

led.Set() 将 PA4 设为高电平状态,关掉LED。

编译这个代码:

$ egc
$ arm-none-eabi-size cortexm0.elf
   text    data     bss     dec     hex filename
   9772     172     168   10112    2780 cortexm0.elf

正如你所看到的,这个闪烁程序占用了 2320 字节,比最基本程序占用空间要大。还有 6440 字节的剩余空间。

看看代码是否能运行:

$ openocd -d0 -f interface/stlink.cfg -f target/stm32f0x.cfg -c 'init; program cortexm0.elf; reset run; exit'
Open On-Chip Debugger 0.10.0+dev-00319-g8f1f912a (2018-03-07-19:20)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
debug_level: 0
adapter speed: 1000 kHz
adapter_nsrst_delay: 100
none separate
adapter speed: 950 kHz
target halted due to debug-request, current mode: Thread 
xPSR: 0xc1000000 pc: 0x0800119c msp: 0x20000da0
adapter speed: 4000 kHz
** Programming Started **
auto erase enabled
target halted due to breakpoint, current mode: Thread 
xPSR: 0x61000000 pc: 0x2000003a msp: 0x20000da0
wrote 10240 bytes from file cortexm0.elf in 0.817425s (12.234 KiB/s)
** Programming Finished **
adapter speed: 950 kHz

在这篇文章中,这是我第一次,将一个短视频转换成动画 PNG。我对此印象很深,再见了 YouTube。 对于 IE 用户,我很抱歉,更多信息请看 apngasm。我本应该学习 HTML5,但现在,APNG 是我最喜欢的,用来播放循环短视频的方法了。

STM32F030F4P6

更多的 Go 语言编程

如果你不是一个 Go 程序员,但你已经听说过一些关于 Go 语言的事情,你可能会说:“Go 语法很好,但跟 C 比起来,并没有明显的提升。让我看看 Go 语言的通道和协程!”

接下来我会一一展示:

import (
    "delay"

    "stm32/hal/gpio"
    "stm32/hal/system"
    "stm32/hal/system/timer/systick"
)

var led1, led2 gpio.Pin

func init() {
    system.SetupPLL(8, 1, 48/8)
    systick.Setup(2e6)

    gpio.A.EnableClock(false)
    led1 = gpio.A.Pin(4)
    led2 = gpio.A.Pin(5)

    cfg := &gpio.Config{Mode: gpio.Out, Driver: gpio.OpenDrain}
    led1.Setup(cfg)
    led2.Setup(cfg)
}

func blinky(led gpio.Pin, period int) {
    for {
        led.Clear()
        delay.Millisec(100)
        led.Set()
        delay.Millisec(period - 100)
    }
}

func main() {
    go blinky(led1, 500)
    blinky(led2, 1000)
}

代码改动很小: 添加了第二个 LED,上一个例子中的 main 函数被重命名为 blinky 并且需要提供两个参数。 main 在新的协程中先调用 blinky,所以两个 LED 灯在并行使用。值得一提的是,gpio.Pin 可以同时访问同一 GPIO 口的不同引脚。

Emgo 还有很多不足。其中之一就是你需要提前规定 goroutines(tasks) 的最大执行数量。是时候修改 script.ld 了:

ISRStack = 1024;
MainStack = 1024;
TaskStack = 1024;
MaxTasks = 2;

INCLUDE stm32/f030x4
INCLUDE stm32/loadflash
INCLUDE noos-cortexm

栈的大小需要靠猜,现在还不用关心这一点。

$ egc
$ arm-none-eabi-size cortexm0.elf
   text    data     bss     dec     hex filename
  10020     172     172   10364    287c cortexm0.elf

另一个 LED 和协程一共占用了 248 字节的 Flash 空间。

STM32F030F4P6

通道

通道是 Go 语言中协程之间相互通信的一种推荐方式。Emgo 甚至能允许通过中断处理来使用缓冲通道。下一个例子就展示了这种情况。

package main

import (
    "delay"
    "rtos"

    "stm32/hal/gpio"
    "stm32/hal/irq"
    "stm32/hal/system"
    "stm32/hal/system/timer/systick"
    "stm32/hal/tim"
)

var (
    leds  [3]gpio.Pin
    timer *tim.Periph
    ch    = make(chan int, 1)
)

func init() {
    system.SetupPLL(8, 1, 48/8)
    systick.Setup(2e6)

    gpio.A.EnableClock(false)
    leds[0] = gpio.A.Pin(4)
    leds[1] = gpio.A.Pin(5)
    leds[2] = gpio.A.Pin(9)

    cfg := &gpio.Config{Mode: gpio.Out, Driver: gpio.OpenDrain}
    for _, led := range leds {
        led.Set()
        led.Setup(cfg)
    }

    timer = tim.TIM3
    pclk := timer.Bus().Clock()
    if pclk < system.AHB.Clock() {
        pclk *= 2
    }
    freq := uint(1e3) // Hz
    timer.EnableClock(true)
    timer.PSC.Store(tim.PSC(pclk/freq - 1))
    timer.ARR.Store(700) // ms
    timer.DIER.Store(tim.UIE)
    timer.CR1.Store(tim.CEN)

    rtos.IRQ(irq.TIM3).Enable()
}

func blinky(led gpio.Pin, period int) {
    for range ch {
        led.Clear()
        delay.Millisec(100)
        led.Set()
        delay.Millisec(period - 100)
    }
}

func main() {
    go blinky(leds[1], 500)
    blinky(leds[2], 500)
}

func timerISR() {
    timer.SR.Store(0)
    leds[0].Set()
    select {
    case ch <- 0:
        // Success
    default:
        leds[0].Clear()
    }
}

//c:__attribute__((section(".ISRs")))
var ISRs = [...]func(){
    irq.TIM3: timerISR,
}

与之前例子相比较下的不同:

  1. 添加了第三个 LED,并连接到 PA9 引脚(UART 头的 TXD 引脚)。
  2. 时钟(TIM3)作为中断源。
  3. 新函数 timerISR 用来处理 irq.TIM3 的中断。
  4. 新增容量为 1 的缓冲通道是为了 timerISRblinky 协程之间的通信。
  5. ISRs 数组作为中断向量表,是更大的异常向量表的一部分。
  6. blinky 中的 for 语句被替换成 range 语句。

为了方便起见,所有的 LED,或者说它们的引脚,都被放在 leds 这个数组里。另外,所有引脚在被配置为输出之前,都设置为一种已知的初始状态(高电平状态)。

在这个例子里,我们想让时钟以 1 kHz 的频率运行。为了配置 TIM3 预分频器,我们需要知道它的输入时钟频率。通过参考手册我们知道,输入时钟频率在 APBCLK = AHBCLK 时,与 APBCLK 相同,反之等于 2 倍的 APBCLK

如果 CNT 寄存器增加 1 kHz,那么 ARR 寄存器的值等于更新事件(重载事件)在毫秒中的计数周期。 为了让更新事件产生中断,必须要设置 DIER 寄存器中的 UIE 位。CEN 位能启动时钟。

时钟外设在低功耗模式下必须启用,为了自身能在 CPU 处于休眠时保持运行: timer.EnableClock(true)。这在 STM32F0 中无关紧要,但对代码可移植性却十分重要。

timerISR 函数处理 irq.TIM3 的中断请求。timer.SR.Store(0) 会清除 SR 寄存器里的所有事件标志,无效化向 NVIC 发出的所有中断请求。凭借经验,由于中断请求无效的延时性,需要在程序一开始马上清除所有的中断标志。这避免了无意间再次调用处理。为了确保万无一失,需要先清除标志,再读取,但是在我们的例子中,清除标志就已经足够了。

下面的这几行代码:

select {
case ch <- 0:
    // Success
default:
    leds[0].Clear()
}

是 Go 语言中,如何在通道上非阻塞地发送消息的方法。中断处理程序无法一直等待通道中的空余空间。如果通道已满,则执行 default,开发板上的LED就会开启,直到下一次中断。

ISRs 数组包含了中断向量表。//c:__attribute__((section(".ISRs"))) 会导致链接器将数组插入到 .ISRs 节中。

blinkyfor 循环的新写法:

for range ch {
    led.Clear()
    delay.Millisec(100)
    led.Set()
    delay.Millisec(period - 100)
}

等价于:

for {
    _, ok := <-ch
    if !ok {
        break // Channel closed.
    }
    led.Clear()
    delay.Millisec(100)
    led.Set()
    delay.Millisec(period - 100)
}

注意,在这个例子中,我们不在意通道中收到的值,我们只对其接受到的消息感兴趣。我们可以在声明时,将通道元素类型中的 int 用空结构体 struct{} 来代替,发送消息时,用 struct{}{} 结构体的值代替 0,但这部分对新手来说可能会有些陌生。

让我们来编译一下代码:

$ egc
$ arm-none-eabi-size cortexm0.elf
   text    data     bss     dec     hex filename
  11096     228     188   11512    2cf8 cortexm0.elf

新的例子占用了 11324 字节的 Flash 空间,比上一个例子多占用了 1132 字节。

采用现在的时序,两个闪烁协程从通道中获取数据的速度,比 timerISR 发送数据的速度要快。所以它们在同时等待新数据,你还能观察到 select 的随机性,这也是 Go 规范所要求的。

STM32F030F4P6

开发板上的 LED 一直没有亮起,说明通道从未出现过溢出。

我们可以加快消息发送的速度,将 timer.ARR.Store(700) 改为 timer.ARR.Store(200)。 现在 timerISR 每秒钟发送 5 条消息,但是两个接收者加起来,每秒也只能接受 4 条消息。

STM32F030F4P6

正如你所看到的,timerISR 开启黄色 LED 灯,意味着通道上已经没有剩余空间了。

第一部分到这里就结束了。你应该知道,这一部分并未展示 Go 中最重要的部分,接口。

协程和通道只是一些方便好用的语法。你可以用自己的代码来替换它们,这并不容易,但也可以实现。接口是Go 语言的基础。这是文章中 第二部分所要提到的.

在 Flash 上我们还有些剩余空间。


via: https://ziutek.github.io/2018/03/30/go_on_very_small_hardware.html

作者:Michał Derkacz 译者:wenwensnow 校对:wxy

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