属于 [[20220417-21 天计划]] 的第3本书。
[[现代性]]是指的现代社会所具有的一些典型特征。现代(modern)一词16世纪才被创造出来。字面上的含义是「当下或此刻」。人们有了时间的概念,生活不再周而往复。
这本书中对现代性的解释大致分为两个层面:
官僚体制中的人摆脱了道德上的谴责。 冷静、高效、专业的完成自己的工作。
为什么这些正常人能摆脱道德上的自责呢?
犹太人是受害者,但鲍曼说犹太人也负有责任,是大屠杀的帮凶,这些犹太人受到理性的驱动。而理性也是现代性的一个特征。
鲍曼在这本书中提出了一个骇人听闻的观点:「德国纳粹在二战期间实行的对犹太人的种族灭绝是现代性的表现」。
现代官僚制度和现代技术还让屠杀犹太人的纳粹分子在执行任务时摆脱了道德上的困扰。
道德,对他人无条件的责任
现代性体制会压制道德,现代官僚体系会让技术责任代替道德责任,现代社会的原子化倾向会让人们成为互相隔离的冷漠个体。但正因为如此,才更需要重视道德,在任何情况下,一个人都要承担其自己的道德责任,不管发生什么,他都应该去做对的事情。这是避免下一次大屠杀发生的唯一方式。
一直想学习一下视频剪辑,这两天正好拿一个韩剧试一下,但没想到第一步导入就被拦在了外面,不过还好,正好可以学习一下 mkv 格式,以及基本的视频格式。
我在将 mkv 格式的文件导入到 Adobe Premiere 的时候报错:
File format not supported.
mkv 的全称是 Matroska Video File,是一种开放的多媒体档案封装格式,可以将不同编码的影片,音轨,字幕封装到同一个档案中。通常的扩展名是 .mkv
, .mka
, .mks
等等。1
Adobe 从 2019.1.5 版本开始就放弃支持 mkv 格式了2。
本质上 mkv 是一个封装格式,Adobe Premiere 还是支持编辑其中封装的视频内容的。
首先安装 ffmpeg,然后执行:
ffmpeg -i "original_filename.mkv" -codec copy output_name.mp4
这一行命令不会进行转码,所以提取速度约等于文件拷贝的速度,非常快。
上面提到过 mkv 是一种媒体容器,可以将不同编码类型的数据包含到一起。而编码方式则是决定了视频、音频的压缩算法。
可以通过 ffmpeg -i filename.mkv
来查看文件的具体详情。
以一个最简单的例子,为方便学习输出内容有省略:
❯ ffmpeg -i Going.to.You.at.a.Speed.of.493km.S01E04.1080p.DSNP.WEB-DL.AAC2.0.H.264-NYH.mkv
ffmpeg version 5.0.1 Copyright (c) 2000-2022 the FFmpeg developers
built with Apple clang version 13.1.6 (clang-1316.0.21.2)
configuration: --prefix=/usr/local/Cellar/ffmpeg/5.0.1 --enable-shared --enable-pthreads --enable-version3 --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-libaom --enable-libbluray --enable-libdav1d --enable-libmp3lame --enable-libopus --enable-librav1e --enable-librist --enable-librubberband --enable-libsnappy --enable-libsrt --enable-libtesseract --enable-libtheora --enable-libvidstab --enable-libvmaf --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libspeex --enable-libsoxr --enable-libzmq --enable-libzimg --disable-libjack --disable-indev=jack --enable-videotoolbox
libavutil 57. 17.100 / 57. 17.100
libavcodec 59. 18.100 / 59. 18.100
libavformat 59. 16.100 / 59. 16.100
libavdevice 59. 4.100 / 59. 4.100
libavfilter 8. 24.100 / 8. 24.100
libswscale 6. 4.100 / 6. 4.100
libswresample 4. 3.100 / 4. 3.100
libpostproc 56. 3.100 / 56. 3.100
Input #0, matroska,webm, from 'Going.to.You.at.a.Speed.of.493km.S01E04.1080p.DSNP.WEB-DL.AAC2.0.H.264-NYH.mkv':
Metadata:
encoder : libebml v1.4.2 + libmatroska v1.6.4
Duration: 01:03:10.83, start: 0.000000, bitrate: 5704 kb/s
Chapters:
Chapter #0:0: start 1.001000, end 40.999000
Metadata:
title : Intro
Chapter #0:1: start 40.999000, end 3748.957000
Metadata:
title : Scene 1
Chapter #0:2: start 3748.957000, end 3790.826000
Metadata:
title : Credits
Stream #0:0: Video: h264 (High), yuv420p(tv, bt709, progressive), 1920x1080 [SAR 1:1 DAR 16:9], 23.98 fps, 23.98 tbr, 1k tbn (default)
Metadata:
BPS : 5575824
DURATION : 01:03:10.787000000
NUMBER_OF_FRAMES: 90888
NUMBER_OF_BYTES : 2642095527
_STATISTICS_WRITING_APP: mkvmerge v67.0.0 ('Under Stars') 64-bit
_STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
Stream #0:1(kor): Audio: aac (LC), 48000 Hz, stereo, fltp (default)
Metadata:
BPS : 125375
DURATION : 01:03:10.826000000
NUMBER_OF_FRAMES: 177695
NUMBER_OF_BYTES : 59409362
_STATISTICS_WRITING_APP: mkvmerge v67.0.0 ('Under Stars') 64-bit
_STATISTICS_TAGS: BPS DURATION NUMBER_OF_FRAMES NUMBER_OF_BYTES
Stream #0:2(kor): Subtitle: subrip
Metadata:
title : SDH
BPS : 74
DURATION : 01:03:00.359000000
NUMBER_OF_FRAMES: 1167
NUMBER_OF_BYTES : 35163
_STATISTICS_WRITING_APP: mkvmerge v67.0.0 ('Under Stars') 64-bit
_STATISTI
可以看到其中有三段 Stream,可以看到第一段是视频,第二段是音频,而第三段则是字幕,为了方便这里省略了后面还有的多语言字幕。
在每一段中可以看到其编码方案比如视频是 h264, 音频是 aac。
H.264 是一种视频编码,H.264 标准制定的目的就是为了创建一个更好的视频压缩标准,可以在更低的比特率的情况下可以提供更好的视频质量。
Go 语言中常见的容器。
var name [size]T
举例:
var classMates [3]string
# or
classMates2 := [...]string{"A", "B", "C"}
切片是对数组的一个连续片段的引用,容量可变的序列。动态数组。
内部结构包括底层数组指针、大小和容量。
从原数组中生成一个切片:
slice := source[begin:end]
举例:
source := [...]int{1,2,3}
sli := source[0:1]
动态创建切片,可以通过 make
函数动态创建切片
make([]T, size, cap)
直接声明新的切片,不需要指定大小:
var name []T
比如:
ex := []int{1,2,3}
append
函数可以向切片添加元素,返回新的切片。
复制切片内容
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)
}
前端时间给 Proxmox VE 下的虚拟机扩容的时候留意到了这个 growpart 命令,专门用来给分区进行扩容的命令。
growpart - extend a partition in a partition table to fill available space
growpart 工具完成 Linux 系统盘分区扩容及文件系统扩展
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
分区是磁盘的最后一个分区,如果你要扩容的分区在分区中间,可能需要考虑其他方案。
最近想找一个 [[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(协程)是一个更通用的 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 密集型任务:
安装使用:
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 是一个线程计数器,核心是 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()
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())
Lux 是一个使用 Go 语言编写的视频下载命令行工具,支持的平台很多,提供了包括 macOS、Windows、Linux 等等平台的命令行支持,安装和使用非常简单的。Lux 原来的名字是叫做 Annie(安妮),对标的是 macOS 上一款非常著名的视频下载软件叫做 [[Downie]](唐尼)荔枝数码正版授权。但后来改名成了 Lux。
Lux 支持非常多的视频网站:抖音、哔哩哔哩、半次元、pixivision、优酷、YouTube、爱奇艺、芒果 TV、Tumblr、Vimeo、Facebook、斗鱼视频、秒拍、新浪微博、Instagram、Twitter、腾讯视频、网易云音乐、音悦台
项目地址:https://github.com/iawia002/lux
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"
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
来指定输出的名字。
可以使用 -j
输出 JSON 格式结果。
Tailscale 是一种用于构建安全、私有的网络的软件工具,可以在不同设备之间创建虚拟专用网络(VPN),并允许这些设备之间的安全通信。与传统的 VPN 不同,Tailscale 不需要使用 IP 地址或端口转发来实现网络连接。相反,Tailscale 使用每个设备上的唯一身份验证密钥来实现点对点的直接连接,从而提供了更高的安全性和便捷性。Tailscale 使用更高级的 [[WireGuard]] 协议来进行节点和节点之间的通信。
Tailscale 可以在多种操作系统和设备上使用,包括 Windows、macOS、Linux、iOS、Android 和路由器等。它还提供了许多其他功能,如内网穿透、跨设备的文件共享、远程访问和身份验证等,可以帮助用户更轻松地管理和连接其设备和网络。
在接触到 Tailscale 之前,也用过一段时间的 ZeroTier 和 OmniEdge ,ZeroTier 其实到现在未知还一直在用,但是在中国大陆的速度确实不是很快,大部分的时间我只能连个 SSH 查看一下,其他的网络访问都比较慢,并且还丢包。OminiEdge 则是感觉安装的方式还略微有点麻烦,不如现在要介绍的 Tailscale 方便,并且 Tailscale 还有对应的 Ansible Playbook,我配置好之后基本上,如果有新节点的加入只需要跑一下 [[Ansible]] 即可。
Debian/Ubuntu 下安装:
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/bionic.gpg | sudo apt-key add -
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/bionic.list | sudo tee /etc/apt/sources.list.d/tailscale.list
sudo apt update && sudo apt install tailscale
启动:
sudo tailscale up
查看 Tailscale IP 地址:
ip addr show tailscale0
或者
tailscale ip -4
需要注意的是目前是没有方法自定义 Tailscale 分配的 IP 地址。如果想要改变被分配的 IP 地址,可以通过如下方式强制分配新的:
Tailscale ACL(Access Control List),访问控制列表,可以严格限制特定用户或设备在 Tailscale 网络上访问的内容。
Tailscale/Headscale 的默认访问规则是 default deny,也就是黑名单模式,只有在访问规则明确允许的情况下设备之间才能通信。所以 Tailscale/Headscale 默认会使用 allowall 访问策略进行初始化,该策略允许加入到 Tailscale 网络的所有设备之间可以相互访问。
Tailscale/Headscale 通过使用 group 这种概念,可以只用非常少的规则就能表达大部分安全策略。除了 group 之外,还可以为设备打 tag 来进一步扩展访问策略。结合 group 和 tag 就可以构建出强大的基于角色的访问控制(RBAC)策略。
Tailscale 的访问控制权限借鉴了 [[RBAC]] 基于角色的访问控制。
Headscale 的 ACL 策略主要包含以下几个部分:
acls
:ACL 策略定义。groups
:用户的集合。Tailscale 官方控制器的“用户”指的是登录名,必须是邮箱格式。而 Headscale 的用户就是 namesapce。hosts
:定义 IP 地址或者 CIDR 的别名。tagOwners
:指定哪些用户有权限给设备打 tag。autoApprovers
:允许哪些用户不需要控制端确认就可以宣告 Subnet 路由和 Exit Node。acls 部分是 ACL 规则主体,每个规则都是一个 HuJSON 对象,它授予从一组访问来源到一组访问目标的访问权限。
所有的 ACL 规则最终表示的都是允许从特定源 IP 地址到特定目标 IP 地址和端口的流量。虽然可以直接使用 IP 地址来编写 ACL 规则,但为了可读性以及方便维护,建议使用用户、Group 以及 tag 来编写规则,Tailscale 最终会将其转换为具体的 IP 地址和端口。
每一个 ACL 访问规则长这个样子:
- action: accept
src:
- xxx
- xxx
- ...
dst:
- xxx
- xxx
- ...
proto: protocol # 可选参数
Tailscale/Headscale 的默认访问规则是 default deny
,也就是黑名单模式,只有在访问规则明确允许的情况下设备之间才能通信。所以 ACL 规则中的 action
值一般都写 accept
,毕竟默认是 deny 嘛。
src
字段表示访问来源列表,该字段可以填的值都在这个表格里:
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 之前开源的在线版。
macOS 有一个内置的图片压缩命令
sips -s formatOptions high path/*.jpg
这是 [[20220417-21 天计划]] 的第二本书,看过 [[何帆]] 翻译的很多本作品,这一本《大法官说了算:美国司法观察笔记》是何帆多年的司法观察记录。作者以[[苏特大法官]] 的辞职开始说起,先后介绍了大法官是如何产生的,最高法院内部是怎么运行的,网络时代的法庭,法院对言论自由的态度,对死刑的态度,等等角度对大法官展开了详细的描述,最后一章对现在美国的最高法院的每一位大法官做了单独的介绍。
个人感觉这是一本非常适合想要了解大法官,以及最高法院的读者,在书中可以对整个最高法院的历史,以及大法官为何一言九鼎有一个非常直观的认识。
如果读完钦佩于大法官的人格魅力,那么可以继续看[[九人-美国最高法院风云]],如果读完更关心最高法院是如何界定言论自由的,那么继续阅读 [[言论的边界 美国宪法第一修正案简史]] ,如果读完更醉心于案件的错综复杂以及大法官们抽丝剥茧梳理给出判决,那么可以再读[[美国宪政历程 影响美国的 25 个司法大案]]
当然如果不想读这些大部头作品,那么也有牛津通识读本中的 [[美国最高法院通识读本]],[[批评官员的尺度]] 等等作品可以继续。
或许看过美剧、韩剧律政剧的人,对那个蒙着眼睛、一手持剑,一手天平的正义女神不再陌生,我也曾在这些剧集中一次次被法官「正义」的判决所感染。然而稍微了解一下美国的司法史就可以看到在不同的历史时期司法的天平都不是绝对的公平。
美国的历史上存在《惩治煽动性言论法》,曾一度赋予了总统以无上的言论审查权;最高法院也会允许雇主不受任何限制的和劳工签订超长工作时间的合同,大法官们认为雇主有权利和劳工签订不受时间限制的合同;更甚至[[坦尼大法官]]在 1857 年的 [[斯科特案]] 判决中判定黑人不是美国公民,直接导致了南北战争。[[202011041258-最高法院历史上的污点]] 不是一两句话就可以说清楚的,但是正是因为司法只是三权分立中的一个分支,更甚至是一个在最初没有一点地位的分支,司法天平的倾斜甚至倾倒,可以用行政的立法的权力予以纠正。
林肯当上总统之后,用宪法第十四修正案推翻了最高法院关于黑人不是美国公民的判决,将倾斜的天平拨了回来。
而司法的存在也正是为了约束行政权力的过大,以及立法分支的肆意立法。大法官们手握[[司法审查权]],可以对立法分支涉嫌违宪的法律进行审查。正是这三个分支的相互制约才使得美国在过去 200 多年的历史中,一直在修修补补中度日,除了南北战争这一次严重的战争之外一直可以不断地进化。
这两天在 Twitter 刚好看到一则推文,提出一个问题,如果这三个分支都不再很好的执行自己的职责,司法分支不再对超越宪法的立法进行审查,而行政权力以更强硬的手段行政,那么该怎么办?最终给出的答案是美国的持枪自由。但是我们都知道非要走到那一步必然会导致更严重的问题,这也不是这一本书所讨论的问题了。
在最高法院的描述中,一直少不了「自由派」和「保守派」两派大法官的描述。但是,我们要知道,在这里「保守」绝不是一个贬义词,保守派大法官只是始终对宪法保持警惕之心,深怕任意解释宪法会破坏法治框架。而自由派大法官,并非不尊重宪法,只是他们认为一部「活的宪法」才能与时俱进,适应不断变幻的现实,体现制宪先贤的本意。他们会秉持「至善论」(Perfectionism)的观点,不断创制一些新权利,进而将该权利解释为宪法的应有之义。
保守的含义其实颇为多元,可能是对无孔不入的「大政府」的畏惧,可能是对上帝的虔诚信仰,可能是对种族、文化、性的审慎态度,很难以进步或落后加以评判。
美国是一个缺乏改革传统的国家,就像上面提到的那样,越是重大的变革,越是以润物细无声的渐进方式完成。最高法院当然能够推动社会变革,但是「大法官说了算」并不意味着判决是推动变革的主要途径。[[布朗案]]之后依然有百万的黑人儿童无法获得读书的机会。最高法院的判决并非只是权力的宣示,更是一种理想的表达,当权力和理念合二为一时,才能慢慢影响人们的观念,直至形成一种更为先进的文化。这些观念被大多数人接受的时候,就会演变成制度和法律。
无论最高法院如何判决,绝大多数人都会接受判决结果。这种信任建立在过去上百位大法官孜孜努力的基础之上。
在使用 LinuxServer 的 Docker 镜像的时候经常会需要设置 umask 值,这个值的具体作用一直不太清楚,正好整理一下。
在 Linux 或 Unix 操作系统中,所有的新文件都有默认权限的。umask
命令行允许用户设置文件的 creation mask, 这决定了新创建的文件或目录的权限。
预设的文件夹权限是:
0755 drwxr-xr-x
预设的文件权限是:
0644 -rw-r--r--
在 Linux 下创建目录或文件时有一个默认值,这个权限减去 umask 的权限就是新建的目录或文件的实际权限了。
这个配置会被 mkdir
, touch
, tee
等等一些命令使用。
在深入了解 umask 之前,首先再来解释一下 Linux 的权限模型。在 Linux 中,每一个文件都三个类别用户组:
每一个类别都有三个权限:
这使用用户可以决定哪些用户允许读、写、执行这个文件。
使用 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之后的九位,每三位一组:
权限有两种表示方法:
字母 rwx
分别表示读(read),写(write),执行(execute),而 -
表示没有权限。
权限还可以使用数字来表示,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
在 /etc/profile
中可以设置 umask 值。比如不想要其他用户有任何权限,umask 就要设置为 027.
umask 027