分类 技术 下的文章

不要把你又旧又慢的 MacBook 扔进垃圾桶。用 Linux Mint 延长它的寿命。

 title=

去年,我写了篇关于如何用 Linux 赋予旧 MacBook 的新生命的文章,在例子中提到了 Elementary OS。最近,我用回那台 2015 年左右的 MacBook Air,发现遗失了我的登录密码。我下载了最新的 Elementary OS 5.1.7 Hera,但无法让实时启动识别我的 Broadcom 4360 无线芯片组。

最近,我一直在使用 Linux Mint 来翻新旧的笔记本电脑,我想在这台 MacBook Air 上试一下。我下载了 Linux Mint 20.1 ISO,并在我的 Linux 台式电脑上使用 Popsicle 创建了一个 USB 启动器。

 title=

接下来,我将 Thunderbolt 以太网适配器连接到 MacBook,并插入 USB 启动器。我打开系统电源,按下 MacBook 上的 Option 键,指示它从 USB 驱动器启动系统。

Linux Mint 在实时启动模式下启动没问题,但操作系统没有识别出无线连接。

我的无线网络在哪里?

这是因为为苹果设备制造 WiFi 卡的公司 Broadcom 没有发布开源驱动程序。这与英特尔、Atheros 和许多其他芯片制造商形成鲜明对比,但它是苹果公司使用的芯片组,所以这是 MacBook 上的一个常见问题。

我通过我的 Thunderbolt 适配器有线连接到以太网,因此我 在线的。通过之前的研究,我知道要让无线适配器在这台 MacBook 上工作,我需要在 Bash 终端执行三条独立的命令。然而,在安装过程中,我了解到 Linux Mint 有一个很好的内置驱动管理器,它提供了一个简单的图形用户界面来协助安装软件。

 title=

该操作完成后,我重启了安装了 Linux Mint 20.1 的新近翻新的 MacBook Air。Broadcom 无线适配器工作正常,使我能够轻松地连接到我的无线网络。

手动安装无线

你可以从终端完成同样的任务。首先,清除 Broadcom 内核源码的残余。

$ sudo apt-get purge bcmwl-kernel-source

然后添加一个固件安装程序:

$ sudo apt install firmware-b43-installer

最后,为系统安装新固件:

$ sudo apt install linux-firmware

将 Linux 作为你的 Mac 使用

我安装了 Phoronix 测试套件 以获得 MacBook Air 的系统信息。

 title=

系统工作良好。对内核 5.4.0-64-generic 的最新更新显示,无线连接仍然存在,并且我与家庭网络之间的连接为 866Mbps。Broadcom 的 FaceTime 摄像头不能工作,但其他东西都能正常工作。

我非常喜欢这台 MacBook 上的 Linux Mint Cinnamon 20.1 桌面。

 title=

如果你有一台因 macOS 更新而变得缓慢且无法使用的旧 MacBook,我建议你试一下 Linux Mint。我对这个发行版印象非常深刻,尤其是它在我的 MacBook Air 上的工作情况。它无疑延长了这个强大的小笔记本电脑的寿命。


via: https://opensource.com/article/21/4/restore-macbook-linux

作者:Don Watkins 选题:lujun9972 译者:geekpi 校对:wxy

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

在一个有许多加密磁盘的环境中,解锁所有的磁盘是一项困难的任务。 网络绑定磁盘加密 Network bound disk encryption (NBDE)有助于自动解锁 Stratis 卷的过程。这是在大型环境中的一个关键要求。Stratis 2.1 版本增加了对加密的支持,这在《Stratis 加密入门》一文中介绍过。Stratis 2.3 版本最近在使用加密的 Stratis 池时引入了对网络绑定磁盘加密(NBDE)的支持,这是本文的主题。

Stratis 网站 将 Stratis 描述为一个“易于使用的 Linux 本地存储管理”。短视频《使用 Stratis 管理存储》对基础知识进行了快速演示。该视频是在 Red Hat Enterprise Linux 8 系统上录制的,然而,视频中显示的概念也适用于 Fedora Linux 中的 Stratis。

先决条件

本文假设你熟悉 Stratis,也熟悉 Stratis 池加密。如果你不熟悉这些主题,请参考这篇 文章 和前面提到的 Stratis 概述视频

NBDE 需要 Stratis 2.3 或更高版本。本文中的例子使用的是 Fedora Linux 34 的预发布版本。Fedora Linux 34 的最终版本将包含 Stratis 2.3。

网络绑定磁盘加密(NBDE)概述

加密存储的主要挑战之一是有一个安全的方法在系统重启后再次解锁存储。在大型环境中,手动输入加密口令并不能很好地扩展。NBDE 解决了这一问题,允许以自动方式解锁加密存储。

在更高层次上,NBDE 需要环境中的 Tang 服务器。客户端系统(使用 Clevis Pin)只要能与 Tang 服务器建立网络连接,就可以自动解密存储。如果网络没有连接到 Tang 服务器,则必须手动解密存储。

这背后的想法是,Tang 服务器只能在内部网络上使用,因此,如果加密设备丢失或被盗,它将不再能够访问内部网络连接到 Tang 服务器,因此不会被自动解密。

关于 Tang 和 Clevis 的更多信息,请参见手册页(man tangman clevis)、Tang 的 GitHub 页面Clevis 的 GitHub 页面

设置 Tang 服务器

本例使用另一个 Fedora Linux 系统作为 Tang 服务器,主机名为 tang-server。首先安装 tang 包。

dnf install tang

然后用 systemctl 启用并启动 tangd.socket

systemctl enable tangd.socket --now

Tang 使用的是 TCP 80 端口,所以你也需要在防火墙中打开该端口。

firewall-cmd --add-port=80/tcp --permanent
firewall-cmd --add-port=80/tcp

最后,运行 tang-show-keys 来显示输出签名密钥指纹。你以后会需要这个。

# tang-show-keys
l3fZGUCmnvKQF_OA6VZF9jf8z2s

创建加密的 Stratis 池

上一篇关于 Stratis 加密的文章详细介绍了如何设置加密的 Stratis 池,所以本文不会深入介绍。

第一步是捕获一个将用于解密 Stratis 池的密钥。即使使用 NBDE,也需要设置这个,因为在 NBDE 服务器无法到达的情况下,可以用它来手动解锁池。使用以下命令捕获 pool1 密钥。

# stratis key set --capture-key pool1key
Enter key data followed by the return key:

然后我将使用 /dev/vdb 设备创建一个加密的 Stratis 池(使用刚才创建的 pool1key),命名为 pool1

# stratis pool create --key-desc pool1key pool1 /dev/vdb。

接下来,在这个 Stratis 池中创建一个名为 filesystem1 的文件系统,创建一个挂载点,挂载文件系统,并在其中创建一个测试文件:

# stratis filesystem create pool1 filesystem1
# mkdir /filesystem1
# mount /dev/stratis/pool1/filesystem1 /filesystem1
# cd /filesystem1
# echo "this is a test file" > testfile

将 Stratis 池绑定到 Tang 服务器上

此时,我们已经创建了加密的 Stratis 池,并在池中创建了一个文件系统。下一步是将你的 Stratis 池绑定到刚刚设置的 Tang 服务器上。使用 stratis pool bind nbde 命令进行。

当你进行 Tang 绑定时,需要向该命令传递几个参数:

  • 池名(在本例中,pool1
  • 钥匙描述符名称(本例中为 pool1key
  • Tang 服务器名称(在本例中,http://tang-server

记得之前在 Tang 服务器上,运行了 tang-show-keys,显示 Tang 输出的签名密钥指纹是 l3fZGUCmnvKQF_OA6VZF9jf8z2s。除了前面的参数外,还需要用参数 -thumbprint l3fZGUCmnvKQF_OA6VZF9jf8z2s 传递这个指纹,或者用 -trust-url 参数跳过对指纹的验证。

使用 -thumbprint 参数更安全。例如:

# stratis pool bind nbde pool1 pool1key http://tang-server --thumbprint l3fZGUCmnvKQF_OA6VZF9jf8z2s

用 NBDE 解锁 Stratis 池

接下来重启主机,并验证你可以用 NBDE 解锁 Stratis 池,而不需要使用密钥口令。重启主机后,该池不再可用:

# stratis pool list
Name Total Physical Properties

要使用 NBDE 解锁池,请运行以下命令:

# stratis pool unlock clevis

注意,你不需要使用密钥口令。这个命令可以在系统启动时自动运行。

此时,Stratis 池已经可以使用了:

# stratis pool list
Name Total Physical Properties
pool1 4.98 GiB / 583.65 MiB / 4.41 GiB ~Ca, Cr

你可以挂载文件系统,访问之前创建的文件:

# mount /dev/stratis/pool1/filesystem1 /filesystem1/
# cat /filesystem1/testfile
this is a test file

轮换 Tang 服务器密钥

最好定期轮换 Tang 服务器密钥,并更新 Stratis 客户服务器以使用新的 Tang 密钥。

要生成新的 Tang 密钥,首先登录到 Tang 服务器,查看 /var/db/tang 目录的当前状态。然后,运行 tang-show-keys 命令:

# ls -al /var/db/tang
total 8
drwx------. 1 tang tang 124 Mar 15 15:51 .
drwxr-xr-x. 1 root root 16 Mar 15 15:48 ..
-rw-r--r--. 1 tang tang 361 Mar 15 15:51 hbjJEDXy8G8wynMPqiq8F47nJwo.jwk
-rw-r--r--. 1 tang tang 367 Mar 15 15:51 l3fZGUCmnvKQF_OA6VZF9jf8z2s.jwk
# tang-show-keys
l3fZGUCmnvKQF_OA6VZF9jf8z2s

要生成新的密钥,运行 tangd-keygen 并将其指向 /var/db/tang 目录:

# /usr/libexec/tangd-keygen /var/db/tang

如果你再看看 /var/db/tang 目录,你会看到两个新文件:

# ls -al /var/db/tang
total 16
drwx------. 1 tang tang 248 Mar 22 10:41 .
drwxr-xr-x. 1 root root 16 Mar 15 15:48 ..
-rw-r--r--. 1 tang tang 361 Mar 15 15:51 hbjJEDXy8G8wynMPqiq8F47nJwo.jwk
-rw-r--r--. 1 root root 354 Mar 22 10:41 iyG5HcF01zaPjaGY6L_3WaslJ_E.jwk
-rw-r--r--. 1 root root 349 Mar 22 10:41 jHxerkqARY1Ww_H_8YjQVZ5OHao.jwk
-rw-r--r--. 1 tang tang 367 Mar 15 15:51 l3fZGUCmnvKQF_OA6VZF9jf8z2s.jwk

如果你运行 tang-show-keys,就会显示出 Tang 所公布的密钥:

# tang-show-keys
l3fZGUCmnvKQF_OA6VZF9jf8z2s
iyG5HcF01zaPjaGY6L_3WaslJ_E

你可以通过将两个原始文件改名为以句号开头的隐藏文件,来防止旧的密钥(以 l3fZ 开头)被公布。通过这种方法,旧的密钥将不再被公布,但是它仍然可以被任何没有更新为使用新密钥的现有客户端使用。一旦所有的客户端都更新使用了新密钥,这些旧密钥文件就可以删除了。

# cd /var/db/tang
# mv hbjJEDXy8G8wynMPqiq8F47nJwo.jwk   .hbjJEDXy8G8wynMPqiq8F47nJwo.jwk
# mv l3fZGUCmnvKQF_OA6VZF9jf8z2s.jwk   .l3fZGUCmnvKQF_OA6VZF9jf8z2s.jwk

此时,如果再运行 tang-show-keys,Tang 只公布新钥匙:

# tang-show-keys
iyG5HcF01zaPjaGY6L_3WaslJ_E

下一步,切换到你的 Stratis 系统并更新它以使用新的 Tang 密钥。当文件系统在线时, Stratis 支持这样做。

首先,解除对池的绑定:

# stratis pool unbind pool1

接下来,用创建加密池时使用的原始口令设置密钥:

# stratis key set --capture-key pool1key
Enter key data followed by the return key:

最后,用更新后的密钥指纹将 Stratis 池绑定到 Tang 服务器上:

# stratis pool bind nbde pool1 pool1key http://tang-server --thumbprint iyG5HcF01zaPjaGY6L_3WaslJ_E

Stratis 系统现在配置为使用更新的 Tang 密钥。一旦使用旧的 Tang 密钥的任何其他客户系统被更新,在 Tang 服务器上的 /var/db/tang 目录中被重命名为隐藏文件的两个原始密钥文件就可以被备份和删除了。

如果 Tang 服务器不可用怎么办?

接下来,关闭 Tang 服务器,模拟它不可用,然后重启 Stratis 系统。

重启后,Stratis 池又不可用了:

# stratis pool list
Name Total Physical Properties

如果你试图用 NBDE 解锁,会因为 Tang 服务器不可用而失败:

# stratis pool unlock clevis
Execution failed:
An iterative command generated one or more errors: The operation 'unlock' on a resource of type pool failed. The following errors occurred:
Partial action "unlock" failed for pool with UUID 4d62f840f2bb4ec9ab53a44b49da3f48: Cryptsetup error: Failed with error: Error: Command failed: cmd: "clevis" "luks" "unlock" "-d" "/dev/vdb" "-n" "stratis-1-private-42142fedcb4c47cea2e2b873c08fcf63-crypt", exit reason: 1 stdout: stderr: /dev/vdb could not be opened.

此时,在 Tang 服务器无法到达的情况下,解锁池的唯一选择就是使用原密钥口令:

# stratis key set --capture-key pool1key
Enter key data followed by the return key:

然后你可以使用钥匙解锁池:

# stratis pool unlock keyring

接下来,验证池是否成功解锁:

# stratis pool list
Name Total Physical Properties
pool1 4.98 GiB / 583.65 MiB / 4.41 GiB ~Ca, Cr

via: https://fedoramagazine.org/network-bound-disk-encryption-with-stratis/

作者:briansmith 选题:lujun9972 译者:wxy 校对:wxy

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

Cython 创建的 C 模块可以加速 Python 代码的执行,这对使用效率不高的解释型语言编写的复杂应用是很重要的。

 title=

Cython 是 Python 编程语言的编译器,旨在优化性能并形成一个扩展的 Cython 编程语言。作为 Python 的扩展,Cython 也是 Python 语言的超集,它支持调用 C 函数和在变量和类属性上声明 C 类型。这使得包装外部 C 库、将 C 嵌入现有应用程序或者为 Python 编写像 Python 一样简单的 C 语言扩展语法变得容易。

Cython 一般用于创建 C 模块来加速 Python 代码的执行。这在使用解释型语言编写的效率不高的复杂应用中非常重要。

安装 Cython

你可以在 Linux、BSD、Windows 或 macOS 上安装 Cython 来使用 Python:

$ python -m pip install Cython

安装好后,就可以使用它了。

将 Python 转换成 C

使用 Cython 的一个好的方式是从一个简单的 “hello world” 开始。这虽然不是展示 Cython 优点的最好方式,但是它展示了使用 Cython 时发生的情况。

首先,创建一个简单的 Python 脚本,文件命名为 hello.pyx.pyx 扩展名并不神奇,从技术上它可以是任何东西,但它是 Cython 的默认扩展名):

print("hello world")

接下来,创建一个 Python 设置脚本。一个像 Python 的 makefile 一样的 setup.py,Cython 可以使用它来处理你的 Python 代码:

from setuptools import setup
from Cython.Build import cythonize

setup(
    ext_modules = cythonize("hello.pyx")
)

最后,使用 Cython 将你的 Python 脚本转换为 C 代码:

$ python setup.py build_ext --inplace

你可以在你的工程目录中看到结果。Cython 的 cythonize 模块将 hello.pyx 转换成一个 hello.c 文件和一个 .so 库。这些 C 代码有 2648 行,所以它比一个一行的 hello.pyx 源码的文本要多很多。.so 库也比它的源码大 2000 倍(即 54000 字节和 20 字节相比)。然后,Python 需要运行单个 Python 脚本,所以有很多代码支持这个只有一行的 hello.pyx 文件。

要使用 Python 的 “hello world” 脚本的 C 代码版本,请打开一个 Python 提示符并导入你创建的新 hello 模块:

>>> import hello
hello world

将 C 代码集成到 Python 中

测试计算能力的一个很好的通用测试是计算质数。质数是一个比 1 大的正数,且它只有被 1 或它自己除后才会产生正整数。虽然理论很简单,但是随着数的变大,计算需求也会增加。在纯 Python 中,可以用 10 行以内的代码完成质数的计算。

import sys

number = int(sys.argv[1])
if not number <= 1:
    for i in range(2, number):
        if (number % i) == 0:
            print("Not prime")
            break
else:
    print("Integer must be greater than 1")

这个脚本在成功的时候是不会提醒的,如果这个数不是质数,则返回一条信息:

$ ./prime.py 3
$ ./prime.py 4
Not prime.

将这些转换为 Cython 需要一些工作,一部分是为了使代码适合用作库,另一部分是为了提高性能。

脚本和库

许多用户将 Python 当作一种脚本语言来学习:你告诉 Python 想让它执行的步骤,然后它来做。随着你对 Python(以及一般的开源编程)的了解越多,你可以了解到许多强大的代码都存在于其他应用程序可以利用的库中。你的代码越 不具有针对性,程序员(包括你)就越可能将其重用于其他的应用程序。将计算和工作流解耦可能需要更多的工作,但最终这通常是值得的。

在这个简单的质数计算的例子中,将其转换成 Cython,首先是一个设置脚本:

from setuptools import setup
from Cython.Build import cythonize

setup(
    ext_modules = cythonize("prime.py")
)

将你的脚本转换成 C:

$ python setup.py build_ext --inplace

到目前为止,一切似乎都工作的很好,但是当你试图导入并使用新模块时,你会看到一个错误:

>>> import prime
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "prime.py", line 2, in init prime
    number = sys.argv[1]
IndexError: list index out of range

这个问题是 Python 脚本希望从一个终端运行,其中参数(在这个例子中是要测试是否为质数的整数)是一样的。你需要修改你的脚本,使它可以作为一个库来使用。

写一个库

库不使用系统参数,而是接受其他代码的参数。对于用户输入,与其使用 sys.argv,不如将你的代码封装成一个函数来接收一个叫 number(或者 num,或者任何你喜欢的变量名)的参数:

def calculate(number):
    if not number <= 1:
        for i in range(2, number):
            if (number % i) == 0:
                print("Not prime")
                break
    else:
        print("Integer must be greater than 1")

这确实使你的脚本有些难以测试,因为当你在 Python 中运行代码时,calculate 函数永远不会被执行。但是,Python 编程人员已经为这个问题设计了一个通用、还算直观的解决方案。当 Python 解释器执行一个 Python 脚本时,有一个叫 __name__ 的特殊变量,这个变量被设置为 __main__,但是当它被作为模块导入的时候,__name__ 被设置为模块的名字。利用这点,你可以写一个既是 Python 模块又是有效 Python 脚本的库:

import sys

def calculate(number):
    if not number <= 1:
        for i in range(2, number):
            if (number % i) == 0:
                print("Not prime")
                break
    else:
        print("Integer must be greater than 1")

if __name__ == "__main__":
    number = sys.argv[1]    
    calculate( int(number) )

现在你可以用一个命令来运行代码了:

$ python ./prime.py 4
Not a prime

你可以将它转换为 Cython 来用作一个模块:

>>> import prime
>>> prime.calculate(4)
Not prime

C Python

用 Cython 将纯 Python 的代码转换为 C 代码是有用的。这篇文章描述了如何做,然而,Cython 还有功能可以帮助你在转换之前优化你的代码,分析你的代码来找到 Cython 什么时候与 C 进行交互,以及更多。如果你正在用 Python,但是你希望用 C 代码改进你的代码,或者进一步理解库是如何提供比脚本更好的扩展性的,或者你只是好奇 Python 和 C 是如何协作的,那么就开始使用 Cython 吧。


via: https://opensource.com/article/21/4/cython

作者:Alan Smithee 选题:lujun9972 译者:ShuyRoy 校对:wxy

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

现在很多高端笔记本都配备了指纹识别器。Windows 和 macOS 支持指纹登录已经有一段时间了。在桌面 Linux 中,对指纹登录的支持更多需要极客的调整,但 GNOMEKDE 已经开始通过系统设置来支持它。

这意味着在新的 Linux 发行版上,你可以轻松使用指纹识别。在这里我将在 Ubuntu 中启用指纹登录,但你也可以在其他运行 GNOME 3.38 的发行版上使用这些步骤。

前提条件

当然,这是显而易见的。你的电脑必须有一个指纹识别器。

这个方法适用于任何运行 GNOME 3.38 或更高版本的 Linux 发行版。如果你不确定,你可以检查你使用的桌面环境版本

KDE 5.21 也有一个指纹管理器。当然,截图看起来会有所不同。

在 Ubuntu 和其他 Linux 发行版中添加指纹登录功能

进入 “设置”,然后点击左边栏的 “用户”。你应该可以看到系统中所有的用户账号。你会看到几个选项,包括 “指纹登录”。

点击启用这里的指纹登录选项。

Enable fingerprint login in Ubuntu

它将立即要求你扫描一个新的指纹。当你点击 “+” 号来添加指纹时,它会提供一些预定义的选项,这样你就可以很容易地识别出它是哪根手指或拇指。

当然,你可以点击右手食指但扫描左手拇指,不过我看不出你有什么好的理由要这么做。

Adding fingerprint

在添加指纹时,请按照指示旋转你的手指或拇指。

Rotate your finger

系统登记了整个手指后,就会给你一个绿色的信号,表示已经添加了指纹。

Fingerprint successfully added

如果你想马上测试一下,在 Ubuntu 中按 Super+L 快捷键锁定屏幕,然后使用指纹进行登录。

Login With Fingerprint in Ubuntu

在 Ubuntu 上使用指纹登录的经验

指纹登录顾名思义就是使用你的指纹来登录系统。就是这样。当要求对需要 sudo 访问的程序进行认证时,你不能使用手指。它不能代替你的密码。

还有一件事。指纹登录可以让你登录,但当系统要求输入 sudo 密码时,你不能用手指。Ubuntu 中的 钥匙环 也仍然是锁定的。

另一件烦人的事情是因为 GNOME 的 GDM 登录界面。当你登录时,你必须先点击你的账户才能进入密码界面。你在这可以使用手指。如果能省去先点击用户帐户 ID 的麻烦就更好了。

我还注意到,指纹识别没有 Windows 中那么流畅和快速。不过,它可以使用。

如果你对 Linux 上的指纹登录有些失望,你可以禁用它。让我在下一节告诉你步骤。

禁用指纹登录

禁用指纹登录和最初启用指纹登录差不多。

进入 “设置→用户”,然后点击指纹登录选项。它会显示一个有添加更多指纹或删除现有指纹的页面。你需要删除现有的指纹。

Disable Fingerprint Login

指纹登录确实有一些好处,特别是对于我这种懒人来说。我不用每次锁屏时输入密码,我也对这种有限的使用感到满意。

PAM 启用指纹解锁 sudo 应该不是完全不可能。我记得我 在 Ubuntu 中设置脸部解锁时,也可以用于 sudo。看看以后的版本是否会增加这个功能吧。

你有带指纹识别器的笔记本吗?你是否经常使用它,或者它只是你不关心的东西之一?


via: https://itsfoss.com/fingerprint-login-ubuntu/

作者:Abhishek Prakash 选题:lujun9972 译者:geekpi 校对:wxy

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

用开源工具让你的终端窗口在 Mac 上漂亮起来。

 title=

你是否曾经厌倦了在你的 macOS 电脑上看到同样老式的终端窗口?如果是这样,使用开源的 Oh My Zsh 框架和 Powerlevel10k 主题为你的视图添加一些点缀。

这个基本的逐步教程将让你开始定制你的 macOS 终端。如果你是一个 Linux 用户,请查看 Seth Kenlon 的指南 为 Zsh 添加主题和插件 以获得深入指导。

步骤 1:安装 Oh My Zsh

Oh My Zsh 是一个开源的、社区驱动的框架,用于管理你的 Z shell (Zsh) 配置。

 title=

Oh My Zsh 是在 MIT 许可下发布的。使用以下命令安装:

$ sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

步骤 2:安装 Powerlevel10k 字体

 title=

Powerlevel10k 是一个 MIT 许可的 Zsh 主题。在安装 Powerlevel10k 之前,你需要为你的终端安装自定义字体。

Powerlevel10 GitHub 页面,在 README 中 搜索 “fonts”。安装自定义字体的步骤会根据你的操作系统而有所不同。这只需要简单地点击-下载-安装的系列操作。

 title=

步骤 3:安装 Powerlevel10k 主题

接下来,运行以下命令安装 Powerlevel10k:

git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k

完成后,用文本编辑器,比如 Vim,打开 ~/.zshrc 配置文件,设置行 ZSH_THEME="powerlevel10k/powerlevel10k,然后保存文件。

步骤 4:完成 Powerlevel10 的设置

打开一个新的终端,你应该看到 Powerlevel10k 配置向导。如果没有,运行 p10k configure 来调出配置向导。如果你在步骤 2 中安装了自定义字体,那么图标和符号应该正确显示。将默认字体更改为 MeslowLG NF

 title=

当你完成配置后,你应该会看到一个漂亮的终端。

 title=

就是这些了!你应该可以享受你美丽的新终端了。


via: https://opensource.com/article/21/4/zsh-mac

作者:Bryant Son 选题:lujun9972 译者:geekpi 校对:wxy

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

了解 Linux 如何使用库,包括静态库和动态库的差别,有助于你解决依赖问题。

 title=

Linux 从某种意义上来说就是一堆相互依赖的静态和动态库。对于 Linux 系统新手来说,库的整个处理过程简直是个迷。但对有经验的人来说,被构建进操作系统的大量共享代码对于编写新应用来说却是个优点。

为了让你熟悉这个话题,我准备了一个小巧的 应用例子 来展示在普通的 Linux 发行版(在其他操作系统上未验证)上是经常是如何处理库的。为了用这个例子来跟上这个需要动手的教程,请打开命令行输入:

$ git clone https://github.com/hANSIc99/library_sample
$ cd library_sample/
$ make
cc -c main.c -Wall -Werror
cc -c libmy_static_a.c -o libmy_static_a.o -Wall -Werror
cc -c libmy_static_b.c -o libmy_static_b.o -Wall -Werror
ar -rsv libmy_static.a libmy_static_a.o libmy_static_b.o
ar: creating libmy_static.a
a - libmy_static_a.o
a - libmy_static_b.o
cc -c -fPIC libmy_shared.c -o libmy_shared.o
cc -shared -o libmy_shared.so libmy_shared.o
$ make clean
rm *.o

当执行完这些命令,这些文件应当被添加进目录下(执行 ls 来查看):

my_app
libmy_static.a
libmy_shared.so

关于静态链接

当你的应用链接了一个静态库,这个库的代码就变成了可执行文件的一部分。这个动作只在链接过程中执行一次,这些静态库通常以 .a 扩展符结尾。

静态库是多个 目标 object 文件的 归档 archive ar)。这些目标文件通常是 ELF 格式的。ELF 是 可执行可链接格式 Executable and Linkable Format 的简写,它与多个操作系统兼容。

file 命令的输出可以告诉你静态库 libmy_static.aar 格式的归档文件类型。

$ file libmy_static.a
libmy_static.a: current ar archive

使用 ar -t,你可以看到归档文件的内部。它展示了两个目标文件:

$ ar -t libmy_static.a
libmy_static_a.o
libmy_static_b.o

你可以用 ax -x <archive-file> 命令来提取归档文件的文件。被提出的都是 ELF 格式的目标文件:

$ ar -x libmy_static.a
$ file libmy_static_a.o
libmy_static_a.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped

关于动态链接

动态链接指的是使用共享库。共享库通常以 .so 的扩展名结尾(“ 共享对象 shared object ” 的简写)。

共享库是 Linux 系统中依赖管理的最常用方法。这些共享库在应用启动前被载入内存,当多个应用都需要同一个库时,这个库在系统中只会被加载一次。这个特性减少了应用的内存占用。

另外一个值得注意的地方是,当一个共享库的 bug 被修复后,所有引用了这个库的应用都会受益。但这也意味着,如果一个 bug 还没被发现,那所有相关的应用都会遭受这个 bug 影响(如果这个应用使用了受影响的部分)。

当一个应用需要某个特定版本的库,但是 链接器 linker 只知道某个不兼容版本的位置,对于初学者来说这个问题非常棘手。在这个场景下,你必须帮助链接器找到正确版本的路径。

尽管这不是一个每天都会遇到的问题,但是理解动态链接的原理总是有助于你修复类似的问题。

幸运的是,动态链接的机制其实非常简洁明了。

为了检查一个应用在启动时需要哪些库,你可以使用 ldd 命令,它会打印出给定文件所需的动态库:

$ ldd my_app
        linux-vdso.so.1 (0x00007ffd1299c000)
        libmy_shared.so => not found
        libc.so.6 => /lib64/libc.so.6 (0x00007f56b869b000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f56b8881000)

可以注意到 libmy_shared.so 库是代码仓库的一部分,但是没有被找到。这是因为负责在应用启动之前将所有依赖加载进内存的动态链接器没有在它搜索的标准路径下找到这个库。

对新手来说,与常用库(例如 bizp2)版本不兼容相关的问题往往十分令人困惑。一种方法是把该仓库的路径加入到环境变量 LD_LIBRARY_PATH 中来告诉链接器去哪里找到正确的版本。在本例中,正确的版本就在这个目录下,所以你可以导出它至环境变量:

$ LD_LIBRARY_PATH=$(pwd):$LD_LIBRARY_PATH
$ export LD_LIBRARY_PATH

现在动态链接器知道去哪找库了,应用也可以执行了。你可以再次执行 ldd 去调用动态链接器,它会检查应用的依赖然后加载进内存。内存地址会在对象路径后展示:

$ ldd my_app
        linux-vdso.so.1 (0x00007ffd385f7000)
        libmy_shared.so => /home/stephan/library_sample/libmy_shared.so (0x00007f3fad401000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f3fad21d000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f3fad408000)

想知道哪个链接器被调用了,你可以用 file 命令:

$ file my_app
my_app: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=26c677b771122b4c99f0fd9ee001e6c743550fa6, for GNU/Linux 3.2.0, not stripped

链接器 /lib64/ld-linux-x86–64.so.2 是一个指向 ld-2.30.so 的软链接,它也是我的 Linux 发行版的默认链接器:

$ file /lib64/ld-linux-x86-64.so.2
/lib64/ld-linux-x86-64.so.2: symbolic link to ld-2.31.so

回头看看 ldd 命令的输出,你还可以看到(在 libmy_shared.so 边上)每个依赖都以一个数字结尾(例如 /lib64/libc.so.6)。共享对象的常见命名格式为:

libXYZ.so.<MAJOR>.<MINOR>

在我的系统中,libc.so.6 也是指向同一目录下的共享对象 libc-2.31.so 的软链接。

$ file /lib64/libc.so.6
/lib64/libc.so.6: symbolic link to libc-2.31.so

如果你正在面对一个应用因为加载库的版本不对导致无法启动的问题,有很大可能你可以通过检查整理这些软链接或者确定正确的搜索路径(查看下方“动态加载器:ld.so”一节)来解决这个问题。

更为详细的信息请查看 ldd 手册页

动态加载

动态加载的意思是一个库(例如一个 .so 文件)在程序的运行时被加载。这是使用某种特定的编程方法实现的。

当一个应用使用可以在运行时改变的插件时,就会使用动态加载。

查看 dlopen 手册页 获取更多信息。

动态加载器:ld.so

在 Linux 系统中,你几乎总是正在跟共享库打交道,所以必须有个机制来检测一个应用的依赖并将其加载进内存中。

ld.so 按以下顺序在这些地方寻找共享对象:

  1. 应用的绝对路径或相对路径下(用 GCC 编译器的 -rpath 选项硬编码的)
  2. 环境变量 LD_LIBRARY_PATH
  3. /etc/ld.so.cache 文件

需要记住的是,将一个库加到系统库归档 /usr/lib64 中需要管理员权限。你可以手动拷贝 libmy_shared.so 至库归档中来让应用可以运行,而避免设置 LD_LIBRARY_PATH

unset LD_LIBRARY_PATH
sudo cp libmy_shared.so /usr/lib64/

当你运行 ldd 时,你现在可以看到归档库的路径被展示出来:

$ ldd my_app
        linux-vdso.so.1 (0x00007ffe82fab000)
        libmy_shared.so => /lib64/libmy_shared.so (0x00007f0a963e0000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f0a96216000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f0a96401000)

在编译时定制共享库

如果你想你的应用使用你的共享库,你可以在编译时指定一个绝对或相对路径。

编辑 makefile(第 10 行)然后通过 make -B 来重新编译程序。然后 ldd 输出显示 libmy_shared.so 和它的绝对路径一起被列出来了。

把这个:

CFLAGS =-Wall -Werror -Wl,-rpath,$(shell pwd)

改成这个(记得修改用户名):

CFLAGS =/home/stephan/library_sample/libmy_shared.so

然后重新编译:

$ make

确认下它正在使用你设定的绝对路径,你可以在输出的第二行看到:

$ ldd my_app
    linux-vdso.so.1 (0x00007ffe143ed000)
        libmy_shared.so => /lib64/libmy_shared.so (0x00007fe50926d000)
        /home/stephan/library_sample/libmy_shared.so (0x00007fe509268000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fe50909e000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fe50928e000)

这是个不错的例子,但是如果你在编写给其他人用的库,它是怎样工作的呢?新库的路径可以通过写入 /etc/ld.so.conf 或是在 /etc/ld.so.conf.d/ 目录下创建一个包含路径的 <library-name>.conf 文件来注册至系统。之后,你必须执行 ldconfig 命令来覆写 ld.so.cache 文件。这一步有时候在你装了携带特殊的共享库的程序来说是不可省略的。

查看 ld.so 的手册页 获取更多详细信息。

怎样处理多种架构

通常来说,32 位和 64 位版本的应用有不同的库。下面列表展示了不同 Linux 发行版库的标准路径:

红帽家族

  • 32 位:/usr/lib
  • 64 位:/usr/lib64

Debian 家族

  • 32 位:/usr/lib/i386-linux-gnu
  • 64 位:/usr/lib/x86_64-linux-gnu

Arch Linux 家族

  • 32 位:/usr/lib32
  • 64 位:/usr/lib64

FreeBSD(技术上来说不算 Linux 发行版)

  • 32 位:/usr/lib32
  • 64 位:/usr/lib

知道去哪找这些关键库可以让库链接失效的问题成为历史。

虽然刚开始会有点困惑,但是理解 Linux 库的依赖管理是一种对操作系统掌控感的表现。在其他应用程序中运行这些步骤,以熟悉常见的库,然后继续学习怎样解决任何你可能遇到的库的挑战。


via: https://opensource.com/article/20/6/linux-libraries

作者:Stephan Avenwedde 选题:lujun9972 译者:tt67wq 校对:wxy

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