From 429bde367a70e2bc52f83c31db4d3d8546ba84c7 Mon Sep 17 00:00:00 2001 From: leafee98 Date: Thu, 28 Apr 2022 14:40:02 +0800 Subject: [PATCH] initial commit --- .gitignore | 3 + .gitmodules | 3 + archetypes/default.md | 9 + config.toml | 74 +++++ content/about.md | 29 ++ content/posts/KVM安装.md | 56 ++++ content/posts/Linux文件系统中的权限.md | 167 ++++++++++ content/posts/Linux服务----systemd.unit.md | 53 +++ content/posts/Linux计划任务----crontab.md | 77 +++++ content/posts/nginx配置webdav.md | 156 +++++++++ content/posts/shell学习笔记.md | 163 +++++++++ content/posts/vsftp常用配置和踩坑.md | 234 +++++++++++++ content/posts/webdav的挂载.md | 74 +++++ .../为单一命令设置代理环境变量的终端函数.md | 94 ++++++ .../树莓派Arch Base系统无头配置wifi连接.md | 203 ++++++++++++ content/posts/正则表达式随笔.md | 111 +++++++ content/posts/科一知识点总结.md | 257 +++++++++++++++ content/posts/科四知识点总结.md | 312 ++++++++++++++++++ content/posts/迁移到wayland事记.md | 48 +++ content/posts/部署davical到apache2.md | 179 ++++++++++ themes/hugo-theme-flat | 1 + 21 files changed, 2303 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 archetypes/default.md create mode 100644 config.toml create mode 100644 content/about.md create mode 100644 content/posts/KVM安装.md create mode 100644 content/posts/Linux文件系统中的权限.md create mode 100644 content/posts/Linux服务----systemd.unit.md create mode 100644 content/posts/Linux计划任务----crontab.md create mode 100644 content/posts/nginx配置webdav.md create mode 100644 content/posts/shell学习笔记.md create mode 100644 content/posts/vsftp常用配置和踩坑.md create mode 100644 content/posts/webdav的挂载.md create mode 100644 content/posts/为单一命令设置代理环境变量的终端函数.md create mode 100644 content/posts/树莓派Arch Base系统无头配置wifi连接.md create mode 100644 content/posts/正则表达式随笔.md create mode 100644 content/posts/科一知识点总结.md create mode 100644 content/posts/科四知识点总结.md create mode 100644 content/posts/迁移到wayland事记.md create mode 100644 content/posts/部署davical到apache2.md create mode 160000 themes/hugo-theme-flat diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1c3fa73 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +public/ +resources/ +.hugo_build.lock diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..863c906 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "themes/hugo-theme-flat"] + path = themes/hugo-theme-flat + url = git@leafee98.com:pub/hugo-theme-flat.git diff --git a/archetypes/default.md b/archetypes/default.md new file mode 100644 index 0000000..8882e0b --- /dev/null +++ b/archetypes/default.md @@ -0,0 +1,9 @@ +--- +title: "{{ replace .Name "-" " " | title }}" +date: {{ .Date }} +tags: [] +categories: [] +draft: true +--- + + diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..fe1f87a --- /dev/null +++ b/config.toml @@ -0,0 +1,74 @@ +title = "Leafee98's Blog" +theme = "hugo-theme-flat" +hasCJKLanguage = true +paginate = 6 +baseURL = "https://leafee98.com/" + +# these values are hugo built in markup config +[markup.highlight] +anchorLineNos = false +codeFences = true +guessSyntax = false +hl_Lines = '' +lineAnchors = '' +lineNoStart = 1 +lineNos = false +lineNumbersInTable = false +noClasses = false +noHl = false +style = 'monokailight' +tabWidth = 4 + +[params.remark42] +host='https://remark42.leafee98.com' +site_id='leafee98.com' +max_shown_comments=100 +theme='light' +locale='en' +show_email_subscription=false +simple_view=true + +# you can set multi row of footers like these +[[params.footer_rows]] +[[params.footer_rows.items]] +name = "Leafee98 on github" +url = "https://github.com/leafee98" +pre = "Leafee98 on GitHub" + +[[params.footer_rows]] +[[params.footer_rows.items]] +name = "Creative Commons Attribution 4.0 International" +url = "https://creativecommons.org/licenses/by/4.0/" +pre = "Copyright CC BY-4.0" + +[[params.footer_rows]] +[[params.footer_rows.items]] +name = "Hugo" +url = "https://gohugo.io" +pre = "Powered by Hugo" +[[params.footer_rows.items]] +name = "theme flat" +url = "https://cgit.leafee98.com/hugo-theme-flat" +pre = "Theme hugo-theme-flat" + + +[[menus.main]] +name = "Archives" +url = "/posts/" +weight = 30 +[[menus.main]] +pageref = "about" +name = "About" +weight = 80 + +[[menus.main]] +name = "Services" +weight = 60 +[[menus.main]] +parent = "Services" +name = "Cgit" +url = "https://cgit.leafee98.com/" +[[menus.main]] +parent = "Services" +name = "PrivateBin" +url = "https://leafee98.com/privatebin/" diff --git a/content/about.md b/content/about.md new file mode 100644 index 0000000..6b6b5e3 --- /dev/null +++ b/content/about.md @@ -0,0 +1,29 @@ +--- +title: "About" +date: 2021-01-04T11:36:10+08:00 +draft: false +--- + +这里只是一个平平无奇的博客,记录本人在玩乐途中学到的新知识,以及一些为避免遗忘而记录下以供自己和他人查阅的小文本。 + +## 小站的结构 + +这里有两种对内容进行分类的方法,一是目录(categories),二是标签(tags),但在 Hugo 中这两个东西其实都是标记一类的东西,一篇文章可以对应零或多个 categories 和 tags,所以所有的 categories 中包含的文章的总数可能会大于或小于实际文章的个数,这个可能会在未来整理一下,使之更加符合一般对 categories 的直觉。 + +## 小站的迁移 + +博客原来存放在 [git page](https://leafee98.github.io),后来迁移到了 wordpress,受益于其内容管理和评论以及搜索功能良久,不过苦于 spam 和数据库对服务器的性能消耗,现在迁移回到了静态博客,并搭配了 remark42 作为评论系统,而且仿照原来在 wordpress 上的主题重新写了一份 Hugo 的主题,总之最后终于算是完成了。 + +## 使用 RSS 订阅源 + +RSS 是好的,封闭的平台是坏的,RSS 可以在不使用封闭的平台的情况下实现对内容的追更,无论是不是在本站,我都建议使用 RSS 或类似服务。 + +本站的 RSS 链接是 `https://leafee98.com/index.xml` ,本站主题尚在早期,尚未将 RSS 添加到网页布局中,未来将进行修缮,RSS 链接或许也会有变,还望谅解。 + +## 小站的其他服务 + +也许你已经发现了,小站除了作为一个平平无奇的博客站点之外,也会有一些奇怪的服务,诸如 PrivateBin、Plik 之类的,这些你都可以在主页的 Services 下拉菜单中找到,欢迎合理使用。 + +## 知识共享许可协议 + +在没有特殊声明的情况下, 博客内容遵循 [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) 协议. diff --git a/content/posts/KVM安装.md b/content/posts/KVM安装.md new file mode 100644 index 0000000..5458f81 --- /dev/null +++ b/content/posts/KVM安装.md @@ -0,0 +1,56 @@ +--- +title: "KVM安装" +date: 2020-02-29T15:12:41+08:00 +tags: [linux, KVM] +draft: false +--- + +> 本篇总结自[how-to-install-virtual-machine-manager-kvm-in-manjaro-and-arch-linux](https://www.fosslinux.com/2484/how-to-install-virtual-machine-manager-kvm-in-manjaro-and-arch-linux.htm). + +## 检查硬件支持 + +``` +LC_ALL=C lscpu | grep Virtualization +``` + +以上语句应当得到`Virtualization: VT-x`或者`Virtualization: AMD-V`的结果, 否则硬件不支持, 请前往BIOS设置虚拟化选项. + +## 检查内核支持 + +运行`zgrep CONFIG_KVM /proc/config.gz`, 得到的结果应该是`CONFIG_KVM_INTEL`或者`CONFIG_KVM_AMD`的值为`m`或`y`. 以下是样例输出. + +``` +CONFIG_KVM_GUEST=y +# CONFIG_KVM_DEBUG_FS is not set +CONFIG_KVM_MMIO=y +CONFIG_KVM_ASYNC_PF=y +CONFIG_KVM_VFIO=y +CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y +CONFIG_KVM_COMPAT=y +CONFIG_KVM=m +CONFIG_KVM_INTEL=m +CONFIG_KVM_AMD=m +CONFIG_KVM_MMU_AUDIT=y +``` + +## 安装KVM(虚拟机管理器) + +**第一步**: 运行以下命令来安装KVM和一些依赖 + +``` +sudo pacman -S virt-manager qemu vde2 ebtables dnsmasq bridge-utils openbsd-netcat +``` + +注意以下两步要完成, 如果此时直接运行虚拟机管理器, 会得到`adduser: The group 'libvirtd’ does not exist`的错误. + +**第二步**: 启用`libvirtd`服务 + +``` +sudo systemctl enable libvirtd.service +``` + +**第三步**: 启动`libvirtd`服务 + +``` +sudo systemctl start libvirtd.service +``` \ No newline at end of file diff --git a/content/posts/Linux文件系统中的权限.md b/content/posts/Linux文件系统中的权限.md new file mode 100644 index 0000000..fdbae0d --- /dev/null +++ b/content/posts/Linux文件系统中的权限.md @@ -0,0 +1,167 @@ +--- +title: "Linux 文件系统中的权限" +date: 2021-09-29T22:01:00+08:00 +tags: [linux, permission, file system] +draft: false +--- + +## 常规权限 + +### 读权限(r) + +- 对文件来说, 就是文件的读取权限, 如 `cat` . +- 对目录来说, 就是查询目录下文件结构的权限, 如 `ls` . + +### 写权限(w) + +- 对文件来说, 就是文件的写入权限, 如重定向输出到这个文件. +- 对目录来说, 就是修改此目录下的文件结构的权限, 包括创建文件/删除文件/移动文件. + +### 执行权限(x) + +- 对文件来说, 就是文件的执行权限. +- 对于目录来说, 就是进入此目录的权限, 并控制访问此目录中的其他文件或目录的权限, **若无此权限, 则目录的读写权限也会受到影响**. + +下面为一些各种情况下进行操作的示例. 可以发现没有 x 权限时, r 权限只能列出目录的文件名称, 不能得知其权限和修改时间等信息; w 权限无法在目录中创建文件; 无法对目录中的文件的内容进行读取或修改. + +仅有 x 权限时, 不能读取目录内文件的名称, 不能在目录中创建或删除文件, 但是可以获取文件的权限信息, 可以修改目录中其他文件的内容. + +``` +$ ls -l +dr-------- 2 leafee98 leafee 4096 Sep 29 20:57 dir + +$ ls -l dir +ls: cannot access 'dir/a': Permission denied +-????????? ? ? ? ? ? a + +...... +...... + +$ ls -l +d-w------- 2 leafee98 leafee 4096 Sep 29 20:57 dir + +$ touch dir/b +touch: cannot touch 'dir/b': Permission denied + +...... +...... + +$ ls -l +drw------- 2 leafee98 leafee 4096 Sep 29 20:57 dir + +$ echo "nya~" > dir/a +zsh: permission denied: dir/a + +$ cat dir/a +cat: dir/a: Permission denied + +...... +...... + +$ ls -l +d--x------ 2 leafee98 leafee 4096 Sep 29 20:57 dir + +$ ls -l dir +ls: cannot open directory 'dir': Permission denied + +$ echo "miao~" > dir/a ; cat dir/a +miao~ + +$ rm dir/a +rm: cannot remove 'dir/a': Permission denied + +$ touch dir/z +touch: cannot touch 'dir/z': Permission denied + +$ ls -l dir/a +-rw-r--r-- 1 leafee98 leafee 6 Sep 29 21:18 dir/a +``` + +## 特殊权限 + +### 用户特殊权限(SUID user+s) + +- 标记到文件(file)时, 此文件在运行时, 会以文件属主的身份运行. +- 标记到目录(directory)时, 不会有其他的作用. + +如命令 `sudo` 就是属主为 root 的添加 SUID 标记的可执行文件. + +``` +$ ls -l /usr/bin/sudo +-rwsr-xr-x 1 root root 223536 Sep 22 14:19 /usr/bin/sudo +``` + +### 组特殊权限(SGID group+s) + +- 标记到文件时, 文件在运行时会以文件属组的身份运行. +- 标记到目录, 所有在此目录下创建的文件, 其属组均会变为该目录的属组. (移动文件至此目录下属组不会改变) + +``` +$ sudo chmod g+s dir ; ls -l +drwsrwsrwx 2 mail daemon 4096 Sep 29 21:40 dir + +$ touch file ; mv file dir/ + +$ touch dir/file2 + +$ ls -l dir +-rw-r--r-- 1 leafee98 leafee 0 Sep 29 21:35 file +-rw-r--r-- 1 leafee98 daemon 0 Sep 29 21:35 file2 +``` + +### 沾滞位(STICKY other+t) + +- 标记到文件时, 不会产生任何效果. +- 标记到目录时, 对于此目录下的所有文件, 将仅有这些文件的属主分别对其有删除权限. + +``` +$ sudo chmod o+t dir ; ls -l +drwxrwxrwt 2 mail daemon 4096 Sep 29 21:38 dir + +$ touch file1 file2 ; sudo chown mail file2 ; ls -l +-rw-r--r-- 1 leafee98 daemon 0 Sep 29 21:38 file1 +-rw-r--r-- 1 mail daemon 0 Sep 29 21:38 file2 + +$ rm file1 file2 ; ls -l +rm: cannot remove 'file2': Operation not permitted +-rw-r--r-- 1 mail leafee 0 Sep 29 21:38 file2 +``` + +## 在命令中使用 + +### chmod 中的标记 + +常规权限的 r 为 4, w 为 2, x 为 1. 且分别对应属主(或称为用户 user), 属组(group), 其他(other). + +``` +$ chmod o+w file +$ chmod g-x file +$ chmod 755 file +``` + +特殊权限的 SUID 为 4, SGID 为 2, STICKY 为 1, 且数字表示权限时不与常规权限同时计算. + +``` +$ chmod u+s file +$ chmod g-s file +$ chmod o+t file +$ chmod 6755 file +``` + +### ls 命令中的标记 + +特殊权限在 ls 命令的输出中会占据常规权限 x 的位置, 如果原来文件或目录已经具有 x 权限, 则新添加的 SUID, SGID, STICKY 会以小写字母 s 或 t 占在相应位置. 如果原来文件或目录不具有 x 权限, 则出现在相应位置的字母会是大写形式. + +``` +$ sudo chmod 7777 dir ; ls -l +drwsrwsrwt 2 mail daemon 4096 Sep 29 21:40 dir + +$ sudo chmod 7666 dir ; ls -l +drwSrwSrwT 2 mail daemon 4096 Sep 29 21:40 dir +``` + +## 参考 + +1. https://www.redhat.com/sysadmin/suid-sgid-sticky-bit +2. https://superuser.com/questions/471844/why-is-setuid-ignored-on-directories +4. https://unix.stackexchange.com/questions/21251/execute-vs-read-bit-how-do-directory-permissions-in-linux-work/21252#21252 diff --git a/content/posts/Linux服务----systemd.unit.md b/content/posts/Linux服务----systemd.unit.md new file mode 100644 index 0000000..be362f9 --- /dev/null +++ b/content/posts/Linux服务----systemd.unit.md @@ -0,0 +1,53 @@ +--- +title: Linux服务 -- systemd.unit +date: 2019-09-14 04:09:45 +0800 +layout: post +categories: [ tech ] +tags: [ linux, systemctl ] + +--- + + +## 概括 + +通过``systemctl``命令可以对服务进行一些基本操作, 包括启动,停止,重启等, 而这条命令操作的服务的位置就在``/etc/systemd/system``目录下, 如果想要我们想要创建一个自己的服务用于开机自动运行, 只需要在这个目录下创建一个名为``{your service name}.service``的文本文件即可, 最简单的服务只需要在文件内写出``[Service]``部分中的``ExecStart``即可运行服务. + +## Linux服务 + +Linux服务一般通过``systemctl``进行管理, 诸如``systemctl start {service name}``启动某服务, 优点就是十分统一, 并且使得各种各样的服务有条理地运行, 不至于发生一个服务明明需要另一个服务的功能, 却在另一个服务运行之前启动, 造成启动失败或者异常. + +``systemctl status {service name}``可以查看服务的状态, 同时会显示出服务最近的几行日志, 如果需要查看更多的日志, 可以使用``journalctl -u {service name}``, 其中``-u``参数是指定unit + +## service文件 + +常用的部分有三个:``Unit``, ``Service``, ``Install`` + +#### Unit + +``Unit``部分是``systemctl``管理的众多模块的通用配置的部分, 这一部分可以写``Description``, ``After``等. ``Description``就是描述, 在``status``作为参数的时候可以在状态的部分看到这里写的描述; ``After``就是指定服务启动的顺序, ``systemd``会读取所有模块(Unit), 根据``Before``,``After``,``Require``等参数构造出一个不会对任何模块造成冲突的启动顺序, 然后依次启动服务, 对于``Require``等参数在前置服务启动失败时还可以指定特殊的行为 + +#### Service + +这一部分就是服务的主体部分, 最最最重要的就是``ExecStart``参数, 即启动服务时运行的命令, 其他的诸如``ExecStop``,``ExecReload``等就是停止和启动服务时运行的命令. + +另一个比较重要的参数就是``User``, 这个参数表示以特定用户的身份启动服务. + +#### Install + +这一部分是在服务需要开机启动时必须的项, 使用``systemctl enable {service name}`` 可以使服务在开机时启动, 其实也就是在特定目录下创建一个指向服务文件的软链接 + +## 示例 + +``` +[Unit] +Description=syncthing service for leafee98 +After=network.target + +[Service] +User=leafee98 +ExecStart=/usr/bin/syncthing -no-browser -gui-address=0.0.0.0:8384 -home=/mnt/leafee98/syncthing/syncHome/ + +[Install] +WantedBy=multi-user.target +``` + diff --git a/content/posts/Linux计划任务----crontab.md b/content/posts/Linux计划任务----crontab.md new file mode 100644 index 0000000..e478e7c --- /dev/null +++ b/content/posts/Linux计划任务----crontab.md @@ -0,0 +1,77 @@ +--- +title: Linux计划任务 -- crontab +layout: post +tags: [ linux, crontab ] +categories: [ tech ] +date: 2019-09-17 11:04:15 +0800 +--- + + +## 使用语法 + +crontab 的每行命令有5个日期时间部分,5个部分之间使用space或tab分隔,后面接着需要执行的命令 + +#### 时间日期部分 + +这一部分语法如下,但是如果不准备深入了解,可以在[crontab guru](crontab.guru)来简单地配置需要的时间 + +```shell +mm hh DD MM dd {command} +# mm : minute (0-59) +# hh : hour (0-23) +# DD : day of month (1-31) +# MM : month (1-12)(or use name) +# dd : day of week (0-7)(0 or 7 is sunday)(or use name) +``` + +- 每一个日期时间的部分都可以使用范围表示``0 0 1 1 1-4``即``0分 0时 1日 1月 周1至周4`` +- 使用星号表示该区域的值可以为任意值``0 0 1 * *``即``0分 0时 1日 任意月 一周内任意天`` +- 使用逗号可以并列多个允许时间``0 0 * * 1,5``表示``0分 0时 0 任意日 任意月 周一和周五`` +- 使用斜杠可以设定步长``* */2 * * *``表示``每两个小时``,``1-7/2``表示``1,3,5,7`` +- 月和周可以使用英文名称,但是列表(逗号分隔)和范围(短横线)将会不再可用 + + +#### 时间的另一种表示 + +除使用5段字符来描述运行的时间外,还可以使用内置的8个字符串来代替这5段字符,这8个字符串中只有`@reboot`是无法用5段字符描述,并且它指示的时间是守护进程`cron`启动的时间,所以具体的启动时机与系统的启动顺序有关 + +```shell +@reboot -- run once, at startup +@yearly -- run once a year '0 0 1 1 *' +@annually -- (same as @yearly) +@monthly -- run once a month '0 0 1 * *' +@weekly -- run once a week '0 0 * * 0' +@daily -- run once a day '0 0 * * *' +@midnight -- (same as @daily) +@hourly -- run once an hour '0 * * * *' +``` + +#### 命令部分 + +- 百分号后的字符会以标准输入的方式输入给命令,除非使用反斜杠escape +- 结尾使用反斜杠**不可以**将命令另起一行而不打断命令 + + +## 注意事项 + +#### 环境变量 + +设定环境变量只需要使用`key = value`即可,每一条环境变量的赋值命令都需要另起一行,等号两边的空格是可选的,其中的`value`可选被引号包括,单双引号均可但必须匹配,设定空值时必须使用引号 + +这些环境变量可以在命令部分使用,但是环境变量时,使用美元符号引用之前的变量的用法将失效,如以下的命令将不再以期望的方式运行 + +```shell +a = 1 +b = 2 +c = $a $b +``` +crontab的环境变量与普通shell环境有所不同,它采用的shell是`/bin/sh`, 并且`path=/usr/bin:/bin`,修改默认shell和mailto的示例如下 + +``` +SHELL = /bin/bash +MAILTO = paul +``` + +#### 时区 + +cron的时间与当前时区有关,然而由于时区不能由各用户自定义,所以整个系统的cron只能按照统一的一个时区来工作 diff --git a/content/posts/nginx配置webdav.md b/content/posts/nginx配置webdav.md new file mode 100644 index 0000000..83dcace --- /dev/null +++ b/content/posts/nginx配置webdav.md @@ -0,0 +1,156 @@ +--- +title: "Nginx配置webdav" +date: 2020-03-24T23:26:53+08:00 +tags: [ linux, nginx ] +draft: false +--- + +> 本质上, webdav就是从http拓展了几条指令, 从而可以用来管理文件系统或进行文件分享. + +## 目录 + +1. 重新编译nginx +2. webdav配置 +3. 认证权限 +4. SSL权限 + +## 重新编译nginx + +原本nginx配置webdav很简单, 只要在配置文件中加入关于[这个模块](http://nginx.org/en/docs/http/ngx_http_dav_module.html)的配置就好了, 可惜官方文档中轻描淡写说了下面一句话, 然后webdav的`PROPFIND,OPTIONS,LOCK,UNLOCK`几条命令就不被支持了, 于是就需要给nginx加入新的module. + +> WebDAV clients that require additional WebDAV methods to operate will not work with this module. + +其实说是要重新编译nginx, 还是因为nginx高性能的定位, 使其不允许动态加载插件, 所以需要拿到插件源码, 配合nginx源码重新编译来达到增加插件的目的. + +### 准备 + +先去克隆这个[arut/nginx-dav-ext-module](https://github.com/arut/nginx-dav-ext-module)这个仓库, 此仓库就是为nginx提供原module所缺失的wendav请求支持. + +然后去[nginx官网](http://nginx.org/en/download.html)下载nginx的源码. 两个源码都放在一个比较方便操作的位置就好, 以下都假设放到了家目录下. + +#### 编译 + +在编译之前, 首先需要了解nginx有一个参数是`-V`, 这个参数可以打印nginx的一些编译信息, 包括在configure步骤的参数, 如果已经现有一个可用的nginx, 只是希望替换原来的二进制程序, 保证编译后的程序和自身发行版的nginx行为尽可能相同, 则可以把此参数打印的configre参数全部复制一下. + +进入nginx源码目录, 运行目录下的`configure`, 附上刚刚拿到的参数, 最后再加上一个`--add-module`的参数, 指向'arut/nginx-dav-ext-module'仓库的目录, 如下: + +``` +./configure --add-module=../nginx-dav-ext-module/ +``` + +如果在配置过程中, 提示缺少某些依赖, 通过自己的包安装器安装即可, 也可以在参数中去掉产生错误的不必要的module. + +此时目录下应该出现`Makefile`文件, 这时使用`make`命令即可开始编译 + +``` +make +``` + +经过取决于机器性能的编译时间以后, `objs`目录下应该已经有各种编译结果了, 可以直接在源码目录以root身份执行`make install`安装, 也可以直接将`objs`目录下的二进制可执行文件覆盖掉原来的`nginx`可执行文件. + +## webdav配置 + +nginx的配置文件中, 每一个配置项都有自己的上下文结构, 比如`location`要在`server`或`location`里面, 在官方文档中, 如果`context`有逗号分隔, 即表示此配置可以写在多种上下文结构中. 如果某配置项直接下载文件的最外层, 那么称此配置项处于`main`上下文中. + +简单来说, 只要在从最外层到内层, 依次配置好`http`,`server`,`location`即可. 换句话说, 只要在http server中加上`dav_ext_lock_zone`, `dav_ext_lock`, `dav_access`, `dav_methods`, `dav_ext_methods`五项配置即可. + +- `dav_methods` 启用的webdav方法 +- `dav_ext_methods` 额外的不被原本webdav模块支持的方法 +- `dav_access` 新创建文件的访问权限 +- `dav_ext_lock_zone` 定义一个共享的锁空间 +- `dav_ext_lock` 启用锁, 并依赖于定义的锁空间 + +``` +http { + include mime.types; + default_type application/octet-stream; + + gzip on; + sendfile on; + + dav_ext_lock_zone zone=webdav_lock_zone:4m; + server { + listen 80; + server_name localhost; + + dav_access user:rw group:r all:r; + dav_methods PUT DELETE MKCOL COPY MOVE; + dav_ext_methods PROPFIND OPTIONS; + dav_ext_lock zone=webdav_lock_zone; + + location / { + root /srv/webdav/; + + create_full_put_path on; + client_body_temp_path /srv/webdav/temp_upload; + } + } +} +``` + +## 认证权限 + +身份认证基于nginx的官方模块`ngx_http_auth_basic_module`, 有`auth_basic`和`auth_basic_user_file`两个选项, 并且通用于`http`, `server`, `location`下. + +- `auth_basic` 是给客户端的请求认证的提示的字符串 +- `auth_basic_user_file` 则是指定依赖的认证文件 + +认证文件可以由Apache httpd的`htpasswd`命令生成, 也可是以如下格式 + +``` +user1:password1:comment1 +user2:password2:comment2 +``` + +## SSL加密 + +此功能依赖于官方`ngx_http_ssl_module`模块. 不求甚解可以直接把默认配置里面对https服务器的SSL部分拿过来, 同时确保`ssl_certificate`和`ssl_certificate_key`两个选项指向合法的对应文件即可. 此外要求监听端口附加`ssl`声明, 如`listen 443 ssl`, 此外同一个`server`可以同时监听SSL和无加密端口. + +证书和密钥可以自己生成一个不被其他人认可的, 也可以从域名服务商处或其他CA获取被认可的. + +## 样例 + +``` +http { + include mime.types; + default_type application/octet-stream; + + gzip on; + sendfile on; + + dav_ext_lock_zone zone=webdav_lock_zone:4m; + server { + listen 80; + listen 443 default_server ssl; + server_name localhost; + + access_log /var/log/nginx/webdav/access.log; + + ssl_certificate /etc/ssl/certs/certificate.pem; + ssl_certificate_key /etc/ssl/private/certificate.key; + ssl_session_cache shared:SSL:1m; + ssl_session_timeout 5m; + ssl_ciphers HIGH:!aNULL:!MD5; + ssl_prefer_server_ciphers on; + + dav_access user:rw group:r all:r; + dav_methods PUT DELETE MKCOL COPY MOVE; + dav_ext_methods PROPFIND OPTIONS; + dav_ext_lock zone=webdav_lock_zone; + + location / { + root /srv/webdav/; + + # enable creating directories without trailing slash + if (-d $request_filename) { rewrite ^(.*[^/])$ $1/ break; } + if ($request_method = MKCOL) { rewrite ^(.*[^/])$ $1/ break; } + + auth_basic "Auth of webdav"; + auth_basic_user_file /srv/webdav/.htpasswd; + + create_full_put_path on; + client_body_temp_path /srv/webdav/temp_upload; + } + } +} +``` diff --git a/content/posts/shell学习笔记.md b/content/posts/shell学习笔记.md new file mode 100644 index 0000000..e87b486 --- /dev/null +++ b/content/posts/shell学习笔记.md @@ -0,0 +1,163 @@ +--- +title: shell学习笔记 +date: 2019-07-20 15:46:09 +0800 +layout: post +categories: [ tech ] +tags: [ linux ] +--- + +### 关于符号 + +* `$` 美元符号, 一般用于取变量的值, 不过总觉得和命令代换有很多相似之处, 具体可见样例, 另外美元符号也会和其他符号产生有意思的组合. + + ```shell + $ var="echo hello" + $ $var + hello + ``` + +* `[]` 相当于test命令, 用于测试条件是否成立, 若成立则退出值为0(真), 由于if, for, case等结构语句通过上一条命令的退出值来决定运行流程, 因此方括号多用于这些结构语句中. + +* `$()` , `` ` ` `` 两种用法相同, 均是命令代换, 即取所包含的命令的输出作为文本值参与运行, 文本值甚至可以是命令, 如直接运行`` `echo pwd` ``则相当于直接运行`pwd`. + +* `$[]` 对于此命令需要提前了解双反引号(上一条), 以及`expr`命令, `expr`官方描述为*Print the value of EXPRESSION to standard output*, 所以可以把`expr`命令做命令代换, 于是`$[]`与`` `expr expression` ``效果相同, 样例如下. + + ```shell + $ var1=`expr 1 + 1` + $ var2=$[1 + 1] + $ echo var1=$var1 var2=$var2 + var1=2 var2=2 + ``` + + 不过有一点奇怪的是, 以下命令的运行结果并不能如我所愿输出`hello`, 不过至少反引号和美元符号加方括号的行为是一样的, 仍然支持我的猜想. + + ```shell + $ alias 2="echo hello" + $ alias + alias 2='echo hello' + $ `expr 1 + 1` + bash: 2: command not found + $ $[1 + 1] + bash: 2: command not found + ``` + +* `;` 可用于分隔命令, 书本上翻译为命令列表, 一般来说, 命令与命令之间通过换行符来进行分隔, 但是有时为了追求代码的紧凑会希望将几条命令放在同一行, 于是这便是分号的用途. + + ```shell + if [ expression ] ; then + command + fi + ``` + +* `()` 用于表示数组, 数组样例见下一个符号的样例, 也用于进程列表, 进程列表中的命令会被开一个子shell运行, 进程列表样例如下. + + ```shell + $ echo $BASH_SUBSHELL # 当前子shell水平为0 + 0 + $ (echo $BASH_SUBSHELL) # 当前子shell水平为0 + 1 + ``` + + 那么之前的命令代换中的括号是否也会被开一个子shell呢, + + ```shell + $ echo $BASH_SUBSHELL # 当前子shell水平为0 + 0 + $ echo $(echo $BASH_SUBSHELL) # 命令代换中子shell水平为1 + 1 + ``` + + 猜想得证. + +* `${}` 此符号用于取数组的值, 需要注意的一点是, 当数组中某一个位置的值被`unset`之后, 该位置后面的值并不会自动向前移动一个序号, 可见样例. + + ```shell + $ arr=( 1 2 3 ) + $ echo ${arr[2]} + 3 + $ unset arr[1] + $ echo ${arr[2]} + 3 + $ echo ${arr[1]} + #空行, 无输出 + $ + ``` + +* `[[ ]]` `(( ))` 双方括号是拓展字符运算, 双圆括号是拓展数学运算, 其中拓展数学运算可支持移位操作,自增操作等高级操作, 拓展字符运算可支持通配符匹配. + +* `;;` 双分号用于case的匹配中, 与单分号不同的是, 单分号只能结束当前命令, 后续仍被认为是这一块的可执行语句, 不能接下一个匹配条件, 只有以双分号结尾, 才能接下一个匹配 + + ```shell + $ cat caseExample.sh + var=2 + case $var in + 1 | 2 ) + echo 1 ; + echo 2 ;; + 3 | 4 ) + echo 3 ; + echo 4 ;; + esac + $ ./caseExample.sh + 1 + 2 + $ + ``` + +### 关于结构化语句 + +* `if` 判断语句 + + * 判断的方法只是简单地根据上一命令的返回值来判断执行结构, 关于这一点, 其实最常用的方括号只是`test`命令, 这一点在上面符号的部分有提及. 通常用法是 + + ```shell + if command1 ; then + command2 + fi + ``` + + 以上用法中, `command1`是任意一个可执行的shell命令, `command2`是条件为真则执行的语句体, 最后`if`语句使用`fi`进行结尾. 需要注意的是, **`command1`的返回值若是`0`则`if`判断为真, 非`0`则判断为假**, 这一点与许多类C语言恰恰相反. 另外, `command1`是按照通常的命令执行方式执行的, 所以如果`command1`命令有输出, 则会直接输出在控制台中. + + * `if`语句也可以在条件为假的时候执行语句, 方法是在结尾`fi`之前加入一个`else`; 当然`if`也可以判断多个条件进行筛选, 方法是使用`elfi`, 样例如下 + + ```shell + if command1 ; then + command2 + elif command3 ; then + command4 + else + command5 + fi + ``` + + 为了代码紧凑, 有时候会在判断命令之后使用分号进行分隔, 并把`then`放在同一行的之后 + + * ​ `if`语句中也可以使用逻辑运算符, 和其他许多类C语言类似, 使用`&&`, `||`, `!`, 分别作为与,或,非. 这些逻辑运算符可以用在`test`命令和普通命令之中. 需要注意的是, 在`test`手册中并没有`&&`,`||`的表述, 不过这些仍然被支持, 因为在shell中, `&&`的行为是若该符号之前的命令运行的返回值为**真**, 则执行下一条命令, `||`的行为是若该符号之前的命令运行返回值为**假**, 则执行下一条命令, 这个被称为"短路", 在C语言中同样适用. + ​ 所以如此来看的话, 使用`command1 && command2`的作为分析, 如果`command1`返回值为真, 则执行`command2`, 此时整个逻辑表达式的值就由`command2`的返回值决定, 若`command2`的返回值也为真, 则最后`$?`的值就是真, 反之则假. 若`command1`返回值为假, 则短路, 最终整个逻辑运算的结果就是`command1`的返回值--假. 原因是逻辑运算符的作用仅仅是决定是否进行短路, 而且条件判断依据仅仅是之前运行的最后一条命令的返回值, 于是整个逻辑运算十分顺利. 或运算同理. + ​ 至于非运算, 叹号`!`其实也是一条命令, 这一点可以在终端不输入任何字符的情况下敲入双tab, 使其打印所有的可执行命令, 其中第一条就是`!`. 样例如下 + + ```shell + $ ! echo 'hello' && echo 'true' ; echo $? + hello + 1 + $ echo 'hello' && echo 'true' ; echo $? + hello + true + 0 + $ ! echo 'hello' || echo 'true' ; echo $? + 'hello' + 'true' + 0 + ``` + +## 特殊变量 + +| 变量 | 含义 | +| ---- | ------------------------------------------------- | +| $$ | 当前shell进程的PID | +| $? | 上一命令运行的返回值 | +| $# | 命令行脚本传递参数的个数 | +| $@ | 作为数组(雾)获取全部命令行参数 | +| $* | 作为一整条字符串获取全部命令行参数 | +| $0 | 当前shell脚本的运行名(脚本的绝对路径或者相对路径) | +| $n | shell脚本的第n个参数 | diff --git a/content/posts/vsftp常用配置和踩坑.md b/content/posts/vsftp常用配置和踩坑.md new file mode 100644 index 0000000..f3d8dca --- /dev/null +++ b/content/posts/vsftp常用配置和踩坑.md @@ -0,0 +1,234 @@ +--- +title: vsftp 配置,踩坑和一些理解 +date: 2019-10-01 20:53:00 +0800 +layout: post +categories: [ tech ] +tags: [ linux, vsftp ] +--- + +## 1. vsftpd虚拟用户的配置 + +配置vsftpd的虚拟用户简单分为三个方面 + +1. 配置pam模块 (见下方小标题) +2. 创建认证信息文件(passwd文件) (见下方小标题) +3. vsftpd.conf配置文件 + +### 1.1 PAM模块 + +pam (*Pluggable Authentication Modules*)为应用和服务提供动态的认证支持, pam模块一般在``/lib/security/``或``/lib/(arch_type)/security``下. + +#### 1.1.1 仅虚拟用户的PAM + +实现仅虚拟用户登录十分简单, 只需要让PAM仅认证虚拟用户即可, 如下指定需要的pam模块和需要的参数即可. + +```conf +# 文件为 /etc/pam.d/vsftpd + +auth required pam_pwdfile.so pwdfile /etc/vsftpd/.passwd +account required pam_permit.so +``` + +#### 1.1.2 仅本地用户的PAM + +一般默认的pam文件即可实现仅本地用户认证, 保持默认即可, 不同的系统的默认pam文件内容也不同 + +```conf +#%PAM-1.0 +# PAM of ArchLinux + +auth required /lib/security/pam_listfile.so item=user sense=deny file=/etc/ftpusers onerr=succeed +auth required /lib/security/pam_unix.so shadow nullok +auth required /lib/security/pam_shells.so +account required /lib/security/pam_unix.so +session required /lib/security/pam_unix.so + +``` + +```conf +## Standard behaviour for ftpd(8). +# PAM of Ununtu + +## Note: vsftpd handles anonymous logins on its own. Do not enable pam_ftp.so. +# +## Standard pam includes + +@include common-account +@include common-session +@include common-auth +auth required pam_shells.so +``` + +#### 1.1.3 同时允许本地和虚拟用户的PAM + +由于Arch Linux和Ubuntu默认的PAM文件不一样, 所以两个配置有所不同. + +如果简单地允许本地和虚拟用户的PAM加在一起, 结果并不是同时允许本地用户和虚拟用户, 因为文档中描述``required``和``requisite``都会在验证失败时直接返回失败, 而``sufficient``在本次验证失败, 则会继续进行后续模块的验证, 所以我的做法是将虚拟用户的验证模块由``required``变更为``sufficient``后添加到本地用户验证模块之前.[^1] + +> - required +> +> failure of such a PAM will ultimately lead to the PAM-API returning failure but only after the remaining stacked modules (for this service and type) have been invoked +> +> - requisite +> +> like required, however, in the case that such a module returns a failure, control is directly returned to the application. +> +> - sufficient +> +> success of such a module is enough to satisfy the authentication requirements of the stack of modules (if a prior required module has failed the success of this one is ignored). A failure of this module is not deemed as fatal to satisfying the application that this type has succeeded. If the module succeeds the PAM framework returns success to the application immediately without trying any other modules. + +注意, Arch Linux的``pam_pwdfile``模块需要在[archlinux.org](archlinux.org)中的AUR自行安装. + +```conf +#%PAM-1.0 +# PAM of ArchLinux + +auth sufficient /lib/security/pam_pwdfile.so pwdfile /etc/vsftpd/.passwd +account sufficient /lib/security/pam_permit.so + +auth required /lib/security/pam_listfile.so item=user sense=deny file=/etc/ftpusers onerr=succeed +auth required /lib/security/pam_unix.so shadow nullok +auth required /lib/security/pam_shells.so +account required /lib/security/pam_unix.so +session required /lib/security/pam_unix.so +``` + +Ubuntu WSL 的配置直接将虚拟用户认证模块粘贴到``@include``之前不能达到期望的结果, 于是参照 Arch Linux 的配置改为如下后成功. + +```conf +#%PAM-1.0 +# PAM of Ubuntu + +auth sufficient pam_pwdfile.so pwdfile /etc/vsftpd/.passwd +account sufficient pam_permit.so + +auth required pam_listfile.so item=user sense=deny file=/etc/vsftpd.ftpusers onerr=succeed +auth required pam_unix.so shadow nullok +auth required pam_shells.so +account required pam_unix.so +session required pam_unix.so +``` + +### 1.2 虚拟用户的passwd文件 + +这个文件的路径和文件名都写在pam模块中, 如``sufficient /lib/security/pam_pwdfile.so pwdfile /etc/vsftpd/.passwd``的最后一个区域便是. + +文件格式就是每行以用户名为起始, 冒号分隔, 后接MD5加密的密码, 样例如下: + +```text +test:$1$aT64AHTK$/xRnwvHafFmTzo6GpaCZL/ +``` + +密码加密可以使用``openssl passwd -1 -noverify ${yourPasswd}``来加密, 只需要将此命令的输出作为加密后密码追加在冒号之后即可. + +### 1.3 vsftpd.conf配置文件 + +启用``guest_enable``选项, 该选项允许虚拟用户一个本地映射用户, 启用虚拟用户**必须配置**, 这一模式下, 所有的非匿名用户都会被映射为``guest_username``用户, **包括本地用户**, 此选项在**启用虚拟用户时是必需的**. + +可选配置``guest_username``选项, 如果不配置, 默认为``ftp``, 该选项是指定映射的本地用户的用户名. + +可选配置``virtual_use_local_privs`` , 该选项令虚拟用户使用本地权限, 即上一条选项相关的``guest_username``的权限, 否则虚拟用户的权限将会与匿名用户同级. + +## 2. 主动模式和被动模式 + +首先需要先明确ftp连接有两条连接, 一个是控制信道, 用于进行认证和命令操作, 另一个是数据信道, 用于传输文件内容. + +**被动模式**中, 客户端向服务器发出连接请求时, 连接的都是控制信道, 然后通过``pasv``进入被动模式, 服务端会返回一个类似``(10,16,55,114,47,70)``的一个文本, 其中前4段就是数据信道的IP地址, 后2段就是数据信道的端口信息, 然后客户端就会根据这些信息发出连接请求进行数据信道的连接. + +关于被动模式下具体端口的计算方法, 简单地说就是倒数第二段乘以256加上倒数第一段, 如上就是``47 * 256 + 70``得到``12102``即为数据信道的端口. 具体一些就是因为端口号的范围时``0-65535``, 即``2^16``, 于是在发送时, 将16位二进制数拆分成两个8位二进制数, 比如上边的``12102``就是``0010 1111 0100 0110``被拆分成``0010 1111``和``0100 0110``, 于是分别以``47``和``70``发送过来. + +**主动模式**则是由在连接控制信道后, 通过``port``命令向服务器发送端口信息, 由服务器向客户端发起连接请求. + +整体上, 主动模式和被动模式各有优缺点, 主动模式部署较为简单, 而且由于是服务端向客户端发送连接请求, 可以很大程度上消除被其他人获取数据信道的可能, 但是缺点则是在IPv4环境下, 绝大多数的客户端都是在NAT下, 这种网络情况很难实现服务端向客户端的连接, 令每一个客户端都在生成自己监听的数据信道的端口的同时令NAT设备转发该端口也是不太现实. + +与之相反, 被动模式则完全不慌客户端处在NAT设备后的情况, 但是唯一的小慌的便是服务端处在NAT下的情况, 不过解决办法也很简单, 只需要指定服务端被动模式监听端口的范围, 同时令自己的NAT设备转发这一范围的端口即可解决, 毕竟比起让全世界都铺满红地毯, 还是自己穿上拖鞋更为现实. + +## 3. 用户 + +### 3.1 登录 + +除匿名用户外, 所有用户在登录时都需要一个本地用户与之对应, 本地用户对应的便是``/etc/passwd``文件中的用户, 虚拟用户需要启用``guest_enable``选项, 对应的用户是名为``guest_username``的选项的值, 如果``guest_enable``选项没有开启, 则会有``500 OPPS: cannot locate user entry``的报错. + +### 3.2 权限 + +关于权限, 本地用户则直接使用Linux的本地权限, 匿名用户的权限则是进程vsftpd的运行权限, 一般是用户``ftp``的权限, 虚拟用户的权限在没有启用``virtual_use_local_privs``选项时权限与匿名用户相同, 启用该选项后则权限为选项``guest_username``所指的用户的权限. + +需要澄明一点, 虚拟用户在vsftp的默认策略看来应该是处于与匿名用户同级的权限, 仅适用在一些安全等级较低的资料的共享中. + +## 4. 关于chroot + +vsftp硬性要求``chroot``的目录不可写, 原因是可写的``chroot``目录会受制于一种名为[Roaring Beast](https://www.auscert.org.au/bulletins/ESB-2012.0018/)的攻击方式. + +本人对这种攻击方式的粗浅理解为, vsftp使用的API并没有告知vsftp当前工作环境是否为``chroot``之后的环境, 而且该API有一个在运行时更新配置文件的特性. 而每一个用户登陆后, 都会产生一个vsftpd子进程专用于对此用户的服务, 当子进程不知道当前是``chroot``环境时, 一旦进行运行时配置文件更新, 就会直接在当前环境中尝试导入库文件进行更新, 所以如果有用户在``chroot``后的根目录下创建类似``/lib``的文件夹, 再放入一些包含恶意代码的库文件, 那么攻击者则可以进行任何破坏. + +## 5. 文件权限 + +### 5.1 文件上传后权限 + +- ``file_open_mode``, 默认值为``0666``, 表示文件上传后的最大权限. +- ``anon_umask``和``local_umask``, 表示文件上传后所应用的掩码, 前者为匿名用户使用的掩码, 后者为本地用户使用的掩码. + +根据以上相关选项, 在如下的配置样例中, 匿名用户上传文件后权限为``664``, 普通用户上传文件后权限为``644``. + +```conf +file_open_mode=0666 +anon_umask=002 +local_umask=022 +``` + +### 5.2 文件修改属主及权限 + +- ``chown_uploads``, ``YES``或``NO``, 表示是否启用修改文件属主功能. +- ``chown_username``, 字符串, 值为修改文件属主的目标用户. +- ``chown_upload_mode``, 字符串, 值为表示文件权限的4位数字, 修改后文件权限会被固定设定为该选项表示的权限. + +相关选项如上, 需要注意以下几点: + +1. 修改属主仅对匿名用户生效. +2. 修改属主后, 文件的属组并不会改变. +3. 修改属主后, 文件的权限也会进行变更, 即变更为``chown_upload_mode``所描述的权限, 权限的变更在*上传后权限*之后, 也就是匿名用户上传文件后, 如果修改文件属主功能启用, 那么文件的最终权限会是``chown_upload_mode``描述的权限. + +所以在以下样例中, 匿名用户上传的文件的权限为``0664``, 属主信息为``localuser:ftp`` (设ftpd守护进程运行时用户及属组为``ftp:ftp``), 注意``chown_upload_mode``设置同组可读写, 使得匿名用户自己上传文件后可以凭借组权限对文件进行读写. + +```conf +file_open_mode=0666 +anon_umask=002 +local_umask=022 + +chown_uploads=YES +chown_username=localuser +chown_upload_mode=0664 +``` + +## 6. 踩坑指南 + +### 6.1 报错 500 OOPS: cannot locate user entry[^2] + +如果是虚拟用户登录时报错, 需要检查``guest_enable``选项是否为``YES``以及``guest_username``是否合法; 如果是本地用户, 则需要检查是否时用户名拼写错误. + +### 6.2 报错 425 Security: Bad IP connecting[^4] + +这一点是因为检测到控制信道和数据信道的IP不相同, 因而报出的错误, 通常出现在布置处在NAT后端的ftp服务时, 特点是使用内网/外网IP可以正常访问, 但是换用外网/内网IP就会报错而获取目录失败. + +应该是为了杜绝通过某种方法获取原用户控制信道对应的数据信道, 实现获取用户下载内容的目的. + +解决办法可以加一行``pasv_promiscuous=YES``解决, 这个选项是允许控制信道和数据信道IP不同, 通常用在部署一些安全信道协议中, 但是会带来一些安全隐患. + +但是既然已经知道了问题出现的原因, 那么只要通过``pasv_address``选项指定特定的控制信道的IP, 并且一直通过这一IP进行访问即可, 不过使用这一选项有时会出现下面的情况, 需要注意``pasv_address``与vsftpd监听的IP类型. + +### 6.3 vsftp进入被动模式时, 发送**0.0.0.0**作为数据信道的主机地址[^3] + +这一点是因为vsftp的默认监听有时候是``listen_ipv6``, 这一监听模式下, ``pasv_address``配置的IPv4地址会被忽略, 于是乎发送出``0.0.0.0``给客户端进行连接. + +**有一个解决办法是禁用``listen_ipv6``转而启用``listen``**. + +有点绕开难点的意思, 不过在IPv6未广泛应用的情况下, 倒也勉强接受. + +### 6.4 报错: 500 OOPS: vsftpd: refusing to run with writable root inside chroot() + +**请修改``chroot``的目录为不可写权限!** + +[^1]: https://www.linuxquestions.org/questions/linux-software-2/how-to-enable-both-virtual-and-local-vsftpd-logins-with-pam-365860/ +[^2]: https://ubuntuforums.org/showthread.php?t=1679782 +[^3]: https://www.centos.org/forums/viewtopic.php?t=52408 +[^4]: https://www.linuxquestions.org/questions/linux-newbie-8/vsftpd-problem-with-425-security-bad-ip-connecting-120158/ diff --git a/content/posts/webdav的挂载.md b/content/posts/webdav的挂载.md new file mode 100644 index 0000000..22c4a03 --- /dev/null +++ b/content/posts/webdav的挂载.md @@ -0,0 +1,74 @@ +--- +title: "Webdav的挂载" +date: 2020-08-23T11:28:36+08:00 +tags: [ linux, mount, systemd ] +draft: false +--- + +webdav 挂载到本地文件系统有优有劣, 好处是权限更加开放, 使用也比较方便, 但缺点是在需要同步时受网络影响较大, 所以建议不要直接打开挂载到本地目录的 webdav 文件, 尤其是 GUI 会卡顿较长时间. + +> 使用 webdav 的本意是同步一下 keepass 密码格式的数据库, 摆脱所有密码都一样的困扰, 于是采取了 webdav 挂载到PC本地目录, 安卓使用 FolderSync 进行同步的解决方案, 实际体验不太令人满意, PC打开文件都需要等待少则几秒的下载文件的时间, 而安卓端由于 webdav 本就不是用来同步的协议, 同步过程中也会出现很多的冲突问题. +> +> 新的解决方案是使用 syncthing 进行 keepass 数据库文件的同步, 有点是每一个终端都会有一个数据库文件的备份, 即便突然断网, 也会有本地备份来供短期使用, 而且本地备份文件在被打开时不需要等待漫长的下载时间. + +由于种种原因要弃用 webdav, 但在弃用前将自动挂载 webdav 的配置做一下笔记. + +## 准备条件 + +安装挂载 webdav 的驱动 `davfs2`, 安装以后可以使用 `mount` 指定 `davfs` 的文件系统格式从而从命令行进行挂载. + +准备一个 webdav 的文件服务, 本人由于当初对于 webdav 的强烈需求以及对容量的极小需求采用了[Koofr](!https://koofr.eu/), (初始空间2G, 支持 webdav, 大陆可用, 速度一般), webdav 的配置信息可以在[这里](!https://koofr.eu/help/koofr_with_webdav/how-do-i-connect-a-service-to-koofr-through-webdav/)找到. + +## 配置记住密码 + +安装好 `davfs2` 以后, 可以在 `~/.davfs2/secrets` 文件中配置挂载目录的远程地址\用户名\密码, 配置样例如下 + +``` +https://app.koofr.net/dav/Koofr leafee98@hotmail.com ThisIsMyPasswordAndIWillNotLetYouKnow2333~ +``` + +## 配置自动给本用户挂载 + +配置本用户自动挂载而不是自动挂载给所有用户, 需要实现不使用 `sudo` 来挂载目录, 这一点只需要在 `/etc/fstab` 文件中写出相应的挂载选项并给出 `user` 选项就可以. + +在 `fstab` 的配置中, 配置分为4列, 分别是 `设备标识/远程地址`, `挂载位置`, `文件系统格式`, `其他选项`, 其中其他选项可以查看对应文件系统的手册了解, 比如上面提到的 `user` 选项就在 `mount.davfs(8)` 中可以找到, 其效果是 `allow an ordinary user to mount the file system`, 此外 `noauto` 的效果是在不能使用 `mount -a` 进行自动挂载, 也即开机时不会自动挂载. 本次配置结果如下. + +``` +# webdav +https://app.koofr.net/dav/Koofr /home/leafee98/Koofr/ davfs user,noauto,uid=2333,gid=2333,file_mode=0664,dir_mode=2775,grpid,rw,_netdev 0 0 +``` + +上述中配置了开机时不会自动挂载, 那么如何使本用户可以在登录时挂载此目录呢, 这里使用了 `systemd` 的 `mount` 类型的服务, 配置内容和 `fstabs` 差不多, 但是需要**注意 `mount` 类型的服务名称和挂载位置相对应**, **`Option` 的内容也需要和 `/etc/fstab` 的内容相一致**, 如下 + +``` +# file name: home-leafee98-Koofr.mount +# file path: /home/leafee98/.config/systemd/user/ +[Unit] +Description=Mount WebDAV Service +After=network-online.target +Wants=network-online.target + +[Mount] +What=https://app.koofr.net/dav/Koofr +Where=/home/leafee98/Koofr/ +Options=user,uid=2333,gid=2333,file_mode=0664,dir_mode=2775,grpid,rw,_netdev +Type=davfs +TimeoutSec=15 + +[Install] +WantedBy=default.target +``` + +接下来只需要启用这个服务就可以实现开机自动为本用户挂载了. + +``` +systemctl --user enable home-leafee98-Koofr.mount +``` + +## 其他一些不小不大的问题 + +由于这个服务是在本用户(`~/.config/systemd/user/`)的目录下, 所以在启用服务时只有此用户可以看到. + +只不过, 由于挂载信息还保存在 `/etc/fstab/` 下, 所以其他用户使用命令行也会启用这个服务就是了. + +此外, 如果在 `/etc/fstab` 里面将 `noauto` 选项去掉, 那么这一个额外的服务就可以省略掉. ~~所以这额外的服务折腾了半天就是自己折腾自己~~ diff --git a/content/posts/为单一命令设置代理环境变量的终端函数.md b/content/posts/为单一命令设置代理环境变量的终端函数.md new file mode 100644 index 0000000..3bb49e5 --- /dev/null +++ b/content/posts/为单一命令设置代理环境变量的终端函数.md @@ -0,0 +1,94 @@ +--- +title: "为单一命令设置环境变量的终端函数" +date: 2021-04-19T14:10:41+08:00 +tags: [linux, shell, bash] +draft: false +--- + +## 实际应用 + +### 需求 + +- 一个命令行函数 +- 将其参数作为命令运行 +- 为运行的命令设置环境变量, 同时不影响原本的 shell 环境变量 + +### 结果 + +``` +function proxyenv { + ( + proxy_dest="http://localhost:8888" + + proxy=${proxy_dest} + http_proxy=${proxy_dest} + https_proxy=${proxy_dest} + + PROXY=${proxy_dest} + HTTP_PROXY=${proxy_dest} + HTTPS_PROXY=${proxy_dest} + + export proxy http_proxy https_proxy PROXY HTTP_RPOXY HTTPS_PROXY + eval "$@" + ) +} +``` + +### 分析 + +使用圆括号创建 subshell 来隔离原来的变量环境, 在内部创建变量或 export 不会影响外部 shell 的变量. + +使用 `eval "$@"` 将传入的参数作为命令执行. 由于 `$@` 的特性会将每一个参数展开为一个使用双引号的字符串, 以及 bash 会自动将双引号包裹的字符串作为一整个字符串并处理掉双引号, 所以不必担心在在调用时使用了双引号而导致变量的位置或者数量产生意料之外的行为(见参考 2). + +## 相关知识 + +### subshell 和 export + +使用括号包裹的命令会被置于一个 subshell 中运行, 即为这些命令单独开一个子进程并同时应运行 shell 来执行这些命令, 子进程中的 shell 称为 subshell. subshell 中绝大多数的环境变量等均与原 shell 相同, 即便有些没有被 export 的变量也能够在 subshell 中获取(见参考 3). + +在 shell 中的变量如果不经过 export, 那么这些变量仅在当前的 shell 以及其 subshell 中可以获取, 在其子进程中则无法获取. + +对于 subshell 和普通子进程的环境变量的区别可以见如下: + +``` +v="hello shell" + +( echo $v ) +bash -c 'echo $v' + +export v + +( echo $v ) +bash -c 'echo $v' +``` + +上面的输出为: + +``` +hello shell + +hello shell +hello shell +``` + +可以看出, 尚未被 export 的变量可以在 subshell 中获取, 但是子进程(这里为新开的 bash)对于这个变量一无所知, 所以第二行输出一个空行; 而已经 export 的变量可以 subshell 和子进程中获取. + +### 特殊变量 * 和 @ + +> `*` +> +> Expands to the positional parameters, starting from one. When the expansion occurs within double quotes, it expands to a single word with the value of each parameter separated by the first character of the IFS special variable. That is, "$*" is equivalent to "$1c$2c...", where c is the first character of the value of the IFS variable. If IFS is unset, the parameters are separated by spaces. If IFS is null, the parameters are joined without intervening separators. +> +> `@` +> +> Expands to the positional parameters, starting from one. When the expansion occurs within double quotes, each parameter expands to a separate word. That is, "$@" is equivalent to "$1" "$2" ... If the double-quoted expansion occurs within a word, the expansion of the first parameter is joined with the beginning part of the original word, and the expansion of the last parameter is joined with the last part of the original word. When there are no positional parameters, "$@" and $@ expand to nothing (i.e., they are removed). + +`$*` 变量会被展开为一个字符串, 不同的参数之间会使用 IFS 变量的第一个字符作为分隔符, 通常情况下是空格, 所以通常的效果就是一个使用空格分隔多个单词的字符串. + +`$@` 变量会被展开为多个字符串, 不同的参数会成为各自独立的字符串, 若变量展开在一个字符串中, 那么展开后的第一个字符串会加入到原字符串的结尾, 最后一个字符串会加入到原字符串的开头, 比如 "start$@end" 会成为 "start$1" "$2" ... "$n-1" "$nend" + +## 参考 + +1. [What is the best way to write a wrapper function that runs commands and logs their exit code](https://stackoverflow.com/questions/372116/what-is-the-best-way-to-write-a-wrapper-function-that-runs-commands-and-logs-the/372120#372120) +2. [Bash script - variable content as a command to run](https://stackoverflow.com/questions/5998066/bash-script-variable-content-as-a-command-to-run/39458935#39458935) +3. [Do parentheses really put the command in a subshell?](https://unix.stackexchange.com/questions/138463/do-parentheses-really-put-the-command-in-a-subshell/138498#138498) diff --git a/content/posts/树莓派Arch Base系统无头配置wifi连接.md b/content/posts/树莓派Arch Base系统无头配置wifi连接.md new file mode 100644 index 0000000..583d949 --- /dev/null +++ b/content/posts/树莓派Arch Base系统无头配置wifi连接.md @@ -0,0 +1,203 @@ +--- +title: 树莓派Arch Base系统无头配置wifi +date: 2020-02-06 19:31:00 +0800 +layout: post +categories: [ tech ] +tags: [ raspi, linux ] +--- + +## 开门见山 + +本文讲解了基于ArchLinux的发行版在没有显示器/键盘/网线, 只有读卡器/一台电脑/WIFI的情况下配置无线连接的事. 细节讲解在后边. + +在我为了无头配置wifi而焦头烂额的时候, 我终于看到了[这么一篇博文](https://ladvien.com/installing-arch-linux-raspberry-pi-zero-w/), 而博文中有这样一番代码. + +``` +#!/bin/sh + +set -e + +if [[ $# -ne 3 ]] ; then + echo "Usage: $0 " + exit 1 +fi + +DISK="$1" +SSID="$2" +PASS="$3" + +if [[ ! -b "${DISK}" ]] ; then + echo "Not a block device: ${DISK}" + exit 1 +fi + +if [[ "${USER}" != "root" ]] ; then + echo "Must run as root." + exit 1 +fi + +echo Mounting +mkdir root +mount "${DISK}2" root + +cat << EOF >> root/etc/systemd/network/wlan0.network +[Match] +Name=wlan0 + +[Network] +DHCP=yes +EOF + +wpa_passphrase "${SSID}" "${PASS}" > root/etc/wpa_supplicant/wpa_supplicant-wlan0.conf + +ln -s \ + /usr/lib/systemd/system/wpa_supplicant@.service \ + root/etc/systemd/system/multi-user.target.wants/wpa_supplicant@wlan0.service + +echo Unmounting +umount root + +echo Cleaning up +rmdir root +``` + +此后又经历了一些小事(大半天), 整个无头配置wifi连接的事就完成了. + +## "我就是不想看代码"版 + +通篇代码都是为了防止用户搞出什么妖魔鬼怪做得防护措施, **核心代码就三条, 从`cat`命令开始, 到`ln`命令结束**, 接下来讲讲这几条代码做的事情. *闲太长的直接看后面的总结*. + +在代码讲解之前先把代码的前半部分先跑一遍, 结果就是**sd卡的系统分区(非引导分区)被挂载到了工作目录下的root目录. 并且当前拥有root权限**. + +### 第一句 + +``` +cat << EOF >> root/etc/systemd/network/wlan0.network +[Match] +Name=wlan0 + +[Network] +DHCP=yes +EOF +``` + +首先是第一句核心代码, 这一句是创建一个`systemd.network`文件并写入内容, **此文件详细用途可自行使用命令`man systemd.network`查询用法**. 概括来说就是可以创建以`.network`为后缀的任意名称的文件在`/etc/systemd/network/`, 这些文件会由进程`systemd-networkd`读取并执行, 用来配置几个网络设备. + +这些文件还有两个目录可以放, 分别是`/run/systemd/network/`和`/usr/lib/systemd/network/`, 不同目录下的相同名字的文件的行为会被前一个覆盖掉, 优先级是`/etc/`大于`/run/`大于`/usr/`. + +`[Match]`节是用来指定要配置的网络设备, 如果有多个文件都匹配到了同一个设备, 那么按照文件名的字符序, 先匹配到此设备的会成功配置, 其他匹配到次设备的文件会被忽略. 注意文件目录的不同不会影响到文件字符序的排名. 在这一节中, 指定要配置的网络设备名为`wlan0` + +`[Network]`节指定网络设备的具体配置内容. 在这里仅启动DHCP服务. + +### 第二句 + +``` +wpa_passphrase "${SSID}" "${PASS}" > root/etc/wpa_supplicant/wpa_supplicant-wlan0.conf +``` + +先来讲讲`wpa_passphrase`命令的功能, 超级简单, 就是把无线的名称和密码以特定的格式打印到标准输出. 通过下面的例子可以清楚看出来效果. + +``` +$ wpa_passphrase name_of_wireless password_of_wireless +network={ + ssid="name_of_wireless" + #psk="password_of_wireless" + psk=0551d34036ce41f72fcc66632e57c6b40f1313a86f92be9c28dbb6e89d597c04 +} +``` + +然后是`/etc/wpa_supplicant/wpa_supplicant-wlan0.conf`文件, 首先应该知道`wpa_supplicant`是一个用于管理无线网络连接的套件, 而`wpa_supplicant`程序是主程序, 其他两个辅助完成功能. 除了`wpa_supplicant`和`wpa_passphrase`以外, 还有一个程序是`wpa_cli`, 用于交互式配置无线网络连接, ~~功能丰富到不会用~~. **此套件的配置文件可以自行使用`man supplicant.conf`命令查询**. + +说了这么多也没说到到底为什么是这个文件, 暂时先不提, 等把第三句看完. + +### 第三句 + +``` +ln -s \ + /usr/lib/systemd/system/wpa_supplicant@.service \ + root/etc/systemd/system/multi-user.target.wants/wpa_supplicant@wlan0.service +``` + +这一句话说废话就是创建了一个指向某个奇怪的文件的软链接放在了另一个奇怪的地方, 说玄幻一些就是手动启用了`wpa_supplicant@`服务, 先别打我, 等我说完. + +ArchLinux和基于ArchLinux的发行版都使用`systemd`来管理服务, 而且越来越多的linux发行发行版开始转变到`systemd`, 简单来说就是`systemd`就是用来管理开机启动项的, 但是另一方面来说, 众多启动项彼此交错, 从挂载磁盘到配置网络, 从启动一个终端到初始化图形化界面, 相互之间顺序虽然不严格, 但是绝对不能出现冲突的顺序, 如果网络都还没配置好, 那启动了http服务也是白搭. 另一方面`systemd`还会监视进程, 一旦某个服务异常终止, 立即要尝试重新启动, 此外还要重定向一下服务进程的输出并作为日志保存. + +`systemd`的配置文件主要有两个位置, `/etc/systemd/`, `/usr/lib/systemd/`, 此外还有`/run/systemd/`应该也是, 这里面可以保存服务等的配置文件, 调用时使用`systemctl start <服务名>`即可启动服务, 若想开机启动服务, 则要配置`[install]`之后才可以使用`systemctl enable <服务名>`来实现. + +通过以下例子可以看出来, 如果代码过长是横拉屏幕而不是自动换行的话应该看起来很不错, 这里在每一次输入命令前都加了一个额外的空行便于观看. + +``` +# cat << EOF >> test-service.service +> [Service] +> ExecStart=echo "hello, world!" +> [Install] +> WantedBy=multi-user.target +> EOF + +# systemctl start test-service + +# systemctl status test-service +● test-service.service + Loaded: loaded (/etc/systemd/system/test-service.service; disabled; vendor preset: disabled) + Active: inactive (dead) + +2月 06 21:23:39 manjaro systemd[1]: Started test-service.service. +2月 06 21:23:39 manjaro echo[25515]: hello, world! +2月 06 21:23:39 manjaro systemd[1]: test-service.service: Succeeded. + +# systemctl enable test-service +Created symlink /etc/systemd/system/multi-user.target.wants/test-service.service → /etc/systemd/system/test-service.service. + +# systemctl disable test-service +Removed /etc/systemd/system/multi-user.target.wants/test-service.service. +``` + +这个例子我们创建了一个最简单的服务并启动了它, 然后使用`systemctl status`查看它的状态, 显示当前未活动(`inactive`), 没有自动启动安排('disabled`), 然后下面三行是日志, 指示了启动/运行结果/结束. + +然后重点来了, 我们使用`systemctl enable`和`systemctl disable`来启用自动启动和禁用自动启动, 然后`systemctl`做了什么? 它说它创建了链接! 仔细看可以发现, 软链接创建的位置就是我们写的`WantedBy`的参数指明的target, 而且链接指向原本的服务. + +, 接下来我们看一看我们刚刚创建的软链接指向的服务文件的内容. + +``` +[Unit] +Description=WPA supplicant daemon (interface-specific version) +Requires=sys-subsystem-net-devices-%i.device +After=sys-subsystem-net-devices-%i.device +Before=network.target +Wants=network.target + +[Service] +Type=simple +ExecStart=/usr/bin/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-%I.conf -i%I + +[Install] +Alias=multi-user.target.wants/wpa_supplicant@%i.service +``` + +但看`ExecStart`一条, 启动了一个`wpa_supplicant`程序, 使用`-c`参数制定了我们第二句写的文件. + +到这里再提一下, **以`@`为文件名结尾的服务文件有特殊意义**, 即服务被调用时, `@`后填写什么与调用哪一个服务文件无关, 而是在服务文件内可以使用%I来获得从字符`@`后到`.service`后缀名之间的文本. 比如启动一个`foo@bar.service`的服务, 那么`systemd`就会启动一个`foo@.service`的服务并把`bar`作为`%I`的替换. + +## 总结 + +所以破案了, 我们第三句创建的软链接启用了一个`systemd`服务, 并把设备名作为`%I`参数传给服务文件, 然后服务通过此参数又找到了第二句写的配置文件来链接无线网络. 此外第一句启用了网络设备的DHCP服务, 以免连接上无线却没有IP导致无法通信. + +## 碎碎念 + +### 起因 + +先是想尝试折腾交叉编译, 然后发现raspbian是arm32的, 就突然觉得raspbian不好使了, 就寻思着换用archLinux或者以之为基础的发行版. + +其实总体来说换个系统没什么麻烦的, 无非就是把系统映像往SD卡里面一写, 然后网线一插并开机, ssh上就万事大吉了, 最多就是在写映像时有的需要手动分一下区罢了. + +然后目前的问题则是, **在连一根网线也没有的情况下, 如何才能让树莓派开机就连上wifi**. 所以查了N久资料以后看到这番代码以后, 终于配置成功并出现了这篇文章. + +### 当下 + +最开始想使用manjaro, 下载以后苦于没有找到什么无头安装的方法, 于是下载了archlinux, 然后发现虽然archlinuxarm可以无头安装, 但是直接配置wifi又没有什么方法, 于是就回到原点. 直到找到了这段代码, 便成功安装了archlinuxarm, 然后发现好像也不是arm64, 又看到manjaro从19.10版本后支持无头安装, 并且manjaro下载就是64bit的, 于是欣然决定, 再换到manjaro, 所以现在是在用manjaro + +## 参考资料 + +- [Installing Arch Linux on Raspberry Pi with Immediate WiFi Access](https://ladvien.com/installing-arch-linux-raspberry-pi-zero-w/) +- man page of `systemd`, `systemd.network`, `systemd.service` +- [Manjaro headless installation and wifi setup](https://www.raspberrypi.org/forums/viewtopic.php?t=250676) diff --git a/content/posts/正则表达式随笔.md b/content/posts/正则表达式随笔.md new file mode 100644 index 0000000..f218632 --- /dev/null +++ b/content/posts/正则表达式随笔.md @@ -0,0 +1,111 @@ +--- +title: 正则表达式随笔 +date: 2019-08-03 16:03:45 +0800 +layout: post +categories: [ tech ] +tags: [ regular-expression ] +--- + +## POSIX基础正则表达式 + +### 纯文本 + +以文本形式直接写出需要匹配的内容 + +> `abc` ===> `abc` + +### 特殊字符 + +\.\*\[\*\^\$\{\}+?\\|() + +### 锚字符 + +* 行首 ^ +* 行尾 $ + +> `^$` ===> 匹配空行 + +### 点号字符 + +匹配换行字符之外的任意单个字符, 必须匹配一个字符 + +> `a.c` ===> `abc`, `a c` + +### 字符组 + +使用方括号定义一个字符组, 方括号中包含素有希望出现在该字符组中的字符 + +> `a[bcd]b` ===> `abb`, `acb`, `adb` + +### 排除型字符组 + +在普通字符组的起始字符写出一个脱字符`^`, 即可匹配字符组之外的所有字符, 换行符除外 + +> `a[^bcd]b` ===> `aab` + +### 区间 + +在字符组中单破折号可在字符组中用作区间 + +> `a[b-f]b` = `a[bcdef]b` ===> `abb`, `acb`, `adb`, `aeb`, `afb` + +### 特殊字符组 + +| 组 | 描述 | +| ----------- | ---------------------------------------------- | +| [[:alpha:]] | 匹配任意字母字符, 不管大写还是小写 | +| [[:alnum:]] | 匹配任意字母数字字符0-9, a-z, A-Z | +| [[:blank:]] | 匹配空格或制表符 | +| [[:digit:]] | 匹配0-9之间的数字 | +| [[:lower:]] | 匹配小写字符a-z | +| [[:print:]] | 匹配任意可打印字符 | +| [[:punct:]] | 匹配标点符号 | +| [[:space:]] | 匹配任意空白字符: 空格, 制表符, NL, FF, VT和CR | +| [[:upper:]] | 匹配任意大写字母字符A-Z | + +> `a[[:alnum:]]c` ===> `abc`, `a1c`, `a8c` + +### 星号 + +在字符后面放置星号表明该字符必须在匹配模式的文本中出现0次或多次 + +> `a[bc]\*c` ===> `abc`, `acc`, `ac`, `abcc`, `abbbbbc` + +## POSIX拓展正则表达式 + +### 问号 + +在字符后面放置星号表明该字符必须在匹配模式的文本中出现0次或1次 + +> `ab?c` ===> `ac`, `abc` + +### 加号 + +在字符后面放置加号表明该字符必须在匹配模式的文本中出现1次或多次 + +> `ab+c` ===> `abc`, `abbc`, `abbbc` + +### 花括号 + +花括号标识允许为可重复的正则表达式指定一个上下限, 通常称为**间隔** + ++ `m` : 正则表达式准确出现m次 ++ `m,n` : 正则表达式出现至少m次, 至多n次 + +> `ab{2}c` ===> `abbc` +> +> `ab{1,2}c` ===>`abc`, `abbc` + +### 竖线 + +表示在检查数据流时, 使用逻辑或的方式指定两个或多个匹配模式 + +> `a(b|c)c` ===> `abc`, `acc` +> +> `abc|abb` ===> `abc`, `abb` + +### 圆括号 + +圆括号用于对正则表达式模式进行分组, 分组时, 该组会被视为一个标准字符, 可以向对普通字符一样给该组用特殊字符来限制匹配 + +> `Sat(urday)?` ===> `Sat`, `Saturday` diff --git a/content/posts/科一知识点总结.md b/content/posts/科一知识点总结.md new file mode 100644 index 0000000..387c84c --- /dev/null +++ b/content/posts/科一知识点总结.md @@ -0,0 +1,257 @@ +--- +layout: post +title: "科一知识点总结" +date: 2019-08-02 21:40:00 +0800 +categories: [ daily ] +tags: [ drive ] +--- + +> 总结截止于2019年8月2日,之后的知识点或可能不再进行更新。 +> +> 总结中不涉及图标题目,仅对于一些易混淆、需要系统记忆的知识点进行总结。 +> +> 本知识点总结或有纰漏或错误,欢迎添加修改后作为自己的笔记或向他人传播,也可作为一个不权威的参考,在二次传播时(如果有的话)如果能署名,是大大的感谢的! +> +> 本总结由leafee [博客](leafee98.github.io)总结,参照安卓应用《驾考宝典》中部分网友总结、官方答案解释等资料而成。 +> +> 使用本总结所造成的的一切后果,作者不负任何责任。 +> +> **由于本博客仍在建设中,文章标签和目录可能会有所改动,导致超链接无法导向需要的文章,请尽可能复制一份备用** + +**驾驶证禁止申领期限** + +- 作弊一年 +- 吊销两年 +- 撤销三年 +- 酒驾五年 +- 肇事逃逸、酒驾重大事故终身 + + + +**交通肇事罪** + +- 交通事故后逃逸的 +- 驾驶安全机件失灵车辆的 +- 无驾驶资格的 + + + +**拘役/有期徒刑年限** + +- 重大事故 3年以下 +- 事故逃逸 3-7年 +- 逃逸致死 7年以上 + + + + **酒驾** + +| 酒驾类型 | 处罚 | +| -------------- | ------------------------------------------------------------ | +| 酒驾普通车 | 初次,暂扣6个月驾驶证,1k-2k罚款;再次,10日以下拘留,1k-2k罚款,吊销驾驶证 | +| 醉驾普通车 | 公安约束至酒醒,吊销驾驶证5年禁证,追究刑事责任 | +| 酒驾营运车 | 15日拘留,5k罚款,吊销驾驶证5年禁证 | +| 醉驾营运车 | 公安约束至酒醒,吊销驾驶证10年禁证,且终身不得驾驶营运车辆,追究刑事责任 | +| 酒醉驾重大事故 | 终生不得申领驾驶证 | + + + +**驾驶证更换** + +- 有效期满前90日内提交更换申请 +- 信息改动后30日内提交修改申请 + + + +**审验期限** + +- 审验时,延期不得超过3年 +- 重大事故后未被吊销驾驶证的,记分周期结束后30日内接受审验 +- 申请换证时,需要到公安交管部门接受审验 + + + +**实习期** + +- 初次申领驾驶证的12个月为实习期 +- 实习期内需在车后粘贴统一的实习标志 +- 实习期内上高速需3年以上驾龄人陪同 +- 实习期内记满12分,注销其实习的准驾车型的驾驶资格 + + + +**普通道路车速** + +- 无道路中心线 + - 城市道路 30 km/h + - 公路 40 km/h +- 有道路中心线 + - 城市道路 50 km/h + - 公路 70 km/h + + + + +**高速公路车速** + +- 正常 + - 车速(km/h) + - 双车道 100-120,60-100 + - 三车道 110-120,90-110,60-90 + - 车距 + - 车速高于100 km/h,100 m车距 + - 车速低于100 km/h,可适当缩短,但大于50 m +- 低能见度(雾灯、近光灯、示廓灯,前后位灯) + - 能见度200 m,100 m车距,60 km/h + - 能见度100 m,50 m车距,40 km/h (危险警报闪光灯) + - 能见度50 m,20 km/h,驶离高速 (危险警报闪光灯) + + + +**其他车速不高于30 km/h的情况** + +- 进出非机动车道,过铁路口、窄路、急弯路 +- 转弯、掉头、下陡坡 +- 恶劣天气,能见度小于50 m(普通公路) +- 冰雪、泥泞道路 +- 牵引车辆 + + + +**车辆故障警告标志摆放** + +- 普通道路 50-100 m +- 高速公路 150 m以外 + + + +**停车远离特殊地点** + +- 距特殊路段50 m以外 (交叉路口、铁路道口、急弯路、窄路(宽度不足4米)、桥梁、陡坡、隧道) +- 公共服务设施30 m以外(公共汽车站、急救站、加油站、消防栓、消防队门前) + + + +**罚款** + +- 200-2000 + - 拼装、报废车辆 + - 超速50%以上 +- 200 + + - 应撤离的交通事故未撤离,且造成拥堵的 +- 1000-2000 + - 酒驾普通车 + + + +**标志类型** + +| 标志 | 图形特点 | 意义 | +| -------- | ---------------------------------- | ------------------------ | +| 警告标志 | 黄底黑边黑图标,三角 | 警告车辆行人注意危险地点 | +| 禁令标志 | 白底红边一斜线,圆形 | 禁止或限制行为 | +| 指示标志 | 蓝底白边白图标,圆形长方形或正方形 | 指示车辆、行人行进 | +| 指路标志 | 指路标志 | 提供方向信息 | + + + +**标线类型** + +| 标线 | 意义 | 举例 | +| -------- | ------------------------------------------------------------ | ------------------------------------------------------------ | +| 指示标线 | 用于指示车行道、行车方向、路面边缘、人行道等设施 | 可跨越对向车行道分界线(黄色虚线),可跨月同向车行道分界线(白色虚线)、车行道边缘线(边缘白色实线【划分机动车道与非机动车道】、边缘白色虚线【用于车辆越线出入道路】、边缘白色虚实线【用以规范车辆行驶轨迹,如公交车站】、边缘黄色单实线【单行路中在左侧划分对向的非机动车道】)、人行横道线(斑马线)、人行横道预告标示(菱形块) | +| 警告标线 | 用于促使车辆驾驶人及行人了解道路特殊情况,提升警觉,准备防范或采取应变措施的标线 | 路面宽度渐变段标线(斜双黄实线)、接近障碍物标线(黄色填充渐宽)、收费岛地面标线(白色填充渐宽)、减速标线(车行道横线减速标线(车辆震动感)、车行道纵向减速标线(车道变窄的视觉冲击))、立面标记(黄黑相间斜杠)、有人看守铁路道口(路面上只有一条白色停车线)、无人看守铁路道口(地面有铁路字样) | +| 禁止标线 | 用以告示道路交通的遵行、禁止、限制等特殊规定 | 双黄实线禁止跨越对向车行道分界线、黄色斜线填充双黄实线禁止跨越对向车行道分界线、黄色单实线禁止跨越对向车行道分界线、黄色虚实线禁止跨越对向车行道分界线、禁止跨越同向车行道分界线、禁止长时停车线(路肩黄虚线)、禁止停车线(路肩黄实线)、停车线(横向白色单实线)、停车让行线(横向白色双实线)、减速让行线(白色双虚线和一个白色倒三角)、导流线(路上可以代替花坛出现的白色V形线填充的弧三角区域)、网状线(黄色线交叉网状的区域)、中心圈(路口中心的白色平行线填充的圆形或菱形)、车种专用车道线、禁止掉头标记(黄色叉和调头标记) | + + + +**标写速度** + +- 黄色数字 最高速度 (地面数字) +- 黑色数字 建议速度 (立式标牌黄底黑边) +- 白色数字 最低速度 (地面数字) + + + +**驾驶证记六分的** + +| 简述 | 原条例 | +| --------------------------------------- | ------------------------------------------------------------ | +| 驾驶证暂扣 | 驾驶证暂扣期间行车的。 | +| 交通信号灯 | 违反交通信号灯的。 | +| 超载(普通20%上,营运20%下) | 营运汽车超载未达20%的,其他车辆超载20%以上的,货车超载30%或违规载人的。 | +| 超速(普通20-50%,营运20%下或其他路跑) | 驾驶中型以上载货汽车、校车在高速公路、城市快速路超过规定时速未达20%的;驾驶中型以上载客汽车、校车在高速公路、城市快速路以外的道路上行驶;驾驶其他汽车超速20%以上未达50%的。 | +| 高速公路普通停车 | 营运客车以外的机车在高速公路车道内停车的。 | +| 应急车道 | 违法占用应急车道的。 | +| 恶劣天气 | 低能见度气象条件下,高速路上不按规定行驶的。 | +| 补领驾驶证 | 欺瞒、欺骗手段补领机动车驾驶证的。 | +| 普通疲劳驾驶 | 普通车辆连续驾驶超过4小时或休息不超过20分钟的。 | +| 运载危险品无标志(无安全措施) | 驾驶机动车运载超限的不可解体未按指定的时间、速度、路线行驶或未悬挂指示标志的;运载爆炸物品、易燃易爆物品、放射性物品、剧毒物品等未按指定的时间、速度、路线行驶的或未悬挂指示标志并采取必要安全措施的。 | +| 不避校车 | 驾驶机动车不按照规定避让校车的 | + + + +**驾驶证记12分的** + +| 简述 | 原条例 | +| ---------------------------------------- | ------------------------------------------------------------ | +| 准驾车型 | 驾驶与准驾车型不符的车辆的。 | +| 酒驾 | 酒驾的。 | +| 超载(营运20+%) | 驾驶营运客车、校车超载20%以上。 | +| 事故后逃逸 | 交通事故后逃逸,尚不构成犯罪的。 | +| 搞牌证的 | 未悬挂号牌的,故意污损、遮挡号牌的,不按规定安装号牌的。伪造号牌、驾驶证、行驶证、校车标牌,使用其他车辆的号牌的。 | +| 高速公路搞事情 | 高速公路上逆行、倒车、掉头的,穿越中央分隔带掉头的。 | +| 高速公路营运停车 | 营运客车在高速公路车道内停车的。 | +| 超速的(普通50+%,营运20+%或其他路50+%) | 驾驶中型以上载客载货汽车在高速公路、城市快速路上超速20%的,或在其他路上超速50%的。驾驶其他机动车超速50%的 | +| 营运、危险疲劳驾驶 | 中型以上载客汽车、危险物品运输车连续4小时未休息的,或休息时间小于20分钟的 | +| 驾驶校车 | 未取得校车驾驶资格驾驶校车的。 | + + + +**扣留驾驶证的** + +- 酒驾醉驾的 +- 驾驶员将驾驶权移交无证人员的 +- 超速50+%的 +- 驾驶拼装、报废车的 +- 重大事故构成犯罪的 +- 记分12分的 + + + +**驾驶机动车前的步骤** + +- 调整驾驶座椅,保证踩踏踏板舒适 +- 调整安全带的松紧与高低 +- 调整方向盘的位置 +- 安全头枕要对准后脑勺来保护颈椎 + + + +**在高速公路需停车排除故障时** + +- 开启危险警告闪光灯 +- 将车辆移至不影响交通的位置 +- 放置警告标识,将人员转移到安全位置,迅速报警 +- 等待救援 + + + +**行人参与交通的特点** + +- 主要 行走随意性大,方向多变 +- 其次 喜欢聚集,围观 + + + +**零落知识点** + +- 货车货物未做好防护措施,掉落货物的,货车全责 +- 对于不合格车辆,一律扣留车辆,没有仅扣留行驶证的说法 +- 铁路道口禁止掉头是因为容易发生事故 +- 左侧超车是因为便于观察,有利于安全 +- 车道图形只有公交车车道,没有大型客车车道,快速公交车道是“BRT”(bus rapid transit)标识或“快速公交”标识 +- 交警手势中,变道手势下降较少,会横向偏移;减速手势是垂直下压 + + diff --git a/content/posts/科四知识点总结.md b/content/posts/科四知识点总结.md new file mode 100644 index 0000000..71353ed --- /dev/null +++ b/content/posts/科四知识点总结.md @@ -0,0 +1,312 @@ +--- +title: 科四知识点总结 +date: 2020-05-11 10:30:10 +0800 +layout: post +categories: [ daily ] +tags: [ drive ] +--- + +> 总结截止于2019年8月2日,之后的知识点或可能不再进行更新,请自行甄别。 +> +> 总结中不涉及图标题目,仅对于一些易混淆、需要系统记忆的知识点进行总结,此外知识点并不全面,题库后半部分的题目有所遗漏。 +> +> 本知识点总结或有纰漏或错误,欢迎添加修改后作为自己的笔记或向他人传播,也可作为一个不权威的参考,传播时无需署名。 +> +> 本总结由leafee [博客](leafee98.github.io)总结,参照安卓应用《驾考宝典》中部分网友总结、官方答案解释等资料而成。 +> +> 使用本总结所造成的的一切后果,作者不负任何责任。 +> +> **由于本博客仍在建设中,文章标签和目录可能会有所改动,导致超链接无法导向需要的文章,请尽可能复制一份备用** + +**动画违法行为** + +- 开车打电话 +- 不系安全带 +- 堵车占用公交车道/应急车道 +- 转弯占用非机动车道 +- 遮挡号牌 +- 超速 +- 闯红灯 +- 不按照车道导向箭头行驶 +- 无证驾驶 +- 酒后驾照 +- 违反禁止交通标志(禁止转弯等) + +**文字描述违法行为** + +- 货运车载客 +- 超速 +- 超载 +- 疲劳驾驶 +- 驾驶与准驾车型不符地车辆 +- 非法载客(货车载人) +- 酒后驾车 +- 肇事逃逸 +- 不按规定会车 +- 不正确使用灯光 +- 驾驶具有安全隐患的机动车 +- 违法停车(高速公路停车等) +- 逆行 +- 非法改装机动车 +- 违法超车(越过道路中心线/弯道超车) +- 使用私家车拖车 +- 低能见度未打开所有灯光(雾灯/近光灯/前后位灯/示廓灯/危险警报灯) + +**驾照类型与准驾车型** + +- A1 --- 大型客车(大型载客汽车) +- A2 --- 牵引车(重型/中型全挂/半挂汽车列车) + +**饮酒后驾车** + +- 20 - 80 毫克/100毫升为饮酒后驾车 +- 80 毫克/100毫升为醉酒驾车 + +**车速限制** + +- 中型客车 高速公路 100km/h +- 货运车辆 高速公路 100km/h + +**避免疲劳驾驶** + +- 连续驾驶不超过4小时 +- 用餐不宜过饱 +- 保持良好的睡眠 +- 餐后适当休息后驾车 + +**超速行驶危害** + +- 反应距离延长 +- 视野变窄(车速过快,两边的事物会比较模糊) +- 加重事故后果 +- 制动距离延长 + +**机动车核定载客人数** + +- 大型客车 --- 核定载客人数20人以上(含20人) +- 中型客车 --- 核定载客人数10-19人(含19人) +- 小型客车 --- 核定载客人数9人以下(含9人) +- 微型载客汽车 --- 核定载客人数8人以下(含8人), 且排量小于1升(含1升) + +**进入驾驶室前的操作** + +从驾驶室车门开始, 逆时针绕车一周, 检查车辆及周边情况, 查看车底/车后有无异常情况, 如玩耍地小孩, 确认安全再上车 + +**出车前的检查** + +轮胎: 检查轮胎的磨损/紧固/气压情况和轮胎侧面的磨损标记; 轮胎标记处的沟槽磨损小于1.6毫米, 要立即更换; 发现螺栓松动, 要进行紧固; 气压不足, 要找出原因, 采取适当措施予以处理 + +油/液: 检查冷却液/发动机机油/燃油等是否有渗漏现象 + +**会车** + +- 会车时, 要靠右避让 +- 会车时, 有障碍物一侧的车辆让对方先行, 未驶入障碍路段的车辆让驶入障碍路段的车辆先行 +- 会车时, 狭窄地坡路, 上坡先行, 但是未进入坡道的车辆让坡道中的车辆先行 + +**灯光** + +- 路边临时停车 --- 示廓灯 + 双闪 +- 夜间超越前方车辆 --- 远近交替 +- 夜间通过急弯/坡路 --- 远近交替 +- 夜间通过没有信号灯的路口 --- 远近交替 +- 夜间执行通过路口 --- 近光灯 +- 夜间同防线近距离跟车行驶 --- 近光灯 +- 夜间与机动车会车 --- 近光灯 +- 夜间在照明条件良好道路行驶 --- 近光灯 +- 夜间在没有路灯, 照明不良的情况下行驶 --- 远光灯 + +**频繁变更车道的危害** + +- 扰乱交通秩序 +- 影响正常通行 +- 易引发交通事故 + +**转弯** + +- 进入弯道前提前减速 +- 右转靠右转小弯, 左转靠**右**转大弯 +- 急弯处要: 减速靠路右侧行驶, 不能占用对方车道, 注意对面来车, 鸣喇叭示意 +- 进入环岛不需要开启转向灯, 出岛开启右转向灯 +- 三车道道路在图中没有给出标线的情况下, 左侧为左转, 中间为直行, 右侧为右转(注意自己当前车道) +- 竖向三列转向灯, 左侧为左转信号灯, 中间为直行信号灯, 右侧为右转信号灯(注意当前管得到自己的转向灯) +- 左转弯在道路中心圈左侧转弯, 不得碾压实线 +- 转弯时视线受阻, 对方鸣喇叭, 自己也应当鸣喇叭回应 + +**通过铁路路口和特殊路段** + +- 通过交叉路口, 注意观察当前有车的方向 +- 通过铁路路口, 无人看守需要一停二看三通过, 有人看守也需要进入道口前提前减速减档 +- 通过人行横道, 要一看二慢三通过 + +**超车** + +- 超车时, 繁华路段/交叉路口/铁道路口/人行横道/急弯路/宽度不足4米的摘录或者窄桥/陡坡/隧道或者容易发生危险的路段, 应当放弃超车 +- 良好的超车路段, 视线良好, 对面无来车, 路面无障碍物, 道路宽直 + +**ABS系统** + +- ABS系统在紧急制动时的最大作用: 保持转向能力 +- ABS系统在紧急制动的同时转向有可能发生侧滑 +- ABS系统不能保证缩短制动距离, 比如冰雪路上 + +**车流汇入** + +- 驾车汇入主路时, 应注意左侧车辆 +- 驾车从主路汇入辅路时, 应注意观察减速慢行 +- 应注意观察侧后方车辆动态, 即观察同向来车 + +**道路停车避让** + +- 人行道有人, 应当停车避让, 减速慢行则程度不够 +- 马路中间有个球, 有可能有儿童窜出来, 应当立即停车 + +**鸣喇叭** + +- 禁鸣喇叭标志路段不得鸣喇叭 +- 学校附近, 居民小区附近不得鸣喇叭 + +**公交车** + +- 预防公交车突然起步: 减速, 缓慢超越 +- (停车)避让公交车附近的行人 +- 预防公交车的 突然停车, 突然起步, 行人从公交附近穿出, 保持安全车距 + +**车辆制动** + +- 机动车涉水, 制动效果会变差 +- 影响制动距离的因素: + - 车辆行驶速度 + - 路面状况 + - 驾驶人反映时间 + - 载货量的多少以及制动器的结构形式等 + +**超车** + +- 鸣喇叭提示 +- 从左侧超车 +- 夜间交替使用远近光灯 +- 提前开启左转向灯 +- 超车完毕, 与被超车拉开必要的安全距离后开启右转向灯驶回原车道 + +**跟车** + +- 跟车安全距离的原因 + - 跟车太近, 容易追尾 + - 跟车越近, 越不容易掌控前车前方的情况 + - 防止因前车尾灯损坏, 不能及时发现前车制动 + - 遇到紧急情况时, 能有足够的避让空间 +- 跟车装满大货车需要注意: + - 大货车制动距离相对较长 + - 大货车可能抛撒货物 + - 大货车盲区较大 + - 大货车遮挡小型机动车视线 + +**出车检查** + +- 检查刮水器应当在有水的情况下检查 +- 检查的目的: + - 确认出车方向的安全性 + - 确认机动车车胎是否损毁 + - 确认周围是否有障碍物 + - 确认在车辆附近是否存在安全隐患 +- 出车准备工作: + - 启动车辆, 观察仪表盘, 检查车辆工作是否正常 + - 仔细巡视车辆四周的状况, 观察车底和车身周围是否有障碍物 + - 调整好后视镜 + - 上车关好车门, 调整好座位, 系好安全带 + - 不要把身体伸出车外 + - 不要向车外抛撒物品 + +**行车不良行为** + +- 变更车道不打转向灯 +- 左臂长时间搭在车门窗上 +- 长时间抓变速杆 +- 随意并线 +- 随意向车外抛撒物品 +- 加塞抢行 +- 频繁变更车道 + +**停车** + +- 步骤: + - 按顺行方向停放 + - 车身不得超出停车泊位 + - 关闭电路 + - 锁好车门 +- 可停车位置: + - 停车场 + - 道路施化的停车泊位内 +- 不可停车位置: + - 人行横道 + - 山区容易塌方/泥石流路段 + - 立交桥 + - 隧道 + - 出租车停车位 + - 公共设施30米以内 + - 特殊路段50米以内 +- 其他 + - 临时停车紧靠道路右侧 + +**高速公路** + +- 驶入减速车道, 应关闭转向灯, 车速在驶入匝道前应降低的车速以标志规定为准 +- 进入高速公路时, 进入加速车道, 应提高车速到60km/s以上, 准备汇入高速公路 + +**行车避让** + +- 转弯让直行 +- 右转让左转 +- 相对方向, 右转让左转 +- 支路车辆让行主干道的车辆 +- 机动车让行非机动车 +- 路口外让路口内 + +**各轮胎气压不一致的后果** + +- 加剧轮胎磨损 +- 操纵失控 +- 汽车行驶油耗增大 +- 爆胎 + +**谨慎驾驶原则** + +- 注意力 +- 仔细观察 +- 提前预防 + +**其他** + +- 汽车的专用备胎不可作为正常轮胎长期使用 +- 汽车雨天起步前要使用刮水器 +- 汽车起步应随时注意机动车两侧道路情况, 向左缓慢转向, 逐渐驶入正常行驶车道 +- 安全头枕中心应当支撑头部 +- 危险报警闪光灯/示廓灯/后位灯打开, 于雪天/雾天/夜间临时停车时 +- 雨天跟车行驶, 近光灯的目的: 不干扰前车视线, 有利于自己看清道路 +- 上坡路上, 前车先后溜车, 应当立即停车鸣喇叭提示 +- 掉头, 需要路面有掉头标志, **人行横道禁止掉头** +- 车辆涉水后, **间歇轻踏**制动踏板, 以恢复制动效果 +- 左转车辆只有在直行车道绿灯亮起才可以进入左转待转车道 +- 隧道内车辆故障, 只要车辆还在行驶, 就应该减速慢行坚持驶离隧道, 并在安全的区域停车处理 + +**路标** + +- 铁路道口: 无人看守为小火车头, 有人看守为栅栏, 有叉叉和折线表示有多股铁路与道路相交. 有斜杠表示距离, 每条杠50m +- 注意非机动车: 三角标志, 黄底, 自行车 +- 注意残疾人: 三角, 黄底, 坐轮椅的小人 +- 事故易发路段: 三角, 黄底, 小汽车追尾大货车 +- 注意危险: 三角, 黄底, 叹号 +- 施工路段: 三角, 黄底, 愚公移山 +- 注意村庄或集镇: 三角, 黄底, 小房子和小树 +- 隧道开灯: 三角, 黄底, 小车车入隧道开灯 +- 禁止通行: 圆圈, 白底, 空白 +- 禁止驶入: 圆圈, 红底, 白横线 +- 禁止机动车: 圆圈, 白底, 圆圈加斜线勾掉小汽车正脸 +- 禁止和接触禁止: 禁止为红圈, 解除禁止为黑圈 + +**校车上下学生** + +- 一条车道: 后方停车 +- 两条车道: 后方和相邻车道停车 +- 三条车道: 后方和和相邻车道停车, 左侧车道减速慢行 \ No newline at end of file diff --git a/content/posts/迁移到wayland事记.md b/content/posts/迁移到wayland事记.md new file mode 100644 index 0000000..3a3e2fd --- /dev/null +++ b/content/posts/迁移到wayland事记.md @@ -0,0 +1,48 @@ +--- +title: "迁移到 wayland 事记" +date: 2021-10-24T17:28:00+08:00 +tags: [linux, KVM] +draft: false +--- + +## 一些环境变量 + +设置了一些环境变量,如果不设置这些环境变量,那么有一部分程序会在启动时字体发毛,比如 `MOZ_ENABLE_WAYLAND` 能够避免 firefox 出现字体发毛。 + +```bash +export GDK_BACKEND=wayland # GTK +export QT_QPA_PLATFORM=wayland # QT +export CLUTTER_BACKEND=wayland # Clutter +export SDL_VIDEODRIVER=wayland # SDL +# mozilla wayland envionment +export MOZ_ENABLE_WAYLAND=1 +``` + +## 其他的配置 + +### electron + +为了 electron 专门添加的配置文件, `/.config/electron-flags.conf` + +``` +# file name: ~/.config/electron-flags.conf +--enable-features=UseOzonePlatform +--ozone-platform=wayland +``` + +按照行为来说,上述配置文件应该是所有版本的 electron 都会生效,但是对于旧一些的版本,比如 12 和 13,则需要添加单独的配置文件,但是由于配置内容相同,所以只需要分别建立软链接。 + +``` +# pwd: ~/.config/ +ln -s electron-flags.conf ~/.config/electron12-flags.conf +ln -s electron-flags.conf ~/.config/electron13-flags.conf +``` + +## 现存的大问题 + +electron 在 wayland 环境下不能使用 fcitx5,滚回 Xorg,第二次尝试迁移到 wayland 宣布失败。 + +## 参考 + +1. [ArchWiki](https://wiki.archlinux.org/title/Wayland#GUI_libraries) + diff --git a/content/posts/部署davical到apache2.md b/content/posts/部署davical到apache2.md new file mode 100644 index 0000000..afd1ea9 --- /dev/null +++ b/content/posts/部署davical到apache2.md @@ -0,0 +1,179 @@ +--- +title: "部署davical到apache2" +date: 2021-01-02T12:21:45+08:00 +tags: [ linux, apache, caldav ] +draft: false +--- + +起源于 radicale 的 well-known 自动配置不能与 thunderbird 的 tbsync 插件和平地工作, 以及使用 python 实现的 radicale 在过去的半年中失去响应了 3 次, 所以决定找一个可能更稳定一些, 更加通用一些的支持 caldav 的服务程序, 最终选定了 davical . + +这里将在 debian 系统 apache2 上部署 davical , 同时会配置好 well-known 的重定向, 此外还会有一些实现方式的小推测. + +关于软件依赖等事项不再赘述, 这里只讨论使用 apache 部署 davical 站点的过程. + +## 目录 + +- [目录](#目录) +- [部署 davical 站点](#部署-davical-站点) + - [使用 VirtualHost 部署 davical 为一个新的站点](#使用-virtualhost-部署-davical-为一个新的站点) + - [使用软链接方式部署 davical 到一个 http 子目录](#使用软链接方式部署-davical-到一个-http-子目录) + - [使用别名(Alias)方式部署 davical 到一个 http 子目录](#使用别名alias方式部署-davical-到一个-http-子目录) +- [well-known 的配置](#well-known-的配置) + - [使用 Rewrite 部署 well-known](#使用-rewrite-部署-well-known) + - [客户端的访问体验](#客户端的访问体验) + - [使用 Redirect 部署 well-known](#使用-redirect-部署-well-known) + - [客户端的访问体验](#客户端的访问体验-1) +- [关于 Rewrite 的一些解释](#关于-rewrite-的一些解释) +- [关于 Redirect 时有无后缀斜杠的区别](#关于-redirect-时有无后缀斜杠的区别) + - [一个关于 URI 后缀斜杠并在重定向时被替换的例子](#一个关于-uri-后缀斜杠并在重定向时被替换的例子) + - [一个重定向与直接获取网页文档同时工作的例子](#一个重定向与直接获取网页文档同时工作的例子) + +## 部署 davical 站点 + +部署 davical 有两大类别, 分别是部署为一个新的站点和部署为一个网站的子目录. + +部署为新的站点比较方便, 而且不会对未来可能的新目录产生冲突, 但建议配合 DNS 来使用, 以免浪费一个 80 端口, 此外客户端的配置也十分简单. + +部署为一个 http 子目录兼容性则会更好一些, 适用于更多场景. + +### 使用 VirtualHost 部署 davical 为一个新的站点 + +部署为一个新的站点只需要创建一个新的 VirtualHost 条目, 并指定网页根目录 DocumentRoot 即可. 比如将新站点监听在本机所有 IP 的 81 端口, 只需要在 VirualHost 条目中通配指定所有 IP , 再指定端口 81 即可. + +需要注意的是那个比较容易被忽略的 `Listen 81` 的指令, 这个指令要求 apache2 在运行时监听 81 端口, 如果没有这条指令则会发现站点无法正常使用, 表现为无法建立连接, 在服务器主机上也会发现没有任何进程监听 81 端口. + +``` +Listen 81 + + DocumentRoot /usr/share/davical/htdocs + +``` + +使用这种方式配置以后, 在客户端的配置中需要指定 caldav/carddav 的目录为根目录或忽略不写路径即可. + +### 使用软链接方式部署 davical 到一个 http 子目录 + +这种配置方式不需要去为了建立站点或重定向来修改配置文件, 只需要在当前的站点的 DocumentRoot 的文件目录中建立一个指向 davical 的 `htdocs` 的目录的软链接即可. + +``` +# ls -l +total 2 +-rw-r--r-- 1 root root 10701 Dec 27 23:39 index.html +lrwxrwxrwx 1 root root 26 Dec 28 02:25 davical-link -> /usr/share/davical/htdocs/ +``` + +### 使用别名(Alias)方式部署 davical 到一个 http 子目录 + +在需要部署的站点 (VirtualHost) 中添加 `Alias` 指令就可以实现和建立软链接相同的效果. + +需要注意是否在第一个参数 URI 中后缀一个斜杠, `Alias` 对于 URI 后缀斜杠的行为与 `Redirect` 类似, 具体在[关于 Redirect 时有无后缀斜杠的区别](#关于-redirect-时有无后缀斜杠的区别)中描述. + +``` +Alias "/davical" "/usr/share/davical/htdocs/" +``` + +## well-known 的配置 + +well-known 是一个将各种可能在网页文档某个路径的服务另外在路径 `/.well-known/` 下为指定名称的文档请求返回跳转响应的约定. + +> 比如 caldav 服务部署在 `/davical/caldav.php` 路径, 若配置好 well-known 则访问 `/.well-known/caldav` URI 时, 会在得到一个响应头, 其中 `location` 字段为 `/davical/caldav.php`, 状态码为任意一个跳转状态码 (如 301 或 302), 随后客户端会根据得到的 URI 去再一次请求服务. + +对于 davical 的 well-known 的配置可以参见其 [wiki (Well-known URLs)](https://wiki.davical.org/index.php/Well-known_URLs) , 下面也会进行简短的复述. + +davical 的 well-known 工作机制要求 well-known 的访问被 `/davical-base/caldav.php/.well-known/caldav` 处理, 处理结果中, GET 请求会直接在此 URI 的网页文档下处理, **而 caldav 中用到的 PROPFIND 等请求会返回一个重定向响应, 响应路径为 `/davical-base/caldav.php`** . + +在 apache 的配置当中, **一切配置的目的都是将访问到 `/.well-known/caldav` 到请求重定向到 `/davical-base/caldav.php/.well-known/caldav`**, 实现这一目的的手段有对用户透明的 `Rewrite` 和用户可见的 `Redirect` 两种. + +### 使用 Rewrite 部署 well-known + +假设 davical 被部署在 `/davical-base/` 下, 使用 `Rewrite` 需要先引入模块 `mod_rewrite`, 仅重写 caldav 服务的情况时, 配置如下. + +``` +RewriteEngine On +RewriteRule ^/\.well-known/caldav$ /davical-base/caldav.php/.well-known/caldav [NC,L] +``` + +#### 客户端的访问体验 + +``` +Request: PROPFIND http://hostname/.well-known/caldav +Response: 301 location=/davical-base/caldav.php + +Request: PROPFIND http://hostname/davical-base/caldav.php +Response: ... ... ... ... +``` + +### 使用 Redirect 部署 well-known + +假设 davical 被部署在同一位置, 仅重写 caldav 服务时, 配置如下. + +``` +Redirect /.well-known/caldav /davical-base/caldav.php/.well-known/caldav +``` + +#### 客户端的访问体验 + +``` +Request: PROPFIND http://hostname/.well-known/caldav +Response: 302 location=/davical-base/caldav.php/.well-known/caldav + +Request: PROPFIND http://hostname/davical-base/caldav.php/.well-known/caldav +Response: 301 location=/davical-base/caldav.php + +Request: PROPFIND http://hostname/davical-base/caldav.php +Response: ... ... ... ... +``` + +## 关于 Rewrite 的一些解释 + +`Rewrite` 是简单的修改 URI , 然后将修改后的 URI 中的资源作为响应返回给请求, **这一过程对于客户端是透明的**. + +## 关于 Redirect 时有无后缀斜杠的区别 + +Redirect 只是一个普通的查找替换, 相当于将 URI 中特定前缀替换为第二个参数表述的字符串以后, 将修改之后的 URI 作为响应头中的 location 字段值并以 301 作为状态码返回给浏览器. + +此外, 对于目录文件, 如果 URI 的目标刚好是一个目录文件, 在匹配唯一的情况下, 是否后缀斜杠以及后缀多少个斜杠对于目录项来说没有区别, 即 `/dir` 与 `/dir/` `/dir//` 没有区别. 而对于普通文档, 则后缀一个额外的斜杠以后会无法访问该文档. + +### 一个关于 URI 后缀斜杠并在重定向时被替换的例子 + +所以对于是否加上斜杠, 应考虑是否需要要以斜杠的方式访问. 如网页根目录内容以及目标为 `tmp-file` 的重定向如下. + +``` +# content of the DocumentRoot +-rw-r--r-- 1 root root 9 Jan 2 00:09 tmp-file + +# directive in VirtualHost +Redirect /redirect-file/ /tmp-file +``` + +浏览器访问 URI 为 `http://hostname/redirect-file/` 的网页时, 得到的响应头如下. + +``` +HTTP/1.1 302 Found +Date: Sat, 02 Jan 2021 06:43:49 GMT +Server: Apache/2.4.38 (Debian) +Location: http://hostname/tmp-file +Content-Length: 296 +Keep-Alive: timeout=5, max=100 +Connection: Keep-Alive +Content-Type: text/html; charset=iso-8859-1 +``` + +随后浏览器跳转到 `http://hostname/tmp-file` 最终获取到真正的网页. + +请留意 302 跳转时浏览器访问时提供的 URI 中后缀的斜杠, 以及重定向指令中的源 URI 中的斜杠. + +当访问的 URI 中没有后缀斜杠时, 即访问时提供的 URI 为 `http://hostname/redirect-file` 时, 此重定向指令将不会生效, 最终浏览器得到一个 404 的响应. + +### 一个重定向与直接获取网页文档同时工作的例子 + +``` +# content of the DocumentRoot +-rw-r--r-- 1 root root 9 Jan 2 00:09 redirect-dir +drw-r--r-- 1 root root 9 Jan 2 00:09 tmp-dir + +# directive in VirtualHost +Redirect /redirect-dir/ /tmp-dir +``` + +当如上配置时, URI 为 `http://hostname/redirect-dir` 时, 会直接获取到文件 `redirect-dir` 的内容, 当 URI 为 `http://hostname/redirect-dir/` 时, 会访问到**目录** `tmp-dir` 的内容. diff --git a/themes/hugo-theme-flat b/themes/hugo-theme-flat new file mode 160000 index 0000000..4e73d5d --- /dev/null +++ b/themes/hugo-theme-flat @@ -0,0 +1 @@ +Subproject commit 4e73d5d1eb6f2d0d0cd375b422e60fd22077a29d