分类 技术 下的文章

大家好!几天前我写了篇 小型的个人程序 的文章,里面提到了调用没有文档说明的“秘密” API 很有意思,你需要从你的浏览器中把 cookies 复制出来才能访问。

有些读者问如何实现,因此我打算详细描述下,其实过程很简单。我们还会谈谈在调用没有文档说明的 API 时,可能会遇到的错误和道德问题。

我们用谷歌 Hangouts 举例。我之所以选择它,并不是因为这个例子最有用(我认为官方的 API 更实用),而是因为在这个场景中更有用的网站很多是小网站,而小网站的 API 一旦被滥用,受到的伤害会更大。因此我们使用谷歌 Hangouts,因为我 100% 肯定谷歌论坛可以抵御这种试探行为。

我们现在开始!

第一步:打开开发者工具,找一个 JSON 响应

我浏览了 https://hangouts.google.com,在Firefox的开发者工具中打开“ruby网络rtNetwork/rt/ruby”标签,找到一个 JSON 响应。你也可以使用 Chrome 的开发者工具。

打开之后界面如下图:

找到其中一条 “ 类型 Type ” 列显示为 json 的请求。

为了找一条感兴趣的请求,我找了好一会儿,突然我找到一条 “people” 的端点,看起来是返回我们的联系人信息。听起来很有意思,我们来看一下。

第二步:复制为 cURL

下一步,我在感兴趣的请求上右键,点击 “复制Copy” -> “ 复制为 cURL Copy as cURL ”。

然后我把 curl 命令粘贴到终端并运行。下面是运行结果:

$ curl 'https://people-pa.clients6.google.com/v2/people/?key=REDACTED' -X POST ........ (省略了大量请求标头)
Warning: Binary output can mess up your terminal. Use "--output -" to tell 
Warning: curl to output it to your terminal anyway, or consider "--output 
Warning: <FILE>" to save to a file.

你可能会想 —— 很奇怪,“二进制的输出在你的终端上无法正常显示” 是什么错误?原因是,浏览器默认情况下发给服务器的请求头中有 Accept-Encoding: gzip, deflate 参数,会把输出结果进行压缩。

我们可以通过管道把输出传递给 gunzip 来解压,但是我们发现不带这个参数进行请求会更简单。因此我们去掉一些不相关的请求头。

第三步:去掉不相关的请求头

下面是我从浏览器获得的完整 curl 命令。有很多行!我用反斜杠(\)把请求分开,这样每个请求头占一行,看起来更清晰:

curl 'https://people-pa.clients6.google.com/v2/people/?key=REDACTED' \
-X POST \
-H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:96.0) Gecko/20100101 Firefox/96.0' \
-H 'Accept: */*' \
-H 'Accept-Language: en' \
-H 'Accept-Encoding: gzip, deflate' \
-H 'X-HTTP-Method-Override: GET' \
-H 'Authorization: SAPISIDHASH REDACTED' \
-H 'Cookie: REDACTED'
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'X-Goog-AuthUser: 0' \
-H 'Origin: https://hangouts.google.com' \
-H 'Connection: keep-alive' \
-H 'Referer: https://hangouts.google.com/' \
-H 'Sec-Fetch-Dest: empty' \
-H 'Sec-Fetch-Mode: cors' \
-H 'Sec-Fetch-Site: same-site' \
-H 'Sec-GPC: 1' \
-H 'DNT: 1' \
-H 'Pragma: no-cache' \
-H 'Cache-Control: no-cache' \
-H 'TE: trailers' \
--data-raw 'personId=101777723309&personId=1175339043204&personId=1115266537043&personId=116731406166&extensionSet.extensionNames=HANGOUTS_ADDITIONAL_DATA&extensionSet.extensionNames=HANGOUTS_OFF_NETWORK_GAIA_GET&extensionSet.extensionNames=HANGOUTS_PHONE_DATA&includedProfileStates=ADMIN_BLOCKED&includedProfileStates=DELETED&includedProfileStates=PRIVATE_PROFILE&mergedPersonSourceOptions.includeAffinity=CHAT_AUTOCOMPLETE&coreIdParams.useRealtimeNotificationExpandedAcls=true&requestMask.includeField.paths=person.email&requestMask.includeField.paths=person.gender&requestMask.includeField.paths=person.in_app_reachability&requestMask.includeField.paths=person.metadata&requestMask.includeField.paths=person.name&requestMask.includeField.paths=person.phone&requestMask.includeField.paths=person.photo&requestMask.includeField.paths=person.read_only_profile_info&requestMask.includeField.paths=person.organization&requestMask.includeField.paths=person.location&requestMask.includeField.paths=person.cover_photo&requestMask.includeContainer=PROFILE&requestMask.includeContainer=DOMAIN_PROFILE&requestMask.includeContainer=CONTACT&key=REDACTED'

第一眼看起来内容有很多,但是现在你不需要考虑每一行是什么意思。你只需要把不相关的行删掉就可以了。

我通常通过删掉某行查看是否有错误来验证该行是不是可以删除 —— 只要请求没有错误就一直删请求头。通常情况下,你可以删掉 Accept*RefererSec-*DNTUser-Agent 和缓存相关的头。

在这个例子中,我把请求删成下面的样子:

curl 'https://people-pa.clients6.google.com/v2/people/?key=REDACTED' \
-X POST \
-H 'Authorization: SAPISIDHASH REDACTED' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Origin: https://hangouts.google.com' \
-H 'Cookie: REDACTED'\
--data-raw 'personId=101777723309&personId=1175339043204&personId=1115266537043&personId=116731406166&extensionSet.extensionNames=HANGOUTS_ADDITIONAL_DATA&extensionSet.extensionNames=HANGOUTS_OFF_NETWORK_GAIA_GET&extensionSet.extensionNames=HANGOUTS_PHONE_DATA&includedProfileStates=ADMIN_BLOCKED&includedProfileStates=DELETED&includedProfileStates=PRIVATE_PROFILE&mergedPersonSourceOptions.includeAffinity=CHAT_AUTOCOMPLETE&coreIdParams.useRealtimeNotificationExpandedAcls=true&requestMask.includeField.paths=person.email&requestMask.includeField.paths=person.gender&requestMask.includeField.paths=person.in_app_reachability&requestMask.includeField.paths=person.metadata&requestMask.includeField.paths=person.name&requestMask.includeField.paths=person.phone&requestMask.includeField.paths=person.photo&requestMask.includeField.paths=person.read_only_profile_info&requestMask.includeField.paths=person.organization&requestMask.includeField.paths=person.location&requestMask.includeField.paths=person.cover_photo&requestMask.includeContainer=PROFILE&requestMask.includeContainer=DOMAIN_PROFILE&requestMask.includeContainer=CONTACT&key=REDACTED'

这样我只需要 4 个请求头:AuthorizationContent-TypeOriginCookie。这样容易管理得多。

第四步:在 Python 中发请求

现在我们知道了我们需要哪些请求头,我们可以把 curl 命令翻译进 Python 程序!这部分是相当机械化的过程,目标仅仅是用 Python 发送与 cUrl 相同的数据。

下面是代码实例。我们使用 Python 的 requests 包实现了与前面 curl 命令相同的功能。我把整个长请求分解成了元组的数组,以便看起来更简洁。

import requests
import urllib

data = [
    ('personId','101777723'), # I redacted these IDs a bit too
    ('personId','117533904'),
    ('personId','111526653'),
    ('personId','116731406'),
    ('extensionSet.extensionNames','HANGOUTS_ADDITIONAL_DATA'),
    ('extensionSet.extensionNames','HANGOUTS_OFF_NETWORK_GAIA_GET'),
    ('extensionSet.extensionNames','HANGOUTS_PHONE_DATA'),
    ('includedProfileStates','ADMIN_BLOCKED'),
    ('includedProfileStates','DELETED'),
    ('includedProfileStates','PRIVATE_PROFILE'),
    ('mergedPersonSourceOptions.includeAffinity','CHAT_AUTOCOMPLETE'),
    ('coreIdParams.useRealtimeNotificationExpandedAcls','true'),
    ('requestMask.includeField.paths','person.email'),
    ('requestMask.includeField.paths','person.gender'),
    ('requestMask.includeField.paths','person.in_app_reachability'),
    ('requestMask.includeField.paths','person.metadata'),
    ('requestMask.includeField.paths','person.name'),
    ('requestMask.includeField.paths','person.phone'),
    ('requestMask.includeField.paths','person.photo'),
    ('requestMask.includeField.paths','person.read_only_profile_info'),
    ('requestMask.includeField.paths','person.organization'),
    ('requestMask.includeField.paths','person.location'),
    ('requestMask.includeField.paths','person.cover_photo'),
    ('requestMask.includeContainer','PROFILE'),
    ('requestMask.includeContainer','DOMAIN_PROFILE'),
    ('requestMask.includeContainer','CONTACT'),
    ('key','REDACTED')
]
response = requests.post('https://people-pa.clients6.google.com/v2/people/?key=REDACTED',
    headers={
        'X-HTTP-Method-Override': 'GET',
        'Authorization': 'SAPISIDHASH REDACTED',
        'Content-Type': 'application/x-www-form-urlencoded',
        'Origin': 'https://hangouts.google.com',
        'Cookie': 'REDACTED',
    },
    data=urllib.parse.urlencode(data),
)

print(response.text)

我执行这个程序后正常运行 —— 输出了一堆 JSON 数据!太棒了!

你会注意到有些地方我用 REDACTED 代替了,因为如果我把原始数据列出来你就可以用我的账号来访问谷歌论坛了,这就很不好了。

运行结束!

现在我可以随意修改 Python 程序,比如传入不同的参数,或解析结果等。

我不打算用它来做其他有意思的事了,因为我压根对这个 API 没兴趣,我只是用它来阐述请求 API 的过程。

但是你确实可以对返回的一堆 JSON 做一些处理。

curlconverter 看起来很强大

有人评论说可以使用 https://curlconverter.com/ 自动把 curl 转换成 Python(和一些其他的语言!),这看起来很神奇 —— 我都是手动转的。我在这个例子里使用了它,看起来一切正常。

追踪 API 的处理过程并不容易

我不打算夸大追踪 API 处理过程的难度 —— API 的处理过程并不明显!我也不知道传给这个谷歌论坛 API 的一堆参数都是做什么的!

但是有一些参数看起来很直观,比如 requestMask.includeField.paths=person.email 可能表示“包含每个人的邮件地址”。因此我只关心我能看懂的参数,不关心看不懂的。

(理论上)适用于所有场景

可能有人质疑 —— 这个方法适用于所有场景吗?

答案是肯定的 —— 浏览器不是魔法!浏览器发送给你的服务器的所有信息都是 HTTP 请求。因此如果我复制了浏览器发送的所有的 HTTP 请求头,那么后端就会认为请求是从我的浏览器发出的,而不是用 Python 程序发出的。

当然,我们去掉了一些浏览器发送的请求头,因此理论上后端是可以识别出来请求是从浏览器还是 Python 程序发出的,但是它们通常不会检查。

这里有一些对读者的告诫 —— 一些谷歌服务的后端会通过令人难以理解(对我来说是)方式跟前端通信,因此即使理论上你可以模拟前端的请求,但实际上可能行不通。可能会遭受更多攻击的大型 API 会有更多的保护措施。

我们已经知道了如何调用没有文档说明的 API。现在我们再来聊聊可能遇到的问题。

问题 1:会话 cookie 过期

一个大问题是我用我的谷歌会话 cookie 作为身份认证,因此当我的浏览器会话过期后,这个脚本就不能用了。

这意味着这种方式不能长久使用(我宁愿调一个真正的 API),但是如果我只是要一次性快速抓取一小组数据,那么可以使用它。

问题 2:滥用

如果我正在请求一个小网站,那么我的 Python 脚本可能会把服务打垮,因为请求数超出了它们的处理能力。因此我请求时尽量谨慎,尽量不过快地发送大量请求。

这尤其重要,因为没有官方 API 的网站往往是些小网站且没有足够的资源。

很明显在这个例子中这不是问题 —— 我认为在写这篇文章的过程我一共向谷歌论坛的后端发送了 20 次请求,他们肯定可以处理。

如果你用自己的账号身份过度访问这个 API 并导致了故障,那么你的账号可能会被暂时封禁(情理之中)。

我只下载我自己的数据或公共的数据 —— 我的目的不是寻找网站的弱点。

请记住所有人都可以访问你没有文档说明的 API

我认为本文最重要的信息并不是如何使用其他人没有文档说明的 API。虽然很有趣,但是也有一些限制,而且我也不会经常这么做。

更重要的一点是,任何人都可以这么访问你后端的 API!每个人都有开发者工具和网络标签,查看你传到后端的参数、修改它们都很容易。

因此如果一个人通过修改某些参数来获取其他用户的信息,这不值得提倡。我认为提供公开 API 的大部分开发者们都知道,但是我之所以再提一次,是因为每个初学者都应该了解。: )


via: https://jvns.ca/blog/2022/03/10/how-to-use-undocumented-web-apis/

作者:Julia Evans 选题:lujun9972 译者:lxbwolf 校对:wxy

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

这是一个快速教程,展示了在 Ubuntu 和其他 Linux 发行版上从命令行改变语言的步骤。

事实上,我一直在写西班牙语的文章。如果你没有访问过它并且/或你是一个讲西班牙语的人,请访问 It's FOSS en Español 并查看所有西班牙语的 Linux 内容。

你可能想知道我为什么要和你分享这件事,这是因为这篇文章以这个新页面为例。

在新安装 你喜欢的 Linux 发行版 时,系统会要求你选择一种主语言。有些人,比如说我,后来会考虑把这个语言改成新的,尽管这并不频繁。

你看,我必须同时用西班牙语和英语进行截屏。这就成了一个问题,因为我只有一台电脑,而更换用户对我来说不是一个快速的解决方案。

这就是为什么我想和你分享这个快速技巧,我将告诉你如何在终端中用两行简单的文字改变你的主系统语言。

让我们开始吧!

从终端改变 Linux 系统语言

假设你想把你的主语言从英语改为西班牙语。

确认你将哪种语言设置为默认语言(主语言)。为此,让我们使用 locale 命令。

locale

你应该看到像这样的东西:

team@itsfoss:~$ locale
LANG=en_US.UTF-8
LANGUAGE=
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=

在这里你可以看到主语言是英语。现在要改变它,请按以下方式使用 dpkg 命令:

sudo dpkg-reconfigure locales

当你运行之前的命令,你应该在终端看到下面的页面:

sudo dpkg reconfigure locales

在这里,你应该使用向上和向下的箭头移动直到你到达所需的语言。在我的例子中,我想要西班牙语,更具体地说,是墨西哥西班牙语,因为我是墨西哥人。

不是所有的语言都有这个选项,但如果你的语言有,请选择 UTF-8

找到你的语言后,按空格键来标记,然后回车

Selecting your language

最后,在最后一个窗口中,通过使用箭头键移动到该语言并按下回车键,选择该新语言作为你的默认语言。

Setting new language as default

完成后,你应该在你的终端看到这样的信息:

Generating locales (this might take a while)...
    en_US.UTF-8... done
    es_MX.UTF-8... done
Generation complete.

这就完成了!现在你能够直接从终端改变你的默认语言,次数不限。

如果你对这个话题有任何疑问,请在评论区告诉我们。


via: https://itsfoss.com/change-locales-linux/

作者:Marco Carmona 选题:lujun9972 译者:geekpi 校对:wxy

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

Python 的 httpx 包是一个用于 HTTP 交互的一个优秀且灵活的模块。

 title=

Python 的 httpx 包是一个复杂的 Web 客户端。当你安装它后,你就可以用它来从网站上获取数据。像往常一样,安装它的最简单方法是使用 pip 工具:

$ python -m pip install httpx --user

要使用它,把它导入到 Python 脚本中,然后使用 .get 函数从一个 web 地址获取数据:

import httpx
result = httpx.get("https://httpbin.org/get?hello=world")
result.json()["args"]

下面是这个简单脚本的输出:

    {'hello': 'world'}

HTTP 响应

默认情况下,httpx 不会在非 200 状态下引发错误。

试试这个代码:

result = httpx.get("https://httpbin.org/status/404")
result

结果是:

    <Response [404 NOT FOUND]>

可以明确地返回一个响应。添加这个异常处理:

try:
    result.raise_for_status()
except Exception as exc:
    print("woops", exc)

下面是结果:

    woops Client error '404 NOT FOUND' for url 'https://httpbin.org/status/404'
    For more information check: https://httpstatuses.com/404

自定义客户端

除了最简单的脚本之外,使用一个自定义的客户端是有意义的。除了不错的性能改进,比如连接池,这也是一个配置客户端的好地方。

例如, 你可以设置一个自定义的基本 URL:

client = httpx.Client(base_url="https://httpbin.org")
result = client.get("/get?source=custom-client")
result.json()["args"]

输出示例:

    {'source': 'custom-client'}

这对用客户端与一个特定的服务器对话的典型场景很有用。例如,使用 base_urlauth,你可以为认证的客户端建立一个漂亮的抽象:

client = httpx.Client(
    base_url="https://httpbin.org",
    auth=("good_person", "secret_password"),
)
result = client.get("/basic-auth/good_person/secret_password")
result.json()

输出:

    {'authenticated': True, 'user': 'good_person'}

你可以用它来做一件更棒的事情,就是在顶层的 “主” 函数中构建客户端,然后把它传递给其他函数。这可以让其他函数使用客户端,并让它们与连接到本地 WSGI 应用的客户端进行单元测试。

def get_user_name(client):
    result = client.get("/basic-auth/good_person/secret_password")
    return result.json()["user"]

get_user_name(client)
    'good_person'

def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'application/json')])
    return [b'{"user": "pretty_good_person"}']
fake_client = httpx.Client(app=application, base_url="https://fake-server")
get_user_name(fake_client)

输出:

    'pretty_good_person'

尝试 httpx

请访问 python-httpx.org 了解更多信息、文档和教程。我发现它是一个与 HTTP 交互的优秀而灵活的模块。试一试,看看它能为你做什么。


via: https://opensource.com/article/22/3/python-httpx

作者:Moshe Zadka 选题:lujun9972 译者:geekpi 校对:wxy

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

以下是对 Nitrux 2.0 在性能稳定性方面的点评,以及我们对是否可以将其用作日常使用的看法。

Nitrux Linux 是基于 Debian 的,其特点是采用了修改版的 KDE Plasma 桌面,它被称为 NX 桌面。这个独特的 Linux 发行版带来了它自己的一套 Nitrux 应用程序,它们建立在 Maui 套件和 Qt 上。Nitrux 是没有 systemd 的,它使用 OpenRC 作为初始化系统。凭借所有这些独特的功能和令人惊叹的外观,它是当今最好的 Linux 发行版之一。

Nitrux 团队在 2022 年 2 月发布了它的主要版本 2.0,最近又发布了第一个小版本。因此,我们觉得现在是对这个漂亮的桌面进行评价的好时机。

Nitrux 2.0 应用程序视图

Nitrux 2.0 点评

安装

Nitrux 使用了一个修改版的 Calamares 安装程序。该操作系统的 ISO 包含 临场 live 桌面,在此你可以访问安装操作系统的快捷方式。启动选项包括更多的选项,包括 nomodset 内核启动选项。

在虚拟机测试中,安装很顺利,但在实际的硬件中却失败了,因为我的 NVIDIA 340 有点老。因此,如果你打算安装较新的硬件,应该没有问题。

第一印象和桌面

在外观方面,Nitrux 可以说是与当今所有外观优秀的发行版不相上下,比如深度、Cutefish OS。它们都为用户和 Nitrux 操作系统带来了开箱即用的定制功能。但 Nitrux 的优势在于 KDE Plasma、Plasmoid、Kvuntum 主题与基于 Maui 套件组件的奇妙组合。

当你第一眼看到它的时候,它看起来很好,而且有良好的组织性,底部预配置了 Latte Dock、友好而干净的顶部栏。

它基于 KDE Plasma,你可以轻松地改变外观和感觉,并通过设置在深色和浅色模式之间切换。默认字体 Fire Sans 使它成为一个整体设计完美的桌面。

这个版本采用了 KDE Plasma 5.24+,KDE 框架 5.91 和 xanmod 版的 Linux 内核 5.16。

到目前为止,我的第一印象没有任何槽点。

登录和 Shell

不久前,该团队 引入 了 Maui Shell,这是一个以 Cask 为特色的融合性桌面,即 Shell 层。这是这个体验式 Shell 的第一个版本,用户通过登录窗口就可以看到。

但唯一困扰我的是,Cask(仍然是实验性的)被定为默认登录会话。那些知道的人会把它改成 Plasma,但那些不知道的人会有些吃惊!

使用 Cask 的登录会话

应用程序

Nitrux 使用 AppImage 格式来发布应用程序。大多数预装的应用程序都是 AppImage。而且在通知方面,它们与整个桌面很好地结合在一起。Nitrux 也会检测你的下载文件夹中外部下载的 AppImage 进行安装。

默认情况下,它预装了以下本地 Maui 应用程序

  • Index 文件管理器
  • Station 终端
  • Pix 图像浏览器
  • Nota 文本编辑器
  • Nitro 分享
  • NX 软件中心

Firefox 和 LibreOffice 也预装了,以满足基本需求。你可以根据你的工作流程需要,通过 NX 软件中心安装其他应用程序。

关于 Firefox 和更新 Nitrux 的一点提醒。有一些报告说 Firefox 在进行基本系统更新后被删除。在你点击升级之前,请确保你通过终端用 apt get —upgradable 检查文件的变化。

性能和资源消耗

因为我无法把它安装在我的物理机上。因此,下面提到的性能指标是在 virt-manager 虚拟管理器下测量的。

在空闲状态下,它使用大约 1GB 的内存,CPU 在 9% 到 10%。KWin 窗口管理器和 Latte Dock 在底部消耗了大部分的资源。

Nitrux 2.0 系统在空闲状态下的性能

现在是时候通过一些繁重的工作负载来运行它了。这包括一个文本编辑器、LibreOffice、文件管理器、图像查看器和 Firefox 的五个标签,其中一个标签正在播放一个 YouTube 视频。

你可以在下面的图片中看到资源使用的峰值。在这种状态下,它使用了接近 2GB 的内存,CPU 为 26%。和往常一样,Firefox 浏览器消耗了大部分资源。

Nitrux 2.0 系统在繁重工作状态下的性能

我想说的是,从性能上来说,它的表现还算可以。因为开箱即用的定制版,Latte Dock 和 Kvuntum 主题确实占用了一些资源。而这个指标在空闲和重载状态下要高于基本的 KDE Plasma。

一些有问题的地方

不幸的是,在我的测试过程中,Nitrux 2.0 有几个小问题:

  • 在我的 i3+SSD+4gb+NVIDIA+Broadcom 的旧系统中尝试安装了一个小时后 - 我无法让 Calamares 安装程序开始安装。
  • 临场 live 会话中没有检测到 Wi-Fi。然而,到目前为止,我在这个设备上测试的所有发行版都能检测到它。
  • KWin 在临场会话开始时崩溃了。
  • 由于网络连接的原因,Calamares 安装程序的“下一步”按钮被禁用。这对我来说有点奇怪。
  • 而最小的安装 ISO 也给出了 plymouth failed to start #17 的错误。

然后我在 这里 找到了已知问题部分,其中提到了一些问题。我确信这与 xanmod 版的 Linux 内核 5.16 有关。主线内核本来是没有问题的。

在虚拟机环境中,实验性的 Maui Shell 是不能使用的。点击和触摸操作大多不工作。但考虑到这是一个测试版本,这是可以理解的。

我觉得 Calamares 安装程序的错误需要在下一个版本之前进行更多的测试。

下载 Nitrux 2.0 +

你可以从以下链接下载最新版本:

结束语

如果你喜欢 KDE Plasma,并且不想在定制上花费太多精力,你可以选择 Nitrux 2.0。另外,许多用户喜欢类似于 Debian 的稳定性,而不要 systemd。那么,对他们来说,这是一个完美的选择。

但因为有一些错误,我不会向超小白的新用户推荐这个发行版。如果你对 Linux 有一定的了解,并且知道如何用命令行解决一些小问题,那么它就很适合你。你可以使用 Nitrux 2.0 作为你的日常系统。只是要谨慎对待 Debian 的不稳定软件包,这些软件包在更新后偶尔会出现问题。

加油!


via: https://www.debugpoint.com/2022/03/nitrux-2-0-review/

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

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

编者按:本文系 Linux 中国公开投稿计划所接受的第一篇投稿,而且投稿作者是一位初中学生,让我们为他点赞!

一般来说,安卓设备和 Windows 设备投屏使用的是 miracast 协议,但是该协议要求网卡支持 p2pwifi,而 Linux 下大多数网卡驱动不支持 p2pwifi。

于是我用 Python + FFmpeg + DLNA 完成了一个在 Linux 下的投屏方案。这个方案的不足是延迟有点大。

设置

下面是如何实现。

先装这个 DLNA 库:

pip3 install dlna

然后用 pactl 查找 “监视器信源”(中文输出) 或 “Monitor Source”(英文输出):

pactl list sinks

示例输出:

Sink #0
    State: RUNNING
    Name: alsa_output.pci-0000_05_00.6.HiFi__hw_Generic_1__sink
    Description: Family 17h (Models 10h-1fh) HD Audio Controller Speaker + Headphones
    Driver: module-alsa-card.c
    Sample Specification: s16le 2ch 44100Hz
    Channel Map: front-left,front-right
    Owner Module: 9
    Mute: no
    Volume: front-left: 53814 /  82% / -5.14 dB,   front-right: 53814 /  82% / -5.14 dB
            balance 0.00
    Base Volume: 65536 / 100% / 0.00 dB
    Monitor Source: alsa_output.pci-0000_05_00.6.HiFi__hw_Generic_1__sink.monitor
    Latency: 16676 usec, configured 16000 us...

然后创建一个 CGI 脚本 screen.flv。首先。建立放置该脚本的目录:

mkdir screencast
mkdir screencast/cgi-bin

然后通过 cat 来直接创建该脚本:

cat <<eof>screencast/cgi-bin/screen.flv
#!/bin/bash
echo "Content-Type:video/x-flv"
echo

ffmpeg -f pulse -i <监视器信源>   -f x11grab -i :0  -vcodec h264_nvenc  pipe:.flv
eof

请用上面获得的监视器信源替换文件中的 <监视器信源>

并为它设置可执行权限:

chmod +x screencast/cgi-bin/screen.flv 

注意:如果没有 Nvidia 显卡,或者要使用其他的硬件加速,请把编码方案 h264_nvenc 替换为相应的编码方案。不建议采用软解方式,延迟非常高。

投屏

需要投屏时,首先启动本地 Web 服务器:

cd screencast
python3 -m http.server --cgi 9999&

然后,找到你的 DLNA 设备,然后把 location 后面的 URL 复制下来:

dlna device

示例输出:

=> Device 1:
{
    "location": "http://192.168.3.118:1528/",
    "host": "192.168.3.118",
    "friendly_name": "Kodi",
...

找到你的 Linux 电脑的局域网 IP 地址:

ip addr

示例输出:

3: wlp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 74:4c:a1:82:2e:3f brd ff:ff:ff:ff:ff:ff
    inet 192.168.3.117/24 brd 192.168.3.255 scope global dynamic noprefixroute wlp2s0
       valid_lft 58283sec preferred_lft 58283sec
    inet6 240e:3b3:2ee3:9530:d005:e492:6243:9/128 scope global dynamic noprefixroute 
       valid_lft 6738sec preferred_lft 3138sec
    inet6 240e:3b3:2ee3:9539:f289:6043:c56a:4e7b/64 scope global dynamic noprefixroute 
       valid_lft 7189sec preferred_lft 3589sec
    inet6 240e:3b3:2ee3:9539:3714:eaf0:c549:b8c9/64 scope global dynamic mngtmpaddr noprefixroute 
       valid_lft 7188sec preferred_lft 3588sec
    inet6 fe80::c746:2540:ab7b:20aa/64 scope link 
       valid_lft forever preferred_lft forever
    inet6 fe80::3543:2637:e0fc:3630/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

启动投屏的命令如下:

dlna play -d <URL> http://<局域网 IP>:9999/cgi-bin/screen.flv

请相应替换其中的 <URL><局域网 IP> 参数,此处我替换后的命令是:

dlna play -d http://192.168.3.118:1528/ http://192.168.3.117:9999/cgi-bin/screen.flv

然后在你的电视上设置接受投屏,各种电视设备设置投屏方式不同,请参照具体设备说明。

稍等片刻,视频就会出现在电视上了。投屏效果如下:


作者简介:

calvinlin:一个普通的深圳初中生。


via: https://www.bilibili.com/read/cv15488839

作者:calvinlin 编辑:wxy

本文由贡献者投稿至 Linux 中国公开投稿计划,采用 CC-BY-SA 协议 发布,Linux中国 荣誉推出

你知道什么是“ 停靠区 Dock ” 吧,它通常是你的应用程序“停靠”的底栏,以便快速访问。

许多发行版和桌面环境都提供了某种停靠实现。如果你的发行版没有“ 停靠区 Dock ”,或者你想尝试一些新的停靠应用,Latte Dock 是一个不错的选择。它类似于 macOS 上的停靠区,每次你用鼠标悬停在任何停靠对象上时,都会有一个的抛物线动画。

在本教程中,我将告诉你如何在 Ubuntu 上安装 Latte Dock。我还会展示一些关于使用和定制 Latte Dock 的事情。

在 Ubuntu 上安装 Latte Dock

Latte Dock 是一个流行的应用程序,可以从大多数 Linux 发行版的官方软件库中获得。也就是说你可以使用你的发行版的软件中心或软件包管理器来安装 Latte dock。

Latte 可以从软件中心获得

在 Ubuntu 和其他基于 Ubuntu 的发行版,如 elementary OS、Linux Mint、Pop!\_OS、Zorin OS 上,使用 apt 命令:

sudo apt install latte-dock

这就行了!现在你已经在 Ubuntu 上安装了 Latte Dock。

停用 Ubuntu 自带的停靠区(针对 Ubuntu 用户)

在你启动你闪亮的新停靠区之前,我建议你禁用 Ubuntu 默认提供的停靠区。这里有一个 关于如何禁用 Ubuntu 的停靠区的指南

要禁用停靠区,请在你的终端输入以下内容:

gnome-extensions disable [email protected]

如果你最终改变了主意,你可以用以下命令再次启用 Ubuntu 停靠区:

gnome-extensions enable [email protected]

注意:

这不能禁用 Pop!\_OS 20.04 LTS 上的默认停靠区(尽管它在桌面上默认是隐藏的;只在活动概览中可见)。在使用 COSMIC 桌面环境/扩展的 Pop!\_OS 上,你可以通过“ 设置 Settings ”应用中的“ 桌面 Desktop -> 停靠区 Dock ”来禁用或启用停靠区。

开始使用 Latte Dock

我在教程中使用的是 Pop!\_OS,但这些步骤适用于任何 Linux 发行版。

一旦安装完毕,你会在你的应用程序抽屉里发现一个 Latte Dock 的启动器图标。你可以在这里访问它,或者按 Super 键(通常是 Windows 键;如果你有 Mac 键盘,则按 Command 键)键 + A

从这里打开 Latte Dock:

应用抽屉里高亮显示的 Latte dock

酷!现在你的桌面上已经打开了 Latte Dock。

桌面上的 Latte Dock 屏幕截图

启用 Latte Dock 的自动启动功能

随着 Latte Dock 的打开,以及 Ubuntu 自带停靠区的禁用,如果你现在重启,那么下次你的电脑开机时就不会有任何停靠区了。

让我们现在就来解决这个问题。

在停靠区上点击右键。点击“ 布局 Layouts ”子菜单下的“ 配置 Configure ”选项。

通过进入“布局” -&gt; “配置” 启动设置面板窗口

现在,在“ 偏好 Preferences ”选项卡下,确保“ 在启动时启用自动启动 Enable autostart during startup ”复选框被选中。

启用启动时自动启动复选框

定制你的停靠区

如果你安装了任何 KDE 的产品,定制应该是永无止境的。如果 Latte Dock 不允许定制,那就奇怪了。幸运的是,情况并非如此。

你可以做各种各样的事情来定制 Latte Dock。增加它的大小,使它更透明或半透明,为它设计主题等等。

将应用程序固定在停靠区上

要把你的应用程序固定在 Latte Dock 上,打开该应用程序,右键点击在你停靠区中的应用程序图标。现在点击“ 固定启动器 Pin Launcher”。完成了!你的应用程序现在已经被固定到了停靠区上。

右击正在运行的应用程序并选择钉住启动器选项

你可以通过点击和拖动移动它到左边或右边来改变它在停靠区中的位置。

搜索和安装 Latte Dock 主题

通过右击停靠区打开 Latte Dock 的“ 设置 Settings ”窗口,点击“ 布局 Layout ”子菜单下的“ 配置 Configure ”选项。

你可能已经安装了一些主题(呃...布局)。从已安装的选项列表中选择它,然后点击右侧的切换按钮。

改变 Latte Dock 的主题

你也可以通过点击“ 下载 Download ”按钮来下载更多的主题。它应该向你显示一个可用的主题列表,以供安装。

Latte Dock 插件安装窗口

改变停靠区的外观和行为

正如我前面提到的,在 KDE 产品中有大量的定制选项。

让我们来试试。

右键点击停靠区,点击 “ 停靠区设置 Dock Settings ”。

通过右键点击停靠区进入 Latte Dock 设置

在这里,你会得到各种类型的可以切换的选项。想把停靠区移到显示器的左侧吗?你可以通过“ 位置 Location ”子菜单下提供的选项来实现。

Dock 设置和定制窗口

如果你觉得可用的选项有任何限制,请拨动右上角的“ 高级 Advanced ”开关。

现在可以看到带有高级选项的停靠区设置和定制窗口

现在看起来真是太棒了!

试着切换每个可用的开关。你可以延迟隐藏停靠区。你可以把它放在显示器的一个边缘,把它放在该边缘的中心、左边或右边。你可以做到这一切。

想修饰启动、悬停等效果?在“ 效果 Effects ”选项卡下有更多的调整选项等待着你。

从你的系统中删除 Latte Dock

你安装了 Latte Dock,并对其进行了定制,但觉得它不是你想要的东西。而你现在正在寻找删除 Latte Dock 的方法。很好,我帮你。

你可以使用 apt 软件包管理器删除 Latte Dock。用下面的命令来做:

sudo apt autoremove --purge latte-dock

--purge 标志将删除 Latte Dock 在系统目录中的任何配置文件,除了 ~/.config

仅供高级用户使用:删除用户特定的遗留文件

这不是强制性的,但如果你想删除通常放在 $HOME/.config(即 ~/.config)目录中的用户配置文件。使用 find 命令 来定位 Latte Dock 的配置文件:

find ~/.config -iname "latte*"

你可以安全地从你的 ~/.config 目录中删除这些目录和配置文件。

对于 Ubuntu 用户:重新启用 Ubuntu 停靠区

不要忘了启用 Ubuntu 的停靠区。如果你不记得了,再次启用停靠区的命令在下面:

gnome-extensions enable [email protected]

总结

Latte Dock 是一个来自 KDE 社区的令人惊艳的停靠区 ( ͡° ͜ʖ ͡°)

它提供了大量的主题(布局)、外观和自定义选项,以及一些漂亮的效果。如果你正在考虑定制你的桌面外观和感觉,它肯定是你应该寻找的东西。

如果你最终喜欢上了 Latte Dock 并开始每天使用它,请在评论中告诉我。如果你不喜欢 Latte Dock,也请发表评论让我知道原因。


via: https://itsfoss.com/install-use-latte-dock-ubuntu/

作者:Pratham Patel 选题:lujun9972 译者:wxy 校对:wxy

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