Go 语言学习笔记 7:容器

Go 语言中常见的容器。

数组

var name [size]T

举例:

var classMates [3]string

# or

classMates2 := [...]string{"A", "B", "C"}

切片

切片是对数组的一个连续片段的引用,容量可变的序列。动态数组。

内部结构包括底层数组指针、大小和容量。

  • array 指向底层存储数组的指针
  • len 切片长度
  • cap 切片容量,总是大于等于 len

从原数组中生成一个切片:

slice := source[begin:end]

举例:

source := [...]int{1,2,3}
sli := source[0:1]

动态创建切片,可以通过 make 函数动态创建切片

make([]T, size, cap)
  • T 是切片中的元素类型
  • size 长度
  • cap 预先分配的长度,容量

直接声明新的切片,不需要指定大小:

var name []T

比如:

ex := []int{1,2,3}

对切片的操作

append

append 函数可以向切片添加元素,返回新的切片。

copy

复制切片内容

copy(destSli, srcSli []T)

列表和字典

列表,链表

Go 通过双向链表实现,插入、删除非常高效。

var names list.List
name := list.New()

字典

映射关系,内部通过散列表方式实现。

name := make(map[KeyType]valueType)
package main

import "fmt"

func main() {
    classMate := map[string]string{
        "1": "EV",
        "2": "EV2",
    }
    fmt.Println(classMate)

    classMate1 := make(map[int]string)
    classMate1[0] = "EV"
    classMate1[1] = "EV1"
    fmt.Println(classMate1)

    mate, ok := classMate1[0]
    fmt.Println(mate, ok)
}

容器遍历

通过 for-range 语法

// 数组
nums := [...]int{1, 2, 3, 4, 5, 4, 3, 2, 1}
for k, v := range nums {
    fmt.Println(k, v)
}

// 切片
slis := []int{1, 2, 3, 4, 5, 4, 3, 2, 1}  
for k, v := range slis {  
   println(k, v)  
}

// map
// traverse map
for k, v := range classMate1 {
    fmt.Println(k, v)
}

2022-05-05 golang , google , programming , programming-language

每天学习一个命令:growpart 扩容分区

前端时间给 Proxmox VE 下的虚拟机扩容的时候留意到了这个 growpart 命令,专门用来给分区进行扩容的命令。

growpart - extend a partition in a partition table to fill available space

growpart 工具完成 Linux 系统盘分区扩容及文件系统扩展

Installation

Ubuntu 下可以直接安装:

sudo apt install cloud-guest-utils

使用

注意,对磁盘进行操作是高风险操作,如果对命令不熟悉,请先做好数据的备份,然后再进行操作,或实验。

我以我自己的实际情况为例,我有一个 Proxmox VE 的虚拟机因为磁盘内容告警,所以扩容了一倍,从 64G 扩容到 128GB。

在 Proxmox VE 中停止虚拟机之后扩容,然后启动虚拟机进入系统操作。

首先使用 fdisk -l 来查看磁盘分区信息,可以看到目前系统的分区还是没有改变,但是可以看到磁盘已经有剩余空间了。

因为我这里比较简单,我只想把剩余的空间分配给我当前的系统分区,所以可以直接使用 growpart,如果你还需要复杂操作,比如再划分一个分区之类的,可以考虑 [[parted]] 等命令。

还可以使用 lsblk 再确认一下。

因为我的系统分区是 /dev/sda 磁盘的第二个分区,所以运行 growpart 命令扩容分区

growpart /dev/sda 2

然后再执行以下命令,扩容 ext 文件系统

resize2fs /dev/sda2

再查看磁盘:

df -h
lsblk
fdisk -l

总结

growpart 命令可以非常方便的将分区扩展到全部的磁盘空间,不过需要注意的是,我的例子中 /dev/sda2 分区是磁盘的最后一个分区,如果你要扩容的分区在分区中间,可能需要考虑其他方案。

相关

  • [[gparted]]
  • [[2018-04-03-parted-linux-partition]]
  • [[2016-04-02-fdisk]]
  • [[lsblk]]

2022-05-03 linux , drive , growpart , partition , cli

aiohttp 使用笔记

最近想找一个 [[Wallabag]] 的 Python 客户端,在 GitHub 简单搜寻了一下之后发现了 wallbag_api 这个仓库,看了一下 Python 代码之后发现库中的代码是用 aiohttp 编写的,所以就来学习一下这个 Python 的异步 HTTP 库 aiohttp。

aiohttp 官方简洁明了,Asynchronous HTTP Client/Server for asyncio and Python. aiohttp 是一个基于 asyncio 模块的异步 HTTP 客户端/服务端框架。

可以 看到 aiohttp 不仅是一个 HTTP 客户端,也可以作为服务端。同时支持服务端的 WebSockets 和客户端 WebSockets。

我们知道 Python 下还有一个比较著名的 HTTP Client 库叫做 requests,这是一个同步的 HTTP 调用客户端,使用 requests 发起 HTTP 调用之后需要同步等待返回结果,而在 aiohttp 可以在发起请求之后将将程序的控制权暂时给别人,等待响应返回结果回来了之后再进行处理,这就可以提升系统的性能。

aiohttp 内部使用了 [[python-asyncio]] 来实现,而 Python 下 asyncio 的核心就是 [[Coroutine 协程]]

Coroutine 协程

Coroutine(协程)是一个更通用的 subroutine(子程序)。

async 方法中使用 await 关键字来表示 coroutine。当使用 await 关键字的时候,coroutine 会将当前程序的控制释放给 Event loop。

import asyncio
async def async_func():
    print('start ...')
    await asyncio.sleep(1)
    print('... end!')

async def main():
    async_func()#this will do nothing because coroutine object is created but not awaited
    await async_func()

asyncio.run(main())

如果直接调用 async_func() 不会有任何作用,需要在前面添加 await

协程适合 IO 密集型任务:

  • 网络请求,比如爬虫 [[aiohttp]]
  • 文件读写,[[aiofile]]
  • Web 框架,[[aiohttp]], [[fastapi]]
  • 数据库查询,[[asyncpg]], [[databases]], [[aiomysql]]

Installation

安装使用:

pip install aiohttp

作为客户端

aiohttp 作为客户端。

这里可以和 requests 做一个简单的对比,在 requests 中发起同步请求:

import requests 
def hello()    
     return requests.get("http://httpbin.org/get")     

print(hello())

程序在 requests.get 方法调用时会同步等待请求返回。

而如果使用 aiohttp:

#!/usr/local/bin/python3.6
import asyncio 
from aiohttp import ClientSession 

async def hello():     
    async with ClientSession() as session:         
        async with session.get("http://httpbin.org/headers") as response:                
            response = await response.read()                         
            print(response) 
  
loop = asyncio.get_event_loop() 
loop.run_until_complete(hello())

在这个异步代码中我们可以看到很多的异步关键字,async 以及 await 关键字定义函数为异步。

这里使用 ClientSession() 获取一个 Session,session 可以在多个请求之间保留 cookie 和相关信息。因为 session 关闭是一个异步操作,所以需要使用 async with

session.get 发起调用,也是一个异步操作,所以也需要使用 async,而 with 语句保证 response 可以正确关闭。

最后为了让这个异步方法可以执行,需要将其放入一个事件循环。

作为服务端

[[用 aiohttp 写服务器]] 不是本文的重点,所以简单了解一下,先略过。

from aiohttp import web

routes = web.RouteTableDef()

@routes.get('/')
async def hello(request):
    return web.Response(text="Hello, world")

app = web.Application()
app.add_routes(routes)
web.run_app(app)

控制并发

使用 Semaphore 控制

Semaphore 是一个线程计数器,核心是 acquire()release() 方法。

执行 acquire() 方法时,先判断内部值是否小于 0,如果大于 0,获得锁,内部值减一,如果小于 0,阻塞,直到 release() 方法释放锁,内部值加一。

async def fetch(url, semaphore):
    async with semaphore:
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as response:
                data = await response.text()
                print('data', data + " " + time.ctime())
                return data

async def run():
    url = 'http://127.0.0.1:5000'
    semaphore = asyncio.Semaphore(2)  # 限制并发量为2
    to_get = [fetch(url, semaphore) for _ in range(10)]
    await asyncio.wait(to_get)

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(run())
    loop.close()

使用 TCPConnector 控制

async def fetch(session, url):
    async with session.get(url) as resp:
        if resp.status != 200:
            resp.raise_for_status()
        data = await resp.text()
        print('data', data + " " + time.ctime())
        return data

async def fetch_multi(session, urls):
    tasks = []
    for url in urls:
        task = asyncio.create_task(fetch(session, url))
        tasks.append(task)
    # gather: 搜集所有future对象,并等待返回
    results = await asyncio.gather(*tasks)
    return results

async def main():
    urls = ["http://127.0.0.1:5000/" for _ in range(10)]
    conn = aiohttp.TCPConnector(limit=3)
    async with aiohttp.ClientSession(connector=conn) as session:
        datas = await fetch_multi(session, urls)
        print(datas)

if __name__ == '__main__':
    asyncio.run(main())


2022-05-03 http , aiohttp , python , aio , async

使用 lux 下载哔哩哔哩视频

Lux 是一个使用 Go 语言编写的视频下载命令行工具,支持的平台很多,提供了包括 macOS、Windows、Linux 等等平台的命令行支持,安装和使用非常简单的。Lux 原来的名字是叫做 Annie(安妮),对标的是 macOS 上一款非常著名的视频下载软件叫做 Downie(唐尼)。但后来改名成了 Lux。

Lux 支持非常多的视频网站:抖音、哔哩哔哩、半次元、pixivision、优酷、YouTube、爱奇艺、芒果 TV、Tumblr、Vimeo、Facebook、斗鱼视频、秒拍、新浪微博、Instagram、Twitter、腾讯视频、网易云音乐、音悦台

项目地址:https://github.com/iawia002/lux

Installation

macOS 下:

brew install ffmpeg
brew install lux

或者从 Release 页面下载,手动安装。

curl "https://github.com/iawia002/lux/releases/download/v0.15.0/lux_0.15.0_macOS_64-bit.tar.gz"

Ubuntu 下安装

sudo apt install ffmpeg
wget "https://github.com/iawia002/lux/releases/download/v0.15.0/lux_0.15.0_Linux_64-bit.tar.gz"
tar zxvf lux_0.14.0_Linux_64-bit.tar.gz
sudo mv lux /usr/local/bin
lux --help

使用

直接下载

Lux 的使用很简单,在终端:

lux "https://www.youtube.com/watch?v=QJXPS0gQ6Eg"
lux "https://www.bilibili.com/video/BV1ZJ411h713"

视频链接给的是播放列表里的第二个视频。如果用 youtube-dl 下载会自作主张地下载播放列表的第一个视频。在对付 B 站播放列表方面,Annie 比较乖一点。

Annie 不仅可以下载视频,如果给的是图片的网址,它就下载图片。

给播放列表的链接就下载播放列表:

下载不同分辨率

首先使用 -i 参数查看可供下载的视频分辨率,-i 参数可以一次添加多个视频链接,空格分隔。

❯ lux -i "https://www.bilibili.com/video/BV1ZJ411h713"

 Site:      哔哩哔哩 bilibili.com
 Title:     【中字】金世正 talk演唱会 全场 非常治愈的谈话
 Type:      video
 Streams:   # All available quality
     [64-7]  -------------------
     Quality:         高清 720P avc1.640028
     Size:            122.36 MiB (128300684 Bytes)
     # download with: lux -f 64-7 ...

     [32-12]  -------------------
     Quality:         清晰 480P hev1.1.6.L120.90
     Size:            108.75 MiB (114028043 Bytes)
     # download with: lux -f 32-12 ...

     [64-12]  -------------------
     Quality:         高清 720P hev1.1.6.L120.90
     Size:            108.57 MiB (113847391 Bytes)
     # download with: lux -f 64-12 ...

     [16-7]  -------------------
     Quality:         流畅 360P avc1.64001E
     Size:            86.10 MiB (90287066 Bytes)
     # download with: lux -f 16-7 ...

     [32-7]  -------------------
     Quality:         清晰 480P avc1.64001F
     Size:            67.43 MiB (70708693 Bytes)
     # download with: lux -f 32-7 ...

     [16-12]  -------------------
     Quality:         流畅 360P hev1.1.6.L120.90
     Size:            67.40 MiB (70670783 Bytes)
     # download with: lux -f 16-12 ...

然后使用 -f 来指定要下载的分辨率:

lux -f 64-7 https://www.bilibili.com/video/BV1ZJ411h713

下载列表

使用 -p 来下载视频列表。

如果要指定列表中的位置,可以使用如下几个选项:

  • -start 从视频列表的第几个开始下
  • -end 下载到几个
  • -items 指定要下载哪几个,比如 1,5,6,8-10
  • -eto B 站独有的参数,用于没有标题只有文件名的播放列表

举例:

lux -p -start 1 -end 15 "https://www.bilibili.com/video/BV1no4y1C7oo"

从文件中读取下载链接

可以使用 -F 参数,从包含视频 URL 的文本文件中下载视频:

lux -F /path/to/links.txt

这里也可以用参数 -start-end-items

按住 ctrl+c 可以中断下载,可以续传。

B 站上可以用 av 和 ep 加数字下载视频,比如:

annie -i ep198381 av21877586

还有三个参数也很有用:

指定保存路径

可以使用 -o 参数后面接路径,来指定将视频保存到该路径下:

lux -o ~/Videos/ URL

使用 -O NAME 来指定输出的名字。

输出 JSON

可以使用 -j 输出 JSON 格式结果。

  • 最出名的 [[youtube-dl]] 还有升级版的 [[yt-dlp]]
  • 适配比较多国内的 [[视频下载工具 you-get]]
  • Go 语言写的视频下载命令行工具 [[lux]]
  • C# 编写的 B 站下载 BBDown

2022-05-01 lux , bilibili , annie , video

图片压缩工具 Squoosh 离线版

Squoosh 是 Google 推出的一个图片压缩工具。之前整理macOS 初始化设置 的时候就说过,基本上算是必不可少的一个压缩工具了。

如果要大批量压缩图片,之前也介绍过 jpegoptim 和 optipng

如果要实现更加高阶的图片操作,比如 resize, blur, crop, despeckle, dither, drow on, flip, join, re-sample 等等,也可以了解一下 [[ImageMagick]]。

但使用 Squoosh 的过程中有一点不方便的就是 Google 只提供了在线版,之前也在 issue 中提过,官方回复是本来这个工具就是命令行的一个在线化,没有必要再搞一个离线的版本。

但最近发现 GitHub 上有人做出了一个离线版本的 Squoosh。

离线版本的 Squoosh 基于 Electron,并使用了 GoogleChromeLabs 之前开源的在线版。


2022-04-28 macos , linux , application , squoosh , google , electron , google-chrome , image , image-compress

大法官说了算 美国司法观察笔记 读书笔记

这是 [[20220417-21 天计划]] 的第二本书,看过 [[何帆]] 翻译的很多本作品,这一本《大法官说了算:美国司法观察笔记》是何帆多年的司法观察记录。作者以[[苏特大法官]] 的辞职开始说起,先后介绍了大法官是如何产生的,最高法院内部是怎么运行的,网络时代的法庭,法院对言论自由的态度,对死刑的态度,等等角度对大法官展开了详细的描述,最后一章对现在美国的最高法院的每一位大法官做了单独的介绍。

个人感觉这是一本非常适合想要了解大法官,以及最高法院的读者,在书中可以对整个最高法院的历史,以及大法官为何一言九鼎有一个非常直观的认识。

如果读完钦佩于大法官的人格魅力,那么可以继续看[[九人-美国最高法院风云]],如果读完更关心最高法院是如何界定言论自由的,那么继续阅读 [[言论的边界 美国宪法第一修正案简史]] ,如果读完更醉心于案件的错综复杂以及大法官们抽丝剥茧梳理给出判决,那么可以再读[[美国宪政历程 影响美国的 25 个司法大案]]

当然如果不想读这些大部头作品,那么也有牛津通识读本中的 [[美国最高法院通识读本]],[[批评官员的尺度]] 等等作品可以继续。

司法天平的倾斜

或许看过美剧、韩剧律政剧的人,对那个蒙着眼睛、一手持剑,一手天平的正义女神不再陌生,我也曾在这些剧集中一次次被法官「正义」的判决所感染。然而稍微了解一下美国的司法史就可以看到在不同的历史时期司法的天平都不是绝对的公平。

美国的历史上存在《惩治煽动性言论法》,曾一度赋予了总统以无上的言论审查权;最高法院也会允许雇主不受任何限制的和劳工签订超长工作时间的合同,大法官们认为雇主有权利和劳工签订不受时间限制的合同;更甚至[[坦尼大法官]]在 1857 年的 [[斯科特案]] 判决中判定黑人不是美国公民,直接导致了南北战争。[[202011041258-最高法院历史上的污点]] 不是一两句话就可以说清楚的,但是正是因为司法只是三权分立中的一个分支,更甚至是一个在最初没有一点地位的分支,司法天平的倾斜甚至倾倒,可以用行政的立法的权力予以纠正。

林肯当上总统之后,用宪法第十四修正案推翻了最高法院关于黑人不是美国公民的判决,将倾斜的天平拨了回来。

而司法的存在也正是为了约束行政权力的过大,以及立法分支的肆意立法。大法官们手握[[司法审查权]],可以对立法分支涉嫌违宪的法律进行审查。正是这三个分支的相互制约才使得美国在过去 200 多年的历史中,一直在修修补补中度日,除了南北战争这一次严重的战争之外一直可以不断地进化。

这两天在 Twitter 刚好看到一则推文,提出一个问题,如果这三个分支都不再很好的执行自己的职责,司法分支不再对超越宪法的立法进行审查,而行政权力以更强硬的手段行政,那么该怎么办?最终给出的答案是美国的持枪自由。但是我们都知道非要走到那一步必然会导致更严重的问题,这也不是这一本书所讨论的问题了。

保守和自由派的对决

在最高法院的描述中,一直少不了「自由派」和「保守派」两派大法官的描述。但是,我们要知道,在这里「保守」绝不是一个贬义词,保守派大法官只是始终对宪法保持警惕之心,深怕任意解释宪法会破坏法治框架。而自由派大法官,并非不尊重宪法,只是他们认为一部「活的宪法」才能与时俱进,适应不断变幻的现实,体现制宪先贤的本意。他们会秉持「至善论」(Perfectionism)的观点,不断创制一些新权利,进而将该权利解释为宪法的应有之义。

保守的含义其实颇为多元,可能是对无孔不入的「大政府」的畏惧,可能是对上帝的虔诚信仰,可能是对种族、文化、性的审慎态度,很难以进步或落后加以评判。

美国是一个缺乏改革传统的国家,就像上面提到的那样,越是重大的变革,越是以润物细无声的渐进方式完成。最高法院当然能够推动社会变革,但是「大法官说了算」并不意味着判决是推动变革的主要途径。[[布朗案]]之后依然有百万的黑人儿童无法获得读书的机会。最高法院的判决并非只是权力的宣示,更是一种理想的表达,当权力和理念合二为一时,才能慢慢影响人们的观念,直至形成一种更为先进的文化。这些观念被大多数人接受的时候,就会演变成制度和法律。

无论最高法院如何判决,绝大多数人都会接受判决结果。这种信任建立在过去上百位大法官孜孜努力的基础之上。


2022-04-27 reading , reading-2022 , judge , supreme-court , 司法

每天学习一个命令:umask 命令简单介绍

在使用 LinuxServer 的 Docker 镜像的时候经常会需要设置 umask 值,这个值的具体作用一直不太清楚,正好整理一下。

什么是 umask

在 Linux 或 Unix 操作系统中,所有的新文件都有默认权限的。umask 命令行允许用户设置文件的 creation mask, 这决定了新创建的文件或目录的权限。

预设的文件夹权限是:

0777 drwxrwxrwx

预设的文件权限是:

0666 -rw-rw-rw-

当圆弧在 Linux 下创建目录或文件时有一个默认值,这个权限减去 umask 的权限就是新建的目录或文件的实际权限了。

这个配置会被 mkdir, touch, tee 等等一些命令使用。

Linux 权限模型

在深入了解 umask 之前,首先再来解释一下 Linux 的权限模型。在 Linux 中,每一个文件都三个类别用户组:

  • file owner
  • Group members
  • Everyone else

每一个类别都有三个权限:

  • read
  • write
  • execute

这使用用户可以决定哪些用户允许读、写、执行这个文件。

使用 ls -l dirname 来查看:

drwxr-xr-x 12 einverne users 4.0K Apr  8 20:51 dirname
|[-][-][-]    [------] [---]
| |  |  |        |       |       
| |  |  |        |       +-----------> Group
| |  |  |        +-------------------> Owner
| |  |  +----------------------------> Others Permissions
| |  +-------------------------------> Group Permissions
| +----------------------------------> Owner Permissions
+------------------------------------> File Type

第一个字幕表示文件的类型:

  • d 表示目录
  • - 文件
  • l symbolic link

之后的九位,每三位一组:

  • 第一组,是拥有者的权限
  • 第二组是组权限
  • 第三组是所有人的权限

权限有两种表示方法:

  • Symbolic
  • Numeric

Symbolic annotation

字母 rwx 分别表示读(read),写(write),执行(execute),而 - 表示没有权限。

Numeric

权限还可以使用数字来表示,r 可以使用 4 来表示, w 是 2,x 是 1。

比如 rwxr-xr-x 使用数字表示则是 755.

再回到 umask,在 Linux 系统中,默认的创建文件权限是 666,默认给 user, group, others 读和写的权限。目录的权限是 777。

umask 可以用来查看或改变新文件或目录的权限。umask 只会影响当前 shell 环境。在大部分的 Linux 发行版中,默认的系统级别的 umask value 一般在 pam_umask.so 或者 /etc/profile 中。

直接执行 umask 来查看输出,在我本机输出是 002

umask 值包含了新创建的文件或目录不拥有的权限。

上面提到过,默认的新文件的权限是 666,如果 umask 值是 002 则,新创建的文件权限就是 666-002 结果是 664

用户也可以使用 umask -S 来查看 symbolic notation:

❯ umask -S
u=rwx,g=rwx,o=rx

设置 umask

/etc/profile 中可以设置 umask 值。比如不想要其他用户有任何权限,umask 就要设置为 027.

umask 027

reference


2022-04-26 linux , umask , permission

自建邮件服务器的选择和比较

在过去几年的时间里面,一直再寻求各种服务的 Self-hosted ,但唯独邮件服务器自建起来的步骤比较麻烦,但也不是不可能,甚至邮件服务器的 Self-hosted 方案更加全面。

下面这些邮件服务器架设方案是过去几年里面尝试和使用的。

  • [[Poste]] 分为免费版和收费版,可以使用 Docker 部署,所有服务集中在一个镜像中,部署比较简单,适合商用服务,如果出现问题还可以付费进行咨询。Poste 的付费版本提供了更加强大的日志审查,诊断分析工具等等,具体可以参考官网
  • [[Mailu]] 是一个使用 Python 编写的邮件服务器,可以使用 Docker 安装部署,集成了 dovecot, postfix 等等。个人的使用体验就是比较小巧,但是功能齐全。还自带 Webmail。 使用 Mailu 搭建邮件服务器
  • [[mailcow]] 相对于 Mailu 更加强大,但也相对比较消耗资源,mailcow 可以管理多用户,多域名,后台功能非常详细,使用 [[SOGo]] webmail。 使用 Mailcow 搭建邮件服务器.
  • [[postal]] 一个使用 Rust 编写的邮件服务器,可以发送和接收邮件。可以使用 HTTP 接口
  • [[Maddy]] 是一个使用 Go 语言实现的多合一邮件服务器。没有 Web 界面,需要借助客户端

其他一些方案:

  • [[Mail-in-a-Box]]
  • [[iRedMail]]
  • [[modoboa]]
  • [[hMailServer]] 是一款为 Windows Server 编写的邮件服务器。
  • [[Salmon]] Python 实现的邮件服务器
  • docker-mailserver
  • [[zimbra]]

总结

我个人在首先尝试 Mailu ,学习基本的邮件服务器的协议必要的 DNS 配置之后,从 Mailu 切换长期使用 Mailcow。Mailcow 支持多用户,多域名配置,相对 Mailu 要重一些。所以如果是简单的轻度使用推荐 Mailu,Python 编写,Docker 镜像依赖简单,后台简洁。如果是重度使用,那么推荐 Mailcow,虽然镜像搭建稍微复杂,后台管理也稍微复杂一些,但是更强大。

更多总结: https://medevel.com/list-os-mail-server/


2022-04-25 mail-server , email , self-hosted , self-host , linux , docker , smtp

使用 Mailcow 自建邮件服务器

Mailcow 是一个可以使用 Docker 容器化部署的邮件服务器。

GitHub: https://github.com/mailcow/mailcow-dockerized

Mailcow 的优点

Mailcow 相较于 Mailu 整体比较完整,功能相对比较丰富。

  • 支持二步验证,甚至支持 macOS 指纹验证
  • Webmail 使用 SOGo
  • 支持给每个域名增加管理员
  • 有良好的日志查看系统
  • Sync job 功能可以快速、简单地迁移到另外的提供商
  • Web 界面上可以下载 profile,快速在 macOS 和 iOS 中配置使用

缺点

  • 内存占用比较大,只是部署了 Mailcow 就占去了 3G 内存,如果禁用 Solr 和 ClamAV 可以节省内存,日常占用在 1G~2G,但就丧失了搜索和病毒扫描
  • 用的组件比较多,整体使用体验比 Mailu 慢

安装

Mailcow 整体的搭建过程比较简单,如果之前搭建过 Mailu,实际上,参考官网的教程,并没有太多需要再强调的,甚至如果在同一台机器上,从 Mailu 上迁移过来,只需要修改 [[DKIM]] 记录即可。

提前的 DNS 设置可以参考官网

安装:

git clone https://github.com/mailcow/mailcow-dockerized
cd mailcow-dockerized

然后执行:

./generate_config.sh

交互命令中输入自己的 MAILCOW_HOSTNAME,比如 mail.example.com

然后启动:

docker-compose pull
docker-compose up -d

然后使用配置好的域名 mail.example.com 登录,用户名 admin 密码 moohoo

配置 SSL

编辑 mailcow.conf 然后配置 HTTP_BIND=

编辑 data/conf/nginx/redirect.conf:

server {
  root /web;
  listen 80 default_server;
  listen [::]:80 default_server;
  include /etc/nginx/conf.d/server_name.active;
  if ( $request_uri ~* "%0A|%0D" ) { return 403; }
  location ^~ /.well-known/acme-challenge/ {
    allow all;
    default_type "text/plain";
  }
  location / {
    return 301 https://$host$uri$is_args$args;
  }
}

重启:

docker-compose up -d
docker-compose restart nginx-mailcow

使用

进入后台之后,在 Configuration->Mailboxes 添加域名。

客户端设置

几个端口:

Service Encryption Port
IMAP STARTTLS 143
IMAPS SSL 993
POP3 STARTTLS 110
POP3S SSL 995
SMTP STARTTLS 587
SMTPS SSL 465

手工配置

reference


2022-04-23 mailcow , mail , email , email-server , linux , docker , smtp , spf

法官能为民主做什么 读书笔记

这是 [[20220417-21 天计划]] 中的第一本书,记录一下读书笔记。

这本书的作者是最高法院[[斯蒂芬-布雷耶大法官]],英文的标题是 Making our Democracy Work: A Judge’s View 可以看到这是布雷耶大法官多年的观察记录。

三句话总结书的内容

本书主要分为三个部分:

  • 第一部分通过具体的案例介绍民众是如何建立起对最高法院的信任,并接受他们心中不认同的判决的过程。
    • [[马伯里案]] 中确立了[[司法审查权]]
    • 切诺基印第安人土地纷争中涉及到了「判决的可执行性」,如果一个判决没有人愿意执行怎么办?该案件确立了「同案同判」原则。总统动用权力破坏最高法院的判决执行,损害了最高法院的权威
    • 1857 年,臭名昭著的 [[德雷德·斯科特案]]引发内战
    • [[布朗案]] 终结了种族隔离,总统派兵保护黑人学生上学,司法至上的确立
    • [[布什诉戈尔案]],证明了官员和人民已经逐步接受了最高法院的判决和宪法解释,已经形成一种习惯,哪怕内心不认同,也遵循最高法院的宪法解释
  • 第二部分[[斯蒂芬-布雷耶大法官]]提出了一些实用主义的宪法解释方法。
    • 对国会立法,合理推断理性立法者的立法意图
    • 对于行政行为,考虑相关法律的立法目的,兼顾行政分支的专长
    • 解释与联邦主义相关的法律时,注重辅从原则
    • 处理下级法院职能相关问题,考虑专门分工
    • 处理最高法院与本院先例关系时,强调稳定性
  • 第三部分,在解释与个人基本权利相关的法律是,注重价值判断与比例原则

启发或想法

自上一次美国提名大法官开始,已经陆陆续续看过不少的关于最高法院,美国宪政历程,大法官的相关传记也看了不少,但是这一本由大法官主笔的著作依然让我看到了一些不一样的内容。

虽然那些经典的案例在其他著作中也曾经被一遍一遍的分析,但都是旁观者的视角,[[斯蒂芬-布雷耶大法官]]用全书的三分之一的篇幅列举了一个又一个经典案例来回答了一个问题,最高法院的信任是从何而来的。

可以看到的是最高法院从美国建国以来一步步走来并不顺利,也曾有过多次臭名昭著的判决,但是最高法院拥有[[司法审查权]],只要好好的利用这一个至上的权力,不过分迎合主流,为社会的少数群体发声,维护他们的权利,最高法院就可以一步一步慢慢地获得民众的信任。

而且可以看到的是,民众的权利也只有在最高法院,在宪法的保护下,才不会一步步被庞大的国家机器所侵犯,遇到不公和政府的权力扩张,可以随时通过最高法院去维护。

公民自由的要旨就在于,任何个人受到侵害,都有申请法律保护的权利

第二个与众不同的便是,在其他的著作中我们只能通过最后的判决以及判词来揣摩大法官的思考与想法,而这一部著作的第二部分,作者让我们窥探到了其判案的逻辑,以及内心的思考。

书中的第二部分更像是一个如何做法官的说明书,[[斯蒂芬-布雷耶大法官]]讲述大法官应该怎么做才能赢得并延续公众对大法官的信任。

布雷耶大法官总结了一套实用主义法律解释方法。

  • 不拘泥于法律条文起草的时代,应用到不断变化的现实中
  • 解释先发时,充分考虑其他政府的职能能彼此之间的关系

司法权的存在一方面是为少数族群争取应得的权利,另一方面是防止政府,国会权力的无限扩张,而这两者本身就不矛盾,政府权力的扩张一定会侵害到个体权利。

民众对大法官的信任从何而来?

最高法院通过解释和裁判,尽职履责,促进宪法有效实施,从而赢得并延续公众对它的信任。

过分迎合主流政治势力的判决,会削弱甚至剥夺宪法对人民的保护,尤其是对非主流个人、群体的保护力度。[[德雷德·斯科特案]]

法官能为民主做什么?

布雷耶认为,最高法院能实现制宪者心中切实可行的民主,推动宪法在实践中有效地运行。

如何界定个人自由?

[[比例原则]] 来平衡宪法价值观与实际利益诉求之间的冲突。

谁应该看这本书

对三权分立感兴趣,想要了解最高法院,以及大法官的人。

三个 Quotes

公民自由的要旨就在于,任何个人受到侵害,都有申请法律保护的权利。

公众的信任,并非自动脱胎于成文宪法的存在。它必须经过构建、打造,而且一旦形成,就必须永久维持。

我们的社会,自由是一项基本标准”,未经审判的拘押“即使有例外,也必须给予严格限制”。“值此最具挑战与最不确定的时刻,我国对正当程序的承诺正经受遭受最严峻的考验;也正是在这个时候,我们也必须在自己的家园,守护那些我们在海外为之浴血奋战的原则”

制宪先贤们试图创造的民主政体,能够维护自由,有效运行,并垂范久远。他们也意识到,确有必要由一个机构来守护宪法创制的法律边界。

《积极自由》中指出,如果公众不积极参与美国的政治生活,宪法对创制民主政体的影响将微乎其微。同样,如果公众仅仅因为不喜欢对宪法的某种解释,就恣意置之不理,宪法对实现切实可行的宪政民主之影响,也将乏善可陈。

当本杰明·富兰克林被问及制宪会议创立了什么样的政府时,他给出了那句著名的回答:“一个共和国,夫人,如果你们能好好维系它的话。”由此带来的挑战是,如何令我们继承的民主宪法,始终处于切实可行的状态。

司法独立是一个国家的基本理念。但是,当苏共一名党委书记打电话给法官,告诉他某个案子该如何裁判时,司法独立将荡然无存——因为某些潜在的惩罚是不言自明的,这个法官可能再没有像样的住房,子女也可能不会再得到很好的教育。


2022-04-22 reading , reading-2022 , 司法 , 大法官 , 布雷耶

电子书

最近文章

  • 将字幕压制到视频中 本文总结一下将字幕文件压制到视频中的方式,(当然我个人是非常不喜欢直接将字幕压制到视频流中作为硬字幕压制的,但有些时候可能就是需要分享这样硬字幕的视频,比如视频网站,所以也会在下文总结一下)。
  • 解决 Clash for Windows 节点测速 timeout 问题 [[Clash for Windows]] 使用过程中一直没有什么问题,但是昨天心血来潮把 Clash for Windows 从 0.18.8 升级到了最新版本(0.20.5) ,然后发现节点全部 timeout。但可以排除的是这些节点肯定是可以用的,因为在手机上是完全没有问题的。
  • Arc 浏览器初印象 很早之前就在 Twitter 上看到有人分享了 Arc 浏览器的使用体验,说是非常惊艳,我就稍微的浏览了一下官网,抱持怀疑的态度先注册了一下体验,一直好奇到了 2022 年能够在浏览器上做出什么样的创新,自 Chrome 横空出世以来,快,安全迅速抢占了浏览器市场。剩下的一点点份额被 Firefox,Safari,Edge,[[Vivaldi]] 等等占据,早两年的时候我也写过一篇标题略微耸动的文章 —- 我可能要抛弃用了很多年的 Chrome 改用 Vivaldi ,但事实是 3年多过去了,我日常用的还是 Chrome,虽然 Google 在浏览器插件,隐私等等问题上这两年来一直被诟病,但至少还没有彻底地激怒我这个用户。
  • 使用开源 Wakapi 代替 WakaTime 统计编码时间 之前折腾 GitHub Profile 的时候发现了 [[WakaTime]] 这样一款统计编码时间的工具,之后在读 waka-readme 项目的时候发现,还有两个完全开源的后端兼容版本,一个是 Golang 编写的 [[wakapi]] ,一个是 Huskell 编写的 hakatime 。
  • 使用 WakaTime 统计编码时间 [[WakaTime]] 是为程序员打造的编码统计 Dashboard,可以同来统计项目,编程语言,IDE,编码时间等等内容。 之前在折腾 GitHub Profile 的时候发现的,可以在 GitHub Profile 页面中动态的展示最近的编程状态。