日常并不写 c++ 项目,看到 Acl 这个库比较有意思,就试着编译了一下 samples

照猫画虎,记录一下遇到的相关问题

Acl

https://github.com/acl-dev/acl

Acl – One Advanced C/C++ Library for Unix/Windows

Acl build

BUILD.md 但感觉写的比较简单,还是看了 Makefile

最后用make all_lib && make packinstall生成 include 和 lib

Sample build

Sample 代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <thread>
#include "acl_cpp/lib_acl.hpp"

void run(void) {
const char* addr = "127.0.0.1:8088";
acl::server_socket server;
if (!server.open(addr)) { // Bind and listen the local address.
return;
}

while (true) {
acl::socket_stream* conn = server.accept(); // Wait for connection.
if (conn == NULL) {
break;
}
std::thread thread([=] { // Start one thread to handle the connection.
char buf[256];
int ret = conn->read(buf, sizeof(buf), false); // Read data.
if (ret > 0) {
conn->write(buf, ret); // Write the received data.
}
delete conn;
});
thread.detach();
}
}

环境为 macOS,g++ 为 clang,vim 编辑会提示一些问题

  • #include “acl_cpp/lib_acl.hpp” 这行报文件找不到
  • std::thread thread([=] { 这行报expected_expression: expected expression

第一个是因为 clang 不知道你的 include 路径

第二个是[=] {} lambda 表达式是C++11标准,也需要告诉一下 clang

这两个问题都可以用compile_flags.txt解决

方法是在本文件同目录下生成compile_flags.txt文件,内容为

1
2
-std=c++11
-I../include/acl-lib

就跟传给 gcc / g++ 的参数一样,但更推荐的是compile_commands.json的方式,并且是在编译时自动生成

于是我们写CMakeLists.txt

CMake

引入 CMake 调整目录结构如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.
├── CMakeLists.txt
├── apps
│   └── main.cpp
├── build
├── include
│   └── acl-lib
│   ├── acl
│   ├── acl_cpp
│   ├── fiber
│   └── protocol
├── lib
│   └── libacl_all.a
└── src
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
cmake_minimum_required(VERSION 3.5)
project(MyProject VERSION 1.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 11)

add_executable(test apps/main.cpp)

target_link_libraries(test PUBLIC acl_all)
target_link_directories(test
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/lib>
$<INSTALL_INTERFACE:lib>
)

target_include_directories(test
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/acl-lib>
$<INSTALL_INTERFACE:include/acl-lib>
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
)

在 CMakeLists 中指定 C++ 标准 11

指定 include 的头文件地址,include 为第三方库目录,src 为私有代码库目录

指定 libacl_all.a 文件所在路径

最后在 build 目录下

1
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 ..

会生成compile_commands.json

1
2
3
4
5
6
7
[
{
"directory": "/Users/hbspy/test/acl/build",
"command": "/Library/Developer/CommandLineTools/usr/bin/c++ -I/Users/hbspy/test/acl/include/acl-lib -I/Users/hbspy/test/acl/src -arch arm64 -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX12.3.sdk -std=gnu++11 -o CMakeFiles/test.dir/apps/main.cpp.o -c /Users/hbspy/test/acl/apps/main.cpp",
"file": "/Users/hbspy/test/acl/apps/main.cpp"
}
]

这里还会报一个错,ld: entry point (_main) undefined.

原因 clang 没找到入口的 main 函数,把 samples 中的 void run 改成 int main 并修改一下 return 细节就可以了

此时的 vim 中,已经可以正确的根据生成的 compile_commands.json 找到 include 的头文件地址

以及认识[=] {}这样的 C++11 标准了

可喜可贺

遇到了 macOS 上的ESC键失效,在 vim 中只能使用Ctrl + C退出插入模式

原因竟然是因为 Siri

死去的 Siri 突然开始攻击我,焯!

Quit Siri

It appears that this escape key issue is caused by Siri. More specifically, this issue may occur when Siri freezes. To address this, force-quit Siri and ESC will start working again. Here is how:

  • On your Mac, open Activity Monitor (Applications > Utilities).
  • Find Siri.
  • Click the Stop (X) button and select Force Quit.

REF: https://macreports.com/esc-escape-key-not-working-on-mac-fix/

使用自建 GitLab,通过 CI build Docker 的过程

弯弯绕很多,值得记录

附一份官方中文文档 极狐 https://docs.gitlab.cn/jh/ci/

安装 GitLab Runner

在项目的 Setting -> CI/CD -> Runners 中查看 Runner 情况

其中 Specific runners 为该项目专用 Runners,以外还支持 Shared runners 共享的 Runners

Show Runner installation instructions 可查看安装指引

gitlab-runner 可直接装在 linux 环境下,或跑在 Docker 环境中

这里我们按照 Environment: Linux, Architecture: amd64 的指引

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Download the binary for your system
sudo curl -L --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-linux-amd64

# Give it permissions to execute
sudo chmod +x /usr/local/bin/gitlab-runner

# Create a GitLab CI user
sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash

# Register runner
sudo gitlab-runner register

# Install and run as service
sudo gitlab-runner install --user=gitlab-runner --working-directory=/home/gitlab-runner
sudo gitlab-runner start

注册过程中的 url, token 皆可在 Specific runners 中查看,其它需要关注的有

  1. 输入 Runner 的 tag,给该 runner 打标签,当你想用这个 Runner 时,在.gitlab-ci.yml的 tags 字段中指明
  2. 选择 Runner 的 Executor,常用的 Executor 有 shell, ssh, docker
    • shell 即以宿主机作为 Runner 所有 jobs 的执行器,Runner 将会从远程仓库 pull 你的工程,工程的目录为:<working-directory>/builds/<short-token>/<concurrent-id>/<namespace>/<project-name>
    • ssh 即远程到另一台主机执行,这也就是为什么有 Shared runners 共享 Runners 概念
    • docker 指定一个默认镜像,或根据.gitlab-ci.yml中的指定,拉起一个 container 去作业,好处是环境隔离、干净,需要注意的是,如果作业是要 docker build,则需要 Docker-in-Docker,详情参考 https://docs.gitlab.cn/jh/ci/docker/using_docker_build.html

还需要关注的有

由于 gitlab-runner 是以非 root 权限跑的,需要添加对 docker 的权限并验证

1
2
3
4
usermod -aG docker gitlab-runner

# Test
sudo -u gitlab-runner -H docker info

GitLab 启用 Container Registry

参考 https://docs.gitlab.cn/jh/administration/packages/container_registry.html

根据搭建 GitLab 的方式,修改gitlab.yml或者gitlab.rb,以gitlab.rb为例,添加如下

1
2
registry['enable'] = true
registry_external_url 'https://registry.gitlab.example.com'

docker 登录

使用docker login <url>登录到 GitLab Container Registry

如果该 URL 未启用 HTTPS,则需要在/etc/docker/daemon.json中指定

1
2
3
{
"insecure-registries" : ["URL"]
}

登录到需要用户名密码认证的 Registry,若未使用 Credentials store,docker 会在$HOME/.docker/config.json中存储 auth 信息,并附上安全提示

如果是通过gitlab-ci.yml进行的操作,参考 https://docs.gitlab.cn/jh/user/packages/container_registry/

可以使用$CI_REGISTRY_USER, $CI_REGISTRY_PASSWORD, $CI_JOB_TOKEN等方式登录,密码是一次性的,并无安全风险

也可以使用 credentials helpers

但要注意 gpg 生成 key 时,不能有 phrase

因为 pass 在提取密码时,如果是有 phrase 的 key,需要输入 phrase,但 docker push/pull 等操作直接跳过了这一步并 exit 2

1
read(9, "exit status 2: gpg: public key d"..., 512) = 127

导致直接 denied: access forbidden

除非预先手动使用pass,并输入 phrase,让 session 记录,但这显然不适合 GitLab CI 场景

Docker 提供四种 credentials helpers

linux 上可使用 pass

  1. 安装 pass

自行安装 pass

1
dnf install pass
  1. 下载 credential-helper

使用 docker-credential-pass-xxx,下载,解压,并 mv 到合适的 bin 目录

  1. 配置

编辑$HOME/.docker/config.json

1
2
3
{
"credsStore": "pass"
}

初始化 pass 需要用到 gpg-id,需要先生成

  1. gpg2

安装 pinentry,并生成 key

1
2
3
dnf install pinentry

gpg2 --gen-key

但这里有一个坑点,参考 https://unix.stackexchange.com/questions/477445/www-data-user-cannot-generate-gpg-key

When using pinentry, you must have the proper permissions of the terminal device (e.g. /dev/tty1) in use. However, with su (or sudo), the ownership stays with the original user, not the new one. This means that pinentry will fail with a Permission denied error, even as root.

也就是说,sudo/su 后的用户可能用不了,会提示 Permission denied,甚至你 sudo 之后是 root

比如这里我们要在 gitlab-runner 的账户下 gpg2 --gen-key,就不能以 root 登录然后su gitlab-runner

要么直接以 gitlab-runner 登录,要么使用文章中给出的一个方法

1
2
3
4
5
6
7
mkdir /path/to/gpg-alt
GNUPGHOME=/path/to/gpg-alt gpg2 --gen-key

mv /path/to/gpg-alt /home/gitlab-runner/.gnupg
chown -R gitlab-runner:gitlab-runner /home/gitlab-runner/.gnupg
find /home/gitlab-runner/.gnupg -type d -exec chmod 700 {} \;
find /home/gitlab-runner/.gnupg -type f -exec chmod 600 {} \;
  1. 配置 pass
1
pass init <gpg-id>

不容易,后面的事就是写.gitlab-ci.yml了,给份最基本的参考

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
stages:
- build
- deploy

before_script:
- echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" "$CI_REGISTRY" --password-stdin

build_docker:
stage: build
script:
- docker build -t $CI_REGISTRY_IMAGE .
- docker tag $CI_REGISTRY_IMAGE:latest $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME
- docker push $CI_REGISTRY_IMAGE:latest
only:
- tags
tags:
- builder

deploy_docker:
stage: deploy
script:
- echo SUCCESS
only:
- tags
tags:
- builder

之前有关于 SSH Aruba AC 提示 port 22:2: Too many authentication failures

添加了选项 IdentitiesOnly=yes 就好了的文章

今天再继续记录一下原因

sshd 会有一个MaxAuthTries的限制,作用是在多次认证失败后直接断开TCP连接

但是这里会有一个问题,key 交换也是算次数的

可以通过ssh-add -l查看目前 load 了多少 key

key 会依次与对端 sshd 进行尝试

所以如果对端 sshd 的 MaxAuthTries 设置的很小,则会产生还没试到正确的 key,就报 Too many authentication failures 了

IdentitiesOnly=yes的作用,即是只使用IdentityFile设置的 key,不用默认已 load 的 key 进行尝试,减少 AuthTries

Aruba AC 应该就是默认的 MaxAuthTries 估计只有 1 或 2,只启用了 password 认证,你一尝试用 key 就失败

Useful Tools 备忘录

好用的日志浏览器,实用且 Colorful

dnf 可直接 install

1
lnav.x86_64 : Curses-based tool for viewing and analyzing log files

Features

  • Single Log View
  • Automatic Log Format Detection
  • Filters
  • Timeline View
  • Pretty-Print View
  • Query Logs Using SQL
  • “Live” Operation
  • Themes
  • Syntax Highlighting
  • Tab-completion
  • Custom Keymaps
  • Sessions
  • Headless Mode

https://lnav.org/

如何让 SNMP 正确返回超过 16TB 的文件系统

需要 Net-SNMP >= 5.5

snmpd.conf中加入以下配置,realStorageUnits 0

详见 https://linux.die.net/man/5/snmpd.conf

realStorageUnits
controlls how the agent reports hrStorageAllocationUnits, hrStorageSize and hrStorageUsed in hrStorageTable. With this option set to ‘0’, the agent re-calculates these values for big storage drives with small allocation units so hrStorageAllocationUnits x hrStorageSize gives real size of the storage.
Example:
Linux xfs 16TB filesystem with 4096 bytes large blocks will be reported as hrStorageAllocationUnits = 8192 and hrStorageSize = 2147483647, so 8192 x 2147483647 gives real size of the filesystem (=16 TB).

Setting this directive to ‘1’ (=default) turns off this calculation and the agent reports real hrStorageAllocationUnits, but it might report wrong hrStorageSize for big drives because the value won’t fit into Integer32. In this case, hrStorageAllocationUnits x hrStorageSize won’t give real size of the storage.

总就来说就是,默认情况下 SNMP 的 hrStorageAllocationUnits 是真实的 Block size,常见为 4096 bytes

1
2
3
4
5
6
[root@pan ~]# stat -f .
File: "."
ID: 4bbdbd4b4b7c6438 Namelen: 255 Type: ext2/ext3
Block size: 4096 Fundamental block size: 4096
Blocks: Total: 12868767 Free: 11452648 Available: 10797288
Inodes: Total: 3276800 Free: 3211062

于是 hrStorageSize 就会超过 Integer32 的最大值

目前本体使用的是

  • Adobe Acrobat Pro DC 2100120135
    • Acrobat_DC_Web_WWMUI.exe
    • AcrobatDCUpd2100120135.msp

Crack 使用的是

Adobe-GenP-2.7.zip

对 2021 及以前友好,2022 本体大概正常,但 PDFMaker 可能不行

如遇到 Acrobat PDFMaker 试用版已过期 问题

可尝试编辑注册表

HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Adobe\Adobe Acrobat\DC\Activation

添加 DWORD

  • “IsAMTEnforced” = dword:00000001
  • “IsNGLEnforced” = dword:00000000

  1. 代码高亮工具
1
brew install highlight
  1. highlight
1
2
3
4
5
6
# -s 主题
# -u 指定编码,否则中文会乱码,贴不到 keynote 里去
# -t tab 转换成几个空格,防止 keynote 中 \t 展示宽度不一致问题
# -O rtf 可被 keynote 识别

highlight -s molokai -u utf-8 -t 4 -O rtf <filename> | pbcopy
  1. 在 keynote 中粘贴

grep 带星号的文件名 返回了意外的结果

grep filename[asterisk] returns unexpected result [1]

1
2
3
4
5
$ ls
file1.txt file2.txt 'file*.txt'

$ ls | grep file*.txt
无输出

在执行grep命令之前,*先被 shell expanded 了,所以实际执行的命令是ls | grep file1.txt file2.txt 'file*.txt'

就变成了在 file2.txt 和 ‘file*.txt’ 中查找 ‘file1.txt’ 这个文本,而因为已经有文件输入,ls 的管道被忽略了

验证

1
2
3
echo 'no file1.txt' > file2.txt
$ ls | grep file*.txt
file2.txt:no file1.txt

所以,如果想只查找 ‘file*.txt’,则可以加引号

1
2
$ ls | grep '*.txt'
file*.txt

如果想使用其正则功能,则需要加上 -E

1
2
3
4
$ ls | grep -E '*.txt'
file1.txt
file2.txt
file*.txt

  1. https://stackoverflow.com/questions/20473441/grep-filenameasterisk-returns-unexpected-result ↩︎

测试连接失败

DNS 污染导致域名解析有问题,写 Hosts 可破

1
2
3
4
5
6
vim /etc/hosts

// 我只加了这两条,可以依据自身网络状况继续添加

54.230.62.121 api.themoviedb.org
13.266.238.82 api.themoviedb.org

搜索不到涩涩内容

尽管已经在账户设置中开启搜索结果中包含成人内容,但那只影响页面搜索

Video Staion 使用的 API 中并未实现

所以我们修改源码

1
2
3
4
5
6
7
8
9
vim /var/packages/VideoStation/target/plugins/syno_themoviedb/util_themoviedb.py

# _get_movie_search_data 中添加 include_adult=true 影响电影的搜索

url = constant.THEMOVIEDB_URL + 'search/movie?include_adult=true&api_key=' + api_key + '&query=' + nameEncode + '& language=' + \

# _get_tv_search_data 中添加 include_adult=true 影响剧集的搜索

url = constant.THEMOVIEDB_URL + "search/tv?include_adult=true&api_key=" + api_key + '&query=' + \

好耶!涩涩!

https://api.themoviedb.org/3/search/tv?api_key=xxx&query=Shoujo%20Sect&include_adult=true

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
"page": 1,
"results": [
{
"backdrop_path": "/9EWPzs6KSgZwOvWD8plkcWQjeh0.jpg",
"first_air_date": "2008-07-25",
"genre_ids": [
16
],
"id": 45473,
"name": "Shoujo Sect: Innocent Lovers",
"origin_country": [
"JP"
],
"original_language": "ja",
"original_name": "少女セクト ~Innocent Lovers~",
"overview": "Handa Shinobu and Naitou Momoko have known each other since childhood. Shinobu fell in love with Momoko from the day they first met. Now in high school, Momoko has forgotten about the past, but Shinobu has not. Both follow their own paths but Shinbobu still hopes for Momoko to remember the promise they made long ago.",
"popularity": 4.103,
"poster_path": "/jGpFhasLjo75ZjNrg1OAGs31UEP.jpg",
"vote_average": 7,
"vote_count": 1
}
],
"total_pages": 1,
"total_results": 1
}
0%