systemctl命令

简介

systemd 是由红帽公司的一名叫做 Lennart Poettering 的员工开发,systemdLinux 系统中最新的初始化系统(init),它主要的设计目的是克服 Sys V 固有的缺点,提高系统的启动速度,systemdupstart 是竞争对手,ubantu 上使用的是 upstart 的启动方式,centos 7上使用 systemd 替换了 Sys VSystemd 目录是要取代 Unix 时代依赖一直在使用的 init 系统,兼容 Sys VLSB 的启动脚本,而且能够在进程启动中更有效地引导加载服务。
system:系统启动和服务器守护进程管理器,负责在系统启动或运行时,激活系统资源,服务器进程和其他进程,根据管理,字母 d 是守护进程(daemon)的缩写,systemd 这个名字的含义就是它要守护整个系统。
监视和控制systemd的主要命令是 systemctl

systemd 新特性

  • 系统引导时实现服务并行启动
  • 按需启动守护进程
  • 同时采用 socket 式与 D-Bus 总线式激活服务
  • 系统状态快照和恢复
  • 利用 Linuxcgroups 监视进程
  • 维护挂载点和自动挂载点
  • 各服务间基于依赖关系进行精密控制

示例

  • 检查systemd是否正在运行

    1
    ps -eaf | grep systemd

systemd 作为父守护进程运行(PID = 1)。 在上面的命令ps中使用(-e)选择所有进程,(-a)选择除会话前导之外的所有进程和(-f)选择完整格式列表(即-eaf)。

  • 分析systemd启动过程

    1
    systemd-analyze

exp: Startup finished in 714ms (kernel) + 1.483s (initrd) + 8.458s (userspace) = 10.656s

  • 分析每个进程在引导时花费的时间

    1
    systemd-analyze blame

exp:
2.682s network.service
2.221s kdump.service
1.773s cloud-init-local.service
1.302s tuned.service
910ms YDService.service
869ms cloud-config.service
793ms vdo.service
650ms cloud-final.service
533ms polkit.service
526ms cloud-init.service
411ms lvm2-monitor.service
405ms rhel-dmesg.service
402ms ntpd.service
399ms acpid.service
348ms systemd-journal-flush.service
337ms nginx.service
316ms dev-vda1.device

  • 分析启动时的关键链

    1
    systemd-analyze critical-chain

exp:
The time after the unit is active or started is printed after the “@” character.
The time the unit takes to start is printed after the “+” character.
multi-user.target @7.016s
└─tuned.service @5.713s +1.302s
└─network.target @5.708s
└─network.service @3.025s +2.682s
└─network-pre.target @3.024s
└─cloud-init-local.service @1.250s +1.773s
└─basic.target @1.243s
└─sockets.target @1.243s
└─dbus.socket @1.242s
└─sysinit.target @1.242s
└─systemd-update-utmp.service @1.225s +15ms
└─auditd.service @1.012s +212ms
└─systemd-tmpfiles-setup.service @991ms +20ms
└─rhel-import-state.service @902ms +88ms
└─local-fs.target @897ms
└─local-fs-pre.target @897ms
└─lvm2-monitor.service @485ms +411ms
└─lvm2-lvmetad.service @557ms
└─lvm2-lvmetad.socket @485ms
└─-.slice

  • 检查单元或者服务是否启用

    1
    systemctl is-enabled nginx.service
  • 检查单元或服务是否正在运行

    1
    2
    systemctl status nginx.service
    systemctl status nginx
  • 列出所有服务(包括启用和禁用)

    1
    systemctl list-unit-files --type=service
  • 启动,重新启动,停止,重新加载服务

    1
    2
    3
    4
    systemctl start nginx.service
    systemctl restart nginx.service
    systemctl stop nginx.service
    systemctl reload nginx.service
  • 如何在引导时激活服务并启用或禁用服务(系统引导时自动启动服务)

    1
    2
    3
    systemctl is-active nginx.service
    systemctl enable nginx.service
    systemctl disable nginx.service
  • 如何使用systemctl命令终止服务

    1
    systemctl kill nginx
  • 检查服务的所有配置详细信息

    1
    systemctl show nginx
  • 分析服务的关键链(nginx)

    1
    systemd-analyze critical-chain nginx.service

exp:
The time after the unit is active or started is printed after the “@” character.
The time the unit takes to start is printed after the “+” character.

nginx.service +337ms
└─network.target @5.708s
└─network.service @3.025s +2.682s
└─network-pre.target @3.024s
└─cloud-init-local.service @1.250s +1.773s
└─basic.target @1.243s
└─sockets.target @1.243s
└─dbus.socket @1.242s
└─sysinit.target @1.242s
└─systemd-update-utmp.service @1.225s +15ms
└─auditd.service @1.012s +212ms
└─systemd-tmpfiles-setup.service @991ms +20ms
└─rhel-import-state.service @902ms +88ms
└─local-fs.target @897ms
└─local-fs-pre.target @897ms
└─lvm2-monitor.service @485ms +411ms
└─lvm2-lvmetad.service @557ms
└─lvm2-lvmetad.socket @485ms
└─-.slice

  • 获取服务的依赖项列表(nginx)

    1
    systemctl list-dependencies nginx.service

exp:
nginx.service
● ├─-.mount
● ├─system.slice
● └─basic.target
● ├─rhel-dmesg.service
● ├─selinux-policy-migrate-local-changes@targeted.service
● ├─paths.target
● ├─slices.target
● │ ├─-.slice
● │ └─system.slice
● ├─sockets.target
● │ ├─dbus.socket
● │ ├─dm-event.socket
● │ ├─rpcbind.socket
● │ ├─systemd-initctl.socket
● │ ├─systemd-journald.socket
● │ ├─systemd-shutdownd.socket
● │ ├─systemd-udevd-control.socket
● │ └─systemd-udevd-kernel.socket
● ├─sysinit.target
● │ ├─dev-hugepages.mount
● │ ├─dev-mqueue.mount
● │ ├─kmod-static-nodes.service
● │ ├─lvm2-lvmetad.socket
● │ ├─lvm2-lvmpolld.socket
● │ ├─lvm2-monitor.service
● │ ├─plymouth-read-write.service
● │ ├─plymouth-start.service
● │ ├─proc-sys-fs-binfmt_misc.automount
● │ ├─rhel-autorelabel.service
● │ ├─rhel-domainname.service
● │ ├─rhel-import-state.service
● │ ├─rhel-loadmodules.service
● │ ├─sys-fs-fuse-connections.mount
● │ ├─sys-kernel-config.mount
● │ ├─sys-kernel-debug.mount
● │ ├─systemd-ask-password-console.path
● │ ├─systemd-binfmt.service
● │ ├─systemd-firstboot.service
● │ ├─systemd-hwdb-update.service
● │ ├─systemd-journal-catalog-update.service
● │ ├─systemd-journal-flush.service
● │ ├─systemd-journald.service
● │ ├─systemd-machine-id-commit.service
● │ ├─systemd-modules-load.service
● │ ├─systemd-random-seed.service
● │ ├─systemd-sysctl.service
● │ ├─systemd-tmpfiles-setup-dev.service
● │ ├─systemd-tmpfiles-setup.service
● │ ├─systemd-udev-trigger.service
● │ ├─systemd-udevd.service
● │ ├─systemd-update-done.service
● │ ├─systemd-update-utmp.service
● │ ├─systemd-vconsole-setup.service
● │ ├─cryptsetup.target
● │ ├─local-fs.target
● │ │ ├─-.mount
● │ │ ├─rhel-readonly.service
● │ │ ├─systemd-fsck-root.service
● │ │ └─systemd-remount-fs.service
● │ └─swap.target
● └─timers.target
● └─systemd-tmpfiles-clean.timer

参考文章

systemctl 命令详解及使用教程
CentOS7下Systemctl详解

改变

If you keep studying, you’ll definitely go far.

如果你继续学习,你肯定会走得很远。

6月12日:写代码
  • 把二期要做的需求基本实现完毕,更新提交到远端分支
6月13日上午:做分享
  • 给团队的同事分享 Git 以及 Git Flow
6月13日下午:交接工作
  • 给交接的同事讲解了一遍需求和对应代码
6月14日上午:离职
  • 离开毕业工作的第一家公司,大约要3年了
  • 离开工作以来第一个团队,能得到大家的认可真的很高兴很幸运
  • 离开第一个全程在跟进的大项目,前端,这个月在进行用户验收测试(UAT),下个月要上线了吧
  • 离开最熟悉的环境和人,每天一起吃饭的伙伴,一起培训的模友
  • 离开朝九晚六的辛福生活哈哈哈
6月14日下午:入职
  • 公司总共不到十个人,一起创业
  • 开发方向从前端转到后端
6月15日下午:参加需求会议
  • 我在新公司第一个项目,任务管理系统,觉得这是一个好的开始
6月16日
  • 睡懒觉
  • 理发
  • 看房子
  • 画画
6月17日早晨
  • 步行到地铁,然后挤地铁上班,时间一半一半吧
6月18日晚上
  • 到家21点半了,吃饭有点儿晚
6月19日上午
  • 四个人一起去西北六环和一家上市公司谈合作
  • 午饭蹭了大佬一顿饭,龙虾是真的不错
6月20日
  • 一天写的并且调通的代码倍数是我入职到这天之前写的总数的两倍吧
  • 周末想去看《千与千寻》

2019年6月20日记

Git

服务器上的Git

Git 可以使用四种主要的协议来传输资料:本地协议(Local),HTTP 协议(https://),SSH(Secure Shell)协议(user@server:path/to/repo.git)及 Git 协议(git://)。

.gitignore

  • 所有空行或者以 # 开头的行都会被 Git 忽略
  • 可以使用标准的 glob 模式匹配
  • 匹配模式可以以(/)开头防止递归
  • 匹配模式可以以(/)结尾指定目录
  • 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反

所谓的 glob 模式是指 shell 所使用的简化了的正则表达式

  • 星号(*)匹配零个或多个任意字符
  • [abc] 匹配任何一个列在方括号中的字符(这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c)
  • 问号(?)只匹配一个任意字符
  • 如果在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配 (比如 [0-9] 表示匹配所有 0 到 9 的数字)
  • 使用两个星号(*) 表示匹配任意中间目录,比如a/**/z 可以匹 配 a/z, a/b/z 或 a/b/c/z等。

Example:

  1. .a 结尾的文件(no .a files)

    1
    *.a
  2. 跟踪 lib.a 文件,即使你忽略以.a 结尾的文件(but do track lib.a, even though you’re ignoring .a files above)

    1
    !lib.a
  3. 忽略当前目录下的 TODO 下的文件,子目录下的不忽略(only ignore the TODO file in the current directory, not subdir/TODO)

    1
    /TODO
  4. 忽略所有 build 目录下的文件(ignore all files in the build/ directory)

    1
    build/
  5. 忽略所有 doc 目录下一级以 .txt 结尾的文件(ignore doc/notes.txt, but not doc/server/arch.txt)

    1
    doc/*.txt
  6. 忽略所有 doc 目录下以 .pdf 结尾的文件(ignore all .pdf files in the doc/ directory)

    1
    doc/**/*.pdf

查看更多 .gitignore 示例

git config

命令 含义
git config –list 列出所有 Git 当时能找到的配置
git config 检查 Git 的某一项配置
git help config 获得 config 命令的手册

git clone

克隆远程仓库,aaa1 是自定义本地仓库的名字,可忽略。

1
git clone https://github.com/aaa/aaa aaa1

git branch

提交对象的 master 分支。它会在每次的提交操作中自动向前移动。
Git 的 “master” 分支并不是一个特殊分支。它就跟其它分支完全没有区别。之所以几乎每一个仓库都有 master 分支,是因为 git init 命令默认创建它,并且大多数人都懒得去改动它。
git branch -v 查看每一个分支的最后一次提交,--merged--no-merged 这两个有用的选项可以过滤这个列表中已经合并或尚未合并到当前分支的分支。
git branch -d 删除分支,如果分支包含了还未合并的工作,尝试使用 git branch -d 命令删除它时会失败,如果真的想要删除分支并丢掉那些工作,如同帮助信息里所指出的,可以使用 -D 选项强制删除它。
可以通过 git ls-remote (remote) 来显式地获得远程引用的完整列表,比如 git ls-remote origin,或者通过 git remote show (remote) 获得远程分支的更多信息。
设置已有的本地分支跟踪一个刚刚拉取下来的远程分支,或者想要修改正在跟踪的上游分支,你可以在任意时间使用 -u--set-upstream-to 选项运行 git branch 来显式地设置(git branch -u origin/serverfix)。
如果想要查看设置的所有跟踪分支,可以使用 git branch-vv 选项。这会将所有的本地分支列出来并且包含更多的信息,如每一个分支正在跟踪哪个远程分支与本地分支是否是领先、落后或是都有。
需要重点注意的一点是这些数字的值来自于你从每个服务器上最后一次抓取的数据。这个命令并没有连接服务器,它只会告诉你关于本地缓存的服务器数据。如果想要统计最新的领先与落后数字,需要在运行此命令前抓取所有的远程仓库。可以像这样做: git fetch --all; git branch -vv
git push origin --delete serverfix:删除远程分支

git status

如果你使用 git status -s 命令或 git status --short 命令,你将得到一种更为紧凑的格式输出。

1
2
3
4
5
6
git status -s
M README
MM Rakefile
A lib/git.rb
M lib/simplegit.rb
?? LICENSE.txt

新添加的未跟踪文件前面有 ?? 标记。
新添加到暂存区中的文件前面有 A 标记。
修改过的文件前面有 M 标记,M 有两个可以出现的位置,出现在右边的 M 表示该文件被修改了但是还没放入暂存区,出现在靠左边的 M 表示该文件被修改了并放入了暂存区。

git rm

要从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),然后提交。 可以用 git rm 命令完成此项工作,并连带从工作目录中删除指定的文件,这样以后就不会出现在未跟踪文件清单中了。
如果只是简单地从工作目录中手工删除文件,运行 git status 时就会在 “Changes not staged for commit” 部分(也就是 未暂存清单)看到删除文件。需要再运行 git rm 记录此次移除文件的操作。
如果删除之前修改过并且已经放到暂存区域的话,则必须要用 强制删除选项 -f(译注:即 force 的首字母)。 这是一种安全特性,用于防止误删还没有添加到快照的数据, 这样的数据不能被 Git 恢复。
我们想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录 中。 换句话说,你想让文件保留在磁盘,但是并不想让 Git 继续跟踪。 当你忘记添加 .gitignore 文件,不小 心把一个很大的日志文件或一堆 .a 这样的编译生成文件添加到暂存区时,这一做法尤其有用。 为达到这一目 的,使用 --cached 选项:
git rm --cached README
git rm 命令后面可以列出文件或者目录的名字,也可以使用 glob 模式。比方说:
git rm log/\*.log
注意到星号 * 之前的反斜杠 \, 因为 Git 有它自己的文件模式扩展匹配方式,所以我们不用 shell 来帮忙展开。 此命令删除 log/ 目录下扩展名为 .log 的所有文件。

git checkout

要特别注意的一点是当抓取到新的远程跟踪分支时,本地不会自动生成一份可编辑的副本(拷贝)。 换一句话说,这种情况下,不会有一个新的 serverfix 分支 - 只有一个不可以修改的 origin/serverfix 指针。
可以运行 git merge origin/serverfix 将这些工作合并到当前所在的分支。 如果想要在自己的 serverfix 分支上工作,可以将其建立在远程跟踪分支之上:
git checkout -b serverfix origin/serverfix
这是一个十分常用的操作所以 Git 提供了 --track 快捷方式:
git checkout --track origin/serverfix

git push

运行 git push origin serverfix:awesomebranch 来将本地的 serverfix 分支推送到远程仓库上的 awesomebranch 分支。

git config --global push.default simple

push.default可用的值如下:

  • nothing
    不推送任何东西并有错误提示,除非明确指定分支引用规格。强制使用分支引用规格来避免可能潜在的错误。
  • current
    推送当前分支到接收端名字相同的分支。
  • upstream
    推送当前分支到上游@{upstream}。这个模式只适用于推送到与拉取数据相同的仓库,比如中央工作仓库流程模式。
  • simple
    在中央仓库工作流程模式下,拒绝推送到上游与本地分支名字不同的分支。也就是只有本地分支名和上游分支名字一致才可以推送,
    就算是推送到不是拉取数据的远程仓库,只要名字相同也是可以的。在 Git 2.0中,simple 将会是 push.default 的默认值。simple 只会推送本地当前分支。
  • matching
    推送本地仓库和远程仓库所有名字相同的分支。
    这是 Git 当前版本的缺省值。

git diff

若要查看已暂存的将要添加到下次提交里的内容,可以用 git diff --cached 命令或者 git diff --staged
git diff 本身只显示尚未暂存的改动,而不是自上次提交以来所做的所有改动。 所以有时候你一下子暂存了所有更新过的文件后,运行 git diff 后却什么也没有,就是这个原因。

git commit

有时候我们提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了。此时,可以运行带有 --amend 选 项的提交命令尝试重新提交

1
2
3
git commit -m 'initial commit'
git add forgotten_file
git commit --amend

当使用 git commit 进行提交操作时,Git 会先计算每一个子目录(本例中只有项目根目录)的校验和,然后在 Git 仓库中这些校验和保存为树对象。随后,Git 便会创建一个提交对象,它除了包含上面提到的那些信息外, 还包含指向这个树对象(项目根目录)的指针。

1
2
git add README test.rb LICENSE
git commit -m 'The initial commit of my project'

现在,Git 仓库中有五个对象:三个 blob 对象(保存着文件快照)、一个树对象(记录着目录结构和 blob 对象 索引)以及一个提交对象(包含着指向前述树对象的指针和所有提交信息)。

git remote

命令 含义
git remote 查看你已配置的远程仓库服务器
git remote -v 显示需要读写远程仓库使用的 Git 保存的简写与其对应的 URL
git remote add 添加一个新的远程Git仓库,同时指定一个你可以轻松引用的简写
git remote show [remote-name] 查看某一个远程仓库的更多信息
git remote rename respA respB 重命名引用的名字
git remote rm respC 移除

git rebase

原理是首先找到这两个分支(即当前分支 experiment、变基操作的目标基底分支 master)的最近共同祖 先 C2,然后对比当前分支相对于该祖先的历次提交,提取相应的修改并存为临时文件,然后将当前分支指向目 标基底 C3, 最后以此将之前另存为临时文件的修改依序应用。
提取在 C4 中引入的补丁和修改,然后在 C3 的基础上应用一次。 在 Git 中,这种操作就叫做变基。你可以使用 rebase 命令将提交到某一分支上的所有修改都移至另一分支上,就好像“重新 播放”一样。

变基的风险

!!不要对在你的仓库外有副本的分支执行变基。

如果你遵循这条金科玉律,就不会出差错。否则,人民群众会仇恨你,你的朋友和家人也会嘲笑你,唾弃你。
变基操作的实质是丢弃一些现有的提交,然后相应地新建一些内容一样但实际上不同的提交。如果你已经将提交推送至某个仓库,而其他人也已经从该仓库拉取提交并进行了后续工作,此时,如果你用 git rebase 命令 重新整理了提交并再次推送,你的同伴因此将不得不再次将他们手头的工作与你的提交进行整合,如果接下来你 还要拉取并整合他们修改过的提交,事情就会变得一团糟。

1
2
git rebase master(target) (:into current)
git rebase master(target) server(into)

常用 git alias

1
git config --global alias.pl pull
  • a => !git add . && git status
  • aa => !git add . && git add -u . && git status
  • ac => !git add . && git commit
  • acm => !git add . && git commit -m
  • alias => !git config –list | grep ‘alias.‘ | sed ‘s/alias.([^=])=(.)/\1\ => \2/‘ | sort
  • au => !git add -u . && git status
  • br => branch
  • c => commit
  • ca => commit –amend
  • ci => commit
  • cm => commit -m
  • co => checkout
  • d => diff
  • l => log –graph –all –pretty=format:’%C(yellow)%h%C(cyan)%d%Creset %s %C(white)- %an, %ar%Creset’
  • last => log -1 HEAD
  • lg => log –color –graph –pretty=format:’%C(bold white)%h%Creset -%C(bold green)%d%Creset %s %C(bold green)(%cr)%Creset %C(bold blue)<%an>%Creset’ –abbrev-commit –date=relative
  • ll => log –stat –abbrev-commit
  • llg => log –color –graph –pretty=format:’%C(bold white)%H %d%Creset%n%s%n%+b%C(bold blue)%an <%ae>%Creset %C(bold green)%cr (%ci)’ –abbrev-commit
  • master => checkout master
  • pl => pull
  • s => status
  • spull => svn rebase
  • spush => svn dcommit
  • st => status
  • unstage => reset HEAD –

参考书籍

progit_v2.1.19

常用布局

面包屑导航(Breadcrumb navigation)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
.breadcrumb ul {
list-style: none;
margin: 0;
padding: 0;
display: flex;
}

.breadcrumb a,
.breadcrumb span {
padding: .5em 1em;
}

.breadcrumb li::before {
content: "→";
}

.breadcrumb li:first-child::before {
content: "";
}
1
2
3
4
5
6
7
8
<nav aria-label="Breadcrumb" class="breadcrumb">
<ul>
<li><a href="">Home</a></li>
<li><a href="">Category</a></li>
<li><a href="">Sub-Category</a></li>
<li><span aria-current="page">Product</span></li>
</ul>
</nav>

居中元素(Center an element)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.container {
border: 2px solid rgb(75, 70, 74);
border-radius: .5em;
height: 200px;
display: flex;
align-items: center;
justify-content: center;
}

.item {
border: 2px solid rgb(95, 97, 110);
border-radius: .5em;
padding: 20px;
width: 10em;
}
1
2
3
<div class="container">
<div class="item">I am centered!</div>
</div>

粘性页脚(Sticky footers)

A sticky footer pattern is one where the footer of your page “sticks” to the bottom of the viewport in cases where the content is shorter than the viewport height.

flex

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.wrapper {
min-height: 100%;
display: flex;
flex-direction: column;
}

.page-header,
.page-footer {
flex-shrink: 0;
}

.page-body {
flex-grow: 1;
}
1
2
3
4
5
6
7
<div class="wrapper">
<header class="page-header">This is the header</header>
<main class="page-body">
<p>Main page content here, add more if you want to see the footer push down.</p>
</main>
<footer class="page-footer">Sticky footer</footer>
</div>

grid

1
2
3
4
5
.wrapper {
min-height: 100%;
display: grid;
grid-template-rows: auto 1fr auto;
}
1
2
3
4
5
6
7
<div class="wrapper">
<header class="page-header">This is the header</header>
<article class="page-body">
<p>Main page content here, add more if you want to see the footer push down.</p>
</article>
<footer class="page-footer">Sticky footer</footer>
</div>

分割导航(Split navigation)

A navigation pattern where some links are visually separated from the others.

1
2
3
4
5
6
7
8
9
10
11
12
13
.main-nav {
display: flex;
margin: 0;
padding: 0;
list-style: none;
}
.main-nav a {
padding: .5em 1em;
display: block;
}
.push {
margin-left: auto;
}

1
2
3
4
5
6
7
8
<nav>
<ul class="main-nav">
<li><a href="">About</a></li>
<li><a href="">Products</a></li>
<li><a href="">Our Team</a></li>
<li class="push"><a href="">Contact</a></li>
</ul>
</nav>

带标识的列表组

In this recipe we will create a list group pattern with badges that indicate a count.Our list items should be displayed with the badges lined up on the right, no matter how much content the item has. The badge should always be centered vertically whether there is a single line of content, or more than one.

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
.list-group {
list-style: none;
margin: 0;
padding: 0;
border: 1px solid #ccc;
border-radius: .5em;
width: 20em;
}
.list-group li {
border-top: 1px solid #ccc;
padding: .5em;
display: flex;
justify-content: space-between;
align-items: center;
}
.list-group li:first-child {
border-top: 0;
}
.list-group .badge {
background-color: rebeccapurple;
color: #fff;
font-weight: bold;
font-size: 80%;
border-radius: 10em;
min-width: 1.5em;
padding: .25em;
text-align: center
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<ul class="list-group">
<li>Item One
<span class="badge">2</span>
</li>
<li>Item Two
<span class="badge">10</span>
</li>
<li>Item Three
<span class="badge">9</span>
</li>
<li>Item Four
<span class="badge">0</span>
</li>
</ul>

分页器(Pagination)

The pagination pattern typically displays items in a row. To ensure that the pagination is understandable by people using a screenreader, we mark the items up as a list inside a <nav> element, and then use CSS to display the layout visually as a row.

Typically, the pagination component will be centered horizontally underneath the content.

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
.visuallyhidden {
border: 0;
clip: rect(0 0 0 0);
height: auto;
margin: 0;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
white-space: nowrap;
}
nav {
display: flex;
justify-content: center;
border-top: 1px solid #eee;
margin-top: 1em;
padding-top: .5em;
}
.pagination {
list-style: none;
margin: 0;
padding: 0;
display: flex;
}
.pagination li {
margin: 0 1px;
}
.pagination a {
display: block;
padding: .5em 1em;
border: 1px solid #999;
border-radius: .2em;
text-decoration: none;
}
.pagination a[aria-current="page"] {
background-color: #333;
color: #fff;
}
1
2
3
4
5
6
7
8
9
10
<nav aria-label="pagination">
<ul class="pagination">
<li><a href=""><span aria-hidden="true">«</span><span class="visuallyhidden">previous set of pages</span></a></li>
<li><a href=""><span class="visuallyhidden">page </span>1</a></li>
<li><a href="" aria-current="page"><span class="visuallyhidden">page </span>2</a></li>
<li><a href=""><span class="visuallyhidden">page </span>3</a></li>
<li><a href=""><span class="visuallyhidden">page </span>4</a></li>
<li><a href=""><span class="visuallyhidden">next set of pages</span><span aria-hidden="true">»</span></a></li>
</ul>
</nav>

卡片布局(Card)

The card component can contain a variety of content, including a heading, image, content and a footer.
Each card should be the same height, and footers should stick to the bottom of the card.
When added to a collection of cards, the cards should line up in two dimensions.

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
img {
max-width: 100%;
}
.cards {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
grid-gap: 20px;
max-width: 800px;
margin: 1em auto;
}
.card {
display: grid;
grid-template-rows: max-content 200px 1fr;
border: 1px solid #999;
border-radius: 3px;
}
.card img {
object-fit: cover;
width: 100%;
height: 100%;
}
.card h2 {
margin: 0;
padding: .5rem;
}
.card .content {
padding: .5rem;
}
.card footer {
background-color: #333;
color: #fff;
padding: .5rem;
}
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
<div class="cards">

<article class="card">
<header>
<h2>A short heading</h2>
</header>
<img src="balloons.jpg" alt="Hot air balloons">
<div class="content">
<p> The idea of reaching the North Pole by means of balloons appears to have been entertained many years ago. </p>
</div>
</article>

<article class="card">
<header>
<h2>A short heading</h2>
</header>
<img src="balloons2.jpg" alt="Hot air balloons">
<div class="content">
<p>Short content.</p>
</div>
<footer>I have a footer!</footer>
</article>

<article class="card">
<header>
<h2>A longer heading in this card</h2>
</header>
<img src="balloons.jpg" alt="Hot air balloons">
<div class="content">
<p>In a curious work, published in Paris in 1863 by Delaville Dedreux, there is a
suggestion for reaching the North Pole by an aerostat.</p>
</div>
<footer>I have a footer!</footer>
</article>

<article class="card">
<header>
<h2>A short heading</h2>
</header>
<img src="balloons2.jpg" alt="Hot air balloons">
<div class="content">
<p> The idea of reaching the North Pole by means of balloons appears to have been entertained many
years ago. </p>
</div>
</article>

</div>

多列布局(Column layouts)

There are a number of design patterns you might want to achieve with your columns:

  • A continuous thread of content broken up into newspaper-style columns.
  • A single row of items arranged as columns, with all heights being equal.
  • Multiple rows of columns lined up by row and column.
1
2
3
4
5
6
7
.container {
border: 2px solid rgb(75, 70, 74);
border-radius: .5em;
padding: 20px;
column-width: 10em;
column-rule: 1px solid rgb(75, 70, 74);
}
1
2
3
4
5
6
7
8
<div class="container">
<p>Veggies es bonus vobis, proinde vos postulo essum magis kohlrabi welsh onion daikon amaranth tatsoi tomatillo
melon azuki bean garlic.</p>
<p>Gumbo beet greens corn soko endive gumbo gourd. Parsley shallot courgette tatsoi pea sprouts fava bean collard
greens dandelion okra wakame tomato. Dandelion cucumber earthnut pea peanut soko zucchini.</p>
<p>Turnip greens yarrow ricebean rutabaga endive cauliflower sea lettuce kohlrabi amaranth water spinach avocado
daikon napa cabbage asparagus winter purslane kale. Celery potato scallion desert raisin horseradish spinach.</p>
</div>

参考文章

CSS Layout cookbook

TCP

TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。

  • 应用层向 TCP 层发送用于网间传输的、用8位字节表示的数据流,然后 TCP 把数据流分区成适当长度的报文段(通常受该计算机连接的网络的数据链路层的最大传输单元(MTU)的限制)。
  • 之后 TCP 把结果包传给 IP 层,由它来通过网络将包传送给接收端实体的 TCP 层。
  • TCP 为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。
  • 接收端实体对已成功收到的包发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。
  • TCP 用一个校验和函数来检验数据是否有错误;在发送和接收时都要计算校验和。

TCP 报文结构

  1. 源端口(Source Port)- 16 位(bit
  2. 目标端口(Destination Port)- 16 位
    源端口号和目的端口号,用来标识同一台计算机的不同的应用进程。TCP 报头中的源端口号和目的端口号同 IP 数据报中的源 IP 与目的 IP 唯一确定一条 TCP 连接。
  3. 序列号(Sequence Number)- 发送数据包中的第一个字节的序列号,32位
    在 TCP 传送的流中,每一个字节一个序号。比如一个报文段的序号为 300,此报文段的数据部分共有 100 字节,则下一个报文段的序号为 400。序号确保了 TCP 传输的有序性。
  4. 确认序列号(Acknowledgment Number)- 32位
    指明下一个期待收到的字节序号,表明该序号之前的所有数据已经正确无误的收到。确认号只有当 ACK 标志为 1 时才有效。
  5. 数据偏移(Data Offset)- 4位,该字段的值是 TCP 首部(包括选项)长度除以4
    首部长度也叫数据偏移,是因为首部长度实际上指示了数据区在报文段中的起始偏移值。
  6. 保留(Reserved):为将来定义新的用途保留,现在一般置 0
  7. 控制标志位 - 6位
  8. 窗口(Window)- 滑动窗口大小,16位
    用来告诉TCP连接对端自己能够接收的最大数据长度。窗口大小最大为 65535。
  9. 校验和(Checksum)- 奇偶校验,16位
    此校验和是对整个的 TCP 报文段,包括 TCP 头部和 TCP 数据,以 16 位字进行计算所得。由发送端计算和存储,并由接收端进行验证。
  10. 紧急指针(Urgent Pointers)- 紧急指针,16位
    只有当 URG 标志置 1 时紧急指针才有效。紧急指针是一个正的偏移量,和顺序号字段中的值相加表示紧急数据最后一个字节的序号。 TCP 的紧急方式是发送端向另一端发送紧急数据的一种方式。
  11. 选项和填充(Options、Padding)
    最常见的可选字段是最长报文大小,又称为 MSS (Maximum Segment Size),每个连接方通常都在通信的第一个报文段 (为建立连接而设置 SYN 标志为 1 的那个段)中指明这个选项,它表示本端所能接受的最大报文段的长度。选项长度不一定是 32 位的整数倍,所以要加填充位,即在这个字段中加入额外的零,以保证 TCP 头是 32 的整数倍。
  12. 数据
控制位 说明
URG 紧急指针标志,为 1 时表示紧急指针有效,为 0 则忽略紧急指针
ACK (Acknowledgement) 确认序号标志,为 1 时表示确认号有效,为 0 表示报文中不含确认信息,忽略确认号字段
PSH push 标志,为 1 表示是带有 push 标志的数据,指示接收方在接收到该报文段以后,应尽快将这个报文段交给应用程序,而不是在缓冲区排队
RST 重置连接标志,用于重置由于主机崩溃或其他原因而出现错误的连接。或者用于拒绝非法的报文段和拒绝连接请求
SYN (Synchronize) 同步序号,用于建立连接过程,在连接请求中,SYN=1 和 ACK=0 表示该数据段没有使用捎带的确认域,而连接应答捎带一个确认,即 SYN=1 和 ACK=1
FIN (Finish) 用于释放连接,为 1 时表示发送方已经没有数据发送了,即关闭本方数据流

TCP 建立连接 (三次握手)

TCP三次握手的过程如下:

  1. 客户端发送 SYN(SEQ=x)报文给服务器端,进入SYN_SEND状态。
  2. 服务器端收到 SYN 报文,回应一个 SYN (SEQ=y)ACK (ACK=x+1)报文,进入 SYN_RECV 状态。
  3. 客户端收到服务器端的 SYN 报文,回应一个 ACK(ACK=y+1)报文,进入 Established 状态。

三次握手完成,TCP 客户端和服务器端成功地建立连接,可以开始传输数据了。

TCP 关闭连接 (四次挥手)

建立一个连接需要三次握手,而终止一个连接要经过四次握手,这是由 TCP 的半关闭(half-close)造成的。

  1. 客户端调用 close() 函数,并发送一个 FIN (finish) 标志为 1 的数据包给服务端,来表示本方的数据已经全部发送完毕,此时客户端进入 FIN_WAIT_1 状态。TCP 规定,FIN 报文段即使不携带数据,也要消耗一个序号。
  2. 服务端收到客户端的释放报文后,发出确认报文,其中 ACK=1, ack=u+1,并且带上自己的序列号 seq=v。表明自己接受到了客户端关闭连接的请求,但还没准备好关闭连接 (半关闭状态),也就是说客户端已经没有数据要发送了,但服务端仍有可能会发送数据。发送完毕后,服务端进入 CLOSE_WAIT 状态。当客户端收到该报文后,客户端就进入 FIN-WAIT-2 状态,等待服务器发送连接释放报文。
  3. 服务器端准备好关闭连接时,会向客户端发送一个连接释放报文,其中 FIN=1,ack=u+1。由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为 seq=w。发送完毕后,服务端便进入 LAST-ACK(最后确认) 状态。
  4. 客户端收到服务器的连接释放报文后,需要发送一个确认包,其中 ACK=1,ack=w+1,而自己的序列号是 seq=u+1,并进入了 TIME-WAIT (时间等待)状态,等待过程可能出现的要求重传的 ACK 包。
    此时 TCP 连接还没有释放,必须经过 2 * MSL (Maximum Segment Lifetime, 最长报文段寿命) 时间后,当客户端撤销相应的 TCB 后,才会进入 CLOSED 状态。
    而服务器只要收到了客户端发出的确认,立即进入 CLOSED 状态。同样,撤销 TCB 后,就结束了这次的 TCP 连接。

TCPUDP 的对比

UDP TCP
是否连接 无连接 面向连接
是否可靠 不可靠传输,不使用流量控制和拥塞控制 可靠传输,使用流量控制和拥塞控制
连接对象个数 支持一对一,一对多,多对一和多对多交互通信 只能是一对一通信
传输方式 面向报文 面向字节流
首部开销 首部开销小,仅 8 字节 首部最小 20 字节,最大 60 字节
适用场景 适用于实时应用 (IP 电话、视频会议、直播等) 适用于要求可靠传输的应用,例如文件传输

参考文章

[HTTP 系列] 第 1 篇 —— 从 TCP/UDP 到 DNS 解析