在alpine镜像内由CGO引起的命令未找到问题

事情是这样的,我用了别人的一个Go语言写的程序,魔改了一下,在ubuntu上编译,丢到alpine里跑。
本来应该是一切顺利,可以我把容器运行起来后直接退出了,查看log发现报错”命令未找到“。情况如下:

1
2
3
4
5
6
7
8
9
10
11
/app # ls -l
total 17856
-rw-r--r-- 1 root root 871 Jun 11 17:30 config.json
-rwxr-xr-x 1 root root 73 Jun 11 17:19 deploy.sh
-rwxr-xr-x 1 root root 18276352 Jun 11 18:19 v
/app # file v
v: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, stripped
/app # ./v
sh: ./v: not found
/app # /app/v
sh: /app/v: not found

这不是见了鬼了吗?这个程序明明在这里啊,怎么没找到呢?最开始被这迷惑的报错信息给影响了,都没往编译问题上去想。我以为是文件损坏了,计算一下校验和发现并不是。然后我以“golang alpine not found” 为关键词搜索,发现有人说是sh脚本文件中crlf换行符的问题。
照着别人说的把deploy.sh中crlf改成unix的lf,问题依旧,于是我翻到搜索结果的第二页,有人说是alpine库文件的问题,又照着别人说的运行命令:

1
2
/app # mkdir /lib64
/app # ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2

终于,错误信息变了,变成了:

1
2
3
/app # ./v
Error relocating ./v: __vfprintf_chk: symbol not found
Error relocating ./v: __fprintf_chk: symbol not found

这下我就确定了,是编译环境和运行环境库不一致的问题。然后仔细对比了我和原作者构建脚本的差异,果然粗心大意少配置了个环境变量:

1
2
env:
CGO_ENABLE: 0

至此,问题解决,花了两个多小时。回顾一下,这么简单的问题本应该是分分钟解决的,花了这么久不应该,但这也并不全是我的粗心,主要还是被报错信息误导了。

记录一下,方便同样“粗心”的朋友^_^。

V语言学习笔记

在github trending上看到的项目,粗略看了下语法,真是集各家之长啊。正如一条评论所说:

“If Go and Rust had a baby it would be this language. Grandpa C should be proud.”
// TODO

更改Gitlab主邮箱

由于域名快到期了,gitlab的主邮箱是这域名的邮箱,就想着更改一下吧,结果找了半天设置也没找到设置主邮箱的地方,搜一下才发现遇到这个问题的人还不少,而且也有人提过issue,最早的一次是在五年前https://forum.gitlab.com/t/profile-settings-emails/312,一年前又有人提,但是issue直接被关闭了,不过在这条issue下面我找到了方法。

https://gitlab.com/-/profile if you edit ‘Email’ it changes primary.
It’s just ridiculously non-obviously labeled and a free-form input field rather than e.g. selecting the email from the ones you added already.

给出解决方法的这位老哥跟我的感受一样啊,so ridiculous。

虽然是小问题,但还是要记录一下,方便后面其他同样遇到的这个问题的朋友。

使用cloudflare-workers作为CDN

1.添加记录

在DNS记录中添加一条IPv6记录指向100::。(WHY?)

typenamecontent
AAAAcdn100::

2.创建worker

创建一个worker代码如下:

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
28
29
30
31
32
addEventListener("fetch", event => {
event.respondWith(handleRequest(event))
})

const BUCKET_NAME = "akame-moe"
const BUCKET_URL = `https://storage.googleapis.com/${BUCKET_NAME}`

async function serveAsset(event) {
const url = new URL(event.request.url)
const cache = caches.default
let response = await cache.match(event.request)

if (!response) {
response = await fetch(`${BUCKET_URL}${url.pathname}`)
const headers = { "cache-control": "public, max-age=14400" }
response = new Response(response.body, { ...response, headers })
event.waitUntil(cache.put(event.request, response.clone()))
}
return response
}

async function handleRequest(event) {
if (event.request.method === "GET") {
let response = await serveAsset(event)
if (response.status > 399) {
response = new Response(response.statusText, { status: response.status })
}
return response
} else {
return new Response("Method not allowed", { status: 405 })
}
}

Read More

implementing an authenticated link using nginx-module-njs

sometimes, we need an authenticated link to provent our resources form abusing.
now we will accomplish that by using nginx-module-njs. here we go.

install nginx and nginx-module-njs module

1
2
3
4
5
wget http://nginx.org/keys/nginx_signing.key -O nginx_signing.key
sudo apt-key add nginx_signing.key
echo "deb http://nginx.org/packages/mainline/ubuntu/ xenial nginx" | sudo tee -a /etc/apt/sources.list
sudo apt-get update
sudo apt-get install nginx nginx-module-njs

Read More