0%

see build_ffmpeg on linux for how to build ffmpeg easily

1
2
3
4
5
export LD_LIBRARY_PATH=~/code//ffmpeg/install/lib:.
cd ~/code//ffmpeg/install/bin

# run
./ffplay -i /e/RES/Videos/h2645/sample-An.mp4 -threads 1 -filter_threads 1

threads

  • ffplay: main thread, sleeping
  • SDLTimer: some Timer stuffs
  • PulseHotPlug: pulse audio thread
  • read_thread: demuxer thread
  • video_decoder: decoder thread

video decode process

read_thread:

1
2
ret = av_read_frame(ic, pkt);
packet_queue_put(&is->videoq, pkt);

video_decoder:

1
2
3
4
5
6
7
8
9
10
11
// keep try get_video_frame
// change order of showup of avcodec_send_packet & avcodec_receive_frame for better comprehension
get_video_frame(){
decoder_decode_frame(){
if (packet_queue_get(d->queue, d->pkt, 1, &d->pkt_serial) < 0)
return -1;
avcodec_send_packet(d->avctx, d->pkt);
avcodec_receive_frame(d->avctx, frame);
}
queue_picture(is, frame, pts, duration, fd ? fd->pkt_pos : -1, is->viddec.pkt_serial);
}

buffer control

read_thread: control the buffer size of stream data

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#define MAX_QUEUE_SIZE (15 * 1024 * 1024)
// size is counted in bytes
/* if the queue are full, no need to read more */
if (infinite_buffer<1 &&
(is->audioq.size + is->videoq.size + is->subtitleq.size > MAX_QUEUE_SIZE
|| (stream_has_enough_packets(is->audio_st, is->audio_stream, &is->audioq) &&
stream_has_enough_packets(is->video_st, is->video_stream, &is->videoq) &&
stream_has_enough_packets(is->subtitle_st, is->subtitle_stream, &is->subtitleq)))) {
/* wait 10 ms */
SDL_LockMutex(wait_mutex);
SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10);
SDL_UnlockMutex(wait_mutex);
continue;
}

video_decoder: keep pulling data queued from read_thread, and stop when queued pictures size exceeds

note the value of VIDEO_PICTURE_QUEUE_SIZE

1
2
3
4
5
6
7
8
9
#define VIDEO_PICTURE_QUEUE_SIZE 3
#define SUBPICTURE_QUEUE_SIZE 16
#define SAMPLE_QUEUE_SIZE 9
video_thread::queue_picture(){
frame_queue_peek_writable(){
while (f->size >= f->max_size && !f->pktq->abort_request)
SDL_CondWait(f->cond, f->mutex);
}
}

seek

the key is the concept serial, of both PacketQueue::serial, MyAVPacketList::serial in PacketQueue list, and Decoder::pkt_serial.

ffplay use serial to syn its state.

like when seek happens, the PacketQueue change it serial, then the demuxed packets, finally the Decoder object.

for the seek:

  1. :arrow_left: Left-Arrow Keydown
  2. ffpaly: in SDL event_loop: set {seek_req, seek_flag}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
event_loop(){
case SDLK_LEFT:
incr = seek_interval ? -seek_interval : -10.0;
goto do_seek;
...
do_seek:
stream_seek(cur_stream, pos, incr, 1);
}

/* seek in the stream */
static void stream_seek(VideoState *is, int64_t pos, int64_t rel, int by_bytes)
{
// here this seek_req means a unfinished seek request
if (!is->seek_req) {
is->seek_pos = pos;
is->seek_rel = rel;
is->seek_flags &= ~AVSEEK_FLAG_BYTE;
if (by_bytes)
is->seek_flags |= AVSEEK_FLAG_BYTE;
is->seek_req = 1;
SDL_CondSignal(is->continue_read_thread);
}
}
  1. read_thread: seek demuxer and flush packet_buffer

​ note serial is incre by 1 in packet_queue_flush

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
static int read_thread(void *arg){
for(;;){
if (is->seek_req) {
ret = avformat_seek_file(is->ic, -1, seek_min, seek_target, seek_max, is->seek_flags);
packet_queue_flush(&is->videoq);
}
}
}

static void packet_queue_flush(PacketQueue *q)
{
MyAVPacketList pkt1;

SDL_LockMutex(q->mutex);
while (av_fifo_read(q->pkt_list, &pkt1, 1) >= 0)
av_packet_free(&pkt1.pkt);
q->nb_packets = 0;
q->size = 0;
q->duration = 0;
q->serial++; // propagate to packet serial in packet_queue_put_private
SDL_UnlockMutex(q->mutex);
}

static int packet_queue_put_private(PacketQueue *q, AVPacket *pkt)
{
...
pkt1.serial = q->serial;
...
}
  1. video_decoder: avcodec_flush_buffers when serials unmatch
1
2
3
4
5
6
7
8
9
10
11
12
13
static int decoder_decode_frame(Decoder *d, AVFrame *frame, AVSubtitle *sub) {
do{
int old_serial = d->pkt_serial;
if (packet_queue_get(d->queue, d->pkt, 1, &d->pkt_serial) < 0)
return -1;
if (old_serial != d->pkt_serial) {
avcodec_flush_buffers(d->avctx);
d->finished = 0;
d->next_pts = d->start_pts;
d->next_pts_tb = d->start_pts_tb;
}
} while (1);
}

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#!/bin/bash

# Initialize the timestamp variable with the current date and time
tsf=$(mktemp)
echo $(date -u -d "2024-04-09 23:44:24" +%s) >$tsf
echo "tsf=$tsf"

# Function to prepend text to a file
prepend() {
local tempFile
tempFile=$(mktemp)
echo "$2" > "$tempFile"
cat "$1" >> "$tempFile"
mv "$tempFile" "$1"
}

# Function to generate the content to be prepended
generate_content() {
filename=$(basename "$1" .md)

# Increment the timestamp by one second
ts=$(($(cat $tsf) - 1))

# Convert the timestamp to the date format
date=$(date -u -d "@$ts" +"%Y-%m-%d %T")
echo $ts >$tsf
echo "---
title: $filename
categories:
- [jackfrued-Python-temp]
date: $date
draft: false
tags:
---
"
}

CWD="$(pwd)"

cd source/_posts/Python-100-Days
git reset --hard
rm -r res
rm -r "公开课"
rm -r "番外篇"
rm *.md
# Main script
for file in $(find . -name "*.md"|grep Day |sort); do
content=$(generate_content "$file")
prepend "$file" "$content"
done

标准相关节

  • Table 9-34 – Syntax elements and associated types of binarization, maxBinIdxCtx, and ctxIdxOffset
  • Table 9-39 - the assignment of ctxIdx increments (ctxIdxInc) to binIdx for all ctxIdxOffset
  • Table 9-36 – Binarization for macroblock types in I slices
  • 9.3.3.1.1.3 Derivation process of ctxIdxInc for the syntax element mb_type

主流程

  • Table 9-34 查询相关上下文范围= [ctxIdxOffset = 3,10]
  • Table 9-39 查询知各binIdx对应的ctxIdxOffsetInc的计算方法
  • Table 9-36 查询知mb_type 的二值化表,这是顺序解析bins的指引

各个bin的 ctxIdx = ctxIdxOffset +ctxIdxInc

bin_0

由 Table 9-39 进入 Spec 9.3.3.1.1.3

前置知识: 邻宏块ABCD位置

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
9.3.3.1.1.3 Derivation process of ctxIdxInc for the syntax element mb_type

Input to this process is ctxIdxOffset.

Output of this process is ctxIdxInc.

The derivation process for neighbouring macroblocks specified in clause 6.4.11.1 is invoked and the output is assigned to mbAddrA and mbAddrB.

Let the variable condTermFlagN (with N being either A or B) be derived as follows:

–If any of the following conditions are true, condTermFlagN is set equal to 0:

–mbAddrN is not available,

–ctxIdxOffset is equal to 0 and mb_type for the macroblock mbAddrN is equal to SI,

–ctxIdxOffset is equal to 3 and mb_type for the macroblock mbAddrN is equal to I_NxN,

–ctxIdxOffset is equal to 27 and mb_type for the macroblock mbAddrN is equal to B_Skip or B_Direct_16x16.

–Otherwise, condTermFlagN is set equal to 1.

The variable ctxIdxInc is derived as

Image

计算得到 ctxIdxInc0

bin_1

Table 9-36 标识的所谓 ctxIdx=276 意味着这一个bin使用 二进制DecodeTerminate解码,见 Spec 9.3.3.2 Arithmetic decoding process

bin_{n>1}

对于binIdx = [2, 5 or 6],解码第三、四个比特分别使用上下文 ctxIdxOffset + 3、 ctxIdxOffset + 4

第4bit和第5bit上下文依赖于第3bit,见 Spec 9.3.3.1.2(依赖输入ctxIdxOffset + binIdx)

这里的结果比较有趣,结合 Table 9-36的表可以得到结果,无视第5个bit的上下文偏移增量的计算,只需要在bin_3为1时,插入对 ctxIdxInc=5 的bin解析就行,于是产生 [ctxIdxInc0, 276, 3, 4, 5, 6, 7], 或者 [ctxIdxInc0, 276, 3, 4, 6, 7]的上下文索引增量序列

code

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
33
int decode_mb_type_cabac(Macroblock_t* curMB)
{
Slice_t* slice = curMB->slice;

const int ctxIdxOffset = 3;
int ctxInc0 = ctxIdxOffset;
if (slice->mbTypeA & (MT_INTRA16x16 | MT_INTRA_PCM))
ctxInc0++;
if (slice->mbTypeB & (MT_INTRA16x16 | MT_INTRA_PCM))
ctxInc0++;

if (0 == slice->cabac.decoder.DecodeDecision(slice->cabac.bac_contexts + ctxInc0))
return 0; // I_NxN

if (slice->cabac.decoder.DecodeTermination())
return 25; // I_PCM

int ret = 1;
if (slice->cabac.decoder.DecodeDecision(slice->cabac.bac_contexts + ctxIdxOffset + 3))
ret += 12;
if (slice->cabac.decoder.DecodeDecision(slice->cabac.bac_contexts + ctxIdxOffset + 4))
{
ret += 4;
if (slice->cabac.decoder.DecodeDecision(slice->cabac.bac_contexts + ctxIdxOffset + 5))
ret += 4;
}
if (slice->cabac.decoder.DecodeDecision(slice->cabac.bac_contexts + ctxIdxOffset + 6))
ret += 2;
if (slice->cabac.decoder.DecodeDecision(slice->cabac.bac_contexts + ctxIdxOffset + 7))
ret += 1;

return ret;
}

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#!/bin/bash
CWD=$(pwd)
INSTALL_PATH=$CWD/install

check_repo(){
woring_dir=$1
dir=$2
required_branch=$3
repo_url=$4
cd $woring_dir

if [[ ! -d $dir ]];then
git clone $repo_url $dir
fi

if [[ "$required_branch" != "" ]]; then
echo "
on $dir"
cd $dir
git checkout $required_branch
git reset --hard
fi
cd $CWD
}

check_www(){
woring_dir=$1
dir=$2
www_file=$3
www_url=$4
shift 4
if_custom_commands=$@
cd $woring_dir

if [[ ! -f $www_file ]];then
wget $www_url $www_file
fi

if [[ ! -d $dir ]]; then
if [[ "$if_custom_commands" == "" ]]; then
tar -xvf $www_file
else
$@
fi
fi
cd $CWD
}

active_target=
set_target(){
active_target=$1
echo "
activating $active_target"
}
check(){
$@ >$CWD/build/logs/$active_target.log 2>$CWD/build/logs/$active_target.error.log
retval=$?
if [[ "$retval" != "0" ]];then
echo "target $active_target: failed retval=$retval $@"
exit $retval
fi
}

##################################################
# 准备目录 #
mkdir -p $CWD/build/logs 2>/dev/null
rm $CWD/build/logs/* 2>/dev/null
mkdir -p 3rd 2>/dev/null


###################################################
# 第三方库 #

# check_repo 3rd/x264 master https://code.videolan.org/videolan/x264.git
check_repo 3rd libvpx main https://chromium.googlesource.com/webm/libvpx
check_www 3rd lame-3.100 lame-3.100.tar.gz https://zenlayer.dl.sourceforge.net/project/lame/lame/3.100/lame-3.100.tar.gz

set_target libvpx
cd 3rd/libvpx
check ./configure --prefix=$INSTALL_PATH --enable-vp8 --enable-vp9 --enable-pic --disable-examples --disable-docs --enable-vp9-highbitdepth
check make install -j
cd $CWD


set_target lame-3.100
cd 3rd/lame-3.100
check ./configure --prefix=$INSTALL_PATH --enable-shared=no
check make install -j
cd $CWD

##################################################
# ffmpeg #
check_repo . ffmpeg n6.1 https://github.com/FFmpeg/FFmpeg.git

set_target ffmpeg
export PKG_CONFIG_PATH=$CWD/install/lib/pkgconfig
cd ffmpeg
check ./configure \
--prefix=$INSTALL_PATH \
--extra-cflags=-I$CWD/install/include \
--extra-ldflags=-L$CWD/install/lib \
--enable-libvpx \
--enable-libmp3lame
check make install -j
cd $CWD

docker installation

1
2
3
4
5
6
7
8
9
10
11
12
13
for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done

# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

user config

1
usermod -aG docker lull

pull alpine

even if docker hub shows no alpine 3.15

1
docker pull alpine:3.15

create container

  • -i: keep STDIN, 否则 docker start 直接退出,docker exec 也无效,非交互模式应该是在启动脚本里加入long live server
  • -t: 创建伪终端,更好的cli交互体验
  • –name alpine: 指定名字
  • –publish-all: 公开端口
  • -v /e:/e 共享挂载目录
  • 1
    docker run -it --name alpine --publish-all -v /e:/e alpine:3.15

run

start container if not yet

1
docker ps  |grep alpine || docker start alpine

run interactive ali

1
docker exec -it  alpine sh

Appendix

running ssh service in these containers is a bit annoying

although you could just run

1
2
apk add openssh
`which sshd`

外部流量入口

此处port=10001 可以切换成其他端口

然后所有这类流量先通过 dokodemo-door 通通传入38001

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"inbounds": [
{
"listen": "0.0.0.0",
"port": 10001,
"protocol": "dokodemo-door",
"settings": {
"address": "127.0.0.1",
"port": 38001,
"network": "tcp",
"followRedirect": false
}
}
]
}

分流

此处fallbacks描述分流规则

  • 默认回落流量到31296,一般无法解析的流量会分发给nginx,以隐藏xray的响应特征
  • 满足TLS ALPN协商的走到31302
  • 尝试匹配首包 HTTP PATH(installpathws or installpathws2),成功走到31297 | 31299
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
{
"inbounds": [
{
"port": 38001,
"fallbacks": [
{
"dest": 31296,
"xver": 1
},
{
"alpn": "h2",
"dest": 31302,
"xver": 0
},
{
"path": "/installpathws",
"dest": 31297,
"xver": 1
},
{
"path": "/installpathws2",
"dest": 31299,
"xver": 1
}
]
}
...
]
}

响应端口

示例为vless
streamSettings.wsSettings.path 对应 分流回落的fallbacks.path
inbounds.listen 对应输入端口

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
33
34
{
"inbounds": [
{
"port": 31297,
"listen": "127.0.0.1",
"protocol": "vless",
"tag": "VLESSWS",
"settings": {
"clients": [
{
"id": "uuid-idxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"email": "username_xxxx-VLESS_WS"
}
],
"decryption": "none"
},
"streamSettings": {
"network": "ws",
"security": "none",
"wsSettings": {
"acceptProxyProtocol": true,
"path": "/installpathws"
}
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls"
]
}
}
]
}

reference

最近重装了服务器,记录以下重装的操作

创建用户lull

1
2
3
4
sudo su
adduser lull
# 添加到sudo组以使用sudo命令,就不要手动更改sudoers了
usermod -aG sudo lull

配置SSH登录选项

1
2
3
4
5
6
7
8
9
mkdir ~/.ssh
# 查看本地公钥 cat ~/.ssh/id_rsa.pub
echo "xxxxx
" >> ~/.ssh/authorized_keys

# 禁止密码登录
# vim /etc/sshd_config
# change properties:
# PasswordAuthentication no

xrrraay

1
2
3
4
5
6
7
8
9
10
11
12
13
# 安装nginx
apt install nginx
# 安装xray
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
# xray默认用户nobody污染权限
chmod 777 /var/log/xray -r

## 更改xray服务配置 /etc/systemd/system/xray.service.d/10-donot_touch_single_conf.conf
## 添加xray出入口配置文件
## 更改nginx 配置文件

systemctl enable nginx.service
systemctl enable xray.service

node (非系统版本)

nvm 是node版本管理工具

1
2
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
nvm install --lts

文档服务器:编译

1
2
3
4
5
6
7
8
9
10
11
sudo mkdir /code
sudo chmod 777 /code

git clone git@github.com:September007/doc-site-hexo.git
cd doc-site-hexo
git submodule update --init --recursive

npm install -g hexo
npm i
hexo g;hexo g; hexo g;

文档服务器:部署

certbot生成证书

1
2
3
4
5
6
7
sudo apt instal certbot
sudo certbot certonly --standalone -d www.cheerlisten.com
# Successfully received certificate.
# Certificate is saved at: /etc/letsencrypt/live/www.cheerlisten.com/fullchain.pem
# Key is saved at: /etc/letsencrypt/live/www.cheerlisten.com/privkey.pem
# This certificate expires on 2024-03-02.
# These files will be updated when the certificate renews.

服务器配置 /etc/nginx/conf.d/all/doc-server.conf
nginx 服务器配置
sudo ln -s /etc/nginx/conf.d/all/doc-server.conf /etc/nginx/conf.d/

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
server {
listen 443 ssl;
server_name www.cheerlisten.com;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_certificate /etc/letsencrypt/live/www.cheerlisten.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/www.cheerlisten.com/privkey.pem; # managed by Certbot

location / {
root /code/doc-site-hexo/public/;
index index.html tags/index.xml index.xml;
}
location /doc/ {
alias /code/doc-site-hexo/public/;
index tags/index.html tags/index.xml index.html index.xml;
}

#error_page 404 /404.html;

# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

杂项

更改设备名

1
sudo echo "LiteServer-ALiYun" > /etc/hostname

fix certbot dep urllib error: pip install -U 'requests-toolbelt>=1'

最近重装了服务器,记录以下重装的操作

创建用户lull

1
2
3
4
sudo su
adduser lull
# 添加到sudo组以使用sudo命令,就不要手动更改sudoers了
usermod -aG sudo lull

配置SSH登录选项

1
2
3
4
5
6
7
8
9
mkdir ~/.ssh
# 查看本地公钥 cat ~/.ssh/id_rsa.pub
echo "xxxxx
" >> ~/.ssh/authorized_keys

# 禁止密码登录
# vim /etc/sshd_config
# change properties:
# PasswordAuthentication no

xrrraay

1
2
3
4
5
6
7
8
9
10
11
12
13
# 安装nginx
apt install nginx
# 安装xray
bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install
# xray默认用户nobody污染权限
chmod 777 /var/log/xray -r

## 更改xray服务配置 /etc/systemd/system/xray.service.d/10-donot_touch_single_conf.conf
## 添加xray出入口配置文件
## 更改nginx 配置文件

systemctl enable nginx.service
systemctl enable xray.service

node (非系统版本)

nvm 是node版本管理工具

1
2
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
nvm install --lts

文档服务器:编译

1
2
3
4
5
6
7
8
9
10
11
sudo mkdir /code
sudo chmod 777 /code

git clone git@github.com:September007/doc-site-hexo.git
cd doc-site-hexo
git submodule update --init --recursive

npm install -g hexo
npm i
hexo g;hexo g; hexo g;

文档服务器:部署

certbot生成证书

1
2
3
4
5
6
7
sudo apt instal certbot
sudo certbot certonly --standalone -d www.cheerlisten.com
# Successfully received certificate.
# Certificate is saved at: /etc/letsencrypt/live/www.cheerlisten.com/fullchain.pem
# Key is saved at: /etc/letsencrypt/live/www.cheerlisten.com/privkey.pem
# This certificate expires on 2024-03-02.
# These files will be updated when the certificate renews.

服务器配置 /etc/nginx/conf.d/all/doc-server.conf
nginx 服务器配置
sudo ln -s /etc/nginx/conf.d/all/doc-server.conf /etc/nginx/conf.d/

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
server {
listen 443 ssl;
server_name www.cheerlisten.com;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_certificate /etc/letsencrypt/live/www.cheerlisten.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/www.cheerlisten.com/privkey.pem; # managed by Certbot

location / {
root /code/doc-site-hexo/public/;
index index.html tags/index.xml index.xml;
}
location /doc/ {
alias /code/doc-site-hexo/public/;
index tags/index.html tags/index.xml index.html index.xml;
}

#error_page 404 /404.html;

# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

杂项

更改设备名

1
sudo echo "LiteServer-ALiYun" > /etc/hostname

fix certbot dep urllib error: pip install -U 'requests-toolbelt>=1'

1
2
3
4
5
6
7
8
9
10
11
# 更新当前包
sudo apt update; sudo apt upgrade -y
sudo apt dist-upgrade
sudo apt autoremove

sudo apt install update-manager-core

# reboot

sudo do-release-upgrade --check-dist-upgrade-only -d
sudo do-release-upgrade -d

磁盘占用工具 ncdu

左右键进出目录

1
2
3
4
5
6
7
8
9
sudo apt install ncdu
sudo su
cd /
ncdu
# 15.2 GiB [##########] /var
# 6.7 GiB [#### ] /home
# 5.0 GiB [### ] /usr
# 4.0 GiB [## ] /root
# 1.7 GiB [# ] /lib

处理

1
2
3
4
# 1. 额外用户xxx
sudo deluser xxx; sudo rm -r /home/xxx
# 2. 清除root账户vscode缓存
sudo rm /root/.vscode-server -r; sudo rm /root/.vscode-server-insiders -r

/var

1
2
3
4
5
6
7
8
9
10
11
12
13
--- /var ----------------------------
8.9 GiB [##########] /log
5.5 GiB [###### ] /lib
723.0 MiB [ ] /cache
3.3 MiB [ ] /backups
32.0 KiB [ ] /tmp
32.0 KiB [ ] /spool
28.0 KiB [ ] /snap
e 4.0 KiB [ ] /opt
e 4.0 KiB [ ] /mail
e 4.0 KiB [ ] /local
@ 0.0 B [ ] lock
@ 0.0 B [ ] run

/var/log

编辑 /etc/logrotate.conf: rotate 属性默认2
编辑 /etc/logrotate.d/rsyslog: 添加 属性 size 100k
编辑 /etc/systemd/journald.conf限制journal 大小: SystemMaxUse=100M
删除docker服务: sudo service docker stop;sudo apt remove docker; sudo apt autoremove; rm /var/log

至此,37.8G–>22.3G, 懒得动手了