snapshot

中文翻译是不靠谱的。
Snapshot:
In computer systems, a snapshot is the state of a system at a particular point in time.
和”快“没有任何关联。

Git在每一次commit时,都会完整的存储当前版本所有修改的文件,而非只存储diff。

blob

tree

常见错误

HEAD detached at be2dbb9

Detached head means you are no longer on a branch, you have checked out a single commit in the history (in this case the commit previous to HEAD, i.e. HEAD^).
解决办法 git checkout master

参考:https://stackoverflow.com/questions/3965676/why-did-my-git-repo-enter-a-detached-head-state/3965714#3965714

参考

https://support.apple.com/zh-cn/HT201236

command + A 全选
command + B 加粗
command + C 复制
command + D 收藏
command + F 查找
command + N 新建
command + O 打开
command + P 打印
command + Q 退出当前程序
command + R 刷新
command + S 保存
command + U 下划线
command + V 粘贴
command + W 关闭窗口
command + X 剪切
command + Y 重做
下划线
command + Z 撤销
command + shift + 3 截屏
command + shift + 4 选择截屏
command + option + esc 任务管理器
command + option + h 隐藏其他窗口
command + delete 移到废纸篓

https://brew.sh/

Homebrew 能干什么?

使用 Homebrew 安装 Apple 没有预装但 你需要的东西。

比如

1
$ brew install wget

为什么不通过app store安装呢?

因为wget tree等基本东西,app store里没有。为啥呢?

brew安装与app-store安装有什么不同?

brew会把软件安装到/usr/local下,而从网上下载dmg/pkg安装包复制安装的目标路径是/applications

Homebrew 会将软件包安装到独立目录,并将其文件软链接至 /usr/local 。

s

##

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ tree -L 1 -a
.
├── .CFUserTextEncoding
├── .DS_Store
├── .Trash
├── .atom
├── .bash_history
├── .bash_sessions
├── .sogouinput
├── .ssh # ssh key 目录,类似linux
├── .viminfo
├── Applications
├── Desktop
├── Documents
├── Downloads
├── Library
├── Movies
├── Music
├── Pictures
├── Public
└── Zotero # 为什么zotero会在这儿?

既然类似linux,为什么没有.bashrc目录?

mac中遇到的坑

粘贴板的坑

比如chrome的粘贴板有时会独立于系统粘贴板,在系统其它地方command + C复制的内容,在chrome粘贴不上。

解决办法:

  1. 方式一:重启一下chrome或者那个app
  2. 方式二:运行命令killall pboard,重启粘贴板

#

文件系统 - 文件

一切皆文件

UNIX 系统中除进程之外的一切皆是文件,而 Linux 保持了这一特性。为
了便于文件的管理,Linux 还引入了目录(有时亦被称为文件夹)这一概念。

Linux 系统的顶层目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/              根目录
├── bin 存放用户二进制文件
├── boot 存放内核引导配置文件
├── dev 存放设备文件
├── etc 存放系统配置文件
├── home 用户主目录
├── lib 动态共享库
├── lost+found 文件系统恢复时的恢复文件
├── media 可卸载存储介质挂载点
├── mnt 文件系统临时挂载点
├── opt 附加的应用程序包
├── proc 系统内存的映射目录,提供内核与进程信息
├── root root 用户主目录
├── sbin 存放系统二进制文件
├── srv 存放服务相关数据
├── sys sys 虚拟文件系统挂载点
├── tmp 存放临时文件
├── usr 存放用户应用程序
└── var 存放邮件、系统日志等变化文件

Linux 与其他类 UNIX 系统一样并不区分文件与目录:目录是记录了其他文件名的文件。使用命令 mkdir 创建目录时,若期望创建的目录的名称与现有的文件名(或目录名)重复,则会创建失败。

元数据 VS 用户数据

我们知道文件都有文件名与数据,这在 Linux 上被分成两个部分:用户数据 (user data) 与元
数据 (metadata)。

  • 用户数据,即文件数据块 (data block),数据块是记录文件真实内容的地方;
  • 元数据则是文件的附加属性,如文件大小、创建时间、所有者等信息。
    元数据中的 inode 号(inode 是文件元数据的一部分但其并不包含文件名,inode 号即索引节点
    号)才是文件的唯一标识而非文件名。

通过文件名打开文件

通过文件名打开文件

软链接 VS 硬链接

为解决文件的共享使用,Linux 系统引入了两种链接:硬链接 (hard link) 与软链接(又称符号链接,即 soft link 或 symbolic link)

链接为 Linux 系统解决了文件的共享使用,还带来了隐藏文件路径、增加权限安全及节省存储等好处。若一个 inode 号对应多个文件名,则称这些文件为硬链接。换言之,硬链接就是同一个文件使用了多个别名(见 图 2.hard link 就是 file 的一个别名,他们有共同的 inode)。硬链接可由命令 link 或 ln 创建。如下是对文件 oldfile 创建硬链接。

软链接的访问

由于硬链接是有着相同 inode 号仅文件名不同的文件,因此硬链接存在以下几点特性:

  1. 文件有相同的 inode 及 data block;
  2. 只能对已存在的文件进行创建;
  3. 不能交叉文件系统进行硬链接的创建;
  4. 删除一个硬链接文件并不影响其他有相同 inode 号的文件。(删除的只是filename)
  5. 不能对目录进行创建,只可对文件创建;

逐个详解

1.

2.

3.

  1. 硬链接不能对目录进行创建,只可对文件创建;

目录是树形结构。ls -a能看到目录底下有. 和.. 指向本目录和父目录,如果对父目录建立软连接就有可能会成环,破坏树形结构

5.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ echo sss > oldfile
$ link oldfile newfile # 2. oldfile要存在,newfile必须不存在,
$ ls -li
6277186 -rw-r--r-- 2 xusong staff 4 Jul 24 20:54 newfile
6277186 -rw-r--r-- 2 xusong staff 4 Jul 24 20:54 oldfile

# 5. 删除一个硬链接文件并不影响其他有相同 inode 号的文件。(删除的只是filename)
$ rm oldfile
$ ls -li
6277186 -rw-r--r-- 1 xusong staff 4 Jul 24 20:54 newfile

# 5. 不能对目录进行创建,只可对文件创建;
# 目录是树形结构。ls -a能看到目录底下有. 和.. 指向本目录和父目录,如果对父目录建立软连接就有可能会成环,破坏树形结构
$ mkdir old_dir
$ ls -lia
6277575 drwxr-xr-x 3 xusong staff 96 Jul 24 21:04 .
6277177 drwxr-xr-x 6 xusong staff 192 Jul 24 21:04 ..
6277580 drwxr-xr-x 2 xusong staff 64 Jul 24 21:04 old_dir
$ link old_dir new_dir
link: old_dir: Is a directory

FAQ

思考
软链接,是链接的node号还是路径名?
路径名。在git中看到的是路径名。另外,被link的目录删除再新建一个一样的,照样能识别。

1
2
3
4
5
6
# bash1

cd a/b/c

# bash2
mv test test

#

【Docker系列】docker中的权限

docker 客户端

1
2
$ ls -lh /usr/bin/docker
-rwxr-xr-x 1 root root 37M Apr 26 15:18 /usr/bin/docker

默认所有用户都能够执行docker命令,但是执行其他命令,会出现权限问题。

docker 服务

1
2
$ docker images
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.37/images/json: dial unix /var/run/docker.sock: connect: permission denied

执行查询镜像命令,报错。因为该用户不在docker用户组。而只有docker用户组才有权限访问docker server。

1
2
3
4
5
$ cd /var/run/
$ ls -lh | grep docker
drwx------ 9 root root 200 Jul 7 11:03 docker
-rw-r--r-- 1 root root 4 Jul 6 14:33 docker.pid
srw-rw---- 1 root docker 0 Jul 6 14:32 docker.sock # docker server

docker.sock属于docker用户组。

1
2
$ cat /etc/group | grep docker
docker:x:999:song.xu01

添加权限

1
$ usermod -aG docker 用户名 # 添加到docker用户组

【Docker系列】Docker的存储

简介

https://docs.docker.com/storage/storagedriver/

每个Docker镜像(Image)都引用了一些只读的(read-only)层(layer),不同的文件系统layer也不同。这些layer堆叠在一起构成了容器(Container)的根文件系统(root filesystem)。

当你基于Ubuntu 创建一个新的容器的时候,你其实只是在它的上层又增加了一个新的、薄的、可写层。这个新增的可写层称为容器层(container layer)。当这个新的容器运行时,所有的改动(比如创建新文件、修改已有文件、删除文件等)都会写到这一层。

存储 - 镜像层(Layers)

镜像层依赖于一系列的底层技术,比如文件系统(filesystems)、写时复制(copy-on-write)、联合挂载(union mounts)等

docker的镜像分层技术

容器层是可写层。

例如:
docker history tensorflow/tensorflow:1.8.0-gpu

tensorflow的镜像分层

写时拷贝策略(CopyOnWrite)

CopyOnWrite容器即写时复制的容器。通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,之后再将原容器的引用指向新的容器。这样做的好处是我们可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器。

缺点

  • 内存占用问题:
    在进行写操作的时候,内存里会同时驻扎两个对象的内存,旧的对象新写入的对象(注意:在复制的时候只是复制容器里的引用,只是在写的时候会创建新对象添加到新容器里,而旧容器的对象还在使用,所以有两份对象内存)。
    docker的什么操作会写容器?不涉及文件写操作的会涉及到容器的写操作吗?只有commit操作会写操作?
  • 数据一致性问题

COW的应用

CopyOnWrite容器非常有用,可以在非常多的并发场景中使用到。

COW在java

从JDK1.5开始Java并发包里提供了两个使用CopyOnWrite机制实现的并发容器,它们是CopyOnWriteArrayList和CopyOnWriteArraySet

COW在C++

C++的STL中,曾经也有过Copy-On-Write的玩法,参见陈皓的《C++ STL String类中的Copy-On-Write》,后来,因为有很多线程安全上的事,就被去掉了。

数据持久化

配置本地镜像与容器的存储位置

默认情况下Docker的存放位置为:/var/lib/docker
可以通过下面命令查看具体位置:

1
docker info | grep "Docker Root Dir"

解决这个问题,最直接的方法当然是挂载分区到这个目录,但是我的数据盘还有其他东西,这肯定不好管理,所以采用修改镜像和容器的存放路径的方式达到目的。

这个方法里将通过软连接来实现。

首先停掉Docker服务:

1
2
3
systemctl restart docker
或者
service docker stop

然后移动整个/var/lib/docker目录到目的路径:

1
2
mv /var/lib/docker /root/data/docker
ln -s /root/data/docker /var/lib/docker

这时候启动Docker时发现存储目录依旧是/var/lib/docker,但是实际上是存储在数据盘的,你可以在数据盘上看到容量变化。

docker的挂载

unmount

系统文件夹使用的是devicemapper文件系统,可以用来限制容器的磁盘使用。

在devicemapper驱动下,多出两个文件,一个是 devicemapper 一个是metadata

文件目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/var/lib/docker# ls
aufs
builder
buildkit
containerd
containers
image
network
plugins
runtimes
swarm
tmp
trust
volumes

参考