vault backup: 2022-09-30 21:53:03
Affected files: .obsidian/workspace 03. 專注Study/Android/ADB 取得 APK 的 icon.md 03. 專注Study/Android/ADB.md 03. 專注Study/Android/AOSP.md 03. 專注Study/Android/Android programming.md 03. 專注Study/Android/AudioTrack.md 03. 專注Study/Android/Ktor.md 03. 專注Study/Android/Service.md 03. 專注Study/Android/Tools.md 03. 專注Study/Android/UI.md 03. 專注Study/C++/C++17.md 03. 專注Study/C++/Class template.md 03. 專注Study/C++/GCC.md 03. 專注Study/C++/Structured binding declaration.md 03. 專注Study/C++/for_each.md 03. 專注Study/C++/lambda.md 03. 專注Study/C++/lvalue.md 03. 專注Study/C++/move operator.md 03. 專注Study/C++/rvalue.md 03. 專注Study/C++/智慧指標.md 03. 專注Study/RxKotlin/20200207 - Study RxKotlin.md 04. Programming/COM/20210726 - COM Interface.md 04. Programming/DB/MySQL.md 04. Programming/DB/sqlite.md 04. Programming/Design Pattern.md 04. Programming/FFMPEG/00. Introduction.md 04. Programming/FFMPEG/01. Setup.md 04. Programming/FFMPEG/FFMpeg.md 04. Programming/Flask.md 04. Programming/Kotlin/class.md 04. Programming/Kotlin/run, let, with, also 和 apply.md 04. Programming/Media Foundation/20210604 - Windows media foundation.md 04. Programming/OpenCV.md 04. Programming/OpenGL.md 04. Programming/Python/argparse.ArgumentParser.md 04. Programming/Python/decorator.md 04. Programming/Python/logging.md 04. Programming/Python/opencv.md 04. Programming/Python/subprocess.md 04. Programming/Python/threading.md 04. Programming/Python/tkinter.md 04. Programming/Python/檢測工具.md 04. Programming/QT/Dropdown button.md 04. Programming/QT/QVariant.md 04. Programming/QT/Qt.md 04. Programming/UML.md 04. Programming/演算法.md 05. 資料收集/99. templates/blogHeader.md 05. 資料收集/99. templates/date.md 05. 資料收集/99. templates/front matter.md 05. 資料收集/99. templates/note.md 05. 資料收集/99. templates/table.md 05. 資料收集/99. templates/thisWeek.md 05. 資料收集/99. templates/日記.md 05. 資料收集/99. templates/讀書筆記.md 05. 資料收集/Linux/CLI/cut.md 05. 資料收集/Linux/CLI/scp.md 05. 資料收集/Linux/CLI/timedatectl.md 05. 資料收集/Linux/Programming.md 05. 資料收集/Linux/Ubuntu.md 05. 資料收集/Tool Setup/Hardware/RaspberryPi.md 05. 資料收集/Tool Setup/Software/Chrome.md 05. 資料收集/Tool Setup/Software/Obisidian.md 05. 資料收集/Tool Setup/Software/SublimeText.md 05. 資料收集/Tool Setup/Software/VirtualBox.md 05. 資料收集/Tool Setup/Software/Visual Studio Code.md 05. 資料收集/Tool Setup/Software/Windows Setup.md 05. 資料收集/Tool Setup/Software/Windows Terminal.md 05. 資料收集/Tool Setup/Software/freefilesync.md 05. 資料收集/Tool Setup/Software/vim.md 05. 資料收集/名言佳句.md 05. 資料收集/架站/Gitea.md 05. 資料收集/架站/HTTP Server/Apache.md 05. 資料收集/架站/HTTP Server/Nginx/Reverse Proxy(Layer4).md 05. 資料收集/架站/Pelican blog.md 05. 資料收集/架站/Proxmox VE.md 05. 資料收集/架站/SWAG Reverse proxy.md 05. 資料收集/架站/Storj.md 05. 資料收集/架站/Trojan.md 05. 資料收集/每週外食.md 05. 資料收集/科技/802.11.md 05. 資料收集/科技/HDR Sensor.md 05. 資料收集/科技/量子電腦.md 05. 資料收集/科技/鋰電池.md 05. 資料收集/興趣嗜好/RC/Traxxas Sledge.md 05. 資料收集/興趣嗜好/RC/好盈電變調整中立點.md 05. 資料收集/興趣嗜好/RC/差速器調教教學.md 05. 資料收集/興趣嗜好/模型/舊化作例.md 05. 資料收集/興趣嗜好/軍武/虎式.md 05. 資料收集/讀書筆記/20201201 - 學習如何學習.md 05. 資料收集/讀書筆記/20201218 - Kotlin權威2.0.md 05. 資料收集/讀書筆記/20201224 - 寫作是最好的自我投資.md 05. 資料收集/讀書筆記/20210119 - 中產悲歌.md 05. 資料收集/讀書筆記/20210220 - 最高學習法.md 05. 資料收集/讀書筆記/20210320 - 最高學以致用法.md 05. 資料收集/讀書筆記/20210406 - 精準購買.md 05. 資料收集/讀書筆記/20210723 - 高手學習.md 05. 資料收集/讀書筆記/20220526 - 深入淺出設計模式.md 05. 資料收集/讀書筆記/20220619 - 精確的力量.md 05. 資料收集/軟體工具/IPFS.md 05. 資料收集/軟體工具/MkDocs.md 05. 資料收集/軟體工具/Obsidian.md 05. 資料收集/軟體工具/docker.md 05. 資料收集/軟體工具/git/apply.md 05. 資料收集/軟體工具/git/submodule.md 05. 資料收集/軟體工具/youtube-dl.md 05. 資料收集/面試準備/技术面试最后反问面试官的话.md
This commit is contained in:
10
05. 資料收集/99. templates/blogHeader.md
Normal file
10
05. 資料收集/99. templates/blogHeader.md
Normal file
@@ -0,0 +1,10 @@
|
||||
Title:
|
||||
Date: {{date:YYYY-MM-DD}} {{time:HH:mm}}
|
||||
Modified: {{date:YYYY-MM-DD}} {{time:HH:mm}}
|
||||
Category:
|
||||
Tags:
|
||||
Slug:
|
||||
Authors: Awin Huang
|
||||
Summary:
|
||||
|
||||
This is the content of post.
|
||||
1
05. 資料收集/99. templates/date.md
Normal file
1
05. 資料收集/99. templates/date.md
Normal file
@@ -0,0 +1 @@
|
||||
{{date:YYYY-MM-DD}}
|
||||
7
05. 資料收集/99. templates/front matter.md
Normal file
7
05. 資料收集/99. templates/front matter.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
tags:
|
||||
aliases:
|
||||
date: {{date}}
|
||||
time: {{time:HH:mm:ss}}
|
||||
description:
|
||||
---
|
||||
6
05. 資料收集/99. templates/note.md
Normal file
6
05. 資料收集/99. templates/note.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
date: {{date}}
|
||||
tags:
|
||||
aliases:
|
||||
-
|
||||
---
|
||||
5
05. 資料收集/99. templates/table.md
Normal file
5
05. 資料收集/99. templates/table.md
Normal file
@@ -0,0 +1,5 @@
|
||||
| header | header | header |
|
||||
|:------:|:------ | ------:|
|
||||
| 1-2 | 1-1 | 1-3 |
|
||||
| 2-2 | 2-1 | 2-3 |
|
||||
| 3-2 | 3-1 | 3-3 |
|
||||
8
05. 資料收集/99. templates/thisWeek.md
Normal file
8
05. 資料收集/99. templates/thisWeek.md
Normal file
@@ -0,0 +1,8 @@
|
||||
- Week{{date:ww}}: {{date:YYYY-MM-DD(ddd)}}
|
||||
- 星期一:
|
||||
- 星期二:
|
||||
- 星期三:
|
||||
- 星期四:
|
||||
- 星期五:
|
||||
- 星期六:
|
||||
- 星期日:
|
||||
47
05. 資料收集/99. templates/日記.md
Normal file
47
05. 資料收集/99. templates/日記.md
Normal file
@@ -0,0 +1,47 @@
|
||||
時間:{{time:HH:mm:ss}}
|
||||
|
||||
### TAG
|
||||
|
||||
|
||||
### All TODOs
|
||||
```tasks
|
||||
not done
|
||||
path does not include 2021
|
||||
path does not include 2022/01
|
||||
path does not include 2022/02
|
||||
path does not include 2022/03
|
||||
path does not include 2022/04
|
||||
path does not include 02. PARA/04. Archives(歸檔)
|
||||
path does not include 001. Kong
|
||||
group by folder
|
||||
group by filename
|
||||
group by heading
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Doing TODOs
|
||||
```tasks
|
||||
not done
|
||||
has start date
|
||||
happens before tomorrow
|
||||
path does not include 2021
|
||||
path does not include 2022/01
|
||||
path does not include 2022/02
|
||||
path does not include 2022/03
|
||||
path does not include 2022/04
|
||||
path does not include 02. PARA/04. Archives(歸檔)
|
||||
path does not include 001. Kong
|
||||
group by folder
|
||||
group by filename
|
||||
group by heading
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 新增TODO
|
||||
#### 私事
|
||||
|
||||
#### 公事
|
||||
|
||||
### 今日回顧
|
||||
11
05. 資料收集/99. templates/讀書筆記.md
Normal file
11
05. 資料收集/99. templates/讀書筆記.md
Normal file
@@ -0,0 +1,11 @@
|
||||
書名:
|
||||
日期:{{date:YYYY-MM-DD(ddd)}}
|
||||
Link:
|
||||
|
||||
# 筆記
|
||||
|
||||
|
||||
# 心得
|
||||
|
||||
|
||||
# TODO
|
||||
172
05. 資料收集/Linux/CLI/cut.md
Normal file
172
05. 資料收集/Linux/CLI/cut.md
Normal file
@@ -0,0 +1,172 @@
|
||||
## cut
|
||||
Linux 的 `cut` 指令是一個實用的文字處理工具,可以將每一行文字的部份字元或欄位擷取出來,以下是使用方式與範例。
|
||||
|
||||
### 擷取字元
|
||||
|
||||
對於欄位寬度是固定的資料,可以使用擷取固定位置字元的方式,把指定的欄位抓出來,典型的例子就是從 `ls` 指令的輸出中擷取檔案權限。假設我們的 `ls` 指令與輸出資料如下:
|
||||
```bash
|
||||
# 僅輸出最後 5 筆檔案資訊
|
||||
ls -l | tail -n 5
|
||||
```
|
||||
|
||||
```
|
||||
drwxr-xr-x 2 gtwang gtwang 4096 11月 7 22:29 影片
|
||||
drwxr-xr-x 7 gtwang gtwang 4096 2月 6 21:01 文件
|
||||
drwxr-xr-x 4 gtwang gtwang 4096 2月 22 21:09 桌面
|
||||
drwxr-xr-x 2 gtwang gtwang 4096 1月 6 2017 模板
|
||||
drwxrwxr-x 2 gtwang gtwang 4096 1月 6 2017 音樂
|
||||
```
|
||||
|
||||
如果我們想要擷取第一欄中的檔案權限(也就是第 2 個字元到第 10 個字元),可以使用 `cut` 指令配合 `-c` 參數,將每一行的第 2 個字元至第 10 個字元抓出來:
|
||||
|
||||
```bash
|
||||
# 擷取第 2 個字元至第 10 個字元
|
||||
ls -l | tail -n 5 | cut -c 2-10
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
rwxr-xr-x
|
||||
rwxr-xr-x
|
||||
rwxr-xr-x
|
||||
rwxr-xr-x
|
||||
rwxrwxr-x
|
||||
```
|
||||
|
||||
如果要擷取多個不連續的的區段,逗號分隔每個區段,例如:
|
||||
|
||||
```bash
|
||||
# 擷取第 2-3 個、第 5-6 個與第 8-9 個字元
|
||||
ls -l | tail -n 5 | cut -c 2-3,5-6,8-9
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
rwr-r-
|
||||
rwr-r-
|
||||
rwr-r-
|
||||
rwr-r-
|
||||
rwrwr-
|
||||
```
|
||||
|
||||
### 排除字元
|
||||
|
||||
上面的範例中我們都是設定要擷取的部份,如果想要設定排除的部份,可以加上 `--complement` 這個補集參數,這樣 `cut` 就會將指定的部份刪除,留下剩餘的部份:
|
||||
|
||||
```bash
|
||||
# 排除第 2 個字元至第 10 個字元
|
||||
ls -l | tail -n 5 | cut -c 2-10 --complement
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
d 2 gtwang gtwang 4096 11月 7 22:29 影片
|
||||
d 7 gtwang gtwang 4096 2月 6 21:01 文件
|
||||
d 4 gtwang gtwang 4096 2月 22 21:09 桌面
|
||||
d 2 gtwang gtwang 4096 1月 6 2017 模板
|
||||
d 2 gtwang gtwang 4096 1月 6 2017 音樂
|
||||
```
|
||||
|
||||
### 擷取欄位
|
||||
|
||||
若我們的資料欄位寬度不是固定的,而是使用特定的字元分隔不同的欄位,例如逗點分隔檔(csv 檔):
|
||||
```
|
||||
5.1,3.5,1.4,0.2,"setosa"
|
||||
4.9,3,1.4,0.2,"setosa"
|
||||
7,3.2,4.7,1.4,"versicolor"
|
||||
6.4,3.2,4.5,1.5,"versicolor"
|
||||
5.9,3,5.1,1.8,"virginica"
|
||||
```
|
||||
|
||||
若要擷取這個 csv 檔的特定欄位,可以使用 `cut` 指令加上 `-d` 參數指定欄位分隔字元,並以 `-f` 參數指定欲擷取的欄位,例如擷取出第 2 個欄位:
|
||||
|
||||
```bash
|
||||
# 擷取 CSV 檔的第二個欄位
|
||||
cut -d , -f 2 data.csv
|
||||
```
|
||||
|
||||
Output:
|
||||
```
|
||||
3.5
|
||||
3
|
||||
3.2
|
||||
3.2
|
||||
3
|
||||
```
|
||||
|
||||
若要擷取多個欄位,也是使用逗號分隔每個欄位:
|
||||
|
||||
```bash
|
||||
# 擷取 CSV 檔的第 1-3 個與第 5 個欄位
|
||||
cut -d , -f 1-3,5 data.csv
|
||||
```
|
||||
|
||||
```
|
||||
5.1,3.5,1.4,"setosa"
|
||||
4.9,3,1.4,"setosa"
|
||||
7,3.2,4.7,"versicolor"
|
||||
6.4,3.2,4.5,"versicolor"
|
||||
5.9,3,5.1,"virginica"
|
||||
```
|
||||
|
||||
Linux 中的 `/etc/passwd` 檔案內容是以冒號分隔欄位的,若要從中擷取特定的欄位,可以指定以冒號為分隔字元:
|
||||
|
||||
```bash
|
||||
# 擷取 /etc/passwd 的第 1 個與第 7 個欄位
|
||||
head -n 5 /etc/passwd | cut -d : -f 1,7
|
||||
```
|
||||
|
||||
```
|
||||
root:/bin/bash
|
||||
daemon:/usr/sbin/nologin
|
||||
bin:/usr/sbin/nologin
|
||||
sys:/usr/sbin/nologin
|
||||
sync:/bin/sync
|
||||
```
|
||||
|
||||
### 排除欄位
|
||||
|
||||
若要排除某些特定欄位,而留下其餘的欄位,同樣可以使用 `--complement` 參數:
|
||||
|
||||
```bash
|
||||
# 排除 CSV 檔的第二個欄位
|
||||
cut -d , -f 2 --complement data.csv
|
||||
```
|
||||
|
||||
```
|
||||
5.1,1.4,0.2,"setosa"
|
||||
4.9,1.4,0.2,"setosa"
|
||||
7,4.7,1.4,"versicolor"
|
||||
6.4,4.5,1.5,"versicolor"
|
||||
5.9,5.1,1.8,"virginica"
|
||||
```
|
||||
|
||||
### 輸出分隔字元
|
||||
`cut` 在輸出多欄位的資料時,預設會以輸入檔案所使用的分隔字元來分隔輸出的欄位,若要改變輸出欄位的分隔字元,可以使用 `--output-delimiter` 參數來指定:
|
||||
|
||||
```bash
|
||||
# 指定輸出欄位分隔字元
|
||||
head -n 5 /etc/passwd | cut -d : -f 1,7 --output-delimiter="^_^"
|
||||
```
|
||||
|
||||
```
|
||||
root^_^/bin/bash
|
||||
daemon^_^/usr/sbin/nologin
|
||||
bin^_^/usr/sbin/nologin
|
||||
sys^_^/usr/sbin/nologin
|
||||
sync^_^/bin/sync
|
||||
```
|
||||
|
||||
### 實用範例
|
||||
Linux 的系統管理者時常會需要使用 `ps` 指令查看各行程的狀態,但由於 `ps` 的輸出資訊很多,如果我們只想看程式的 PID 與指令內容,就可以用 `cut` 把要用的資訊擷取來:
|
||||
|
||||
```bash
|
||||
# 找出所有 Python 程式的 PID 與指令內容
|
||||
ps aux | grep python | sed 's/\s\+/ /g' | cut -d ' ' -f 2,11-
|
||||
```
|
||||
|
||||
```
|
||||
17100 grep --color=auto python
|
||||
27904 /usr/bin/python -Es /usr/sbin/tuned -l -P
|
||||
33890 /usr/bin/python -Es /usr/sbin/firewalld --nofork --nopid
|
||||
```
|
||||
57
05. 資料收集/Linux/CLI/scp.md
Normal file
57
05. 資料收集/Linux/CLI/scp.md
Normal file
@@ -0,0 +1,57 @@
|
||||
`scp` 指令的語法跟一般的 `cp` 類似,只不過 `scp` 可以在不同的 Linux 主機之間複製檔案,其語法為:
|
||||
```
|
||||
scp [帳號@來源主機]:來源檔案 [帳號@目的主機]:目的檔案
|
||||
```
|
||||
|
||||
# 保留檔案時間與權限
|
||||
若要讓檔案在複製之後,還可保留原本的修改時間、存取時間與權限,可以加上 `-p` 參數:
|
||||
```
|
||||
scp -p /path/file1 myuser@192.168.0.1:/path/file2
|
||||
```
|
||||
|
||||
# 資料壓縮
|
||||
若要將資料壓縮之後再傳送,減少網路頻寬的使用量,可以加上 `-C` 參數:
|
||||
```
|
||||
scp -C /path/file1 myuser@192.168.0.1:/path/file2
|
||||
```
|
||||
|
||||
# 限制傳輸速度
|
||||
若要限制網路的使用頻寬,可以用 `-l` 指定可用的網路頻寬上限值(單位為 Kbit/s):
|
||||
```
|
||||
# 限制傳輸速度為 400 Kbit/s
|
||||
scp -l 400 /path/file1 myuser@192.168.0.1:/path/file2
|
||||
```
|
||||
|
||||
這樣就會限制 `scp` 只能使用 `400` Kbit/s,也就是 `400 / 8 = 50` KB/s。
|
||||
|
||||
# 自訂連接埠
|
||||
一般 SSH 伺服器的連接埠號為 22,如果遇到使用非標準埠號的伺服器,可以用 `-P` 來指定埠號。若遠端的 SSH 伺服器使用 `2222` 這個連接埠,我們就可以這樣複製檔案:
|
||||
```
|
||||
# 使用 2222 連接埠
|
||||
scp -P 2222 /path/file1 myuser@192.168.0.1:/path/file2
|
||||
```
|
||||
|
||||
# IPv4 與 IPv6
|
||||
`-4` 與 `-6` 兩個參數分別可以讓 `scp` 使用 IPv4 與 IPv6 來傳輸資料:
|
||||
```
|
||||
# 使用 IPv4
|
||||
scp -4 /path/file1 myuser@192.168.0.1:/path/file2
|
||||
|
||||
# 使用 IPv6
|
||||
scp -6 /path/file1 myuser@192.168.0.1:/path/file2
|
||||
```
|
||||
|
||||
# 更快的方法:使用SSH+TAR
|
||||
```
|
||||
ssh 使用者@主機 "cd 目標目錄 ;tar -zcvf - 目標" | cat > 目標.tar.gz
|
||||
```
|
||||
|
||||
例:
|
||||
```
|
||||
ssh 192.168.0.22 "cd /var ;tar -zcvf - log" | cat > 22_log.tar.gz
|
||||
```
|
||||
|
||||
# 參考
|
||||
- [SSH + TAR 取代 SCP @ Vexed's Blog :: 隨意窩 Xuite日誌](https://blog.xuite.net/vexed/tech/586811949)
|
||||
- [Linux中互传文件:ssh+tar 与Scp 比较 - 简书](https://www.jianshu.com/p/856a2dc883e0)
|
||||
- [轉貼--ssh tar 命令把遠端檔拉回來或推過去 --- 山城風雲的點滴](http://jimsung168.blogspot.com/2014/01/ssh-tar.html)
|
||||
14
05. 資料收集/Linux/CLI/timedatectl.md
Normal file
14
05. 資料收集/Linux/CLI/timedatectl.md
Normal file
@@ -0,0 +1,14 @@
|
||||
用`timedatectl`可以看現在的時間、時區等等。也可以改變時區。
|
||||
![[Pasted image 20220516125616.png]]
|
||||
|
||||
用`timedatectl list-timezones`列出所有時區,我們已經知道我們的時區是Taipei,所以可以用grep直接把它抓出來:
|
||||
```bash
|
||||
timedatectl list-timezones | grep -i taipei
|
||||
```
|
||||
結果如下:
|
||||
![[Pasted image 20220516125742.png]]
|
||||
|
||||
設定時區:
|
||||
```
|
||||
timedatectl set-timezone Asia/Taipei
|
||||
```
|
||||
1
05. 資料收集/Linux/Programming.md
Normal file
1
05. 資料收集/Linux/Programming.md
Normal file
@@ -0,0 +1 @@
|
||||
- [The Linux Kernel Module Programming Guide](https://sysprog21.github.io/lkmpg/?fbclid=IwAR0iZMkTCkhHzGbL41qqAmdZADiGtZe7Cw556NMuXpwv4cfD0yEer0lcCiU)
|
||||
13
05. 資料收集/Linux/Ubuntu.md
Normal file
13
05. 資料收集/Linux/Ubuntu.md
Normal file
@@ -0,0 +1,13 @@
|
||||
## Hyper-V
|
||||
### Set screen resolution
|
||||
1. `sudo vim /etc/default/grub`
|
||||
2. Find `GRUB_CMDLINE_LINUX_DEFAULT`
|
||||
3. Add `video=hyperv_fb:1600x9000`, e.g. `GRUB_CMDLINE_LINUX_DEFAULT="quiet splash video=hyperv_fb:1600x900"`
|
||||
4. `sudo update-grub `
|
||||
5. `sudo reboot`
|
||||
|
||||
## VirtualBox
|
||||
### Settting
|
||||
#### 操作分享資料夾
|
||||
需要把目前的使用者加到`vboxsf` group才能夠操作分享資料夾。
|
||||
`sudo adduser $USER vboxsf`
|
||||
134
05. 資料收集/Tool Setup/Hardware/RaspberryPi.md
Normal file
134
05. 資料收集/Tool Setup/Hardware/RaspberryPi.md
Normal file
@@ -0,0 +1,134 @@
|
||||
### 登入
|
||||
- 帳號:`pi`
|
||||
- 密碼:`<你自己設的密碼>`
|
||||
|
||||
### 設定固定IP
|
||||
#### Ethernet
|
||||
打開`/etc/dhcpcd.conf`,設定如下:
|
||||
```
|
||||
interface eth0
|
||||
static ip_address=192.168.1.20/24
|
||||
static routers=192.168.1.1
|
||||
static domain_name_servers=168.95.1.1 1.1.1.1
|
||||
```
|
||||
|
||||
#### WIFI
|
||||
打開`/etc/dhcpcd.conf`,設定如下:
|
||||
```
|
||||
interface wlan0
|
||||
static ip_address=192.168.1.21/24
|
||||
static routers=192.168.1.1
|
||||
static domain_name_servers=168.95.1.1 1.1.1.1
|
||||
```
|
||||
|
||||
確定`dhcpcd`與`networking`是enabled,不確定可以直接用下面的命令來啟動。
|
||||
```shell
|
||||
systemctl enable dhcpcd ;\
|
||||
systemctl enable networking
|
||||
```
|
||||
|
||||
### 更新記憶卡容量
|
||||
- [Taiwan-RaspberryPi | 台灣樹莓派 - (1)更新記憶卡容量](https://www.taiwan-raspberrypi.com/start/setting/1%E6%9B%B4%E6%96%B0%E8%A8%98%E6%86%B6%E5%8D%A1%E5%AE%B9%E9%87%8F/)
|
||||
|
||||
### 設定免密碼登入
|
||||
1. 將自己的public key copy到RaspberryPi上:
|
||||
```
|
||||
scp ~/.ssh/rpi.pub pi@<IP_ADDR>:~/.ssh/
|
||||
```
|
||||
2. 登入到RaspberryPi,這一次要輸入密碼:
|
||||
```shell
|
||||
ssh pi@<IP_ADDR>
|
||||
```
|
||||
3. (現在是在RaspberryPi上操作)把剛剛的public key加到`authorized_keys`裡面:
|
||||
```bash
|
||||
cd ~/.ssh ;\
|
||||
cat id_rsa.pub >> authorized_keys
|
||||
```
|
||||
|
||||
## 安裝
|
||||
### Python3
|
||||
```shell
|
||||
sudo apt install python3
|
||||
```
|
||||
|
||||
### Docker
|
||||
#### Install
|
||||
```shell
|
||||
# Install some required packages first
|
||||
sudo apt update ; sudo apt install -y apt-transport-https ca-certificates curl gnupg2 software-properties-common
|
||||
|
||||
# Get the Docker signing key for packages
|
||||
curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg | sudo apt-key add -
|
||||
|
||||
# Add the Docker official repos
|
||||
echo "deb [arch=$(dpkg --print-architecture)] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") \
|
||||
$(lsb_release -cs) stable" | \
|
||||
sudo tee /etc/apt/sources.list.d/docker.list
|
||||
|
||||
# Install Docker
|
||||
sudo apt update ; sudo apt install -y --no-install-recommends docker-ce cgroupfs-mount
|
||||
```
|
||||
|
||||
#### Confirm installation
|
||||
```shell
|
||||
sudo docker run --rm hello-world
|
||||
```
|
||||
如果成功,會有如下的訊息:
|
||||
![[Pasted image 20210125183754.png]]
|
||||
|
||||
### docker-compose
|
||||
```shell
|
||||
# Install required packages
|
||||
sudo apt update ; sudo apt install -y python3-pip libffi-dev
|
||||
|
||||
# Install Docker Compose from pip (using Python3)
|
||||
# This might take a while
|
||||
sudo pip3 install docker-compose
|
||||
```
|
||||
|
||||
#### Confirm installation
|
||||
```shell
|
||||
docker-compose -version
|
||||
```
|
||||
會輸出docker-compose的版本,類似下面:
|
||||
```
|
||||
docker-compose version 1.28.0, build unknown
|
||||
```
|
||||
|
||||
## 更新
|
||||
```shell
|
||||
sudo apt-get update `# 1. 更新 /etc/apt/sources.list 底下的套件清單。` ;\
|
||||
sudo apt-get upgrade `# 2. 比對套件清單決定是否需要更新,但如果要更新的套件有相依性問題,則放棄更新。` ;\
|
||||
sudo apt-get dist-upgrade `# 3. 會處理新版本套件與相依性套件的衝突,並試著安裝/移除有問題的套件來完成更新。` ;\
|
||||
sudo apt-get autoremove `# 4. 刪除之前因為有相依性而安裝,但現在已經不再使用的套件(非必要)。` ;\
|
||||
sudo apt-get autoclean `# 5. 清除下載到 /var/cache/apt/archives 的 .deb 套件檔(非必要)` ;\
|
||||
sudo rpi-update `# 6. 更新核心和韌體到最新版本(可能不穩定),因此更新前一定要先備份重要資料`
|
||||
```
|
||||
|
||||
## 備份
|
||||
1. 下載必須的工具
|
||||
```
|
||||
wget https://raw.githubusercontent.com/Drewsif/PiShrink/master/pishrink.sh
|
||||
sudo chmod +x pishrink.sh
|
||||
sudo mv pishrink.sh /usr/local/bin
|
||||
```
|
||||
1. 插入隨身碟,並將隨身碟mount起來。記住mount的路徑,這邊假設是`/mnt/usb0`。
|
||||
2. 用`lsblk`確認SD卡的device node,這邊假設SD卡是`/dev/mmcblk0`。
|
||||
3. 輸入以下指令,將整片microSD卡備份到USB隨身碟
|
||||
```
|
||||
sudo dd if=/dev/mmcblk0 of=/mnt/usb0/PiBackup_20220513.img bs=1M
|
||||
```
|
||||
這個命令會將整張SD卡dummp到隨身碟,SD卡有多大,產生的img檔就會有多大。
|
||||
這個命令會花上好一點時間。
|
||||
> `dd`命令並不會顯示任何進度或是訊息,若是希望在執行過程中看到一些訊息,可以加入`status=progress`,將可以看到速度的訊息。
|
||||
> 但是`progress`這個小工具是需要另外安裝的,可以用`sudo apt install progress`來安裝。
|
||||
> 例:`sudo dd if=/dev/mmcblk0 of=/mnt/usb0/PiBackup_20220513.img bs=1M status=progress`
|
||||
5. 切換到隨身碟的目錄:`cd /mnt/usb0`。
|
||||
6. 用以下命令來把img變小:
|
||||
```
|
||||
sudo pishrink.sh -z PiBackup_20220513.img
|
||||
```
|
||||
這個命令也會花上好一點時間。
|
||||
|
||||
### 參考
|
||||
- [[Raspberry Pi] 備份樹莓派系統Micro SD卡的最佳做法_PiShrink @ skybow](https://skybow.pixnet.net/blog/post/121176894-%5Braspberry-pi%5D-%E5%82%99%E4%BB%BD%E6%A8%B9%E8%8E%93%E6%B4%BEsd%E5%8D%A1%E7%9A%84%E6%9C%80%E4%BD%B3%E5%81%9A%E6%B3%95)
|
||||
22
05. 資料收集/Tool Setup/Software/Chrome.md
Normal file
22
05. 資料收集/Tool Setup/Software/Chrome.md
Normal file
@@ -0,0 +1,22 @@
|
||||
## Cache to Ramdisk
|
||||
1. 關閉 Chrome
|
||||
2. 開啟檔案總管至以下路徑:`%USERPROFILE%\AppData\Local\Google\Chrome\User Data\Default`
|
||||
3. 刪除 Cache 資料夾
|
||||
4. 用管理員權限開啟 cmd
|
||||
5. 輸入以下指令以建立 Symbolic Link: `mklink /d "%USERPROFILE%\AppData\Local\Google\Chrome\User Data\Default\Cache\" "R:\TEMP\Chrome\"`
|
||||
6. (Optional) 如果有多個使用者的話: `mklink /d "%USERPROFILE%\AppData\Local\Google\Chrome\User Data\Profile 1\Cache\" "R:\TEMP\Chrome\"`
|
||||
|
||||
## 網站黑名單
|
||||
- 用[uBlacklist](https://chrome.google.com/webstore/detail/ublacklist/pncfbmialoiaghdehhbnbhkkgmjanfhe)來阻擋不想要的網站
|
||||
- uBlacklist 也可以設定黑名單,推薦黑名單:
|
||||
- [danny0838/content-farm-terminator at gh-pages](https://github.com/danny0838/content-farm-terminator/tree/gh-pages)
|
||||
- [標準內容農場清單](https://danny0838.github.io/content-farm-terminator/files/blocklist/content-farms.txt)
|
||||
- [類內容農場清單](https://danny0838.github.io/content-farm-terminator/files/blocklist/nearly-content-farms.txt)
|
||||
- [社群內容農場清單](https://danny0838.github.io/content-farm-terminator/files/blocklist/sns-content-farms.txt)
|
||||
- [假新聞網站清單](https://danny0838.github.io/content-farm-terminator/files/blocklist/fake-news.txt)
|
||||
- [詐騙網站清單](https://danny0838.github.io/content-farm-terminator/files/blocklist/scam-sites.txt)
|
||||
- [cobaltdisco/Google-Chinese-Results-Blocklist: 我终于能用谷歌搜中文了……](https://github.com/cobaltdisco/Google-Chinese-Results-Blocklist)
|
||||
- [中文搜索结果黑名单](https://raw.githubusercontent.com/cobaltdisco/Google-Chinese-Results-Blocklist/master/uBlacklist_subscription.txt)
|
||||
|
||||
### 參考
|
||||
- [效率封殺 Google 搜尋裡面的垃圾結果與內容農場 | jkgtw's blog ](https://www.jkg.tw/p3525/)
|
||||
275
05. 資料收集/Tool Setup/Software/Obisidian.md
Normal file
275
05. 資料收集/Tool Setup/Software/Obisidian.md
Normal file
@@ -0,0 +1,275 @@
|
||||
---
|
||||
tags:
|
||||
aliases:
|
||||
date: 2022-05-26
|
||||
time: 14:51:12
|
||||
description:
|
||||
---
|
||||
|
||||
## YAML front matter
|
||||
官方說明:[YAML front matter - Obsidian Help](https://help.obsidian.md/Advanced+topics/YAML+front+matter)
|
||||
目前使用的front matter是[[front matter]]。
|
||||
|
||||
## 自動產生時間日期
|
||||
Obsidian在抽入template的時候,可以使用`{{date}}`來表示日期,用`{{time}}`來表示時間。
|
||||
|
||||
### `{{date}}` & `{{time}}`
|
||||
`{{date}}`產生的時間格式為`2022-05-26`,可以使用參數來更改格式,例如不要讓月份與日期自動補0,可以用`{{date:YYYY-M-D}}`。
|
||||
時間也一樣,`{{time}}`產生的格式為`14:48:45`,也有其他參數來變更格式,其他更詳細參考[Moment.js | Docs](https://momentjs.com/docs/#/displaying/)。
|
||||
|
||||
## Customize CSS
|
||||
路徑是`<valut_name>\.obsidian\snippets\obsidian.css`
|
||||
Obsidian預設定義了很多CSS class,只要更改這些class就可以定義自己喜歡的外觀。
|
||||
- [Obsidian自定义样式修改教程 - 知乎](https://zhuanlan.zhihu.com/p/373888121)
|
||||
- [obsidian-css-snippets](https://github.com/Dmytro-Shulha/obsidian-css-snippets/tree/master/Snippets)
|
||||
- [使用 CSS 代码片段增强 Obsidian 视觉效果(一) | ReadingHere](https://www.readinghere.com/blog/using-css-snippets-to-enhance-obsidian-visuals-cn/)
|
||||
|
||||
## My CSS
|
||||
The CSS content:
|
||||
```css
|
||||
/*************************************************************
|
||||
* Headers
|
||||
*/
|
||||
.cm-header-1, .markdown-preview-section h1 {
|
||||
color: #081f37;
|
||||
}
|
||||
|
||||
.cm-header-2, .markdown-preview-section h2 {
|
||||
color: #1e549f;
|
||||
}
|
||||
|
||||
.cm-header-3, .markdown-preview-section h3 {
|
||||
color: #2e79ba;
|
||||
}
|
||||
|
||||
.cm-header-4, .markdown-preview-section h4 {
|
||||
color: #5fc9f3;
|
||||
}
|
||||
|
||||
.cm-header-5, .markdown-preview-section h5 {
|
||||
color: #415865;
|
||||
}
|
||||
|
||||
.cm-header-6, .markdown-preview-section h6 {
|
||||
color: #7a9eb1;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* List
|
||||
*/
|
||||
.cm-list-1 {
|
||||
font-family: Cascadia Code;
|
||||
}
|
||||
|
||||
.cm-list-2 {
|
||||
font-family: Cascadia Code;
|
||||
}
|
||||
|
||||
.cm-list-3 {
|
||||
font-family: Cascadia Code;
|
||||
}
|
||||
|
||||
.cm-list-4 {
|
||||
font-family: Cascadia Code;
|
||||
}
|
||||
|
||||
.cm-list-5 {
|
||||
font-family: Cascadia Code;
|
||||
}
|
||||
|
||||
span.cm-formatting-list-ul {
|
||||
visibility: hidden !important;
|
||||
}
|
||||
|
||||
span.cm-formatting-list-ul:after {
|
||||
content: '• '; /* ITS theme; for Blue Topaz */
|
||||
margin-left: -12px;
|
||||
color: var(--accent); /* ITS theme; for Blue Topaz --text-normal */
|
||||
visibility: visible !important;
|
||||
}
|
||||
|
||||
ol {
|
||||
font-family: Cascadia Code;
|
||||
padding-inline-start: 2.5rem;
|
||||
}
|
||||
|
||||
ul {
|
||||
font-family: Cascadia Code;
|
||||
padding-inline-start: 2.4rem;
|
||||
list-style-type: disc;
|
||||
}
|
||||
|
||||
/*Make list marker to be a circle*/
|
||||
input[type="checkbox"],
|
||||
.cm-formatting-task {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
border-radius: 50%;
|
||||
border: 1px solid var(--text-faint);
|
||||
padding: 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.cm-s-obsidian span.cm-formatting-task {
|
||||
color: transparent;
|
||||
width: 1.1em !important;
|
||||
height: 1.1em;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
input[type="checkbox"]:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
input[type="checkbox"]:checked,
|
||||
.cm-formatting-task.cm-property {
|
||||
background-color: var(--text-accent-hover);
|
||||
border: 1px solid var(--text-accent-hover);
|
||||
background-position: center;
|
||||
background-size: 60%;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url('data:image/svg+xml; utf8, <svg width="12px" height="10px" viewBox="0 0 12 8" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g transform="translate(-4.000000, -6.000000)" fill="%23ffffff"><path d="M8.1043257,14.0367999 L4.52468714,10.5420499 C4.32525014,10.3497722 4.32525014,10.0368095 4.52468714,9.8424863 L5.24777413,9.1439454 C5.44721114,8.95166768 5.77142411,8.95166768 5.97086112,9.1439454 L8.46638057,11.5903727 L14.0291389,6.1442083 C14.2285759,5.95193057 14.5527889,5.95193057 14.7522259,6.1442083 L15.4753129,6.84377194 C15.6747499,7.03604967 15.6747499,7.35003511 15.4753129,7.54129009 L8.82741268,14.0367999 C8.62797568,14.2290777 8.3037627,14.2290777 8.1043257,14.0367999"></path></g></g></svg>');
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* External link & Internal link
|
||||
*/
|
||||
.cm-s-obsidian span.cm-link,
|
||||
.cm-s-obsidian span.cm-url,
|
||||
.cm-s-obsidian span.cm-hmd-internal-link {
|
||||
color: #0000EE;
|
||||
font-family: Cascadia Code;
|
||||
}
|
||||
|
||||
a.external-link {
|
||||
color: #0000EE;
|
||||
font-family: Cascadia Code;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* Outline
|
||||
*/
|
||||
.outline {
|
||||
font-size: 0.8rem;
|
||||
font-weight: 200;
|
||||
}
|
||||
|
||||
.outline .tree-item {
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.outline .tree-item-self {
|
||||
padding-top: 0.2rem;
|
||||
padding-bottom: 0.1rem;
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.3rem;
|
||||
}
|
||||
|
||||
.outline .tree-item-collapse {
|
||||
left: 0.1rem;
|
||||
}
|
||||
|
||||
.outline .tree-item-inner{
|
||||
position:relative;
|
||||
padding-top: 0.2rem;
|
||||
/* padding-left: 1rem; */
|
||||
padding-left: 1.7em;
|
||||
text-indent: -0.8em;
|
||||
margin-left: 0.2rem;
|
||||
/* font-size: 0.9em; */
|
||||
}
|
||||
|
||||
.outline .tree-item-children {
|
||||
margin-left: 0.7rem;
|
||||
padding-left: 0.5rem;
|
||||
margin-top: -0.3rem;
|
||||
padding-top: 0.3rem;
|
||||
border-left: 1px solid var(--sidebar-marks, var(--background-modifier-border));
|
||||
border-radius: 4px;
|
||||
transition:all 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
.outline .tree-item-children:hover {
|
||||
border-left-color: var(--sidebar-marks-hover, var(--background-secondary));
|
||||
}
|
||||
|
||||
.outline .collapse-icon + .tree-item-inner {
|
||||
font-weight: 400;
|
||||
padding-left: 0.2rem;
|
||||
/* margin-left: 0rem; */
|
||||
/* font-size: 1em; */
|
||||
}
|
||||
|
||||
.outline .collapse-icon {
|
||||
margin-top: 0.2rem;
|
||||
margin-left: -0.4rem;
|
||||
margin-right: -0.4rem;
|
||||
width: 2rem;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************
|
||||
* Sidebar
|
||||
*/
|
||||
/*Vault name*/
|
||||
.nav-folder.mod-root > .nav-folder-title {
|
||||
padding-left: 6px;
|
||||
font-size: 14px;
|
||||
font-weight: bolder;
|
||||
top: -6px; /* higher */
|
||||
cursor: default;
|
||||
color: var(--base2);
|
||||
}
|
||||
|
||||
.nav-folder-title,
|
||||
.nav-file-title {
|
||||
font-size: 0.8em;
|
||||
font-family: consolas;
|
||||
line-height: 0.8em;
|
||||
}
|
||||
|
||||
.nav-folder-title {
|
||||
font-weight: bold;
|
||||
color: #132743;
|
||||
}
|
||||
|
||||
.nav-file-title {
|
||||
color: #407088;
|
||||
}
|
||||
|
||||
.nav-folder,
|
||||
.nav-file {
|
||||
margin: 0 !important;
|
||||
border-left: 1px solid rgba(118, 158, 165, 0.2);
|
||||
}
|
||||
|
||||
.cm-quote {
|
||||
line-height: 1.2em;
|
||||
/*font-style: italic;*/
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************
|
||||
* Quote
|
||||
*/
|
||||
.cm-formatting-quote:before {
|
||||
margin-right: -0.1em;
|
||||
color: var(--color-10) !important;
|
||||
font-family: "ico";
|
||||
content: "\edd5";
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************
|
||||
* Code block(inline)
|
||||
*/
|
||||
.cm-s-obsidian span.cm-inline-code {
|
||||
/*font-size: 1em;*/
|
||||
}
|
||||
```
|
||||
|
||||
## 參考
|
||||
- [使用 CSS 代码片段增强 Obsidian 视觉效果(一) | ReadingHere](https://www.readinghere.com/blog/using-css-snippets-to-enhance-obsidian-visuals-cn/)
|
||||
- [obsidian-css-snippets](https://github.com/Dmytro-Shulha/obsidian-css-snippets/tree/master/Snippets)
|
||||
- [Obsidian自定义样式修改教程 - 知乎](https://zhuanlan.zhihu.com/p/373888121)
|
||||
- [Day 26 : 插件篇 05 — 做好筆記備份,使用 Obsidian Git自動備份筆記到 Github - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天](https://ithelp.ithome.com.tw/articles/10280373)
|
||||
24
05. 資料收集/Tool Setup/Software/SublimeText.md
Normal file
24
05. 資料收集/Tool Setup/Software/SublimeText.md
Normal file
@@ -0,0 +1,24 @@
|
||||
```json
|
||||
// Settings in here override those in "Default/Preferences.sublime-settings",
|
||||
// and are overridden in turn by syntax-specific settings.
|
||||
{
|
||||
"close_windows_when_empty": true,
|
||||
"draw_indent_guides": false,
|
||||
"font_face": "Fira Code",
|
||||
"font_size": 11,
|
||||
"highlight_modified_tabs": true,
|
||||
"ignored_packages":
|
||||
[
|
||||
"Vintage"
|
||||
],
|
||||
"show_full_path": true,
|
||||
"show_tab_close_buttons": false,
|
||||
"spell_check": false,
|
||||
"tab_size": 4,
|
||||
"translate_tabs_to_spaces": true,
|
||||
"use_tab_stops": true,
|
||||
"draw_white_space": "all",
|
||||
"trim_trailing_white_space_on_save": true,
|
||||
"word_separators": "./\\()\"'-:,.;<>~!@#%^&*|+=[]{}`~?"
|
||||
}
|
||||
```
|
||||
6
05. 資料收集/Tool Setup/Software/VirtualBox.md
Normal file
6
05. 資料收集/Tool Setup/Software/VirtualBox.md
Normal file
@@ -0,0 +1,6 @@
|
||||
## 讓Virtualbox與Hyper-V並存
|
||||
用Administrator打開Powershell,輸入以下指令:
|
||||
```
|
||||
cd "C:\Program Files\Oracle\VirtualBox"
|
||||
./VBoxManage.exe setextradata global "VBoxInternal/NEM/UseRing0Runloop" 0
|
||||
```
|
||||
328
05. 資料收集/Tool Setup/Software/Visual Studio Code.md
Normal file
328
05. 資料收集/Tool Setup/Software/Visual Studio Code.md
Normal file
@@ -0,0 +1,328 @@
|
||||
# 快速鍵
|
||||
## 顯示快速鍵列表
|
||||
- Windows: `Ctrl + k` + `Ctrl + s`
|
||||
- Mac: `⌘ + k` + `⌘ + s`
|
||||
|
||||
## 分割目前視窗
|
||||
- Windows: `Ctrl + \`
|
||||
- Mac: `⌘ + \`
|
||||
|
||||
## 程式格式化
|
||||
### 格式化整個文件
|
||||
`Shift + Alf + f`
|
||||
|
||||
### 格式化選取的範圍
|
||||
`Ctrl + k` + `Ctrl + f`
|
||||
|
||||
### setting.json
|
||||
- `"editor.formatOnType": true`:輸入一行後,自動格式化目前這一行。
|
||||
- `"editor.formatOnSave": true`:儲存時格式化檔案。
|
||||
- `"editor.formatOnPaste": true`:貼上程式碼時格式化貼上的內容。
|
||||
|
||||
```json
|
||||
{
|
||||
"python.terminal.activateEnvironment": true, // 自動啟動環境
|
||||
"python.linting.pylintEnabled": true, // 需要 pip install pylint
|
||||
"python.linting.enabled": true,
|
||||
"python.autoComplete.addBrackets": true, // 自動為自動完成的function加上括號
|
||||
"python.languageServer": "Pylance",
|
||||
"python.analysis.completeFunctionParens": true,
|
||||
"jupyter.sendSelectionToInteractiveWindow": true,
|
||||
"jupyter.interactiveWindowMode": "perFile",
|
||||
|
||||
"terminal.integrated.fontFamily": "Fira Code", // For Windows
|
||||
"terminal.integrated.profiles.windows": {
|
||||
"Command Prompt": {
|
||||
"path": [
|
||||
"${env:windir}\\Sysnative\\cmd.exe",
|
||||
"${env:windir}\\System32\\cmd.exe"
|
||||
],
|
||||
"args": [],
|
||||
"icon": "terminal-cmd"
|
||||
},
|
||||
"Git Bash": {
|
||||
"source": "Git Bash"
|
||||
},
|
||||
"PowerShell -NoProfile": {
|
||||
"source": "PowerShell",
|
||||
"args": ["-NoProfile"]
|
||||
}
|
||||
},
|
||||
"terminal.integrated.defaultProfile.windows": "Command Prompt",
|
||||
"terminal.integrated.cwd": "${fileDirname}",
|
||||
|
||||
// "editor.fontFamily": "Cascadia code Light",
|
||||
// "editor.fontFamily": "PragmataPro Liga",
|
||||
// "editor.fontFamily": "Fira Code Retina",
|
||||
"editor.fontFamily": "Iosevka Expanded",
|
||||
// "editor.fontFamily": "Hasklig Light",
|
||||
"editor.fontSize": 14,
|
||||
"editor.fontLigatures": true,
|
||||
"editor.fontWeight": "normal",
|
||||
"editor.minimap.renderCharacters": false,
|
||||
"editor.renderWhitespace": "boundary",
|
||||
"editor.renderIndentGuides": false,
|
||||
"editor.insertSpaces": true,
|
||||
"editor.tabSize": 4,
|
||||
"editor.bracketPairColorization.enabled": true,
|
||||
|
||||
"outline.showVariables": false,
|
||||
|
||||
"sync.gist": "aaee0ee8733879ef2da2eb1b4bf8a993",
|
||||
"sync.quietSync": false,
|
||||
"sync.removeExtensions": true,
|
||||
"sync.syncExtensions": true,
|
||||
"sync.autoDownload": false,
|
||||
"sync.autoUpload": false,
|
||||
"sync.forceDownload": false,
|
||||
|
||||
"files.trimTrailingWhitespace": true,
|
||||
"files.insertFinalNewline": true,
|
||||
|
||||
"explorer.confirmDelete": false,
|
||||
|
||||
"workbench.colorTheme": "One Dark Pro",
|
||||
"workbench.iconTheme": "material-icon-theme",
|
||||
"workbench.editorAssociations": {
|
||||
"*.ipynb": "jupyter.notebook.ipynb"
|
||||
},
|
||||
|
||||
"oneDarkPro.vivid": true,
|
||||
"gitlens.advanced.messages": {
|
||||
"suppressImproperWorkspaceCasingWarning": true
|
||||
},
|
||||
"workbench.colorCustomizations": {
|
||||
"editor.lineHighlightBackground": "#1073cf2d",
|
||||
"editor.lineHighlightBorder": "#9fced11f"
|
||||
},
|
||||
"editor.wordWrap": "off",
|
||||
"diffEditor.wordWrap": "off",
|
||||
"editor.guides.indentation": false,
|
||||
"editor.guides.bracketPairs": false,
|
||||
}
|
||||
```
|
||||
|
||||
## 折疊程式碼
|
||||
### 收起目前區塊
|
||||
- Windows: `Ctrl + Shift + [`
|
||||
- Mac: `⌥ + ⌘ + [`
|
||||
|
||||
### 打開目前區塊
|
||||
- Windows: `Ctrl + Shift + ]`
|
||||
- Mac: `⌥ + ⌘ + ]`
|
||||
|
||||
### 收起目前區塊(整個檔案)
|
||||
- Windows: `Ctrl + (K => 0) (zero)`
|
||||
- Mac: `⌘ + (K => 0) (zero)`
|
||||
|
||||
### 打開目前區塊(整個檔案)
|
||||
- Windows: `Ctrl + (K => J) `
|
||||
- Mac: `⌘ + (K => J)`
|
||||
|
||||
## 在「已開啟的檔案」間跳轉
|
||||
`Ctrl + tab`
|
||||
|
||||
# Plugin
|
||||
## Setting Sync
|
||||
- 參考:[https://marketplace.visualstudio.com/items?itemName=Shan.code-settings-sync](https://marketplace.visualstudio.com/items?itemName=Shan.code-settings-sync)
|
||||
~~- GIST Token: `e0f7c5233e3c6dafee77047f61ea74f0d01d24e1`~~
|
||||
- GIST Token: `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`
|
||||
- GIST ID: [`aaee0ee8733879ef2da2eb1b4bf8a993`](https://gist.github.com/AwinHuang/aaee0ee8733879ef2da2eb1b4bf8a993)
|
||||
- GIST address: [https://gist.github.com/AwinHuang/aaee0ee8733879ef2da2eb1b4bf8a993](https://gist.github.com/AwinHuang/aaee0ee8733879ef2da2eb1b4bf8a993)
|
||||
|
||||
# Code snippets
|
||||
## html.json
|
||||
```json
|
||||
{
|
||||
"HTML template": {
|
||||
"prefix": "HTML_template",
|
||||
"body": [
|
||||
"<!doctype html>",
|
||||
"",
|
||||
"<html lang=\"en\">",
|
||||
"<head>",
|
||||
" <meta charset=\"utf-8\">",
|
||||
" <meta name=\"description\" content=\"Awin's HTML template\">",
|
||||
" <meta name=\"author\" content=\"Awin Huang\">",
|
||||
" <script src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js\"></script>",
|
||||
" <title>A HTML template</title>",
|
||||
"</head>",
|
||||
"",
|
||||
"<body>",
|
||||
" <H1>Awin's HTML template</H1>",
|
||||
" <p>Click to hide</p>",
|
||||
"</body>",
|
||||
"</html>",
|
||||
"",
|
||||
"<script>",
|
||||
" $(document).ready(function(){",
|
||||
" $(\"p\").click(function(){",
|
||||
" $(this).hide();",
|
||||
" });",
|
||||
" });",
|
||||
"</script>",
|
||||
],
|
||||
"description": "HTML template"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## python.json
|
||||
```json
|
||||
{
|
||||
"Python template": {
|
||||
"prefix": "Python_Template",
|
||||
"body": [
|
||||
"import sys",
|
||||
"import argparse",
|
||||
"",
|
||||
"",
|
||||
"def main(args=None):",
|
||||
" ${1:pass}",
|
||||
"",
|
||||
"",
|
||||
"if __name__ == '__main__':",
|
||||
" parser = argparse.ArgumentParser()",
|
||||
" parser.add_argument(\"first_file\", help=\"The first file\")",
|
||||
" parser.add_argument(\"-s\", \"--sample_args\", default=\"sample_args\", help=\"Modify this arguments for you\")",
|
||||
" args = parser.parse_args()",
|
||||
" main(args)",
|
||||
" sys.exit(0)"
|
||||
],
|
||||
"description": "Python script template"
|
||||
},
|
||||
|
||||
"F Print": {
|
||||
"prefix": "f-print",
|
||||
"body": [
|
||||
"print(f'$1 = {$1}')"
|
||||
],
|
||||
"description": "print() with f-string and default {}"
|
||||
},
|
||||
"Q Print": {
|
||||
"prefix": "q-print",
|
||||
"body": [
|
||||
"print('$1 = {}, '.format($1))"
|
||||
],
|
||||
"description": "print() with f-string and default {}"
|
||||
},
|
||||
"Debug RobotRun": {
|
||||
"prefix": "debug_robotrun",
|
||||
"body": [
|
||||
"import os",
|
||||
"import sys",
|
||||
"sys.path.insert(0, 'D:/codes/logitech/')",
|
||||
"import RobotRun",
|
||||
"print('+------------------------------------------------------------------------------+')",
|
||||
"print('| |')",
|
||||
"print('| RobotRun: {}'.format(RobotRun.__file__))",
|
||||
"print('| |')",
|
||||
"print('+------------------------------------------------------------------------------+')",
|
||||
],
|
||||
"description": "Change RobotRun to local version"
|
||||
},
|
||||
"Flask template": {
|
||||
"prefix": "Flask_Template",
|
||||
"body": [
|
||||
"## Flask template",
|
||||
"## Author: Awin Huang",
|
||||
"## Date: 2020/04/09",
|
||||
"",
|
||||
"import os, sys",
|
||||
"import datetime",
|
||||
"import json",
|
||||
"from flask import Flask, render_template, request",
|
||||
"",
|
||||
"",
|
||||
"app = Flask(__name__)",
|
||||
"",
|
||||
"## Setup log",
|
||||
"handler = logging.FileHandler('flask.log', delay=False)",
|
||||
"handler.setLevel(logging.INFO)",
|
||||
"app.logger.addHandler(handler)",
|
||||
"app.logger.setLevel(logging.INFO)",
|
||||
"",
|
||||
"",
|
||||
"def info_log(msg):",
|
||||
" app.logger.info(msg)",
|
||||
" # print(msg)",
|
||||
"",
|
||||
"",
|
||||
"def error_log(msg):",
|
||||
" app.logger.error(msg)",
|
||||
"",
|
||||
"",
|
||||
"@app.route('/')",
|
||||
"def index():",
|
||||
" info_log('Return main page to user.')",
|
||||
" return 'Hello, this is main page'",
|
||||
"",
|
||||
"",
|
||||
"## Receive a GET request",
|
||||
"@app.route('/get_get', methods=['GET'])",
|
||||
"def run_testcase():",
|
||||
" command = request.args.get('command')",
|
||||
" value = 'This is value for GET'",
|
||||
" return {",
|
||||
" 'command': command,",
|
||||
" 'value': value",
|
||||
" }",
|
||||
"",
|
||||
"",
|
||||
"## Receive a POST request",
|
||||
"@app.route('/get_post', methods=['POST'])",
|
||||
"def get_post():",
|
||||
" command = request.form['command']",
|
||||
" value = 'This is value for POST'",
|
||||
" return {",
|
||||
" 'command': command:",
|
||||
" 'value': value",
|
||||
" }",
|
||||
"",
|
||||
"",
|
||||
"if __name__ == '__main__':",
|
||||
" app.debug = True",
|
||||
" app.run(host='0.0.0.0')",
|
||||
],
|
||||
"description": "Flask template"
|
||||
},
|
||||
"Datetime now": {
|
||||
"prefix": "now_dt",
|
||||
"body": [
|
||||
"datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S:%f')"
|
||||
],
|
||||
"description": "Get datetime.now() with format '%Y-%m-%d %H:%M:%S:%f'"
|
||||
},
|
||||
"Run process": {
|
||||
"prefix": "runprocess",
|
||||
"body": [
|
||||
"import multiprocessing as mp",
|
||||
"",
|
||||
"process = mp.Process(target=task_set.run, args=(self.task_sync, args))",
|
||||
"process.start()",
|
||||
"process.join()"
|
||||
],
|
||||
"description": "Run function in a process"
|
||||
},
|
||||
"Sleep with dots": {
|
||||
"prefix": "sleepdots",
|
||||
"body": [
|
||||
"for i in range($1):",
|
||||
" import time",
|
||||
" print(\".\", end=\"\", flush=True)",
|
||||
" time.sleep(1)",
|
||||
],
|
||||
"description": "Sleep and print \".\" every second"
|
||||
},
|
||||
"Sleep with numbers": {
|
||||
"prefix": "sleepnum",
|
||||
"body": [
|
||||
"for i in range($1):",
|
||||
" print(f\"{i+1} \", end=\"\", flush=True)",
|
||||
" time.sleep(1)",
|
||||
],
|
||||
"description": "Sleep and print number every second"
|
||||
},
|
||||
}
|
||||
|
||||
```
|
||||
166
05. 資料收集/Tool Setup/Software/Windows Setup.md
Normal file
166
05. 資料收集/Tool Setup/Software/Windows Setup.md
Normal file
@@ -0,0 +1,166 @@
|
||||
### Install tools
|
||||
#### 先安裝
|
||||
- 手動安裝[Google Drive](https://www.google.com/drive/download/),以取得本檔案。
|
||||
|
||||
#### 自動安裝
|
||||
1. 安裝[Chocolatey](https://chocolatey.org/),用Administrator身份打開powershell,輸入下列指令:
|
||||
```
|
||||
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
|
||||
```
|
||||
2. 用安裝常用的工具
|
||||
```
|
||||
choco install 7zip adobereader vscode hxd sublimetext4 microsoft-windows-terminal androidstudio intellijidea-community git winmerge freefilesync freedownloadmanager gsudo firacode cascadiacode sourcecodepro delta --yes
|
||||
```
|
||||
|
||||
列表:
|
||||
- 7zip
|
||||
- adobereader
|
||||
- vscode
|
||||
- hxd
|
||||
- [sublimetext4](https://community.chocolatey.org/packages/sublimetext4/4.0.0.412100)
|
||||
- microsoft-windows-terminal
|
||||
- androidstudio
|
||||
- [intellijidea-community](https://chocolatey.org/packages/intellijidea-community)
|
||||
- git
|
||||
- winmerge
|
||||
- [freefilesync](https://chocolatey.org/packages/freefilesync)
|
||||
- [freedownloadmanager](https://chocolatey.org/packages/FreeDownloadManager)
|
||||
- [gsudo](https://community.chocolatey.org/packages/gsudo)
|
||||
- [firacode](https://community.chocolatey.org/packages/FiraCode)
|
||||
- [cascadiacode](https://community.chocolatey.org/packages/cascadiacode)
|
||||
- [sourcecodepro](https://community.chocolatey.org/packages/SourceCodePro)
|
||||
- [delta](https://community.chocolatey.org/packages/delta)
|
||||
|
||||
移除:
|
||||
- [TeraCopy](https://chocolatey.org/packages/TeraCopy)
|
||||
- googlechrome
|
||||
- make
|
||||
|
||||
#### 手動安裝
|
||||
1. Google drive
|
||||
2. Google drive(Logitech)
|
||||
3. Python 3.6.3
|
||||
4. Python 3.9
|
||||
6. Visual Studio 2017
|
||||
7. Visual Studio 2019
|
||||
8. Office 365
|
||||
9. Lightroom
|
||||
10. [Enpass](https://www.enpass.io/)
|
||||
11. [ShareX](https://getsharex.com/)
|
||||
12. [win32diskimager](https://sourceforge.net/projects/win32diskimager/)
|
||||
13. [卡巴斯基](https://www.kaspersky.com.tw/)
|
||||
|
||||
#### Portable App
|
||||
1. Aegisub portable
|
||||
2. Audacity 2.3.3
|
||||
3. Cheat Engine 7.0
|
||||
4. cmder v1.3.12
|
||||
5. ConEmu
|
||||
6. ConvertZZ.1.0.0.3
|
||||
7. CrystalDiskMark 6.0.1 x64
|
||||
8. EzMeta
|
||||
9. ffmpeg-2020-09-20-full_build
|
||||
10. FileZillaPortable
|
||||
11. Geek Uninstaller 1.4.7
|
||||
12. HxDPortable
|
||||
13. ImgBurnPortable
|
||||
14. IntelliJ IDEA
|
||||
15. JDownloader 2.0
|
||||
16. PhraseExpress
|
||||
17. Process Explorer 16.21
|
||||
18. Q-Dir 9.01
|
||||
19. Rufus
|
||||
20. Sandboxie
|
||||
21. [Speccy](https://www.ccleaner.com/speccy)
|
||||
22. [ThunderbirdPortable](https://portableapps.com/apps/internet/thunderbird_portable)
|
||||
23. [WindowGrid 1.3.11](http://windowgrid.net/)
|
||||
24. [wiztree_3_35_portable](https://wiztreefree.com/download)
|
||||
|
||||
### Upgrade
|
||||
#### Upgrade by Chocolately
|
||||
```
|
||||
choco upgrade all -y
|
||||
```
|
||||
|
||||
### Setup
|
||||
#### Setup doskey in **Command Prompt**
|
||||
1. 切換到`Document`資料夾。
|
||||
2. 建立`cmdinit.cmd`,內容如下:
|
||||
```
|
||||
@echo off
|
||||
doskey sl="C:\Program Files\Sublime Text 3\sublime_text.exe"
|
||||
doskey ll=dir
|
||||
doskey rrp="cd C:\Python363\lib\site-packages\RobotRun" $T C:
|
||||
doskey rra=cd "G:\My Drive\codes\Projects\RobotRunApplications" $T G:
|
||||
doskey gpull=git pull origin master
|
||||
doskey gpush=git push origin master
|
||||
doskey gs=git status
|
||||
doskey gd=git diff
|
||||
doskey e.=explorer.exe .
|
||||
```
|
||||
|
||||
#### Setup bashrc in **Git bash**
|
||||
1. 打開`~/.bashrc`。
|
||||
2. 內容如下:
|
||||
```bash
|
||||
export PATH="/c/Users/ahuang11/AppData/Local/Android/Sdk/platform-tools:$PATH"
|
||||
|
||||
alias adb="/c/EasyAVEngine/Tools/Android/ADB/adb.exe"
|
||||
alias sl="/c/Program\ Files/Sublime\ Text/subl.exe"
|
||||
alias fastboot='/c/Users/ahuang11/AppData/Local/Android/Sdk/platform-tools/fastboot.exe'
|
||||
alias rrp='cd /c/Python363/lib/site-packages/RobotRun'
|
||||
alias rra='cd /c/RobotRun'
|
||||
alias rrd='cd /g/My\ Drive/codes/Projects/RobotRunDocs'
|
||||
alias rro='cd /c/RobotRun/Output'
|
||||
alias coderrp='cd "/c/Python363/lib/site-packages/RobotRun" ; code "/c/Python363/lib/site-packages/RobotRun"'
|
||||
alias coderra='cd "/c/RobotRun"; code "/c/RobotRun"'
|
||||
alias coderras='code "/d/GoogleDriveLogi/codes/Projects/RobotRunAutoServer"'
|
||||
alias ctest='code "/g/My Drive/codes/test"'
|
||||
alias ad='adb devices'
|
||||
alias fd='fastboot devices'
|
||||
alias e.='explorer.exe .'
|
||||
|
||||
##----- Connection -----
|
||||
alias gods='ssh awin@192.168.1.11'
|
||||
alias gorp320='ssh pi@192.168.1.20'
|
||||
|
||||
##----- Git -----
|
||||
alias gs="git status"
|
||||
alias gd="git diff"
|
||||
alias gpull='git pull origin master'
|
||||
alias gpush='git push origin master'
|
||||
alias gpushmain='git push origin main'
|
||||
alias gc='git clone'
|
||||
alias gclogi='git clone --config user.name="Awin Huang" --config user.email=ahuang11@logitech.com $@'
|
||||
|
||||
##----- Python enviroment swich -----
|
||||
alias pyv='echo PY_PYTHON=$PY_PYTHON'
|
||||
|
||||
function set_py() {
|
||||
echo "Original Python verison is \"$PY_PYTHON\""
|
||||
export PY_PYTHON=$1
|
||||
echo " New Python verison is \"$PY_PYTHON\""
|
||||
|
||||
if [ ! -z "$2" ]
|
||||
then
|
||||
py "${@:2}"
|
||||
fi
|
||||
}
|
||||
|
||||
function py36() {
|
||||
set_py "3.6.3" "$@"
|
||||
}
|
||||
|
||||
function py39() {
|
||||
set_py "3.9" "$@"
|
||||
}
|
||||
```
|
||||
|
||||
#### Setup Windows Terminal
|
||||
|
||||
1. 開啟Windows Terminal。
|
||||
2. 按`ctrl + ,`打開設定,之後參考[[Windows Terminal]]。
|
||||
|
||||
#### Setup WSL2
|
||||
- [[安裝筆記] Windows 10 安裝 Linux 子系統 (WSL2) | Kenmingの鮮思維](http://www.kenming.idv.tw/note_window10_install_wsl2/)
|
||||
- [[安裝筆記] Windows 10 WSL 2 安裝 Docker Desktop (含更改 Docker Image 路徑) | Kenmingの鮮思維](http://www.kenming.idv.tw/win10_wsl2_install_docker-desktop/)
|
||||
181
05. 資料收集/Tool Setup/Software/Windows Terminal.md
Normal file
181
05. 資料收集/Tool Setup/Software/Windows Terminal.md
Normal file
@@ -0,0 +1,181 @@
|
||||
## Setup
|
||||
### New tab as Administrator
|
||||
- [使用系統管理員身分開啟 Windows Terminal 分頁](https://blog.poychang.net/run-windows-terminal-as-administrator-with-elevated-admin-permissions/)
|
||||
|
||||
### Use powerline in Git-Bash
|
||||
- [Light & simple powerline theme for Git bash for windows](https://github.com/diesire/git_bash_windows_powerline)
|
||||
|
||||
#### Install
|
||||
```shell
|
||||
cd $HOME
|
||||
mkdir -p .bash/themes/git_bash_windows_powerline
|
||||
git clone https://github.com/diesire/git_bash_windows_powerline.git .bash/themes/git_bash_windows_powerline
|
||||
```
|
||||
|
||||
And add following lines to `~/.bashrc`.
|
||||
```
|
||||
# Theme
|
||||
THEME=$HOME/.bash/themes/git_bash_windows_powerline/theme.bash
|
||||
if [ -f $THEME ]; then
|
||||
. $THEME
|
||||
fi
|
||||
unset THEME
|
||||
```
|
||||
|
||||
參考:
|
||||
- [powerline/fonts: Patched fonts for Powerline users.](https://github.com/powerline/fonts)
|
||||
|
||||
## Settings.json
|
||||
```json
|
||||
// This file was initially generated by Windows Terminal 1.6.10571.0
|
||||
// It should still be usable in newer versions, but newer versions might have additional
|
||||
// settings, help text, or changes that you will not see unless you clear this file
|
||||
// and let us generate a new one for you.
|
||||
|
||||
// To view the default settings, hold "alt" while clicking on the "Settings" button.
|
||||
// For documentation on these settings, see: https://aka.ms/terminal-documentation
|
||||
// This file was initially generated by Windows Terminal 1.2.2381.0
|
||||
// It should still be usable in newer versions, but newer versions might have additional
|
||||
// settings, help text, or changes that you will not see unless you clear this file
|
||||
// and let us generate a new one for you.
|
||||
|
||||
// To view the default settings, hold "alt" while clicking on the "Settings" button.
|
||||
// For documentation on these settings, see: https://aka.ms/terminal-documentation
|
||||
{
|
||||
"$schema": "https://aka.ms/terminal-profiles-schema",
|
||||
|
||||
"defaultProfile": "{00000000-0000-0000-ba54-000000000002}",
|
||||
|
||||
// You can add more global application settings here.
|
||||
// To learn more about global settings, visit https://aka.ms/terminal-global-settings
|
||||
|
||||
// If enabled, selections are automatically copied to your clipboard.
|
||||
"copyOnSelect": false,
|
||||
|
||||
// If enabled, formatted data is also copied to your clipboard
|
||||
"copyFormatting": false,
|
||||
|
||||
// Start position
|
||||
"initialCols": 205,
|
||||
"initialRows": 30,
|
||||
"initialPosition": "15,400", // x,y
|
||||
|
||||
// A profile specifies a command to execute paired with information about how it should look and feel.
|
||||
// Each one of them will appear in the 'New Tab' dropdown,
|
||||
// and can be invoked from the commandline with `wt.exe -p xxx`
|
||||
// To learn more about profiles, visit https://aka.ms/terminal-profile-settings
|
||||
"profiles":
|
||||
{
|
||||
"defaults":
|
||||
{
|
||||
// Put settings here that you want to apply to all profiles.
|
||||
},
|
||||
"list":
|
||||
[
|
||||
{
|
||||
// Make changes here to the powershell.exe profile.
|
||||
"guid": "{61c54bbd-c2c6-5271-96e7-009a87ff44bf}",
|
||||
"name": "Windows PowerShell",
|
||||
"commandline": "powershell.exe",
|
||||
"hidden": false
|
||||
},
|
||||
{
|
||||
"guid": "{41dd7a51-f0e1-4420-a2ec-1a7130b7e950}",
|
||||
"name": "Windows PowerShell(Administrator)",
|
||||
"commandline": "gsudo.exe powershell.exe",
|
||||
"hidden": false,
|
||||
"colorScheme": "Solarized Dark",
|
||||
"fontFace": "Fira Code",
|
||||
"icon" : "C:\\Users\\awinh\\OneDrive\\圖片\\icon\\console_red.png"
|
||||
},
|
||||
{
|
||||
// Make changes here to the cmd.exe profile.
|
||||
"guid": "{0caa0dad-35be-5f56-a8ff-afceeeaa6101}",
|
||||
"name": "Command Prompt",
|
||||
"commandline": "cmd.exe",
|
||||
"hidden": false
|
||||
},
|
||||
{
|
||||
"guid": "{b453ae62-4e3d-5e58-b989-0a998ec441b8}",
|
||||
"name": "Azure Cloud Shell",
|
||||
"source": "Windows.Terminal.Azure",
|
||||
"hidden": false,
|
||||
},
|
||||
{
|
||||
"guid": "{00000000-0000-0000-ba54-000000000002}",
|
||||
"name" : "Bash",
|
||||
"commandline": "%PROGRAMFILES%/git/usr/bin/bash.exe -i -l",
|
||||
"icon": "%PROGRAMFILES%/Git/mingw64/share/git/git-for-windows.ico",
|
||||
"startingDirectory" : "D:\\GoogleDrive\\codes",
|
||||
"font":
|
||||
{
|
||||
"face": "CaskaydiaCove NF",
|
||||
"size": 12
|
||||
},
|
||||
"historySize" : 9000,
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
// Add custom color schemes to this array.
|
||||
// To learn more about color schemes, visit https://aka.ms/terminal-color-schemes
|
||||
"schemes": [],
|
||||
|
||||
// Add custom keybindings to this array.
|
||||
// To unbind a key combination from your defaults.json, set the command to "unbound".
|
||||
// To learn more about keybindings, visit https://aka.ms/terminal-keybindings
|
||||
"keybindings":
|
||||
[
|
||||
// Copy and paste are bound to Ctrl+Shift+C and Ctrl+Shift+V in your defaults.json.
|
||||
// These two lines additionally bind them to Ctrl+C and Ctrl+V.
|
||||
// To learn more about selection, visit https://aka.ms/terminal-selection
|
||||
{ "command": {"action": "copy", "singleLine": false }, "keys": "ctrl+c" },
|
||||
{ "command": "paste", "keys": "ctrl+v" },
|
||||
|
||||
// Press Ctrl+Shift+F to open the search box
|
||||
{ "command": "find", "keys": "ctrl+shift+f" },
|
||||
|
||||
// Press Alt+Shift+D to open a new pane.
|
||||
// - "split": "auto" makes this pane open in the direction that provides the most surface area.
|
||||
// - "splitMode": "duplicate" makes the new pane use the focused pane's profile.
|
||||
// To learn more about panes, visit https://aka.ms/terminal-panes
|
||||
{ "command": { "action": "splitPane", "split": "auto", "splitMode": "duplicate" }, "keys": "alt+shift+d" },
|
||||
// Full screen
|
||||
{ "command": "toggleFullscreen", "keys": "alt+x" },
|
||||
// Open new default tab
|
||||
{ "command": "newTab", "keys": "ctrl+t" },
|
||||
// Close current pane
|
||||
{ "command": "closePane", "keys": "ctrl+w" },
|
||||
// Split pane in vertical
|
||||
{ "command": { "action": "splitPane", "split": "vertical"}, "keys": "ctrl+shift+E" },
|
||||
// Split pane in horizontal
|
||||
{ "command": { "action": "splitPane", "split": "horizontal"}, "keys": "ctrl+shift+O" },
|
||||
// Goto next tab
|
||||
{ "command": "nextTab", "keys": "ctrl+pagedown" },
|
||||
// Goto previous tab
|
||||
{ "command": "prevTab", "keys": "ctrl+pageup" },
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## oh-my-posh on bash
|
||||
以下步驟都是在 [Windows Terminal](https://apps.microsoft.com/store/detail/windows-terminal/9N0DX20HK701) 中的 Git bash[^1] 執行。
|
||||
1. 先下載一個你喜歡的theme: [https://ohmyposh.dev/docs/themes](https://ohmyposh.dev/docs/themes)
|
||||
2. 下載並安裝字型:[Caskaydia Cove Nerd Font](https://github.com/ryanoasis/nerd-fonts/releases/download/v2.1.0/CascadiaCode.zip?WT.mc_id=-blog-scottha)
|
||||
3. Install OhMyPosh: `winget install JanDeDobbeleer.OhMyPosh`
|
||||
4. 建立並修改 `~/.profile`,然後加入
|
||||
`eval "$(oh-my-posh --init --shell bash --config ~/OneDrive/appConfigs/ohmyposh/themes/montys.omp.json)"`
|
||||
注意最後的 `montys.omp.json` 就是第一步下載的theme,這邊要改成你自己的路徑。
|
||||
5. 修改 Windows Terminal 的 setting.json,將字型改為 `CaskaydiaCove NF`
|
||||
![[20220614221618_oh-my-posh_setting.png|600]]
|
||||
6. 成果
|
||||
![[20220614220342_oh-my-posh_result.png|600]]
|
||||
|
||||
[^1]: 在 [Windows Terminal](https://apps.microsoft.com/store/detail/windows-terminal/9N0DX20HK701) 中設定 Git bash 可以參考:[Windows Terminal's 設定 Git Bash 和 SSH @ 傑克! 真是太神奇了! :: 痞客邦 ::](https://magicjackting.pixnet.net/blog/post/225162505-windows-terminal's-%E8%A8%AD%E5%AE%9A-git-bash-%E5%92%8C-ssh)
|
||||
|
||||
## Reference
|
||||
- [Windows Terminal 美化 for WSL 2 Ubuntu (zsh + zim + powerlevel10k)](http://www.kenming.idv.tw/windows-terminal-%e7%be%8e%e5%8c%96-for-wsl-2-ubuntu-zsh-zim-powerlevel10k/)
|
||||
- [Oh My Posh](https://ohmyposh.dev/)
|
||||
- [How to make the ultimate Terminal Prompt on Windows 11 - This video is LONG and WORDY and DETAILED - YouTube](https://www.youtube.com/watch?v=VT2L1SXFq9U)
|
||||
- [My Ultimate PowerShell prompt with Oh My Posh and the Windows Terminal - Scott Hanselman's Blog](https://www.hanselman.com/blog/my-ultimate-powershell-prompt-with-oh-my-posh-and-the-windows-terminal)
|
||||
- [Windows-Terminal配置OhMyPosh来美化GitBash_偕臧x的博客-CSDN博客](https://blog.csdn.net/qq_33154343/article/details/120661945)
|
||||
5
05. 資料收集/Tool Setup/Software/freefilesync.md
Normal file
5
05. 資料收集/Tool Setup/Software/freefilesync.md
Normal file
@@ -0,0 +1,5 @@
|
||||
1. ![[Pasted image 20210321201359.png]]
|
||||
2. ![[Pasted image 20210321201503.png]]
|
||||
|
||||
參考:
|
||||
- [FreeFileSync: RealTimeSync - YouTube](https://www.youtube.com/watch?v=9KXo6yOhTWo)
|
||||
27
05. 資料收集/Tool Setup/Software/vim.md
Normal file
27
05. 資料收集/Tool Setup/Software/vim.md
Normal file
@@ -0,0 +1,27 @@
|
||||
### `~/.vimrc`
|
||||
```vim
|
||||
set t_Co=256
|
||||
colorscheme koehler
|
||||
|
||||
set nocompatible
|
||||
syntax on
|
||||
set showmode
|
||||
set showcmd
|
||||
set encoding=utf-8
|
||||
|
||||
set cindent
|
||||
set expandtab
|
||||
set tabstop=4
|
||||
set softtabstop=4
|
||||
set shiftwidth=4
|
||||
|
||||
set number
|
||||
set cursorline
|
||||
"set textwidth=80
|
||||
set ruler
|
||||
|
||||
set showmatch
|
||||
set hlsearch
|
||||
set incsearch
|
||||
set ignorecase
|
||||
```
|
||||
11
05. 資料收集/名言佳句.md
Normal file
11
05. 資料收集/名言佳句.md
Normal file
@@ -0,0 +1,11 @@
|
||||
- 初聞不知曲中意,再聽已是曲中人。
|
||||
- 讀書,就是要先將厚書讀薄,再將薄書讀厚。
|
||||
- 種一棵樹最好的時候,一個是過去,一個是現在 - dead aid by Dambisa Moyo [^1] ^901833
|
||||
- [[20201224 - 寫作是最好的自我投資#^d7f87c|葉勝陶先生:「語言是有聲無形的文章,文章是有形無聲的語言。」]]
|
||||
- [[20201224 - 寫作是最好的自我投資#^fad99d|蘇格拉底:「未經審查的人生沒有價值。」]]
|
||||
- [[20201224 - 寫作是最好的自我投資#^fd93cf|「專業,二十一世紀你唯一的生存之道。」 - 大前研一]]
|
||||
- [[20201224 - 寫作是最好的自我投資#^a00bcf|「任何一個好產品都是聰明人用笨功夫做出來的」 - 咪蒙]]
|
||||
- [[20201224 - 寫作是最好的自我投資#^7e896d|「天才的唯一秘密,就在於刻意練習,用自己一套系統性的方法,不斷突破自己的邊界」 - 刻意練習,安德斯.艾瑞克森]]
|
||||
|
||||
|
||||
[^1]: [“種一棵樹最好的時間是十年前,其次是現在”出自哪裡?](https://zhidao.baidu.com/question/652202353537726525.html)
|
||||
52
05. 資料收集/架站/Gitea.md
Normal file
52
05. 資料收集/架站/Gitea.md
Normal file
@@ -0,0 +1,52 @@
|
||||
## docker-compose.yml
|
||||
```yaml
|
||||
version: "3"
|
||||
|
||||
networks:
|
||||
gitea:
|
||||
external: false
|
||||
|
||||
services:
|
||||
server:
|
||||
image: gitea/gitea:latest
|
||||
container_name: gitea
|
||||
environment:
|
||||
- USER_UID=1000
|
||||
- USER_GID=1000
|
||||
- DB_TYPE=mysql
|
||||
- DB_HOST=db:3306
|
||||
- DB_NAME=gitea
|
||||
- DB_USER=gitea
|
||||
- DB_PASSWD=gitea
|
||||
- TZ=Asia/Taipei
|
||||
restart: always
|
||||
networks:
|
||||
- gitea
|
||||
volumes:
|
||||
- ./datas/gitea:/data
|
||||
- /home/git/.ssh/:/data/git/.ssh
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
ports:
|
||||
- "3000:3000"
|
||||
- "322:322"
|
||||
depends_on:
|
||||
- db
|
||||
|
||||
db:
|
||||
image: mysql:8
|
||||
restart: always
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=gitea
|
||||
- MYSQL_USER=gitea
|
||||
- MYSQL_PASSWORD=gitea
|
||||
- MYSQL_DATABASE=gitea
|
||||
networks:
|
||||
- gitea
|
||||
volumes:
|
||||
- ./datas/db:/var/lib/mysql
|
||||
```
|
||||
|
||||
## 文件
|
||||
- [Gitea Docs: Config Cheat Sheet](https://docs.gitea.io/zh-tw/config-cheat-sheet/)
|
||||
- [How to Install Gitea on Ubuntu Using Docker](https://www.digitalocean.com/community/tutorials/how-to-install-gitea-on-ubuntu-using-docker)
|
||||
108
05. 資料收集/架站/HTTP Server/Apache.md
Normal file
108
05. 資料收集/架站/HTTP Server/Apache.md
Normal file
@@ -0,0 +1,108 @@
|
||||
## Install
|
||||
```
|
||||
sudo apt update && sudo apt install apache2
|
||||
```
|
||||
|
||||
## 測試Apache
|
||||
```
|
||||
sudo service apache2 status
|
||||
```
|
||||
|
||||
## 設置虛擬主機(Virtual Hosts)
|
||||
假設要建立2個網站*test1.ui-code.com*與*test2.ui-code.com*
|
||||
|
||||
### 建立目錄並設置權限(Permissions)
|
||||
```
|
||||
sudo mkdir -p /var/www/test1.ui-code.com/public_html
|
||||
sudo mkdir -p /var/www/test2.ui-code.com/public_html
|
||||
sudo chmod -R 755 /var/www
|
||||
```
|
||||
|
||||
### 建立測試頁面
|
||||
#### 建立test1.ui-code.com的測試頁面
|
||||
```
|
||||
sudo nano /var/www/test1.ui-code.com/public_html/index.html
|
||||
```
|
||||
填入以下內容:
|
||||
```html
|
||||
<html>
|
||||
<head>
|
||||
<title>Welcome to test1.ui-code.com</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Welcome to test1.ui-code.com</h2>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
#### 建立test2.ui-code.com的測試頁面
|
||||
```
|
||||
sudo nano /var/www/test2.ui-code.com/public_html/index.html
|
||||
```
|
||||
填入以下內容:
|
||||
```html
|
||||
<html>
|
||||
<head>
|
||||
<title>Welcome to test2.ui-code.com</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Welcome to test2.ui-code.com</h2>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
### 建立虛擬主機文件(Virtual Host Files)
|
||||
虛擬主機文件位於 /etc/apache2/sites-available/ 中,其用於告訴 Apache 網頁伺服器如何響應(Respond )各種網域請求(Request)。
|
||||
讓我們為test1.ui-code.com 網域創建一個新的虛擬主機文件。
|
||||
```
|
||||
sudo nano /etc/apache2/sites-available/test1.ui-code.com.conf
|
||||
```
|
||||
|
||||
將以下內容貼上:
|
||||
```
|
||||
<VirtualHost *:80>
|
||||
ServerAdmin webmaster@test1.ui-code.com
|
||||
ServerName test1.ui-code.com
|
||||
ServerAlias www.test1.ui-code.com
|
||||
DocumentRoot /var/www/test1.ui-code.com/public_html
|
||||
ErrorLog ${APACHE_LOG_DIR}/error.log
|
||||
CustomLog ${APACHE_LOG_DIR}/access.log combined
|
||||
</VirtualHost>
|
||||
```
|
||||
|
||||
再來為test2.ui-code.com 網域創建一個新的虛擬主機文件。
|
||||
```
|
||||
sudo nano /etc/apache2/sites-available/test2.ui-code.com.conf
|
||||
```
|
||||
|
||||
將以下內容貼上:
|
||||
```
|
||||
<VirtualHost *:80>
|
||||
ServerAdmin webmaster@test2.ui-code.com
|
||||
ServerName test2.ui-code.com
|
||||
ServerAlias www.test2.ui-code.com
|
||||
DocumentRoot /var/www/test2.ui-code.com/public_html
|
||||
ErrorLog ${APACHE_LOG_DIR}/error.log
|
||||
CustomLog ${APACHE_LOG_DIR}/access.log combined
|
||||
</VirtualHost>
|
||||
```
|
||||
|
||||
### 啟用新的虛擬主機文件(Virtual Host Files)
|
||||
現在我們有兩個虛擬主機文件,我們需要使用 a2ensite 工具來啟用它們。
|
||||
```
|
||||
sudo a2ensite test1.ui-code.com
|
||||
sudo a2ensite test2.ui-code.com
|
||||
```
|
||||
|
||||
測試配置語法是否有錯誤。
|
||||
```
|
||||
apachectl configtest
|
||||
```
|
||||
|
||||
如果「Syntax OK」,重啟 Apache。
|
||||
```
|
||||
sudo systemctl reload apache2
|
||||
```
|
||||
|
||||
## 參考
|
||||
- [[教學][Ubuntu 架站] 在 Ubuntu 20.04 安裝 Apache 網頁伺服器,並架設多個網站(多網域) | 優程式](https://ui-code.com/archives/271)
|
||||
292
05. 資料收集/架站/HTTP Server/Nginx/Reverse Proxy(Layer4).md
Normal file
292
05. 資料收集/架站/HTTP Server/Nginx/Reverse Proxy(Layer4).md
Normal file
@@ -0,0 +1,292 @@
|
||||
## Reverse Proxy(Layer4)
|
||||
一般的Reverse Proxy所用的方法雖然可以反向代理多個網站,但是對於像是Trojan這種TLS不行被中斷的服務來說,會導致handshake失敗,所以需要用Nginx的stream來做Layer 4的轉發。
|
||||
|
||||
### docker-compose.yaml
|
||||
需要先把`nginx.conf`與`mime.types`給copy到data目錄下。
|
||||
依序執行下面2個命令:
|
||||
```shell
|
||||
sudo docker run --rm -it nginx cat /etc/nginx/nginx.conf > nginx.conf
|
||||
sudo docker run --rm -it nginx cat /etc/nginx/mime.types > mime.types
|
||||
```
|
||||
然後:
|
||||
```shell
|
||||
mkdir data ;\
|
||||
mv nginx.conf mime.types data
|
||||
```
|
||||
|
||||
建立`docker-compose.yaml`
|
||||
```yaml
|
||||
version: '3'
|
||||
services:
|
||||
nginx_reverseproxy_l4:
|
||||
container_name: nginx
|
||||
restart: always
|
||||
image: nginx
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
volumes:
|
||||
- ./data:/etc/nginx
|
||||
```
|
||||
|
||||
修改`data/nginx.conf`:
|
||||
```nginx
|
||||
events {
|
||||
worker_connections 1024; <-- event 不用動
|
||||
}
|
||||
|
||||
stream {
|
||||
map $ssl_preread_server_name $backend_name {
|
||||
tjn.awin.one trojan;
|
||||
storj.awin.one swag;
|
||||
}
|
||||
|
||||
# trojan
|
||||
upstream trojan {
|
||||
server 192.168.1.31:443;
|
||||
}
|
||||
|
||||
# swag
|
||||
upstream swag {
|
||||
server 192.168.1.20:44320;
|
||||
}
|
||||
|
||||
# 监听 443 并开启 ssl_preread
|
||||
server {
|
||||
listen 80 reuseport;
|
||||
listen 443 reuseport;
|
||||
listen [::]:443 reuseport;
|
||||
proxy_pass $backend_name;
|
||||
ssl_preread on;
|
||||
}
|
||||
}
|
||||
|
||||
http {
|
||||
... <-- http 不用動
|
||||
}
|
||||
```
|
||||
|
||||
重點來源:
|
||||
1. [Trojan 共用 443 端口方案 - 程小白](https://www.chengxiaobai.cn/record/trojan-shared-443-port-scheme.html)
|
||||
2. [NaiveProxy + Trojan + 多HTTPS站点共存,复用443端口 | 心底的河流](https://lhy.life/20200815-naiveproxy+trojan/)
|
||||
3. `$ssl_preread_server_name`的官方說明:[Module ngx_stream_ssl_preread_module](http://nginx.org/en/docs/stream/ngx_stream_ssl_preread_module.html)
|
||||
|
||||
## Reverse Proxy
|
||||
|
||||
> **重要**:確定docker與docker-compose已經安裝好。
|
||||
> 參考[[RaspberryPi#Docker]]與[[RaspberryPi#docker-compose]]
|
||||
|
||||
### Use SWAG docker
|
||||
[swag](https://github.com/linuxserver/docker-swag)(之前叫做letsencrypt)是linuxserver.io包裝的Nginx webserver和reverse proxy的container。
|
||||
|
||||
#### Setup HTTPS
|
||||
1. 建立folder
|
||||
```bash
|
||||
mkdir -p ~/dockers/linuxserverswag ; cd ~/dockers/linuxserverswag
|
||||
```
|
||||
|
||||
2. 建立`docker-compose.yaml`:
|
||||
```
|
||||
vim docker-compose.yaml
|
||||
```
|
||||
|
||||
填入內容如下:
|
||||
```yaml
|
||||
version: "2.1"
|
||||
services:
|
||||
swag:
|
||||
image: ghcr.io/linuxserver/swag
|
||||
container_name: swag
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=Asia/Taipei
|
||||
- URL=awin.one
|
||||
- SUBDOMAINS=wildcard
|
||||
- VALIDATION=dns
|
||||
- CERTPROVIDER= #optional
|
||||
- DNSPLUGIN=cloudflare #optional
|
||||
- PROPAGATION= #optional
|
||||
- DUCKDNSTOKEN= #optional
|
||||
- EMAIL=awinhuang@gmail.com
|
||||
- ONLY_SUBDOMAINS=false #optional
|
||||
- EXTRA_DOMAINS= #optional
|
||||
- STAGING=false #optional
|
||||
- MAXMINDDB_LICENSE_KEY= #optional
|
||||
volumes:
|
||||
- ./config:/config
|
||||
ports:
|
||||
- 44320:443
|
||||
- 8020:80 #optional
|
||||
restart: unless-stopped
|
||||
|
||||
```
|
||||
|
||||
3. 先跑一次:
|
||||
```bash
|
||||
sudo docker-compose up
|
||||
```
|
||||
會發現有錯誤,這是正常的,錯誤訊息像這樣:
|
||||
```
|
||||
swag | Unsafe permissions on credentials configuration file: /config/dns-conf/cloudflare.ini
|
||||
swag | Cleaning up challenges
|
||||
swag | Error determining zone_id: 9103 Unknown X-Auth-Key or X-Auth-Email. Please confirm that you have supplied valid Cloudflare API credentials. (Did you enter the correct email address and Global key?)
|
||||
swag | ERROR: Cert does not exist! Please see the validation error above. Make sure you entered correct credentials into the /config/dns-conf/cloudflare.ini file.
|
||||
```
|
||||
按`ctrl + c`退出。這時候`config`目錄也會有swag所mapping出來的相關檔案。修改`config/dns-conf/cloudflare.ini`:
|
||||
```bash
|
||||
vim config/dns-conf/cloudflare.ini
|
||||
```
|
||||
把`config/dns-conf/cloudflare.ini`改為:
|
||||
```
|
||||
# Instructions: https://github.com/certbot/certbot/blob/master/certbot-dns-cloudflare/certbot_dns_cloudflare/__init__.py#L20
|
||||
# Replace with your values
|
||||
|
||||
With global api key:
|
||||
dns_cloudflare_email = awinhuang@gmail.com
|
||||
dns_cloudflare_api_key = <YOUR_API_KEY_FROM_CLOUDFLARE>
|
||||
|
||||
# With token (comment out both lines above and uncomment below):
|
||||
#dns_cloudflare_api_token = 0123456789abcdef0123456789abcdef01234567
|
||||
```
|
||||
|
||||
4. 再跑一次:
|
||||
```bash
|
||||
sudo docker-compose up
|
||||
```
|
||||
這一次就可以順利取得認證了,訊息像這樣:
|
||||
```
|
||||
swag | IMPORTANT NOTES:
|
||||
swag | - Congratulations! Your certificate and chain have been saved at:
|
||||
swag | /etc/letsencrypt/live/awin.one/fullchain.pem
|
||||
swag | Your key file has been saved at:
|
||||
swag | /etc/letsencrypt/live/awin.one/privkey.pem
|
||||
swag | Your certificate will expire on 2021-04-26. To obtain a new or
|
||||
swag | tweaked version of this certificate in the future, simply run
|
||||
swag | certbot again. To non-interactively renew *all* of your
|
||||
swag | certificates, run "certbot renew"
|
||||
swag | - If you like Certbot, please consider supporting our work by:
|
||||
swag |
|
||||
swag | Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
|
||||
swag | Donating to EFF: https://eff.org/donate-le
|
||||
swag |
|
||||
swag | New certificate generated; starting nginx
|
||||
swag | Starting 2019/12/30, GeoIP2 databases require personal license key to download. Please retrieve a free license key from MaxMind,
|
||||
swag | and add a new env variable "MAXMINDDB_LICENSE_KEY", set to your license key.
|
||||
swag | [cont-init.d] 50-config: exited 0.
|
||||
swag | [cont-init.d] 60-renew: executing...
|
||||
swag | The cert does not expire within the next day. Letting the cron script handle the renewal attempts overnight (2:08am).
|
||||
swag | [cont-init.d] 60-renew: exited 0.
|
||||
swag | [cont-init.d] 70-templates: executing...
|
||||
swag | [cont-init.d] 70-templates: exited 0.
|
||||
swag | [cont-init.d] 99-custom-files: executing...
|
||||
swag | [custom-init] no custom files found exiting...
|
||||
swag | [cont-init.d] 99-custom-files: exited 0.
|
||||
swag | [cont-init.d] done.
|
||||
swag | [services.d] starting services
|
||||
swag | [services.d] done.
|
||||
swag | nginx: [alert] detected a LuaJIT version which is not OpenResty's; many optimizations will be disabled and performance will be compromised (see https://github.com/openresty/luajit2 for OpenResty's LuaJIT or, even better, consider using the OpenResty releases from https://openresty.org/en/download.html)
|
||||
swag | Server ready
|
||||
```
|
||||
最後一行的`swag | Server ready`表示server已經跑起來了。先按下`ctrl + c`退出,再來設定reverse proxy。
|
||||
|
||||
5. 修正`config/dns-conf/cloudflare.ini`的安全性問題
|
||||
```
|
||||
cd ~/dockers/linuxserverswag ; chmod 600 config/dns-conf/cloudflare.ini
|
||||
```
|
||||
|
||||
#### Setup reverse proxy
|
||||
1. 建立folder:
|
||||
```
|
||||
cd ~/dockers/linuxserverswag ; mkdir -p config/nginx/sites-available config/nginx/sites-enabled
|
||||
```
|
||||
|
||||
2. 建立以下檔案:
|
||||
- `config/nginx/sites-available/common.conf`,內容:
|
||||
```
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
add_header X-Frame-Options SAMEORIGIN;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
```
|
||||
- `config/nginx/sites-available/common_location.conf`,內容:
|
||||
```
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
```
|
||||
- `config/nginx/sites-available/storj.conf`,內容:
|
||||
```
|
||||
upstream storj {
|
||||
server 192.168.1.11:14002;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name storj.awin.one;
|
||||
|
||||
include /config/nginx/sites-available/common.conf;
|
||||
include /config/nginx/ssl.conf;
|
||||
|
||||
location / {
|
||||
proxy_pass http://192.168.1.11:14002/;
|
||||
include /config/nginx/sites-available/common_location.conf;
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
3. 在`config/nginx/sites-enabled`裡面建立要enable的config:
|
||||
```
|
||||
cd config/nginx/sites-enabled ; ln -s ../sites-available/storj.conf . ; cd -
|
||||
```
|
||||
|
||||
4. 修改`config/nginx/nginx.conf`:
|
||||
```
|
||||
vim config/nginx/nginx.conf
|
||||
```
|
||||
找到`include /config/nginx/site-confs/*;`這一行,把它comment掉,在下面新增一行:
|
||||
```
|
||||
include /config/nginx/sites-enabled/*.conf;
|
||||
```
|
||||
|
||||
5. 啟動swag:
|
||||
```
|
||||
cd ~/dockers/linuxserverswag ; sudo docker-compose up -d
|
||||
```
|
||||
|
||||
#### Restart
|
||||
```bash
|
||||
cd ~/dockers/linuxserverswag ; sudo docker-compose restart
|
||||
```
|
||||
|
||||
#### Update certification
|
||||
1. 進到dockr的swag bash裡面:`sudo docker exec -it swag /bin/bash`
|
||||
2. 輸入 `certbot renew`
|
||||
3. ![[Pasted image 20210422205534.png]]
|
||||
|
||||
#### Trouble shooting
|
||||
- 如果遇到類似下面的錯誤:
|
||||
```
|
||||
ERROR: for swag Cannot start service swag: driver failed programming external connectivity on endpoint swag (7c527d046631e0957de0b831ca25bed296de76e2eb96378964cb0110d7fb017d): Bind for 0.0.0.0:443 failed: port is already allocated.
|
||||
```
|
||||
表示有其他程式佔住了80 port,可能是其他docker container或是service,必須先關閉它們。[^1]
|
||||
|
||||
#### 參考來源
|
||||
1. [linuxserver/docker-swag: Nginx webserver and reverse proxy with php support and a built-in Certbot (Let's Encrypt) client. It also contains fail2ban for intrusion prevention.](https://github.com/linuxserver/docker-swag)
|
||||
2. [How to set up an easy and secure reverse proxy with Docker, Nginx & Letsencrypt](https://www.freecodecamp.org/news/docker-nginx-letsencrypt-easy-secure-reverse-proxy-40165ba3aee2/)
|
||||
3. [SWAG setup - LinuxServer.io](https://docs.linuxserver.io/general/swag#understanding-the-proxy-conf-structure)
|
||||
|
||||
-----
|
||||
- 參考
|
||||
- [NGINX Docs | NGINX Reverse Proxy](https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/)
|
||||
- [Nginx 設定反向代理 Reverse Proxy](https://www.opencli.com/linux/nginx-config-reverse-proxy)
|
||||
- [用 Nginx 伺服器建立反向代理](https://noob.tw/nginx-reverse-proxy/)
|
||||
- [俄羅斯不愧是戰鬥民族:nginx - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天](https://ithelp.ithome.com.tw/articles/10188498)
|
||||
|
||||
[^1]: [啟動docker時出現「Cannot start service :driver failed programming external connectivity on endpoint xxx, Bind for 0.0.0.0:80 failed: port is already allocated 」](https://mitsuiwei.com/docker-cannot-start-service/)
|
||||
26
05. 資料收集/架站/Pelican blog.md
Normal file
26
05. 資料收集/架站/Pelican blog.md
Normal file
@@ -0,0 +1,26 @@
|
||||
## Create a site
|
||||
Use `pelican-quickstart` to create a new site.
|
||||
|
||||
## Plugin
|
||||
```bash
|
||||
git clone --recursive https://github.com/getpelican/pelican-plugins.git
|
||||
```
|
||||
|
||||
## Theme
|
||||
先把所有佈景主題都clone下來:
|
||||
```bash
|
||||
git clone --recursive https://github.com/getpelican/pelican-themes.git
|
||||
```
|
||||
|
||||
把`pelicanconf.py`裡面的`THEME`指向theme的目錄就可以換佈景主題了。例如要用[[blue-penguin](https://github.com/jody-frankowski/blue-penguin)]這一個主題。把`pelicanconf.py`裡面加入`THEME = 'pelican-themes/blue-penguin'`就可以了。
|
||||
|
||||
## 預覽
|
||||
```
|
||||
make html
|
||||
make serve
|
||||
```
|
||||
|
||||
參考:
|
||||
- [koko's Note – Python - 安裝 Pelican Theme 來改變你的靜態網站主題](https://note.koko.guru/install-pelican-theme.html)
|
||||
- [nest theme](https://github.com/molivier/nest)
|
||||
- [Flex theme](https://github.com/alexandrevicenzi/Flex/wiki/Custom-Settings)
|
||||
260
05. 資料收集/架站/Proxmox VE.md
Normal file
260
05. 資料收集/架站/Proxmox VE.md
Normal file
@@ -0,0 +1,260 @@
|
||||
# 安裝
|
||||
## 下載ISO
|
||||
- [Get the free Proxmox VE ISO installer](https://www.proxmox.com/en/downloads/category/iso-images-pve)
|
||||
|
||||
## 準備USB disk
|
||||
- 用[Rufus](https://rufus.ie/)的話
|
||||
1. 在遇到詢問是否要下載 Grub 時,請選擇「否」
|
||||
2. 必須使用DD mode來建立開機碟。(參考:[Prepare Installation Media - Proxmox VE](https://pve.proxmox.com/wiki/Prepare_Installation_Media#_instructions_for_windows))
|
||||
![[Pasted image 20210128212917.png]]
|
||||
|
||||
# 設定
|
||||
## 關閉「闔上螢幕後休眠」
|
||||
打開`/etc/systemd/logind.conf`:
|
||||
```
|
||||
nano /etc/systemd/logind.conf
|
||||
```
|
||||
找到下面兩行,把值改成ignore:
|
||||
```
|
||||
HandleLidSwitch=ignore
|
||||
HandleLidSwitchDocked=ignore
|
||||
```
|
||||
然後重開機:
|
||||
```
|
||||
systemctl restart systemd-logind.service
|
||||
```
|
||||
圖示:
|
||||
![[Pasted image 20210129194144.png]]
|
||||
|
||||
## 增加硬碟
|
||||
先用`lsblk`列出所有硬碟,這裡假設`sda`是我們的開機磁碟,我要要新增`sdb`:
|
||||
```
|
||||
root@pve:~# lsblk
|
||||
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
|
||||
sda 8:0 0 931.5G 0 disk <-- 目前在用的
|
||||
├─sda1 8:1 0 1007K 0 part
|
||||
├─sda2 8:2 0 512M 0 part
|
||||
└─sda3 8:3 0 931G 0 part
|
||||
sdb 8:16 0 111.8G 0 disk <-- 要新增的
|
||||
├─sdb1 8:17 0 100M 0 part
|
||||
├─sdb2 8:18 0 16M 0 part
|
||||
├─sdb3 8:19 0 111.1G 0 part
|
||||
└─sdb4 8:20 0 563M 0 part
|
||||
```
|
||||
|
||||
然後安裝`parted`,我們要用它來分割硬碟:
|
||||
```
|
||||
apt install parted
|
||||
```
|
||||
|
||||
開始分割:
|
||||
```
|
||||
parted /dev/sdb mklabel gpt
|
||||
```
|
||||
|
||||
建立primary partition,格式為`ext4`:
|
||||
```
|
||||
parted -a opt /dev/sdb mkpart primary ext4 0% 100%
|
||||
```
|
||||
|
||||
再來將分割好的硬碟格式化為`ext4`,label命名為`data2`:
|
||||
```
|
||||
mkfs.ext4 -L data2 /dev/sdb1
|
||||
```
|
||||
|
||||
再用`lsblk`看一次,會發現sdb已經重新分割成1個partition了:
|
||||
```
|
||||
root@pve:~# lsblk
|
||||
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
|
||||
sda 8:0 0 931.5G 0 disk
|
||||
├─sda1 8:1 0 1007K 0 part
|
||||
├─sda2 8:2 0 512M 0 part
|
||||
└─sda3 8:3 0 931G 0 part
|
||||
sdb 8:16 0 111.8G 0 disk
|
||||
└─sdb1 8:17 0 111.8G 0 part
|
||||
```
|
||||
|
||||
用`lsblk -fs`可以看到每一個硬碟的檔案系統格式:
|
||||
```
|
||||
root@pve:~# lsblk -fs
|
||||
NAME FSTYPE LABEL UUID FSAVAIL FSUSE% MOUNTPOINT
|
||||
sda1 zfs_member rpool 11775123664036754029
|
||||
└─sda zfs_member rpool 11775123664036754029
|
||||
sda2 vfat rpool 32D0-3449
|
||||
└─sda zfs_member rpool 11775123664036754029
|
||||
sda3 zfs_member rpool 11775123664036754029
|
||||
└─sda zfs_member rpool 11775123664036754029
|
||||
sdb1 ext4 data2 bc6d2c41-a3ca-4b0f-a5de-51ee28ae9cec <-- 剛剛分割的
|
||||
└─sdb
|
||||
```
|
||||
|
||||
接下來,將新硬碟掛載到檔案目錄上,先建立一個新目錄來掛載新硬碟:
|
||||
```shell
|
||||
mkdir -p /mnt/data
|
||||
```
|
||||
|
||||
接下來編輯`/etc/fstab`,將新硬碟寫進來,這樣開機之後才會自動把它掛載起來:
|
||||
```
|
||||
nano /etc/fstab
|
||||
```
|
||||
加入這一行(注意:**data2**要改成你自己的label):
|
||||
```
|
||||
LABEL=data2 /mnt/data ext4 defaults 0 2
|
||||
```
|
||||
|
||||
剛新硬碟掛起來:
|
||||
```
|
||||
mount -a
|
||||
```
|
||||
|
||||
用`df`就可以看到新硬碟了:
|
||||
```
|
||||
root@pve:~# df
|
||||
Filesystem 1K-blocks Used Available Use% Mounted on
|
||||
udev 16288892 0 16288892 0% /dev
|
||||
tmpfs 3262688 9324 3253364 1% /run
|
||||
rpool/ROOT/pve-1 942667136 1267584 941399552 1% /
|
||||
tmpfs 16313440 43680 16269760 1% /dev/shm
|
||||
tmpfs 5120 0 5120 0% /run/lock
|
||||
tmpfs 16313440 0 16313440 0% /sys/fs/cgroup
|
||||
rpool 941399680 128 941399552 1% /rpool
|
||||
rpool/data 941399680 128 941399552 1% /rpool/data
|
||||
rpool/ROOT 941399680 128 941399552 1% /rpool/ROOT
|
||||
/dev/fuse 30720 16 30704 1% /etc/pve
|
||||
tmpfs 3262688 0 3262688 0% /run/user/0
|
||||
/dev/sdb1 114854020 61464 108915208 1% /mnt/data <-- 新硬碟在這裡
|
||||
```
|
||||
|
||||
參考:
|
||||
- [How to add storage to Proxmox](https://nubcakes.net/index.php/2019/03/05/how-to-add-storage-to-proxmox/)
|
||||
|
||||
## 增加iSCSI磁碟
|
||||
### 增加需要CHAP認證的iSCSI磁碟
|
||||
1. 先確認找的到iSCSI磁碟
|
||||
```
|
||||
iscsiadm -m discovery -t st -p 192.168.1.11:3260
|
||||
```
|
||||
如果有找到的話會回傳一串IQN值,像是:
|
||||
```
|
||||
root@pve:~# iscsiadm -m discovery -t st -p 192.168.1.11:3260
|
||||
192.168.1.11:3260,1 iqn.2000-01.com.synology:DiskStation.Target-1.3e589efea3
|
||||
[fe80::211:32ff:fe20:eadd]:3260,1 iqn.2000-01.com.synology:DiskStation.Target-1.3e589efea3
|
||||
```
|
||||
2. 有IQN就可以用下列的命令連線與掛載:
|
||||
```
|
||||
iscsiadm -m node -T iqn.2000-01.com.synology:DiskStation.Target-1.3e589efea3 --op update --name node.session.auth.username --value=名字
|
||||
iscsiadm -m node -T iqn.2000-01.com.synology:DiskStation.Target-1.3e589efea3 --op update --name node.session.auth.password --value=密碼
|
||||
iscsiadm -m node -T iqn.2000-01.com.synology:DiskStation.Target-1.3e589efea3 -l #連線
|
||||
iscsiadm -m node -o update -n node.startup -v automatic #設定開機自動掛載
|
||||
```
|
||||
|
||||
## 增加NFS磁碟
|
||||
1. 先在Synology上開一個NFS disk,設定如下:
|
||||
![[Pasted image 20220506091522.png]]
|
||||
2. 再到Proxmox的 Datacenter->Storage->Add 來增加一個 *NFS*,設定如下
|
||||
![[Pasted image 20220506091624.png]]
|
||||
|
||||
### 更改NFS mount為soft
|
||||
1. 編輯`/etc/pve/storage.cfg`
|
||||
2. 做如下修改
|
||||
![[Pasted image 20220506095531.png]]
|
||||
|
||||
### 參考
|
||||
- [[經驗分享]Proxmox VE 採用 NFS 連接儲存的重點事項](http://blog.jason.tools/2019/02/pve-nfs-mount.html)
|
||||
|
||||
## 設定VM備份目錄
|
||||
如果將VM或LXC備份到某個目錄,先建立要備份的目錄:
|
||||
```shell
|
||||
mkdir -p /mnt/data/backup/
|
||||
```
|
||||
|
||||
再來用WEB UI,操作如下:
|
||||
![[Pasted image 20210129202041.png]]
|
||||
![[Pasted image 20210129202047.png]]
|
||||
|
||||
最後再到 Datacenter->Backups,建立一個scheule來備份就可以了:
|
||||
![[Pasted image 20210129202231.png]]
|
||||
|
||||
## 將資料備份到NAS
|
||||
1. 先在NAS開一個share folder跟一個帳號。
|
||||
![[Pasted image 20210202190402.png]]
|
||||
![[Pasted image 20210202190537.png]]
|
||||
2. Proxmox:到裡將剛剛新開的folder給掛載起來。
|
||||
![[Pasted image 20210202190640.png]]
|
||||
會跳出一個視窗,如下圖來填,記得**content**那一欄有4個要選。
|
||||
![[Pasted image 20210202190709.png]]
|
||||
3. Proxmox:到 Datacenter->Backup 新增一個排程。
|
||||
![[Pasted image 20210202190903.png]]
|
||||
一樣會跳出一個視窗,依需求來填,要注意的是**Storage**必須是前一步驟的**ID**,**Selection Mode**可以選擇**All**。
|
||||
![[Pasted image 20210202191150.png]]
|
||||
|
||||
參考:
|
||||
- [HASS + Proxmox: Automatic Backups to Synology NAS](https://kleypot.com/automatic-offline-backups/)
|
||||
|
||||
## 設定 UPS
|
||||
因為 UPS 的 USB 是連接在 NAS 上,所以Proxmox這邊必須要去monitor NAS那邊所回報的狀態,請確定NAS端有打開「啟用網路不斷電系統伺服器」。
|
||||
1. 安裝 nut:`apt-get install nut`
|
||||
2. 修改 `/etc/nut/nut.conf`,設定 `MODE=netclient`
|
||||
3. 修改 `/etc/nut/upsmon.conf`,加入一行:`MONITOR ups@<NAS_IP> 1 <NAS_Username> <NAS_UserPassword> slave`
|
||||
4. 開始 upsmon:`upsmon start`
|
||||
5. 用 `ps -ef | grep upsmon` 確認 upsmon是否執行:
|
||||
![[Pasted image 20220811145852.png|600]]
|
||||
6. 若正常,可以取回UPS的一些硬體資料,`upsc ups@<NAS_IP>`
|
||||
![[Pasted image 20220811150034.png|360]]
|
||||
|
||||
### 參考
|
||||
- [UPSMON(8)](https://networkupstools.org/docs/man/upsmon.html)
|
||||
- [不斷電系統 | DSM - Synology 知識中心](https://kb.synology.com/zh-tw/DSM/help/DSM/AdminCenter/system_hardware_ups?version=6)
|
||||
- [設定 Proxmox VE連動Synology的不斷電系統](https://cychien.tw/wordpress/2022/02/02/%E8%A8%AD%E5%AE%9A-proxmox-ve%E9%80%A3%E5%8B%95synology%E7%9A%84%E4%B8%8D%E6%96%B7%E9%9B%BB%E7%B3%BB%E7%B5%B1/)
|
||||
|
||||
## 更新
|
||||
### 加入更新來源
|
||||
編輯`/etc/apt/sources.list`,加入:
|
||||
```
|
||||
deb http://ftp.debian.org/debian bullseye main contrib
|
||||
deb http://ftp.debian.org/debian bullseye-updates main contrib
|
||||
|
||||
# PVE pve-no-subscription repository provided by proxmox.com,
|
||||
# NOT recommended for production use
|
||||
deb http://download.proxmox.com/debian/pve bullseye pve-no-subscription
|
||||
|
||||
# security updates
|
||||
deb http://security.debian.org/debian-security bullseye-security main contrib
|
||||
```
|
||||
|
||||
### 取消訂閱服務
|
||||
編輯`/etc/apt/sources.list.d/pve-enterprise.list`,把下面這行注釋掉:
|
||||
```
|
||||
deb https://enterprise.proxmox.com/debian/pve buster pve-enterprise
|
||||
```
|
||||
也就是變成:
|
||||
```
|
||||
#deb https://enterprise.proxmox.com/debian/pve buster pve-enterprise
|
||||
```
|
||||
|
||||
使用`apt update`來更新套件。
|
||||
使用`apt dist-upgrade`來升級系統版本。
|
||||
|
||||
## 重灌後要做的事情
|
||||
1. 建立ZFS pool。
|
||||
2. 確認S.M.A.R.T. 是否啟用,預設是啟用的。
|
||||
`smartctl -a /dev/<SDA_N>`
|
||||
1. 打開IOMMU
|
||||
2. 打開vm aware
|
||||
3. 增加NFS共享磁碟
|
||||
4. 排程備份
|
||||
5. 上傳安裝Windows需要的驅動ISO
|
||||
1. [Windows VirtIO Drivers](https://pve.proxmox.com/wiki/Windows_VirtIO_Drivers)
|
||||
6. 把常用的VM轉為template
|
||||
7. 安裝[Cockpit-Linux Server](https://pvecli.xuan2host.com/cockpit/), 讓您的PVE有更棒的圖形管理介面。
|
||||
|
||||
## 參考
|
||||
- [套件功能的更新(Proxmox update)](https://wiki.freedomstu.com/books/proxmox-ve-%E8%99%9B%E6%93%AC%E7%B3%BB%E7%B5%B1%E8%A8%98%E9%8C%84/page/%E5%A5%97%E4%BB%B6%E5%8A%9F%E8%83%BD%E7%9A%84%E6%9B%B4%E6%96%B0%EF%BC%88proxmox-update%EF%BC%89)
|
||||
- [裝完PVE後的11件必作清單 (中文翻譯)](https://www.youtube.com/watch?v=pY4Lm2Hoqik)
|
||||
- [Before I do anything on Proxmox, I do this first...](https://www.youtube.com/watch?v=GoZaMgEgrHw&t=0s)
|
||||
|
||||
# Trouble shooting
|
||||
- *Emergency mode*,表示開機失敗,請檢查`/etc/fstab`是不是有無法掛載的disk。
|
||||
|
||||
## 參考
|
||||
- [[Fix] Getting out of emergency mode : Proxmox](https://www.reddit.com/r/Proxmox/comments/hai75k/fix_getting_out_of_emergency_mode/)
|
||||
247
05. 資料收集/架站/SWAG Reverse proxy.md
Normal file
247
05. 資料收集/架站/SWAG Reverse proxy.md
Normal file
@@ -0,0 +1,247 @@
|
||||
[SWAG](https://docs.linuxserver.io/general/swag)可以幫我們反向代理,並且有https。是由linuxserver.io包裝的Nginx webserver和reverse proxy的container。
|
||||
|
||||
#### 建立docker-compose
|
||||
1. 建立folder
|
||||
```bash
|
||||
mkdir -p ~/dockers/linuxserverswag ; cd ~/dockers/linuxserverswag
|
||||
```
|
||||
|
||||
2. 建立`docker-compose.yaml`:
|
||||
```
|
||||
vim docker-compose.yaml
|
||||
```
|
||||
|
||||
填入內容如下:
|
||||
```yaml
|
||||
version: "2.1"
|
||||
services:
|
||||
swag:
|
||||
image: ghcr.io/linuxserver/swag
|
||||
container_name: swag
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=Asia/Taipei
|
||||
- URL=awin.one
|
||||
- SUBDOMAINS=wildcard
|
||||
- VALIDATION=dns
|
||||
- CERTPROVIDER= #optional
|
||||
- DNSPLUGIN=cloudflare #optional
|
||||
- PROPAGATION= #optional
|
||||
- DUCKDNSTOKEN= #optional
|
||||
- EMAIL=awinhuang@gmail.com
|
||||
- ONLY_SUBDOMAINS=false #optional
|
||||
- EXTRA_DOMAINS= #optional
|
||||
- STAGING=false #optional
|
||||
- MAXMINDDB_LICENSE_KEY= #optional
|
||||
volumes:
|
||||
- ./config:/config
|
||||
ports:
|
||||
- 44320:443
|
||||
- 8020:80 #optional
|
||||
restart: unless-stopped
|
||||
```
|
||||
|
||||
3. 先跑一次:
|
||||
```bash
|
||||
sudo docker-compose up
|
||||
```
|
||||
會發現有錯誤,這是正常的,錯誤訊息像這樣:
|
||||
```
|
||||
swag | Unsafe permissions on credentials configuration file: /config/dns-conf/cloudflare.ini
|
||||
swag | Cleaning up challenges
|
||||
swag | Error determining zone_id: 9103 Unknown X-Auth-Key or X-Auth-Email. Please confirm that you have supplied valid Cloudflare API credentials. (Did you enter the correct email address and Global key?)
|
||||
swag | ERROR: Cert does not exist! Please see the validation error above. Make sure you entered correct credentials into the /config/dns-conf/cloudflare.ini file.
|
||||
```
|
||||
按`ctrl + c`退出。這時候`config`目錄也會有swag所mapping出來的相關檔案。修改`config/dns-conf/cloudflare.ini`:
|
||||
```bash
|
||||
vim config/dns-conf/cloudflare.ini
|
||||
```
|
||||
把`config/dns-conf/cloudflare.ini`改為:
|
||||
```
|
||||
# Instructions: https://github.com/certbot/certbot/blob/master/certbot-dns-cloudflare/certbot_dns_cloudflare/__init__.py#L20
|
||||
# Replace with your values
|
||||
|
||||
With global api key:
|
||||
dns_cloudflare_email = awinhuang@gmail.com
|
||||
dns_cloudflare_api_key = <YOUR_API_KEY_FROM_CLOUDFLARE>
|
||||
|
||||
# With token (comment out both lines above and uncomment below):
|
||||
#dns_cloudflare_api_token = 0123456789abcdef0123456789abcdef01234567
|
||||
```
|
||||
|
||||
4. 再跑一次:
|
||||
```bash
|
||||
sudo docker-compose up
|
||||
```
|
||||
這一次就可以順利取得認證了,訊息像這樣:
|
||||
```
|
||||
swag | IMPORTANT NOTES:
|
||||
swag | - Congratulations! Your certificate and chain have been saved at:
|
||||
swag | /etc/letsencrypt/live/awin.one/fullchain.pem
|
||||
swag | Your key file has been saved at:
|
||||
swag | /etc/letsencrypt/live/awin.one/privkey.pem
|
||||
swag | Your certificate will expire on 2021-04-26. To obtain a new or
|
||||
swag | tweaked version of this certificate in the future, simply run
|
||||
swag | certbot again. To non-interactively renew *all* of your
|
||||
swag | certificates, run "certbot renew"
|
||||
swag | - If you like Certbot, please consider supporting our work by:
|
||||
swag |
|
||||
swag | Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
|
||||
swag | Donating to EFF: https://eff.org/donate-le
|
||||
swag |
|
||||
swag | New certificate generated; starting nginx
|
||||
swag | Starting 2019/12/30, GeoIP2 databases require personal license key to download. Please retrieve a free license key from MaxMind,
|
||||
swag | and add a new env variable "MAXMINDDB_LICENSE_KEY", set to your license key.
|
||||
swag | [cont-init.d] 50-config: exited 0.
|
||||
swag | [cont-init.d] 60-renew: executing...
|
||||
swag | The cert does not expire within the next day. Letting the cron script handle the renewal attempts overnight (2:08am).
|
||||
swag | [cont-init.d] 60-renew: exited 0.
|
||||
swag | [cont-init.d] 70-templates: executing...
|
||||
swag | [cont-init.d] 70-templates: exited 0.
|
||||
swag | [cont-init.d] 99-custom-files: executing...
|
||||
swag | [custom-init] no custom files found exiting...
|
||||
swag | [cont-init.d] 99-custom-files: exited 0.
|
||||
swag | [cont-init.d] done.
|
||||
swag | [services.d] starting services
|
||||
swag | [services.d] done.
|
||||
swag | nginx: [alert] detected a LuaJIT version which is not OpenResty's; many optimizations will be disabled and performance will be compromised (see https://github.com/openresty/luajit2 for OpenResty's LuaJIT or, even better, consider using the OpenResty releases from https://openresty.org/en/download.html)
|
||||
swag | Server ready
|
||||
```
|
||||
最後一行的`swag | Server ready`表示server已經跑起來了。先按下`ctrl + c`退出,再來設定reverse proxy。
|
||||
|
||||
5. 修正`config/dns-conf/cloudflare.ini`的安全性問題
|
||||
```
|
||||
cd ~/dockers/linuxserverswag ; chmod 600 config/dns-conf/cloudflare.ini
|
||||
```
|
||||
|
||||
#### Setup reverse proxy
|
||||
1. 建立folder:
|
||||
```
|
||||
cd ~/dockers/linuxserverswag ; mkdir -p config/nginx/sites-available config/nginx/sites-enabled
|
||||
```
|
||||
|
||||
2. 建立以下檔案:
|
||||
- `config/nginx/sites-available/common.conf`,內容:
|
||||
```
|
||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
||||
add_header X-Frame-Options SAMEORIGIN;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header X-XSS-Protection "1; mode=block";
|
||||
```
|
||||
- `config/nginx/sites-available/common_location.conf`,內容:
|
||||
```
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_set_header X-Forwarded-Port $server_port;
|
||||
```
|
||||
- `config/nginx/sites-available/storj.conf`,內容:
|
||||
```
|
||||
upstream storj {
|
||||
server 192.168.1.11:14002;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name storj.awin.one;
|
||||
|
||||
include /config/nginx/sites-available/common.conf;
|
||||
include /config/nginx/ssl.conf;
|
||||
|
||||
location / {
|
||||
proxy_pass http://192.168.1.11:14002/;
|
||||
include /config/nginx/sites-available/common_location.conf;
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
- `config/nginx/sites-available/blog.conf`,內容:
|
||||
```
|
||||
upstream blog {
|
||||
server 192.168.1.30:80;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name blog.awin.one;
|
||||
|
||||
include /config/nginx/sites-available/common.conf;
|
||||
include /config/nginx/ssl.conf;
|
||||
|
||||
location / {
|
||||
proxy_pass http://192.168.1.30:80/;
|
||||
include /config/nginx/sites-available/common_location.conf;
|
||||
}
|
||||
}
|
||||
```
|
||||
- `config/nginx/sites-available/gitea.conf`,內容:
|
||||
```
|
||||
upstream gitea {
|
||||
server 192.168.1.32:3000; ## 網址
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name gitea.awin.one; ## 網域
|
||||
|
||||
include /config/nginx/sites-available/common.conf;
|
||||
include /config/nginx/ssl.conf;
|
||||
|
||||
location / {
|
||||
proxy_pass http://192.168.1.32:3000/; ## 網址
|
||||
include /config/nginx/sites-available/common_location.conf;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. 在`config/nginx/sites-enabled`裡面建立要enable的config:
|
||||
```
|
||||
cd config/nginx/sites-enabled ; ln -s ../sites-available/storj.conf . ; cd -
|
||||
```
|
||||
|
||||
4. 修改`config/nginx/nginx.conf`:
|
||||
```
|
||||
vim config/nginx/nginx.conf
|
||||
```
|
||||
找到`include /config/nginx/site-confs/*;`這一行,把它comment掉,在下面新增一行:
|
||||
```
|
||||
include /config/nginx/sites-enabled/*.conf;
|
||||
```
|
||||
|
||||
5. 啟動swag:
|
||||
```
|
||||
cd ~/dockers/linuxserverswag ; sudo docker-compose up -d
|
||||
```
|
||||
|
||||
#### Restart
|
||||
```bash
|
||||
cd ~/dockers/linuxserverswag ; sudo docker-compose restart
|
||||
```
|
||||
|
||||
#### Update certification
|
||||
1. 進到dockr的swag bash裡面:`sudo docker exec -it swag /bin/bash`
|
||||
2. 輸入 `certbot renew`
|
||||
3. ![[Pasted image 20210422205534.png]]
|
||||
|
||||
#### Trouble shooting
|
||||
- 如果遇到類似下面的錯誤:
|
||||
```
|
||||
ERROR: for swag Cannot start service swag: driver failed programming external connectivity on endpoint swag (7c527d046631e0957de0b831ca25bed296de76e2eb96378964cb0110d7fb017d): Bind for 0.0.0.0:443 failed: port is already allocated.
|
||||
```
|
||||
表示有其他程式佔住了80 port,可能是其他docker container或是service,必須先關閉它們。[^1]
|
||||
|
||||
#### 參考來源
|
||||
1. [linuxserver/docker-swag: Nginx webserver and reverse proxy with php support and a built-in Certbot (Let's Encrypt) client. It also contains fail2ban for intrusion prevention.](https://github.com/linuxserver/docker-swag)
|
||||
2. [How to set up an easy and secure reverse proxy with Docker, Nginx & Letsencrypt](https://www.freecodecamp.org/news/docker-nginx-letsencrypt-easy-secure-reverse-proxy-40165ba3aee2/)
|
||||
3. [SWAG setup - LinuxServer.io](https://docs.linuxserver.io/general/swag#understanding-the-proxy-conf-structure)
|
||||
4. [NGINX Docs | NGINX Reverse Proxy](https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/)
|
||||
5. [Nginx 設定反向代理 Reverse Proxy](https://www.opencli.com/linux/nginx-config-reverse-proxy)
|
||||
6. [用 Nginx 伺服器建立反向代理](https://noob.tw/nginx-reverse-proxy/)
|
||||
7. [俄羅斯不愧是戰鬥民族:nginx - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天](https://ithelp.ithome.com.tw/articles/10188498)
|
||||
|
||||
[^1]: [啟動docker時出現「Cannot start service :driver failed programming external connectivity on endpoint xxx, Bind for 0.0.0.0:80 failed: port is already allocated 」](https://mitsuiwei.com/docker-cannot-start-service/)
|
||||
80
05. 資料收集/架站/Storj.md
Normal file
80
05. 資料收集/架站/Storj.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# Documentation
|
||||
- [Introduction - Storj](https://documentation.storj.io/)
|
||||
|
||||
## Setup
|
||||
Pull image
|
||||
```shell
|
||||
sudo docker pull storjlabs/storagenode:latest
|
||||
```
|
||||
|
||||
Do this **once**.
|
||||
```shell
|
||||
sudo docker run --rm -e SETUP="true" \
|
||||
--mount type=bind,source="/volume1/homes/awin/Storj/key",destination=/app/identity \
|
||||
--mount type=bind,source="/volume1/docker/Storj/data",destination=/app/config \
|
||||
--name storagenode storjlabs/storagenode:latest
|
||||
```
|
||||
|
||||
## Run
|
||||
```shell
|
||||
sudo docker run -d --restart unless-stopped --stop-timeout 300 \
|
||||
-p 28967:28967 \
|
||||
-p 28967:28967/udp \
|
||||
-p 14002:14002 \
|
||||
-e WALLET="0x9Ce80345355Ad8C17991620E13d8423900CEDcd0" \
|
||||
-e EMAIL="awinhuang@gmail.com" \
|
||||
-e ADDRESS="awin.myds.me:28967" \
|
||||
-e STORAGE="2TB" \
|
||||
--mount type=bind,source="/volume1/homes/awin/Storj/key",destination=/app/identity \
|
||||
--mount type=bind,source="/volume1/docker/Storj/data",destination=/app/config \
|
||||
--name storagenode storjlabs/storagenode:latest
|
||||
```
|
||||
|
||||
## Update configuration
|
||||
### Linux
|
||||
1. Stop docker container
|
||||
```shell
|
||||
sudo docker stop -t 300 storagenode ;\
|
||||
sudo docker rm storagenode ;\
|
||||
sudo docker pull storjlabs/storagenode
|
||||
```
|
||||
2. Run docker again. Check [[Storj#Run]]. [^1]
|
||||
3. Or, create a task, and run below command:
|
||||
```shell
|
||||
echo "Stop storagenode" ;\
|
||||
sudo docker stop -t 300 storagenode ;\
|
||||
sudo docker rm storagenode ;\
|
||||
echo "Pull storagenode" ;\
|
||||
sudo docker pull storjlabs/storagenode ;\
|
||||
echo "Start storagenode" ;\
|
||||
sudo docker run -d --restart unless-stopped --stop-timeout 300 \
|
||||
-p 28967:28967 \
|
||||
-p 14002:14002 \
|
||||
-e WALLET="0x9Ce80345355Ad8C17991620E13d8423900CEDcd0" \
|
||||
-e EMAIL="awinhuang@gmail.com" \
|
||||
-e ADDRESS="awin.myds.me:28967" \
|
||||
-e STORAGE="2TB" \
|
||||
--mount type=bind,source="/volume1/homes/awin/Storj/key",destination=/app/identity \
|
||||
--mount type=bind,source="/volume1/docker/Storj/data",destination=/app/config \
|
||||
--name storagenode storjlabs/storagenode:latest ;\
|
||||
sudo docker ps -a
|
||||
```
|
||||
|
||||
## Start/Stop service
|
||||
### Windows
|
||||
#### Start service
|
||||
In PowerShell:
|
||||
```powershell
|
||||
Start-Service storagenode
|
||||
```
|
||||
|
||||
#### Stop service
|
||||
In PowerShell:
|
||||
```powershell
|
||||
Stop-Service storagenode
|
||||
```
|
||||
|
||||
[^2]
|
||||
|
||||
[^1]: [How do I change values like wallet address or storage capacity? - Storj](https://documentation.storj.io/resources/faq/how-do-i-change-my-parameters-such-as-payout-address-allotted-storage-space-and-bandwidth)
|
||||
[^2]: [How do I shutdown my node for system maintenance? - Storj](https://documentation.storj.io/resources/faq/system-maintenance)
|
||||
38
05. 資料收集/架站/Trojan.md
Normal file
38
05. 資料收集/架站/Trojan.md
Normal file
@@ -0,0 +1,38 @@
|
||||
## 準備
|
||||
1. 新增一台container,先更新container:
|
||||
```
|
||||
apt update ;\
|
||||
apu upgrade -y ;\
|
||||
apt install curl vim -y
|
||||
```
|
||||
2. 安裝trojan:
|
||||
```
|
||||
mkdir -p ~/trojan ;\
|
||||
cd ~/trojan
|
||||
curl -O https://raw.githubusercontent.com/atrandys/trojan/master/trojan_mult.sh ; chmod +x trojan_mult.sh ; ./trojan_mult.sh
|
||||
```
|
||||
3. 
|
||||
4. 
|
||||
5. 
|
||||
6. 
|
||||
|
||||
-----
|
||||
參考:
|
||||
1. [Trojan 上網架設(替代VPN)爬梯子 科學上網 利器 - TWIDC](https://lab.twidc.net/trojan-%E4%B8%8A%E7%B6%B2%E6%9E%B6%E7%BD%AE%E6%9B%BF%E4%BB%A3vpn/)
|
||||
2. [Trojan搭建私人VPN - Lingme](https://lingmin.me/2020/03/03/TrojanVPS/)
|
||||
3. [[转载+修改]使用Trojan-Go科学上网 - 996 RIP](https://typecho.996.rip/index.php/archives/20/)
|
||||
4. Source code: [Releases · trojan-gfw/trojan](https://github.com/trojan-gfw/trojan/releases)
|
||||
|
||||
## 更新憑證
|
||||
1. 更新acme:`acme.sh --upgrade`
|
||||
2. 先停止 trojan-web
|
||||
```bash
|
||||
systemctl stop trojan-web
|
||||
```
|
||||
3. 停止 trojan,如下圖
|
||||
![[Pasted image 20220815134750.png|500]]
|
||||
4. 切換到 `/root/.acme.sh`,執行 `./acme.sh --cron -f`,如果憑證更新成功,應該會看到類似如下訊息:
|
||||
![[Pasted image 20220815135026.png|800]]
|
||||
5. 重啟 trojan:
|
||||
![[Pasted image 20220815135248.png|400]]
|
||||
6. 重啟trojan-web:`systemctl start trojan-web`
|
||||
12
05. 資料收集/每週外食.md
Normal file
12
05. 資料收集/每週外食.md
Normal file
@@ -0,0 +1,12 @@
|
||||
##### 2020-11-16(一) - 披薩,謙謙
|
||||
##### 2020-11-23(一) - 汕頭火鍋,Jiachi
|
||||
##### 2020-11-30(一) - 瓦城,Awin
|
||||
##### 2020-12-07(一) - 福星,Jiachi
|
||||
##### 2020-12-13(日) - 21世紀,睿睿 ^98f39d
|
||||
##### 2020-12-21(一) - Coco,謙謙 ^a0b44c
|
||||
##### 2020-12-28(一) - 翰林茶坊,Awin
|
||||
##### 2021-01-04(一) - 一風堂(老婆、謙謙)、燒肉丼飯(Awin、睿睿) ^347d91
|
||||
##### 2021-01-14(四) - Coco,睿睿
|
||||
##### 2021-01-18(一) - 貝里尼披薩,謙謙
|
||||
##### 2021-02-22(一) - 三合院,Awin
|
||||
##### 2021-03-02(二) - Coco,Jiachi
|
||||
41
05. 資料收集/科技/802.11.md
Normal file
41
05. 資料收集/科技/802.11.md
Normal file
@@ -0,0 +1,41 @@
|
||||
### 802.11k
|
||||
|
||||
802.11k協議的功能是**Radio Resource Measurment**,簡單說就是提供找到最好的AP的信息。
|
||||
|
||||
在WLAN中,終端設備總是傾向於連接信號最好的那個AP,而在實際應用中,這種邏輯可能會造成某個AP被過度使用,而信號稍弱的AP則沒有怎麼用到,從而導致網絡的整體利用效率下降。實現802.11k協議的無線網絡中,如果信號最好的AP已經滿載,則終端設備會連接到信號稍弱的那個AP。
|
||||
|
||||
協議步驟:
|
||||
|
||||
1. AP決定要踢掉某個終端設備
|
||||
2. 通知終端設備變換到另一個AP
|
||||
3. 終端設備請求周圍AP的列表
|
||||
4. AP給出site report
|
||||
5. 終端設備根據site report連到某個AP
|
||||
|
||||
[IEEE 802.11k-2008 - Wikipedia](https://en.wikipedia.org/wiki/IEEE_802.11k-2008)
|
||||
|
||||
### 802.11v
|
||||
|
||||
802.11v是802.11協議族的**WNM(Wireless Network Management)**標準,802.11v協議允許終端設備交換網絡拓撲的信息,包括射頻環境。
|
||||
|
||||
802.11v描述了WNM的增強,包括:
|
||||
|
||||
- **Network assisted Power Savings**:**網絡輔助節能**,幫助終端設備睡眠更長時間,比如,手機等設備通過每隔一段時間跟AP通訊一次來確保跟AP沒有斷開
|
||||
- **Network assisted Roaming**:**網絡輔助漫遊**,允許WLAN發送信息給終端,來確保終端能連接更好的AP。這可以帶來兩點好處:
|
||||
|
||||
1. 負載均衡
|
||||
2. 讓信號不好的終端設備更換AP
|
||||
|
||||
[IEEE 802.11v-2011 - Wikipedia](https://en.wikipedia.org/wiki/IEEE_802.11v-2011)
|
||||
|
||||
### 802.11r
|
||||
|
||||
802.11r的功能是**快速BSS切換**(FT,**Fast Basic Service Set Transition**),也稱為**快速漫遊**(**fast roaming**),是802.11協議的補充。
|
||||
|
||||
在802.11協議中,AP的切換是由設備控制的(其邏輯是:在能連接到的信號中,挑選信號最好的那個連接,連接一直持續到信號低於一個閾值(通常非常弱)才會斷開,然後繼續反复)。
|
||||
|
||||
在802.11的初期,切換(handoff)這個操作是非常簡單的,一共只有4個握手信息需要傳遞,但是隨著發展,[802.11i](https://www.easyatm.com.tw/wiki/802.11i),802.11X,802.11e等協議的加入,握手的信息越來越多,導致切換AP的時間越來越長。
|
||||
|
||||
802.11r通過重新簡化(越來越複雜的)安全握手協議,來實現FT。
|
||||
|
||||
[IEEE 802.11r-2008 - Wikipedia](https://en.wikipedia.org/wiki/IEEE_802.11r-2008)
|
||||
197
05. 資料收集/科技/HDR Sensor.md
Normal file
197
05. 資料收集/科技/HDR Sensor.md
Normal file
@@ -0,0 +1,197 @@
|
||||
## HDR sensor 原理介紹
|
||||
### 1. 什麼是sensor的動態範圍(dynamic range)
|
||||
sensor的動態範圍就是sensor在一幅圖像裡能夠同時體現高光和陰影部分內容的能力。
|
||||
用公式表達這種能力就是:
|
||||
|
||||
$DR = 20log\frac{i_{max}}{i_{min}}$ // DB
|
||||
|
||||
$i_{max}$是sensor的最大不飽和電流,也可以說是sensor剛剛飽和時候的電流
|
||||
$i_{min}$是sensor的底電流(blacklevel)
|
||||
|
||||
### 2. 為什麼HDR在成像領域是個大問題:
|
||||
在自然界的真實情況,有些場景的動態範圍要大於100dB。
|
||||
人眼的動態範圍可以達到100dB。
|
||||
Sensor 的動態範圍:高端的>78dB,消費級的60dB上下
|
||||
所以當sensor的動態範圍小於圖像場景動態範圍的時候就會出現HDR問題----不是暗處看不清,就是亮處看不清,有的甚至兩頭都看不清。
|
||||

|
||||
上圖暗處看不清-前景處的廣告牌和樹影太暗看不清。
|
||||
|
||||

|
||||
上圖亮處看不清--遠處背景的白雲變成了一團白色,完全看不清細節。
|
||||
|
||||
### 3. 解決HDR問題的數學分析
|
||||
|
||||
根據前邊動態範圍公式
|
||||
|
||||
$DR = 20log\frac{i_{max}}{i_{min}}$ // DB
|
||||
|
||||
所以從數學本質上說要提高DR,就是提高$i_{max}$,減小$i_{min}$
|
||||
對於10bit輸出的sensor,從數學上來說,$i_{max}=1023$,$i_{min}=1$
|
||||
動態範圍DR = 60
|
||||
對於12bit輸出的sensor,DR = 72
|
||||
所以從數學上來看,提高sensor 輸出的bit width就可以提高動態範圍,從而解決HDR問題。
|
||||
可是現實上卻沒有這麼簡單。
|
||||
提高sensor的bit width導致不僅sensor的成本提高,整個圖像處理器的帶寬都得相應提高,消耗的內存也都相應提高,這樣導致整個系統的成本會大幅提高。所以大家想出許多辦法,既能解決HDR問題,又可以不增加太多成本。
|
||||
|
||||
## HDR Imaging Digital Overlap
|
||||
|
||||
Digital Overlap是目前比較流行的sensor HDR 技術,在監控與車載相機等領域的應用非常廣泛。Sony於2012年在監控相機市場首先推出基於DOL(digital overlap)HDR技術的圖像傳感器,之後OV與Onsemi也都推出了與DOL類似的HDR技術的圖像傳感器,而且應用領域不局限於監控這種傳統HDR imaging的市場,而且擴展到了Automotive camera市場。現在Sony已經推出了第二代支持虛擬通道DOL HDR技術的sensor。
|
||||
|
||||
### 1. 什麼是時域多幀HDR技術
|
||||
|
||||
相機在時間上連續輸出由欠曝到過曝的圖像,然後做圖像融合,得到HDR圖像。
|
||||

|
||||
融合後HDR圖像
|
||||

|
||||
|
||||
比較典型的一種融合方法是根據luminance,contrast,motion等條件,對第K幀圖像的像素`[i,j]`給出權重。$W_{ij,k}$是第K幀,位置i,j像素的權重,$x_k(i,j)$是原始像素值,$x_f(i,j)$是融合後的像素值。公式如下:
|
||||

|
||||
對彩色圖像,權重的計算會考慮色彩的飽和度等因素。
|
||||
|
||||
### 2. 傳統時域多幀HDR技術存在的局限
|
||||
|
||||
由於傳統時域多幀是基於連續曝光的整幀圖像(Frame Based)進行融合,所以圖像之間的間隔時間就是一幀圖像的周期,由此會產生很多artefacts:
|
||||
|
||||
1. 場景內物體增減
|
||||

|
||||
|
||||
2. 近距離物體快速移動形成拖影
|
||||

|
||||
|
||||
3. Color artefact
|
||||

|
||||
|
||||
Frame based的多曝光HDR技術常用於still image 的capture,也有視頻HDR 採用這種技術,比如sensor以60fps的幀率交替輸出長短曝光,融合後輸出30fps的HDR圖像。
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
早期的HDR video有採用這種技術,自從DOL技術出現後,這種Frame based Video HDR技術就逐漸退出歷史舞台了。
|
||||
|
||||
### 3. 什麼是DOL HDR
|
||||
|
||||
DOL HDR 也叫做 line interleaving HDR 技術。以兩曝光 DOL 為例,sensor每行會以長短曝光兩次先後輸出,從readout角度來看,就是長曝光幀與短曝光幀line interleaving 依次輸出,如下圖,第一行L輸出,第一行S輸出,第二行L輸出,第二行S輸出,以此類推。
|
||||
|
||||

|
||||
|
||||
frame based HDR,長短曝光幀的間隔是一個幀週期,也就是必須一整幀(長)曝光結束,再開始一整幀(短)曝光,如下圖
|
||||
|
||||

|
||||
|
||||
對於DOL HDR而言,由於line interleaving(行的交織),存在兩幀的overlap,等於一幀輸出沒結束,下一幀就來了,長短曝光幀的間隔大大縮小了。
|
||||
|
||||
從下圖可見,長曝光幀與短曝光幀overlap了一部分,所以這種技術叫digital overlap。
|
||||

|
||||
|
||||
### 4. DOL 長短曝光幀的時間間隔
|
||||
|
||||
前邊說過,Frame based HDR 的長短曝光幀的間隔是一幀的時間,那麼 DOL HDR 的長短曝光幀的時間間隔是多大呢?
|
||||
|
||||
如果先輸出長曝光的話
|
||||

|
||||
|
||||
如果先輸出短曝光的話
|
||||

|
||||
|
||||
T= long exposure 的時間
|
||||
所以當然是先輸出長曝光,這樣T(時間間隔)會更小。
|
||||
|
||||
### 5. DOL 長短曝光時間比與動態範圍擴展
|
||||
|
||||
以兩曝光DOL 為例
|
||||
$\text{Exposure ratio} = \frac{\text{Long exposure time}}{\text{short exposure time}}$
|
||||
|
||||
假設Exposure ratio = 16,假設在信號沒有飽和的條件下,相當於曝光最大值增大了16倍:$2^4$。也就是動態範圍擴大了4個bit。
|
||||
以此類推,每增加一個曝光幀,如果exposure ratio =16,動態範圍就可以擴大4bit。
|
||||
按照一般HDR sensor 單曝光為12bit來算的話,4曝光就可以讓sensor輸出的動態範圍擴大到24bit(12+4+4+4)。
|
||||
exposure ratio 也不是越大越好,exposure ratio會受到三方面的製約,圖像質量,sensor設計以及isp line delay buffer。
|
||||
從圖像質量上來說,短曝光時間越短,圖像噪聲越高,長曝光越長,motion的影響越大。Exposure Ratio越大,在圖像融合後的SNR drop也越大。
|
||||
從sensor設計上來說,長短曝光之比受到讀出電路的限制,sony的DOL第二代採用虛擬通道技術一定程度改善了這個限制。
|
||||
從ISP的角度來說line delay buffer 也限制了最大曝光時間。在短曝光行出來之前,第一個長曝光行應該還在delay buffer裡,這樣才能兩者對齊好給後面的frame stitch操作。而長短曝光比越大,需要的line delay buffer就越大。
|
||||
|
||||

|
||||
|
||||
對於sensor做hdr融合case而言,line delay buffer size就是固定的,所以ISP傾向於在isp這端做HDR融合,這樣可以更靈活的設計。(Maver注:對於車載而言,帶寬是個主要關注點,所以大部分用戶不會選擇在ISP側做HDR融合)
|
||||
|
||||
### 6. DOL的局限
|
||||
|
||||
Sony在推出DOL的時候,宣傳DOL是**準同時**輸出長短曝光。既然是**準同時**,那就還不是同時,所以也會有一些典型時域多幀HDR的圖像質量問題,同時DOL也有一些特有的IQ問題。
|
||||
|
||||
1. HDR Transition Artefacts
|
||||
可以從下左圖看到composition noise造成的edge,這種edge有時候會誤導機器視覺。
|
||||

|
||||
|
||||
從DOL hdr的noise profile可以看出來,如下圖,在HDR拼接處,可以看到SNR的顯著變化,叫做snr drop,當SNR drop大的時候,就會出現明顯的edge,如上圖所示。
|
||||

|
||||
曝光比越小,SNR drop就越小, 可以想見,如果曝光比為1,也就沒有snr drop了。反之,曝光比越大,動態範圍越大,snr drop也越大,如下圖所示。
|
||||

|
||||
|
||||
2. Flicker
|
||||
交流電供電光源造成的flickering,如下圖:
|
||||
![[Pasted image 20220908123355.png]]
|
||||
|
||||
交流電供電光源造成的flickering,如下圖:
|
||||

|
||||
為了避免banding,就得讓最小曝光時間是半週期的整數倍。
|
||||

|
||||
|
||||
這樣就不會出現banding了。但是由於最小曝光時間變大了,動態範圍就損失了。所以有時候為了保證不損失動態範圍,就得容忍Flickering。這就得看應用場景了。
|
||||
類似的問題發生在PWM供電的Led光源上,尤其是交通信號燈以及汽車信號燈,如下圖所示
|
||||

|
||||
|
||||
sensor的長曝光幀能catch到led 的light pulse,但是短曝光幀就沒catch到,這樣也會造成flickering甚至信號燈圖像的丟失。
|
||||
這種flicker或者信號燈信息丟失的問題在車載成像系統上是致命的,所以車載HDR現在更傾向採用spatial based HDR技術,比如Sony採用的sub pixel技術或者OV 採用的split pixel技術。
|
||||
|
||||
## HDR imaging split/sub pixel 技術
|
||||
|
||||
我們在上一期講了時域多幀HDR技術:Digital Overlap. 現在在監控領域的WDR sensor主要採用這種技術,如下圖,利用不同的sensor曝光(藍色線所示)覆蓋不同的動態範圍,再把多曝光圖像stitching起來(紅色線所示),達到最大的動態範圍輸出。Sony的imx290,OV的ov4689都是這個類型典型sensor。
|
||||
|
||||

|
||||
|
||||
車載領域也廣泛使用Temporal domain HDR技術,但是隨著車載相機在ADAS與自動駕駛領域的迅速發展,對圖像質量有著特別的需求,導致Temporal domain HDR技術不能滿足需要。車載比較典型的兩個IQ需求是不能有motion artefact 和LED flickering。
|
||||
|
||||
缺點如下:
|
||||
1. motion artefact
|
||||

|
||||
|
||||
2. LED flickering
|
||||

|
||||
|
||||
Temporal HDR 在原理上就存在這些缺陷,所以要解決這個問題就需要使用其他的HDR體制:Spatial HDR 技術是現在車載領域的主流解決方案。
|
||||
|
||||
## Spatial HDR
|
||||
比較典型的是Sony sensor(imx390/490)採用的Subpixel技術與OV sensor(ovx1a)採用的split pixel技術,他們都屬於SpatialHDR技術範疇,其基本原理是一致的。
|
||||
|
||||
1. 大小pixel的分離結構
|
||||
與普通CFA的不同,大小pixel技術的sensor在相鄰位置有一大一小兩個pixel,他們空間上非常接近,可以認為對空間採樣相同。
|
||||

|
||||
由於pixel的大小不同,物理上的sensitivity不同,FWC也不同,會產生與時域HDR一樣的不同曝光效果,形成了對不同動態範圍的覆蓋。如下圖可以看到LPD(Large Pixel Diode)與SPD(Small Pixel Diode)是如何擴展動態範圍的。
|
||||

|
||||
|
||||
2. 大小分離pixel的電路設計
|
||||
典型的大小分離pixel的電路如下圖所示
|
||||

|
||||
SPD和LPD分別用黃色的二極管標出。CGC(conversion gain control)與TG(transfer gate)控制了photo diode 向FD充電,當$TG_S$使能時,FD接收SPD來的電荷,RS會使能讓FD的電荷轉存出來。然後當$TG_L$使能時,FD接收LPD來的電荷,RS會再一次使能讓FD的電荷轉存出來。RST負責在每一次轉存後把FD電容清空。這樣的電路結構就實現了LPD和SPD的分別讀出。這個部分的電路時鐘非常快,所以可以認為大小像素是同時曝光的。後面的讀出電路也會把大小像素同時讀出,由下圖可見,$T_{LPD}$ 與 $T_{SPD}$ 是同時的。
|
||||

|
||||
|
||||
3. 大小像素HDR與時域HDR在motion artefact上的比較
|
||||
由下圖可以看出基於大小像素的HDR與時域HDR在拍攝運動物體上的mot ion artefact比較。
|
||||
左圖是基於大小像素的圖像,完全沒有motion artefact,右圖是時域HDR,可以看到明顯的motion artefact。
|
||||

|
||||
對於這種更挑戰的場景,舞廳的旋轉光球,左圖是大小像素HDR,右圖是時域HDR,可以看到時域HDR的圖像把小的運動光點都混到了一起。
|
||||

|
||||
|
||||
4. 大小像素與Dual conversion gain的結合
|
||||
單獨靠大小像素只能形成兩個曝光的圖像,再結合之前介紹過的DCG技術,在大小pixel分別配合HCG,LCG,就可以形成4曝光。
|
||||
假設單曝光輸出12bit,曝光比是16,那總共的動態範圍可以達到24bit輸出。
|
||||

|
||||
|
||||
5. 兩種場景的切換
|
||||
如下圖,橫軸是場景的光亮度,縱軸是SNR,紅色曲線是LPD像素的SNR曲線,藍色曲線是LPD像素的SNR曲線。
|
||||

|
||||
SPD的飽和點更高,而LPD的低光SNR更高。這兩條曲線說明了大小像素這種設計可以很靈活的適配場景的變化,當場景非常亮的情況,就用大小像素融合輸出,這樣可以擴大動態範圍。
|
||||
當場景非常暗的情況,就完全切換到LPD像素,因為它的SNR更高。
|
||||
|
||||
## 來源
|
||||
- [HDR sensor 原理介紹- 吳建明wujianming - 博客園](https://www.cnblogs.com/wujianming-110117/p/12684011.html)
|
||||
2
05. 資料收集/科技/量子電腦.md
Normal file
2
05. 資料收集/科技/量子電腦.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# 介紹文
|
||||
- [量子電腦:從原理、實作到應用](https://medium.com/@kelispinor/%E9%87%8F%E5%AD%90%E9%9B%BB%E8%85%A6%E6%A5%B5%E7%B0%A1%E4%BB%8B-short-introduction-to-quantum-computer-a7b159861786)
|
||||
4
05. 資料收集/科技/鋰電池.md
Normal file
4
05. 資料收集/科技/鋰電池.md
Normal file
@@ -0,0 +1,4 @@
|
||||
電池的容量是用"mAH(毫安培小時)"來表示的,例如,一塊電池標有3000mAH ,當我們用3000mA的電流(也就是3A)放電時,可以放電一個小時,則電池的放電倍率是1C,如果以6A電流放電,則可以用30分鐘,則屬於2C。
|
||||
|
||||
# 鋰離子電池多少C是什麼意思
|
||||
C:用來表示電池充放電電流大小的比率,即倍率。充放電倍率=充放電電流/額定容量,如1200mAh的電池,0.2C表示240mA(1200mAh的0.2倍率),1C表示1200mA(1200mAh的1倍率)。50C表示50 * 1200 = 6000mA。
|
||||
6
05. 資料收集/興趣嗜好/RC/Traxxas Sledge.md
Normal file
6
05. 資料收集/興趣嗜好/RC/Traxxas Sledge.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# 升級零件
|
||||
1. [差速齒(9579R)](https://youtu.be/t2HpcLTBsTc)
|
||||
2. [前保桿(6835)](https://www.youtube.com/watch?v=aWxCktCLTI8)
|
||||
1. 需要螺絲
|
||||
1. m3x30
|
||||
2. 平頭m4x20
|
||||
1
05. 資料收集/興趣嗜好/RC/好盈電變調整中立點.md
Normal file
1
05. 資料收集/興趣嗜好/RC/好盈電變調整中立點.md
Normal file
@@ -0,0 +1 @@
|
||||
[【RC】FLYSKY 富斯NB4 遥控器基本功能使用教程_哔哩哔哩_bilibili](https://www.bilibili.com/video/BV1pJ411y7yB/)
|
||||
1
05. 資料收集/興趣嗜好/RC/差速器調教教學.md
Normal file
1
05. 資料收集/興趣嗜好/RC/差速器調教教學.md
Normal file
@@ -0,0 +1 @@
|
||||
[(28) 陳春期--HB D812 差速器調教教學 - YouTube](https://www.youtube.com/watch?v=dSYQBz3T6gU)
|
||||
51
05. 資料收集/興趣嗜好/模型/舊化作例.md
Normal file
51
05. 資料收集/興趣嗜好/模型/舊化作例.md
Normal file
@@ -0,0 +1,51 @@
|
||||
### 德國四號
|
||||
![[德國四號_舊化做例_001.jpg|160]]
|
||||
|
||||
### 德國Tiger I
|
||||
![[Tiger I 做例_001.jpg]]
|
||||
![[Tiger I 做例_002.jpg]]
|
||||
![[Tiger I 做例_003.jpg]]
|
||||
![[Tiger I 做例_004.jpg]]
|
||||
![[Tiger I 做例_005.jpg]]
|
||||
![[Tiger I 做例_006.jpg]]
|
||||
|
||||
參考:
|
||||
- [Panzerkampfwagen VI Tiger Sd.Kfz.181, ‘Tiger I’ - Tanks Encyclopedia](https://tanks-encyclopedia.com/ww2/germany/panzer-vi_tiger.php)
|
||||
- [Tiger I Information Center - Paint Schemes](http://www.alanhamby.com/paints.shtml)
|
||||
|
||||
### 德國虎王
|
||||
![[德國虎王_作例_001.jpg]]
|
||||
![[德國虎王_作例_002.jpg]]
|
||||
![[德國虎王_作例_003.jpg]]
|
||||
![[德國虎王_作例_004.jpg]]
|
||||
|
||||
參考:
|
||||
- [Panzerkampfwagen Tiger Ausf.B (Sd.Kfz.182) Tiger II](https://tanks-encyclopedia.com/ww2/germany/panzer-vi_konigstiger.php)
|
||||
|
||||
### Selbstfahrlafette IV
|
||||
- [大麥克斯](https://zh.wikipedia.org/wiki/%E5%A4%A7%E9%BA%A5%E5%85%8B%E6%96%AF)
|
||||
![[Dicker Max_001.jpg]]
|
||||
![[Dicker Max_002.jpg]]
|
||||
![[Dicker Max_003.jpg]]
|
||||
![[Dicker Max_004.jpg]]
|
||||
![[Dicker Max_005.jpg]]
|
||||
![[Dicker Max_006.jpg]]
|
||||
![[Dicker Max_007.jpg]]
|
||||
![[Dicker Max_008.jpg]]
|
||||
![[Dicker Max_009.jpg]]
|
||||
![[Dicker Max_010.jpg]]
|
||||
![[Dicker Max_011.jpg]]
|
||||
![[Dicker Max_012.jpg]]
|
||||
![[Dicker Max_013.jpg]]
|
||||
![[Dicker Max_014.jpg]]
|
||||
![[Dicker Max_015.jpg]]
|
||||
![[Dicker Max_016.jpg]]
|
||||
![[Dicker Max_017.jpg]]
|
||||
![[Dicker Max_018.jpg]]
|
||||
![[Dicker Max_019.jpg]]
|
||||
![[Dicker Max_020.jpg]]
|
||||
![[Dicker Max_021.jpg]]
|
||||
![[Dicker Max_022.jpg]]
|
||||
![[Dicker Max_023.jpg]]
|
||||
![[Dicker Max_024.jpg]]
|
||||
![[Dicker Max_025.jpg]]
|
||||
2
05. 資料收集/興趣嗜好/軍武/虎式.md
Normal file
2
05. 資料收集/興趣嗜好/軍武/虎式.md
Normal file
@@ -0,0 +1,2 @@
|
||||
[二次大戰德軍虎式戰車考證 - Mobile01](https://www.mobile01.com/topicdetail.php?f=637&t=5384277)
|
||||
[戰車之王:米歇爾.魏特曼 @ "Loyalty Is My Honor忠誠即是我的榮耀"WAFFEN-SS 武裝親衛隊簡介 :: 痞客邦 ::](https://mdoohan74.pixnet.net/blog/post/8820801-%E6%88%B0%E8%BB%8A%E4%B9%8B%E7%8E%8B%3A%E7%B1%B3%E6%AD%87%E7%88%BE.%E9%AD%8F%E7%89%B9%E6%9B%BC)
|
||||
183
05. 資料收集/讀書筆記/20201201 - 學習如何學習.md
Normal file
183
05. 資料收集/讀書筆記/20201201 - 學習如何學習.md
Normal file
@@ -0,0 +1,183 @@
|
||||
### 1. 熱情這回事
|
||||
- 大量練習可以改變大腦(讓你學會你以為你永遠不會的事)
|
||||
- 光憑熱情,芭芭拉也沒有太多選擇。
|
||||
- 來一場「圖畫散步」。 ^57c7a7
|
||||
- 千萬不要堅持在閱讀下一頁(或下一章)的時候,就一定要搞懂現在正在讀的東西。
|
||||
- 大概瀏覽整本書的內容,了解其大綱與結構,可以幫助你更快組織好你準備理解的資訊。
|
||||
|
||||
### 2. 慢慢來
|
||||
- 思考有兩種:「專注模式」、「發散模式」 ^1c4ddf
|
||||
- 專注模式 ^23ddb6
|
||||
- 專注模式會「打開」某些腦部位(取決於你學什麼)。
|
||||
- 要成功解決問題,需要**專注模式**。
|
||||
- 發散模式
|
||||
- 腦部放鬆和空閒的狀態。
|
||||
- 可以幫助你進行概念之間的連結。
|
||||
- 休息可以讓你有解決問題的新觀點。
|
||||
- 在最有精神的時候,先從最難的科目開始讀。
|
||||
|
||||
### 3. 我待會兒就做,真的!
|
||||
- 拖延會痛苦(島葉皮質或開始作用)
|
||||
- 但行動20分鐘之後,島葉皮質就會平靜下來。也就是說:「做就對了,不要拖延。」
|
||||
- 番茄鐘工作法 ^c6b5d8
|
||||
- 關閉一切會讓你分心的事物。
|
||||
- 計時25分鐘。
|
||||
- 在這25分鐘內,專注於你的任務。
|
||||
- 休息一下,犒賞一下自己。(但是不可以太久喔)
|
||||
- 在這25分鐘內,要是發現自己分心了,就趕快把自己拉回來,分心是正常的,就是因為你會分心才需要番茄鐘工作法嘛!
|
||||
- 要是時間到了,覺得自己想繼續努力,那就繼續吧,但別忘了但一段落之後休息與犒賞自己。
|
||||
- 食砷者的故事,每天吃一點毒,看似無害,但傷害卻仍然慢慢累積。拖延也是一樣,幾分鐘幾分鐘的累積,日子一久就變成難以挽回的後果。
|
||||
- 「積極回想」,在閱讀之下,移開視線或閉上眼睛,回想一下剛剛學習的內容,或是講出來也可以,愈是覺得困難的部分,就愈要常使用這方法。 ^da7fba
|
||||
|
||||
### 4. 腦連結與太空異形
|
||||
![[neuron.png]]
|
||||
- 神經元愈頻繁的傳訊息給另一個神經元,兩者間的連結就變得愈牢固。
|
||||
- 神經元愈多,突觸愈強大,腦連結也就愈強大。 ^7ac072
|
||||
- 神經元是用不完的!
|
||||
- 比喻可以讓你更快理解事物。 ^6acb4a
|
||||
- 練習可以強化腦連結。
|
||||
|
||||
### 5. 老師書桌的另一邊
|
||||
這一章由艾爾當主角,艾爾也是個「文科生」,他的理科也不好,當他聽到芭芭拉說我們可以重塑阿腦線路的時候,他決定重新學習化學。這章述說了42歲的他如何一起重當學生學化學的故事。
|
||||
艾爾使用的方法有:
|
||||
- 番茄鐘工作法,每次努力個25分鐘,然後休息。第3章的[[20201201 - 學習如何學習#^c6b5d8|番茄鐘工作法]]
|
||||
- 對別人解釋自己學到的東西。艾爾是對著他的狗說話。
|
||||
- 努力回想課程學到的東西。第3章的[[20201201 - 學習如何學習#^da7fba|積極回想]]
|
||||
- 不會的就請教別人。
|
||||
- 交錯。
|
||||
- 大致翻閱每一個章節,弄清楚接下來的內容。第1章的[[20201201 - 學習如何學習#^57c7a7|圖畫散步]]
|
||||
- 腦補一些搞笑畫面。第4章的[[20201201 - 學習如何學習#^6acb4a]]
|
||||
|
||||
很多技巧是前面幾個章節就提到的。
|
||||
|
||||
本章佳句:
|
||||
- 這章有提到之前已經紀錄的佳句:[[名言佳句#^901833|種樹最好的時機是二十年前,其次是現在]]
|
||||
|
||||
### 6. 邊睡邊學
|
||||
- 科學家楊光發現神經元的確會改變。
|
||||
- 睡覺可以鞏固腦連結,讓神經的[[20201201 - 學習如何學習#^7ac072|突觸]]生長。
|
||||
- 但是沒用到的又會消失喔。
|
||||
- 每天學習(或複習)可以讓腦連結更強,讓你更容易回想與記憶。
|
||||
- 所以,很重要:**「每天複習比一口氣讀很久來的重要,也讓自己不那麼累」**。
|
||||
- 腦中的房間是用不完的,**學就對了**。
|
||||
|
||||
### 7. 書包、置物櫃和注意力章魚
|
||||
- 工作記憶
|
||||
- 就像書包,小,但是拿取快速
|
||||
- 工作記憶可以比喻成一隻「注意力章魚」,有四隻手,表示它能一次抓住4個東西,這也說明了為什麼我們沒辦法一次處理太多事情。
|
||||
- 每個人的「注意力章魚」擁有的手臂數量不一樣,反正不要讓自己一次處理太多事情。
|
||||
- 注意力章魚住在大腦的「前額葉皮質」這地方。
|
||||
- [[20201201 - 學習如何學習#^23ddb6|專注模式]]才能讓注意力章魚好好工作。
|
||||
- 長期記憶: ^13eaf6
|
||||
- 就像置物櫃,可以放很多東西,但是距離遠,也不容易搜尋。
|
||||
- 擁有無限空間
|
||||
- 但是必須透過練習才能好好地取用資料。
|
||||
|
||||
### 8. 強化記憶
|
||||
- [[20201201 - 學習如何學習#^13eaf6|長期記憶]]就像置物櫃,要在置物櫃貼一張圖很容易,要把在外面的牙膏擠回去則很難。
|
||||
- 事實就像牙膏,記圖像比記憶事實容易。
|
||||
- 事實是抽象的,無法輕易描繪,因此也難以保存。
|
||||
- 五個記憶訣竅
|
||||
1. 專注:愈常練習你的注意力,就愈能保持專注
|
||||
2. 練習
|
||||
3. 將事物圖像化
|
||||
4. 儲存:關聯!將這些訊息與你已經知道的事物關聯起來,很誇張也沒關係
|
||||
5. 回想、回想、再回想:[[20201201 - 學習如何學習#^da7fba|積極回想]]
|
||||
|
||||
### 9. 腦連結
|
||||
- 透過練習可以建立「腦連結」,不同的腦連結可以互相連結,讓我們的工作記憶可以迅速處理資訊。專家在其領域都有大量且堅固的腦連結組,這也是為什麼專家可以快速而且有效率的處理資訊。
|
||||
- 刻意練習可以建立更強固的腦連結組。
|
||||
- 不停的切換「腦連結組」,會讓注意力章魚非常疲累,這也是為什麼我們應該避免分心和任務切換。
|
||||
- 認知負荷有它的限度。如果工作記憶有太多的資訊需要處理,我們就會陷入困惑,很難將他們弄明白,這是「資訊超載」。
|
||||
- 學習任務的最初階段,通常都是最困難的。有時你不喜歡某些事,是因為你還沒精通它們。
|
||||
|
||||
### 10. 社群共學,發覺你的使命
|
||||
- 這章由泰瑞.索諾斯基講他的學習經驗
|
||||
|
||||
### 11. 鍛鍊大腦
|
||||
- 睡覺時,我們學過的東西會由海馬迴轉移到大腦皮層。
|
||||
- 而大腦皮層負責長期記憶。
|
||||
- 也就是:「睡眠可以幫助學習」。
|
||||
- 運動有助於神經元的生長。運動時,大腦會產生 brain-derived neurotrophic factor(腦源性神經營養因子),簡稱BDNF。
|
||||
- 尤里烏斯.葉戈可以成為冠軍不只是觀看大量學習影片,他也做了大量練習。
|
||||
|
||||
### 12. 形成腦連結
|
||||
- 腦連結組是一條充分練習的思維路徑。
|
||||
- 創造腦連結的方式
|
||||
1. 刻意練習:[[20201201 - 學習如何學習#9 腦連結]]
|
||||
2. 交錯:[[20201201 - 學習如何學習#5 老師書桌的另一邊]]
|
||||
3. 專注
|
||||
- 如果一直練習你本來就會的東西,那就不是刻意練習,而是懶惰學習,這對學習沒有幫助。
|
||||
|
||||
### 13. 問自己重要的問題
|
||||
- 要觀察自己。譬如說對於**讀書應不應該聽音樂**這件事,即使科學家也沒法告訴你好或是不好,但是你可以自己實驗看看,哪一種對你比較有益。
|
||||
- 在不同的地方念書。不要讓你的「注意力章魚」過於習慣一個地方,換個地方念書,你的「注意力章魚」不會習慣於特定地方,變成總是從你的「長期記憶」來拿取東西,這有助於建立你腦連結。
|
||||
- 多元感官學習。試著用其他方式學習,譬如聽書或是做些什麼,總是用同一種方式學習(譬如「看」書),會讓其他學習方式弱化。
|
||||
- 睡覺!睡覺!睡覺!睡眠可以清除腦中的有毒物質。
|
||||
- 先吃青蛙。先從不喜歡或是從困難的開始。
|
||||
- 設定停工時間。這裡我把它理解為「該休息的時候就休息」。
|
||||
|
||||
### 14. 學習帶來的驚喜
|
||||
- 電玩。動作型電玩可以訓練專注力,空間型電玩可以訓練空間感。但有**上癮**的缺點。
|
||||
- 學習不一樣的事物。我們可能會陷入「慣性思考」,你的心智變得太過習慣沿著特定神經通道奔跑,因此不容易改變,讓你的思考不夠靈活。
|
||||
- 「移轉」。無論你學什麼,你的大腦都會找到辦法,讓這些新概念對你原本的興趣產生用處,通常是透過「比喻」,而這就是「移轉」。你在某個部位創造出腦連結,讓你容易在不同的部位也建立起連結。
|
||||
- 用「手寫」來做筆記。這對腦部的刺激比打字更多。
|
||||
- 「工作記憶」欠佳不好嗎?
|
||||
- 因為「工作記憶」不好,表示你的章魚沒有足夠的手來抓住腦中的想法,所以你必須「簡化」、「連結」這些概念。
|
||||
- 會比較容易有「單純化」和「跳耀的創造力」。
|
||||
- 徒步腦 vs. 賽車腦
|
||||
- 徒步腦,學得比較慢,但可能比較細緻與深入
|
||||
- 賽車腦,學得快,但可能忽略了細節。
|
||||
- 你的腦不會是固定的型態,你可能在某些科目是徒步腦,另外某些是賽車腦。
|
||||
- 即使你是徒步腦,你還是能學會東西,只是比較慢而已,千萬不要有「反正我就是學不會」的放棄想法。
|
||||
|
||||
### 15. 如何考出好成績
|
||||
- 考前準備檢核表
|
||||
1. [ ] 你在考試前一晚的睡眠足夠嗎?(如果你的答案是「否」,那麼其他問題的答案可能就不重要了。)
|
||||
2. [ ] 你在課堂上做完筆記後會盡快複習嗎?在複習時,你有運用「積極回想」的技巧,測試自己能否記得重點嗎?
|
||||
3. [ ] 平常你有每天用功讀一點書,而不是等到考前最後一刻才臨時抱佛腳嗎?
|
||||
4. [ ] 讀書時,你有全神貫注,避免分心嗎?
|
||||
5. [ ] 你有換不一樣的地方念書嗎?(休息時間例外)
|
||||
6. [ ] 你是否會仔細閱讀課本或參考書?(只是搜尋你正在解決的問題答案不算數。)當你閱讀時,你是否會避免在課本上劃太多底線和做重點提示?你是否會對重點概念做簡單的筆記,並不時移開視線,看看能否加以回想?
|
||||
7. [ ] 如果你的作業中有問題要解決,你是否靠自己的力量去解題,使這些步驟能組織成腦連結,需要時可以快速想起?
|
||||
8. [ ] 你是否和同學一起討論作業中遇到的問題,或者,至少你會跟同學對一下答案?
|
||||
9. [ ] 你是否主動練習過每一道作業題?
|
||||
10. [ ] 當你看不懂課本的內容時,你是否會請教老師,或者找其他同學來幫助你理解?
|
||||
11. [ ] 你是否花了大量時間專注在你覺得較困難的部分?換句話說,你是否「刻意練習」?
|
||||
12. [ ] 你是否「交錯」學習?換句話說,你有沒有練習在什麼時候運用不同的技巧來解題?
|
||||
13. [ ] 你是否會用有趣的比喻和圖像,像自己或別人解釋重要的概念?
|
||||
14. [ ] 你在學習過程中,有沒有偶爾休息一下,例如站起來,活動一下身體?
|
||||
|
||||
- 硬啟動技巧
|
||||
1. 先瀏覽考題,找出覺得難的題目
|
||||
2. 先作難的
|
||||
3. 一旦卡住(或說花太多時間,譬如5分鐘了還沒解出來),就跳去做簡單的 <- 先吃青蛙
|
||||
|
||||
- 轉換考試壓力,要正面思考
|
||||
- 深呼吸
|
||||
- 檢查考卷(驗算)
|
||||
|
||||
### 16. 從被動到主動
|
||||
- 讓學習有意義,把「我必須學習」轉換成「我要學習」。
|
||||
- 學習時該做的事
|
||||
- 充分利用高強度的「專注模式」和放鬆「發散模式」。
|
||||
- 藉由練習、重複和回想來創造腦連結。
|
||||
- 交錯
|
||||
- 分散學習。每天學一點好過臨時抱佛腳。
|
||||
- 自我測試。測驗以及教導別人。
|
||||
- 使用「比喻」。
|
||||
- 利用番茄鐘工作法。
|
||||
- 先吃青蛙。
|
||||
- 找到讓自己積極學習的方式與意義。
|
||||
- 學習時不該做的事
|
||||
- 沒有充足的睡眠
|
||||
- 消極的反覆閱讀。用「積極回想」來取代反覆閱讀。
|
||||
- 做重點標記或劃底線。
|
||||
- 看一眼解答就以為自己了解了。
|
||||
- 死記硬背。
|
||||
- 懶惰的學習。
|
||||
- 忽略課本。
|
||||
- 沒搞清楚困惑的部分。
|
||||
- 分心
|
||||
- 和朋友聊天
|
||||
- 堅持是學習最重要的部分。堅持,不代表不間段的一直做某件事情,而是在發散模式休息之後,持續返回你的工作。
|
||||
604
05. 資料收集/讀書筆記/20201218 - Kotlin權威2.0.md
Normal file
604
05. 資料收集/讀書筆記/20201218 - Kotlin權威2.0.md
Normal file
@@ -0,0 +1,604 @@
|
||||
### 1. Kotlin應用開發初體驗
|
||||
- 安裝[IntelliJ IDEA](https://www.jetbrains.com/idea/)
|
||||
- 在.kt檔案寫一個`main()`,旁邊會出現小箭頭,就可以直接執行。
|
||||
![[Pasted image 20201225114228.png]]
|
||||
|
||||
- 註解
|
||||
- `//`: 以兩個斜線(`/`)開頭就是註解,會被編譯器忽略
|
||||
- `/* 這行文字是註解 */`: 這是另一種註解,被`/*`與`*/`包圍起來的區段都是註解,這種方可以跨行註解,但是注意,`/* */`裡面不可以再有另一個`/* */`方式的註解。
|
||||
|
||||
### 2. 變數、常數和類型
|
||||
#### 定義一個「可變」變數
|
||||
```Kotlin
|
||||
var experiencePoints: Int = 5
|
||||
--- --- -
|
||||
^ ^ ^
|
||||
| | |
|
||||
| | Assign value
|
||||
| Type
|
||||
Keyword
|
||||
```
|
||||
使用`var`所定義的變數可以再度被改變,例如:
|
||||
```
|
||||
experiencePoints = 10
|
||||
```
|
||||
就會把`experiencePoints`的值變為10。
|
||||
|
||||
#### 定義一個「唯讀」變數
|
||||
使用`val`所定義的變數不可以再被改變,例如,定義一個名叫`myLuckyNumber`的「唯讀」變數:
|
||||
```Kotlin
|
||||
val myLuckyNumber: Int = 7
|
||||
|
||||
myLuckyNumber = 10 <-- ERROR!
|
||||
```
|
||||
|
||||
#### 要用哪一種方式來定義?
|
||||
應該優先使用`val`來定義變數,遇到變數需要改變的時候再來把`val`換成`var`。這總比有人寫出了bug,不小心改動了變數而造成玲成錯誤來的好。明確的錯誤總是比較容易解決。
|
||||
|
||||
#### 類型推斷
|
||||
Kotlin是一個強型別的語言,每一個變數都要有一個明確的「類型」。但Kotlin也有類型推斷的能力。例如:
|
||||
```
|
||||
val myLuckyNumber: Int = 7
|
||||
```
|
||||
因為很明確的`myLuckyNumber`要指定為7,7是一個整數(`Int`),所以`Int`可以忽略,如下:
|
||||
```
|
||||
val myLuckyNumber = 7
|
||||
```
|
||||
在IntellJ中,把游標停在變數上,按下`Ctrl + Shift + P`你會看到它推斷出來的類型:
|
||||
![[Pasted image 20201225120335.png]]
|
||||
|
||||
#### 常數
|
||||
用`const val`來定一一個常數(不會變的)
|
||||
```
|
||||
const val MAX_SCORE = 100
|
||||
```
|
||||
`const val`是編譯時就定義好的,不同於`val`是執行時期才設定的。
|
||||
|
||||
#### 深入學習
|
||||
Java中有兩種類型:「參照類型」(reference types)與「基礎類型」(primitive types)
|
||||
參照類型有對應的code,大都是一個class。基礎類型則沒有,由keyword表示。
|
||||
Java的「參照類型」都是大寫開頭,例如:
|
||||
```
|
||||
Integer point = 5;
|
||||
```
|
||||
基礎類型則是
|
||||
```
|
||||
int point = 5;
|
||||
```
|
||||
|
||||
但在Kotlin中只有「參照類型」,也就是說基礎類別都是大寫,像是`Int`、`String`、`Double`、`Boolean`...等等。
|
||||
雖然說Compiler會有條件的把參照類型轉為基礎類型來增加效率,但對於開發者來說大都是不需在意的。
|
||||
|
||||
### 3. 條件運算式
|
||||
#### if/else
|
||||
語法
|
||||
```kotlin
|
||||
if (<condition>) {
|
||||
// code block if <condition> is true
|
||||
} else {
|
||||
// code block if <condition> is false
|
||||
}
|
||||
```
|
||||
當`<condition>`為`true`的時候,`if`區塊裡面的code就會被執行
|
||||
|
||||
##### 多重條件
|
||||
當有多個condition的時候,可以用`else if`來增加條件,如下:
|
||||
```kotlin
|
||||
if (<condition_1>) {
|
||||
// code block if <condition_1> is true
|
||||
} else if (<condition_2>) {
|
||||
// code block if <condition_2> is true
|
||||
} else if (<condition_3>) {
|
||||
// code block if <condition_3> is true
|
||||
else {
|
||||
// code block if doesn't match any conditions.
|
||||
}
|
||||
```
|
||||
|
||||
##### 比較運算子
|
||||
Kotlin使用的比較運算子如下
|
||||
- `<`: 左側值是否「小於」右側值
|
||||
- `<=`: 左側值是否「小於等於」右側值
|
||||
- `>`: 左側值是否「大於」右側值
|
||||
- `>=`: 左側值是否「大於等於」右側值
|
||||
- `==`: 左側值是否「等於」右側值
|
||||
- `!=`: 左側值是否「不等於」右側值
|
||||
- `===`: 左側的reference是否「等於」右側的reference
|
||||
- `!==`: 左側的reference是否「不等於」右側的reference
|
||||
|
||||
##### 邏輯運算子
|
||||
- `&&`: AND
|
||||
- `||`: OR
|
||||
- `!`: NOT
|
||||
|
||||
##### 條件運算式
|
||||
`if/else`運算式可以直接指派給一個變數,區塊內的最後一行會被當成回傳值設定給變數,例如:
|
||||
```
|
||||
val color = if (type == "tree") {
|
||||
println("type is tree")
|
||||
"GREEN" // <- 最後一行會是return value
|
||||
} else {
|
||||
println("type is not tree")
|
||||
"WHITE" // <- 最後一行會是return value
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### range
|
||||
Kotlin使用`..`來代表一個範圍,例如`1..5`會等於`1, 2, 3, 4, 5`。
|
||||
在`if/else`裡面可以用來代替`>`, `<`之類的邏輯運算,例如:
|
||||
```
|
||||
if (score in 90..100) {
|
||||
println("A")
|
||||
} else if (score in 80..89) {
|
||||
println("B")
|
||||
} else {
|
||||
println("C")
|
||||
}
|
||||
```
|
||||
|
||||
`..`必須左邊小於右邊,若是要由大到小必須使用`downTo`:
|
||||
```
|
||||
3 downTo 1 // 3, 2, 1
|
||||
```
|
||||
另外,跟`..`類似的`until`,差異是`until`不包含右邊的值:
|
||||
```
|
||||
1 until 3 // 1, 2
|
||||
1..3 // 1, 2, 3
|
||||
```
|
||||
|
||||
上述操作也可以轉成list,呼叫`.toList()`即可:
|
||||
```
|
||||
(1..3).toList() // [1, 2, 3]
|
||||
(3 downTo 1).toList() // [3, 2, 1]
|
||||
```
|
||||
|
||||
#### when
|
||||
`when`類似C語言的`switch`,但是`when`更加靈活。先看一個例子:
|
||||
```
|
||||
val comment = when (score) {
|
||||
100 -> "Excellent"
|
||||
in 90..99 -> "A"
|
||||
in 80..89 -> "B"
|
||||
else -> "C"
|
||||
}
|
||||
```
|
||||
`when`會將score與`->`左邊的值做比較,要是成立就執行`->`右邊的區塊,跟`if/else`的條件運算一樣,執行區塊內的最後一行會被return並指派給變數:
|
||||
```
|
||||
val score = 99
|
||||
val name = "Bond"
|
||||
val comment = when (score) {
|
||||
100 -> {
|
||||
val message = "$name, you're Excellent
|
||||
message // <- 最後一行會是return value
|
||||
}
|
||||
in 90..99 -> {
|
||||
val message = "$name, you got A"
|
||||
message // <- 最後一行會是return value
|
||||
}
|
||||
in 80..89 -> {
|
||||
val message = "$name, you got B"
|
||||
message // <- 最後一行會是return value
|
||||
}
|
||||
else -> {
|
||||
val message = "$name, you got C"
|
||||
message // <- 最後一行會是return value
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### String範本
|
||||
用`$`開頭可以將變數的值帶入字串之中,例如:
|
||||
```
|
||||
val score = 100
|
||||
println("My score is $score") // -> 印出"My score is 100"
|
||||
```
|
||||
另外,若用`${}`,Kotlin會先將`{}`區塊求值,如此一來就可以很方便地在字串內做一些簡單處理或運算:
|
||||
```
|
||||
val a = 5
|
||||
val b = 6
|
||||
val result = "Result = ${a + b}"
|
||||
```
|
||||
|
||||
|
||||
### 4. 函數
|
||||
#### 函數的結構
|
||||
一個函數的結構如下
|
||||
```kotlin
|
||||
private fun functionName(arg1: String, arg2: Int): String {
|
||||
// function body
|
||||
}
|
||||
```
|
||||
- `private`是「可見性修飾符」,若是在檔案中,則這個function只有在檔案中是可見的。
|
||||
- `fun functionName`是「函數名稱宣告」,宣告一個函數的開始,其中functionName可以自己命名。
|
||||
- `(arg1: String, arg2: Int)`: 參數。每一組參數由`,`隔開。開頭是參數的名稱,`:`後面是參數的類型。以此例來說,有2組參數,第一組的參數叫做`arg1`,類型是`String`。第二組的參數叫做`arg2`,類型是`Int`。
|
||||
- `{ }`裡面是是函數運算本體。
|
||||
|
||||
#### 預設引數
|
||||
參數可以有一個預設值。例如下例:
|
||||
```
|
||||
fun sayHello(name: String): String {
|
||||
return "Hello $name!"
|
||||
}
|
||||
```
|
||||
一定要傳入一個名字,我們可以預設讓它接受一個空字串,讓他單純說聲"Hello"就好。
|
||||
```
|
||||
fun sayHello(name: String=""): String {
|
||||
return "Hello $name!"
|
||||
}
|
||||
```
|
||||
如此一來,使用者可以直接呼叫`sayHello()`就可以得到字串了。
|
||||
|
||||
#### 單運算式函數
|
||||
對於單純只有一行的函數,我們可以簡化函數的寫法,把大括號省略掉。以上面`sayHello()`的例子來說,可以簡略如下:
|
||||
```
|
||||
fun sayHello(name: String=""): String = "Hello $name!"
|
||||
```
|
||||
|
||||
#### Unit函數
|
||||
對於沒有返回值的函數,其返回值不是`void`,而是`Unit`。這類函數叫做「Unit函數」。
|
||||
|
||||
#### 具名函數引數
|
||||
呼叫函數時,一定要按照函數所定義的參數順序來填寫,否則會出錯,假設有一個函數定義如下:
|
||||
```
|
||||
fun getDiscountPrice(price: float, discount: float): float {
|
||||
return price * (1.0 - discount)
|
||||
}
|
||||
```
|
||||
價錢與折數的順序要是錯位就會造成錯誤,這時候,呼叫函數時明確寫出參數名字可以避免這個情形:
|
||||
```
|
||||
val newPrice = getDiscountPrice(price = 1000.0,
|
||||
discount = 0.3)
|
||||
```
|
||||
一旦使用具名引數,順序不對也沒有關係,像下面這樣寫也是可以的:
|
||||
```
|
||||
val newPrice = getDiscountPrice(discount = 0.3,
|
||||
price = 1000.0)
|
||||
```
|
||||
|
||||
#### Nothing類型
|
||||
`Nothing`表示不可能執行成功。Kotlin標準程式庫的`TODO()`可以給一個經典的用法:
|
||||
```
|
||||
public inline fun TODO(): Nothing = throw NotImplementedError()
|
||||
```
|
||||
我們可以把TODO()用在還沒完成的函數上,例如:
|
||||
```
|
||||
fun notOkFunc(arg1: Int): Int {
|
||||
TODO("Someone finsih this")
|
||||
println("I don't want to implemnt this...") // <- This line is unreachable
|
||||
}
|
||||
```
|
||||
因為某種原因`notOkFunc()`沒有實作完成,它也沒有返回一個`Int`的結果。但因為TODO()返回Nothing的關係,所以編譯器就忽略了這個檢查,反正它會執行失敗。
|
||||
|
||||
#### 奇怪的函數名
|
||||
一般來說函數的名字並不可以有空白或是一些特殊符號,但是Kotlin支援用「反引號」來定義有特殊名字的函數。例如:
|
||||
```
|
||||
fun `** Click to login **`(): Int {
|
||||
...
|
||||
}
|
||||
```
|
||||
呼叫時就變成:
|
||||
```
|
||||
val loginResult = `** Click to login **`()
|
||||
```
|
||||
但支援這種語法的主要原因是為了可以呼叫Java的API,例如,Java有一個叫做`is()`的函數,但是`is`是Kotlin的保留字(用來檢查類型),所以在Kotlin裡面要呼叫Java的`is()`就必須使用這個方法,例如:
|
||||
```
|
||||
fun callJavaIsInKotlin() {
|
||||
`is`() // <- Invokes is() function from Java
|
||||
}
|
||||
```
|
||||
|
||||
### 5. 匿名函數與函數類型
|
||||
#### 匿名函數
|
||||
在`{}`裡面,沒有名字的就是匿名函數,定義一個簡單的匿名函數:
|
||||
```
|
||||
{
|
||||
println("Hello")
|
||||
}
|
||||
```
|
||||
呼叫這個匿名函數:
|
||||
```
|
||||
{
|
||||
println("Hello")
|
||||
}()
|
||||
```
|
||||
其實就跟呼叫一般函數一樣,只是`()`之前是一個函數本體,而不是函數名稱。
|
||||
匿名函數在Kotlin叫做lambda,以後都用lambda來稱呼匿名函數。
|
||||
|
||||
#### 隱式返回
|
||||
lambda預設會返回「最後一行」,而且**不能呼叫**`return`。這是因為編譯器不知道返回資料是來自於lambda或是lambda的呼叫者。
|
||||
下面這個無聊的lambda會返回一個字串:
|
||||
```
|
||||
{
|
||||
"Hello"
|
||||
}
|
||||
```
|
||||
|
||||
#### lambda類型
|
||||
lambda本身是一個類型(type),所以lambda也可以指定給變數。如以下例子:
|
||||
```kotlin
|
||||
val get5 = {
|
||||
val a = 2
|
||||
val b = 3
|
||||
a + b // 最後一行為返回值
|
||||
}
|
||||
|
||||
// 呼叫lambda
|
||||
val number = get5()
|
||||
```
|
||||
lambda類型是由lambda的輸入參數、輸出類型所定義的。
|
||||
|
||||
#### lambda的參數與返回值
|
||||
方法1:將參數類型與返回值定義在變數裡
|
||||
```kotlin
|
||||
val addResult: (a: Int, b: Int) -> Int = {
|
||||
a + b
|
||||
}
|
||||
```
|
||||
上面的例子定義了`addResult`這個lambda,輸入參數有`a`、`b`兩個,兩個的類型都是`Int`,返回值也是`Int`。`{}`內則是實作。
|
||||
|
||||
方法二:將參數類型與返回值定義在變數裡,參數命名則在函數本體裡
|
||||
```kotlin
|
||||
val addResult: (Int, Int) -> Int = {a, b ->
|
||||
a + b
|
||||
}
|
||||
```
|
||||
上面的例子定義了`addResult`這個lambda,輸入是兩個類型為Int的參數,返回類型也是Int,參數名稱`a`、`b`則定義在`{}`,這也表示參數名稱可以由lamdba提供者隨意修改。
|
||||
|
||||
#### lambda的類型推斷
|
||||
如同編譯器可以自東推斷變數的類型,lambda的類型也可以自動推斷,例如:
|
||||
```kotlin
|
||||
val returnHello: () -> String = {
|
||||
"Hello"
|
||||
}
|
||||
```
|
||||
可以簡化成:
|
||||
```kotlin
|
||||
val returnHello = {
|
||||
"Hello"
|
||||
}
|
||||
```
|
||||
很顯然的,這一個沒有輸入參數,回傳值String的lambda。
|
||||
對於有多個參數的lambda,則需要清楚的把參數的名字與類型都寫出來,例如:
|
||||
```kotlin
|
||||
val sayHello = { name: String, age: Int
|
||||
"Hello, I'm $name, $age years old."
|
||||
}
|
||||
```
|
||||
`sayHello()`的推斷類型是:輸入有兩個參數,一個是型別為String的name,另一個是型別為Int的age,然後根據[[20201218 - Kotlin權威2.0#隱式返回]],最後一行是回傳值,所以返回值是String型別。這寫法跟下面的寫法同意:
|
||||
```kotlin
|
||||
val sayHello: (String, Int) -> String = { name, age
|
||||
"Hello, I'm $name, $age years old."
|
||||
}
|
||||
```
|
||||
|
||||
#### `it`關鍵字
|
||||
當lambda只有一個參數的時候,可以用it來當參數的名字,例如:
|
||||
```kotlin
|
||||
val add5: (Int) -> Int = {
|
||||
it + 5
|
||||
}
|
||||
```
|
||||
使用it雖然方便但是對可讀性卻沒有比較好,這點自己權衡使用。
|
||||
|
||||
#### 將lambda當作參數
|
||||
lambda可以當作參數傳給函數,只要在函數內定義好lambda的類型即可。例如,我們可以設計一個函數,接收不同「打招呼lamdba」來產生打招呼字串,我們先定義3個打招呼lambda:
|
||||
1.
|
||||
```kotlin
|
||||
val sayHi = { name: String,
|
||||
"Hi $name"
|
||||
}
|
||||
```
|
||||
2.
|
||||
```kotlin
|
||||
val sayHello = { name: String,
|
||||
"Hello $name"
|
||||
}
|
||||
```
|
||||
3.
|
||||
```kotlin
|
||||
val sayGoodMornig = { name: String,
|
||||
"Good mornig, $name"
|
||||
}
|
||||
```
|
||||
這三個lambda都有同樣的型別,型別都是 (String) -> String,也就是輸入參數是一個String,返回值也是String。
|
||||
接下來,定義我們要使用的函數:
|
||||
```kotlin
|
||||
fun greet(name: String, greetFunc: (String) -> String): String {
|
||||
return greetFunc(name)
|
||||
}
|
||||
```
|
||||
然後我們就可以這樣用:
|
||||
```kotlin
|
||||
val greetString1 = greet("John", sayHi)
|
||||
val greetString2 = greet("John", sayHello)
|
||||
val greetString3 = greet("John", sayGoodMornig)
|
||||
```
|
||||
|
||||
#### 將lambda當作參數的簡略語法
|
||||
如果lambda參數是函數的最後一個參數,那麼便可以使用簡略語法,我們用上面的例子一步一步來看。例如我們直接將`sayHi` lambda寫在`greet()`裡面:
|
||||
```kotlin
|
||||
val greetString1 = greet("John", { name: String ->
|
||||
"Hi $name"
|
||||
})
|
||||
```
|
||||
因為lambda是最後一個,所以可以將lambda移到外面來:
|
||||
```kotlin
|
||||
val greetString1 = greet("John") { name: String ->
|
||||
"Hi $name"
|
||||
}
|
||||
```
|
||||
又因為這個lambda只有一個參數,所以可以用`it`來簡化它,變成:
|
||||
```kotlin
|
||||
val greetString1 = greet("John") {
|
||||
"Hi $it"
|
||||
}
|
||||
```
|
||||
|
||||
#### inline function
|
||||
若想要避免lambda產生記憶體開銷,就可以使用`inline`關鍵字,`inline`關鍵字會函數在使用的地方展開,例如剛剛的sayHi例子,我們將使用lambda的`greet()`函數加上inline,變成:
|
||||
```kotlin
|
||||
inline fun greet(name: String, greetFunc: (String) -> String): String {
|
||||
return greetFunc(name)
|
||||
}
|
||||
```
|
||||
那麼`greet()`就會在呼叫處直接展開,就好像:
|
||||
```kotlin
|
||||
{
|
||||
val result = "Hi $name"
|
||||
return result
|
||||
}
|
||||
```
|
||||
|
||||
#### 將函數當作參數
|
||||
用fun定義的函數也可以像lambda一樣當作參數,只是要在呼叫的時候在函數名前面加上`::`,例如:
|
||||
```kotlin
|
||||
fun sayHi(name: String): String {
|
||||
return "Hi $name"
|
||||
}
|
||||
|
||||
fun greet(name, greetFunc: (String) -> String): String {
|
||||
val greetString = greetFunc(name)
|
||||
return greetString
|
||||
}
|
||||
|
||||
// 呼叫
|
||||
greet("John", ::sayHi)
|
||||
```
|
||||
|
||||
#### 在函數裡返回一個函數
|
||||
若是將函數的返回值定義為相對應的函數類型,即可以返回函數,例如,我們可以設計一個函數,這個函數接受1、2、3三種數字,當使用者輸入1的時候,我們返回`sayHi`來讓使用呼叫,當使用者輸入2的時候,我們返回`sayHelllo`來讓使用呼叫,當使用者輸入2的時候,我們返回`sayGoodMornig`來讓使用呼叫:
|
||||
```kotlin
|
||||
fun selectGreet(number: Int): (String) -> String {
|
||||
when (number) {
|
||||
1 -> sayHi,
|
||||
2 -> sayHello,
|
||||
3 -> sayGoodMornig
|
||||
}
|
||||
}
|
||||
```
|
||||
可以看到`selectGreet`的回傳值是`(String) -> String`,接下來我們可以這樣用:
|
||||
```kotlin
|
||||
val greetFunc = selectGreet(2)
|
||||
val greetString = greetFunc("John") // greetString會是"Hi John"
|
||||
```
|
||||
|
||||
#### lambda也是closure
|
||||
若是在函數裡面回傳一個lambda的時候,回傳的那個lambda在被呼叫的時候還是可以使用當初函數所在位置的變數,這便是closure。例如:
|
||||
```kotlin
|
||||
fun countGreet(): (String) -> String {
|
||||
var count = 0
|
||||
|
||||
return { name ->
|
||||
count = count + 1
|
||||
"[$count] Hi $name"
|
||||
}
|
||||
}
|
||||
```
|
||||
當我們呼叫它的時候:
|
||||
```kotlin
|
||||
val greetFunc = countGreet()
|
||||
val countString1 = greetFunc("John") // countString會等於"[1] Hi Jhon"
|
||||
val countString2 = greetFunc("John") // countString會等於"[2] Hi Jhon"
|
||||
val countString3 = greetFunc("John") // countString會等於"[3] Hi Jhon"
|
||||
```
|
||||
雖然`count`是`countGreet()`內的區域變數,但是`greetFunc()`還是能繼續取用它。
|
||||
能夠接受函數(或是lambda)當參數或是返回函數的函數又叫做**高階函數**。
|
||||
|
||||
### 6. Nullability
|
||||
Kotlin預設是型別都不可以是null。如果有一個型別是`String`的變數,把它設為null的話,compiler就會報錯。
|
||||
```kotlin
|
||||
var name = "John"
|
||||
name = null <-- Error!
|
||||
```
|
||||
|
||||
如果一定要設為null,那麼必須在宣告的時候,用`?`符號告訴compiler說這個變數必須是「可以null的」。
|
||||
```kotlin
|
||||
var name: String? = "John"
|
||||
name = null <-- OK
|
||||
```
|
||||
|
||||
`?`也可以用來判斷函數的回傳值,例如有一個函數它會回傳一個字串,或一個null:
|
||||
```kotlin
|
||||
fun getString(number: Int): String? {
|
||||
if (number > 90) {
|
||||
return "good"
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
```
|
||||
那我們在呼叫這個函數之後,可以方便的用`?`來串接下一個步驟:
|
||||
```kotlin
|
||||
val status = getString(50)?.capitialize()
|
||||
```
|
||||
上面例子是我們在得到"good"字串後,呼叫`String.capitialize()`來把字串的第一個字元變成大寫。`?`符號可以幫我們判斷`getString()`回傳的是不是null,如果不是,就接著呼叫`capitialize()`,如果是null,`capitialize()`就不會被呼叫,status將會是null。上面例子跟下面的程式是一樣的效果,但是明顯簡短的多:
|
||||
```kotlin
|
||||
val status = getString(50)
|
||||
var statusCapital: String? = null
|
||||
if (status) {
|
||||
statusCapital = status.capitialize()
|
||||
}
|
||||
```
|
||||
|
||||
如果串接函數很多個的時候,更能看出效果:
|
||||
```kotlin
|
||||
val number = funcA()?.funcB()?.funcC()?.funcD()
|
||||
```
|
||||
|
||||
#### `!!` operator
|
||||
`!!`,[not-null assertion](https://kotlinlang.org/docs/reference/null-safety.html#the--operator) 用來讓compiler忽略null的檢查,例如:
|
||||
```kotlin
|
||||
var name: String? = null
|
||||
name.capitialize() <-- 會報錯
|
||||
name!!.capitialize() <-- 不會報錯,但是runtime會錯
|
||||
```
|
||||
|
||||
#### `?:` Elvis operator
|
||||
`?:` 就是「要是左邊為false就執行右邊」,`?:`可以很方便的用來設定變數的預設值,例如前面舉過的例子:
|
||||
```kotlin
|
||||
val number = funcA()?.funcB()?.funcC()?.funcD()
|
||||
```
|
||||
要是`funcA()`、`funcB()`、`funcC()`中任何一個的回傳是null,那麼number都會因為無法求值而被設為null,我們可以用`?:`來給它一個預設值:
|
||||
```kotlin
|
||||
val number = funcA()?.funcB()?.funcC()?.funcD() ?: "Default value"
|
||||
```
|
||||
|
||||
#### 異常(Exception)
|
||||
用`throw`來拋出一個異常,例如:
|
||||
```kotlin
|
||||
throw IllegalStateException("Oh! Oh!")
|
||||
```
|
||||
|
||||
#### 自訂異常
|
||||
可以用繼承來建立自己的異常:
|
||||
```kotlin
|
||||
class MyIllegalException(): IllegalStateException("I like new Exception")
|
||||
```
|
||||
|
||||
#### 處理異常
|
||||
用`try/catch`來處理異常:
|
||||
```kotlin
|
||||
var name: String? = null
|
||||
|
||||
name = somefunctionCall()
|
||||
|
||||
try: {
|
||||
val newName = name.capitialize()
|
||||
}
|
||||
catch (e: Exception) {
|
||||
println(e)
|
||||
}
|
||||
```
|
||||
|
||||
#### 先決條件
|
||||
類似C++中的`assert()`,在符合判斷的條件下發出Exception。Kotlin內建5個先決條件函數:
|
||||
|
||||
| Funtion | Description |
|
||||
| ------------------ | ---------------------------------------------------------------------------------------|
|
||||
| `checkNotNull()` | `checkNotNull(condition, String)`,如果condition是`null`,就發出`IllegalStateException` |
|
||||
| `require()` | `require(condition, String)`,如果condition是`false`,就發出`IllegalStateException` |
|
||||
| `requireNotNull()` | `requireNotNull(condition, String)`,如果condition是`null`,就發出`IllegalStateException` |
|
||||
| `error` | `error(condition, String)`,如果condition是`null`,就發出`IllegalStateException` |
|
||||
| `assert` | `assert(condition, String)`,如果condition是`false`,就發出`AssertError` |
|
||||
|
||||
331
05. 資料收集/讀書筆記/20201224 - 寫作是最好的自我投資.md
Normal file
331
05. 資料收集/讀書筆記/20201224 - 寫作是最好的自我投資.md
Normal file
@@ -0,0 +1,331 @@
|
||||
### 1. 會說的人很多,能寫的人太少
|
||||
- 本章在倡導寫作的好處,文中所舉的例子有:北大薛兆豐老師在「得到」平台的收益一年有一千多萬人民幣。還有作者本身在畢業兩年之內,收入千萬。
|
||||
- 寫作可以
|
||||
- 自我認識,思考更縝密
|
||||
- 提升思考,對世界更敏感
|
||||
- 推銷理念,認知更深刻
|
||||
- 擴展人脈
|
||||
- 不寫作的問題
|
||||
- 職場身分不夠明顯(作者是認為「正在失去職場身分」)
|
||||
- 職場邊緣化。作者認為在職場上人脈是重要的資源,寫作可以連結這些資源,反過來說,不寫作的人無法擴展人脈,自然是被邊緣化。
|
||||
- 失去話語權。寫作可以宣傳自己的理念,也展現本身的技能與觀點。不寫作的人就像是不說話的人,沒有人了解你。
|
||||
- 職場影響力
|
||||
- 綜觀上述,強烈的職場身分與優先的話語權,會保障或者開闊你的職場道路。
|
||||
- 薪水代表過去,品牌代表未來
|
||||
|
||||
### 2. 坐下來,開始寫
|
||||
這一章解釋不寫作的心理與解決方式,也說了高品質輸出的方法。
|
||||
- 不寫作的心理
|
||||
- 擔心自己沒東西可寫
|
||||
- 擔心自己無法堅持
|
||||
- 擔心自己的思想太空洞被別人笑話
|
||||
- 覺得自己寫得不夠好,浪費時間
|
||||
- 寫作時,總是有一個審判者
|
||||
- 擔心寫出來的東西被別人認為沒有價值,覺得自己寫的文章很幼稚
|
||||
- 擔心寫出來的文章沒人看
|
||||
- 擔心投入時間卻得不到回報
|
||||
|
||||
- 不寫作的心理,解決方案
|
||||
- 擔心自己的思想太空洞被別人笑話 -> 其實太陽底下沒有新鮮事,道理誰都懂,如果你能提供一個新的角度,或者提供一段親身體驗的經歷,並且真誠的表達出來,這就是你的獨特價值。
|
||||
- 寫作時,總是有一個審判者 -> 先關閉、忽略審判者,寫完之後隔個一、二天再回頭審視修改。
|
||||
- 擔心寫出來的東西被別人認為沒有價值,覺得自己寫的文章很幼稚 -> 允許自己有「寫出世上最爛垃圾」的自由。
|
||||
|
||||
- 寫作的心態
|
||||
- 初學寫作,先寫自己想寫的。把那些如鯁在喉,不吐不快的感受記錄下來,用你自己滿意的方式準確、流暢的講清楚,一篇文章就有不錯的基礎。
|
||||
- 寫就對了,先求有再求好
|
||||
- 刻意練習,把寫東西變成「習慣」
|
||||
- 寫作要誠實
|
||||
- 不要有心理上的完美主義,不要只在心中只看到你幻想中的完美結局。對事情抱有過高的期望,但和現實差距很大,導致成為「行動上的矮子」。所以**完成比完美更重要**。
|
||||
- 養成規律寫作的習慣。村上春樹認為:「做長期工作時,規律性會具有重要意義。」
|
||||
- 保持高品質輸出的五個關鍵詞
|
||||
- 死嗑,保持持續的輸出
|
||||
- 敢拚,不恐懼
|
||||
- 要有自己的立場和鮮明的觀點
|
||||
- 專注
|
||||
- 野心,把格局做大
|
||||
- 好奇心,好奇心就跟肌肉一樣,你愈用它,它就愈能幹。
|
||||
|
||||
### 3. 寫作,是注意力的爭奪
|
||||
- 這一章說明了如何吸引「注意力」,也說明了讓文章有吸引力的方法。
|
||||
- 寫作的目的:
|
||||
- 依對象來分:
|
||||
- 給自己看的
|
||||
- 有特定對象的
|
||||
- **沒有特定對象的**
|
||||
- 依目的性來分:
|
||||
- 自我表達
|
||||
- **影響他人**
|
||||
- 寫作的注意力要求「沒有特定對象的」與「影響他人」,也就是對「不特定的對象產生影響」。
|
||||
- 從四個面向來看寫文章時的考量:
|
||||
- 情境:網路(手機)時代,閱讀時間已經碎片化
|
||||
- 用戶思維: ^1a3dd1
|
||||
- 滿足讀者的閱讀動機,要有同理心
|
||||
- 認知同理心:能從別人的角度看問題
|
||||
- 情感同理心:能體會別人的情緒
|
||||
- 讀者想要得到滿足
|
||||
- 說出讀者的心聲 ^fc39a6
|
||||
- 適應讀者的閱讀情境
|
||||
- 不冗長
|
||||
- 有刺激點
|
||||
- 產品思維:文章解決什麼問題 ^8a2433
|
||||
- 提升專業度
|
||||
- 獨家視角提升辨識度
|
||||
- 社交思維
|
||||
- 未來的一切商業都會連接網路
|
||||
- 社交會成為一切商業的底層架構
|
||||
- 心態
|
||||
- 把格局放大
|
||||
- 不以傳播率為目標
|
||||
- 長期經營
|
||||
- 「取乎其上,得乎其中;取乎其中,得乎其下;取乎其下,則無所得矣。」
|
||||
|
||||
|
||||
### 4. 如何寫出吸引人的好文章?
|
||||
這一章從「如何訂標題」跟「內文的結構與修改」兩方面來說明好文章的特性。
|
||||
#### 標題的特點
|
||||
- 引發共鳴:說到痛點或是心聲
|
||||
- 製造懸念:引起好奇心 ^cbfc4c
|
||||
- 引起爭議:提出質疑、選邊站的觀點
|
||||
- 顛覆認知
|
||||
|
||||
#### 訂出好標題的方法
|
||||
- 觀察、分析
|
||||
- 模仿、套用
|
||||
- 重視市場回饋
|
||||
|
||||
#### 內文的特點
|
||||
- 講故事,不要講道理
|
||||
- 開頭:人物、時間、地點
|
||||
- 誰的故事
|
||||
- 故事情節是故事的主體
|
||||
- 故事加金句 ^edd2d6
|
||||
- 設懸念:讓人有好奇心
|
||||
- 帶入,製造熟悉感
|
||||
- 製造讀者熟悉的問題
|
||||
- 順著對方的意願,解釋問題發生的原因,贏得對方的信任
|
||||
- 給出自己的觀點和對策
|
||||
- 反向鋪陳
|
||||
|
||||
#### 提升文采
|
||||
- 文采:文章帶來審美上的愉悅感
|
||||
- 1. 口語化
|
||||
- 避免過長的從句
|
||||
- 避免多層的邏輯
|
||||
- 避免連續的形容詞
|
||||
- 2. 用文字畫出圖
|
||||
- 多用動詞和名詞
|
||||
- 善抓細節
|
||||
- 多用比喻
|
||||
- 3. 具體化
|
||||
- 利用那些本身容易帶來感官和心理刺激的詞彙,把抽象的概念「刻」在讀者的腦子裡。
|
||||
|
||||
#### 內文修改
|
||||
- 檢查
|
||||
- 想寫的東西表達清楚了嗎?
|
||||
- 語氣是否合適?
|
||||
- 資訊完整嗎?
|
||||
- 故事案例是否可信、吸引人?
|
||||
- 邏輯是否有問題?
|
||||
- 觀點是否簡潔有力?
|
||||
- 有無錯別字?標點錯誤?文法錯誤?
|
||||
- 修改文章就是修改思想
|
||||
- 思路不清晰文章也會不通順
|
||||
- 培養良好的語言習慣
|
||||
- 葉勝陶先生:「語言是有聲無形的文章,文章是有形無聲的語言。」 ^d7f87c
|
||||
- 講話講重點。
|
||||
- 不自誇,不自責
|
||||
- 先把文章改到自己滿意,覺得改無可改。
|
||||
- 誠實面對自己的內心,面對自己不成熟的作品。
|
||||
- 不要過分挑剔,對自己嘮叨不停。
|
||||
|
||||
### 5. 如何寫好一個故事?
|
||||
- 文章需要故事(比喻)。
|
||||
- 卡夫卡說:「書必須是鑿破我們心中冰封海洋的一把斧。」
|
||||
- 這裡利用了第4章的[[20201224 - 寫作是最好的自我投資#^edd2d6|故事加金句]]技巧。
|
||||
- 用故事介紹自己,以獲取信任。
|
||||
- 用故事連結他人,以更好的說服別人。
|
||||
- 重點是和讀者有什麼關係。
|
||||
- 用對方熟悉和認可的故事,將溝通關係由「對抗」轉為「對話」。
|
||||
- 說故事要注意的三件事
|
||||
- 情感真實
|
||||
- 表達克制
|
||||
- 徹底改變思維方式
|
||||
- 村上春樹:「把內容盡量改以簡單的語言來說,把意圖轉換成容易理解的說法,描寫時盡量削掉多餘的贅肉,縮小整體型態,以便放進空間有限的容器裡。」
|
||||
- 相信市場,而非相信靈感
|
||||
- 故事的三要素
|
||||
- 鳳頭:開頭像鳳頭一樣精美
|
||||
- 豬肚:主體有裡有據像豬肚
|
||||
- 豹尾:結尾像豹尾一樣,簡潔有力又有平衡感
|
||||
- 用懸念、衝突建構吸引人的敘事結構
|
||||
- 再次提到「懸念」:[[20201224 - 寫作是最好的自我投資#^cbfc4c|製造懸念:引起好奇心]]
|
||||
- 渲染氣氛、刻畫人物
|
||||
- 場景
|
||||
- 氛圍
|
||||
- 人物
|
||||
- 結尾,給讀者驚喜的最後一個機會
|
||||
- 布魯斯.德席瓦:「結尾是你把小說的主旨釘在讀者記憶中,並讓他回想數天的最後一次機會。」
|
||||
|
||||
### 6. 如何訓練你的邏輯思維?
|
||||
- 表達就是邏輯問題,邏輯就是文章的條理。
|
||||
- 修正邏輯不通的方法
|
||||
- 不使用模糊或多義的語詞
|
||||
- 複雜的事情簡單說
|
||||
- 慎用雙重否定
|
||||
- 不要觀點,卻沒有堅實的推導
|
||||
- 確認事情
|
||||
- 要克制情緒,主觀看法不應變成客觀事實
|
||||
- 迷信專家說法
|
||||
- 有思想,沒有思考
|
||||
- 這一項我把他解讀成:相信某一種說法、思想,卻沒有去思考背後的脈絡與原則。
|
||||
- 蘇格拉底:「未經審查的人生沒有價值。」 ^fad99d
|
||||
- 對容易的想法與結論要感到警惕。
|
||||
- 確保深入了解再給出觀點。
|
||||
- 使用歸納法來表達意見。
|
||||
- 把別人的質疑與反駁當作深入思考的機會。
|
||||
- 三個邏輯思考的技巧
|
||||
- 列出提綱:把觀點想法**分類**。
|
||||
- 框架比細節重要
|
||||
- 分析層面
|
||||
- 闡述的觀點順序
|
||||
- 有邏輯的連接
|
||||
- 循序漸進
|
||||
- 有理論的推導
|
||||
- 有結論、有反思
|
||||
|
||||
### 7. 職場專業文章寫作的方法論
|
||||
這一章的主題在專業文章的寫作技巧、題材選定與技術進步的方法。
|
||||
- 「專業,二十一世紀你唯一的生存之道。」 - 大前研一 ^fd93cf
|
||||
- 寫職場乾貨文,是透過持續的輸出,爭奪職場話語權的方法。
|
||||
- 一篇公開發表的文章,能讓你省掉無數次重複勞動。
|
||||
- 專業文章寫作的兩個要點
|
||||
- 保持理性、冷靜
|
||||
- 注重邏輯
|
||||
- 職場是講道理的地方,不適講感情的地方。
|
||||
1. 選題的「加」與「減」
|
||||
1. 文章要有飽腹感,也就是讀者看完後明確知道收穫了什麼。
|
||||
2. 明確的利益點,想清楚這篇文章對讀者在哪個點上有幫助,圍繞此點綻開論述。
|
||||
3. 文章的「深度」、「廣度」、「角度」至少選一項。
|
||||
4. 開頭的文風與行業同調。結論先行或問題先行。
|
||||
- 不同的行業有不同的風格。
|
||||
2. 表達的「深」與「淺」
|
||||
1. 情節 -> 分析 -> 觀點 -> 結論
|
||||
- 寫好產業分析報告的五個步驟
|
||||
1. 明確目標:為什麼你要做這個分析?
|
||||
2. 界定問題
|
||||
- 拆分問題、各個擊破
|
||||
3. 蒐集資訊
|
||||
- 沒有調查就沒有發言權。
|
||||
- 資訊愈多、愈雜,就愈容易互相印證。
|
||||
4. 研究分析
|
||||
1. 五力分析模型(Five Forces Model)
|
||||
2. SWOT(態勢分析法)
|
||||
1. S: Strength
|
||||
2. W: Weakness
|
||||
3. O: Opportunity
|
||||
4. T: Threat
|
||||
3. 合作競爭
|
||||
5. 輸出成果
|
||||
- 金字塔結構
|
||||
- 構思專題的四格個原則
|
||||
- 專題有整體的規劃
|
||||
- 好的專題就像一部連續劇,會讓觀眾追劇。
|
||||
- 專題的面向:深度 or 時效
|
||||
- 起步階段,切入點要小
|
||||
- 找一個目標(假想敵)
|
||||
- 累積素材的四個方式
|
||||
- 累積專業知識
|
||||
- 從內部觀察行業裏的人和事
|
||||
- 從外部、社會的層面來觀察行業
|
||||
- 整合產業分析
|
||||
- 透過行業內的專業媒體
|
||||
- 透過會層面的報告
|
||||
- 置身第一現場(速度)
|
||||
- 成為社群好召者,進入專業的圈子。
|
||||
- 與高手過招(角度)
|
||||
- 「世界上沒有兩片相同的樹葉」
|
||||
- 高手有敏銳的目光與洞察力,特殊的視角。
|
||||
|
||||
### 8. 你所理解的新媒體寫作,也許都是錯的
|
||||
- 「任何一個好產品都是聰明人用笨功夫做出來的」 - 咪蒙 ^a00bcf
|
||||
- 新媒體的本質
|
||||
- 新媒體是一種工具 -> 增加傳播範圍,加快傳播速度
|
||||
- 競爭,是高效率淘汰低效率的過程 -> 技術的本質不是讓所有人變得更美好,而是把之前同樣的一群人分成兩類。
|
||||
- 掌握新技術 -> 成為贏家
|
||||
- 沒辦法掌握新技術 -> 淘汰
|
||||
- 累積客戶群 -> 得到信任
|
||||
- 新媒體寫作的基本原則
|
||||
- 始於刺激,限於選題,忠於邏輯,癡於文筆,止於經營
|
||||
- 刺激,也就是標題,「標題決定打開率,內容決定轉發率」
|
||||
- 選題,也就是戳中痛點,例如:
|
||||
- 事業上的激進與保守
|
||||
- 生活上的穩定與冒險
|
||||
- 認知成長的前與後
|
||||
- 能力與平台的博弈
|
||||
- 邏輯
|
||||
- 文筆,也就是文采,不光是內容的精彩,也包括文章段落的分配,字型的選用,大小的設定
|
||||
- 顏值即正義
|
||||
- 沒有人有義務透過你邋遢的外表看到你閃光的內心
|
||||
- 建立有力的口號
|
||||
- 經營
|
||||
- 功能介紹
|
||||
- 個人定位
|
||||
- 關注回復
|
||||
- 按鈕設置
|
||||
- 視覺風格
|
||||
- 連結設置
|
||||
|
||||
> ### 心得
|
||||
> 這一章針對網路文章的特性多加說明,然後再一次解說了把文章寫好的方法。但其實這一篇就是重複第3章、第4章、第5章的內容,再重新加以編排。
|
||||
> 例如:
|
||||
> 刺激講的是[[20201224 - 寫作是最好的自我投資#3 寫作,是注意力的爭奪]]與[[20201224 - 寫作是最好的自我投資#標題的特點]]。
|
||||
> 選題是再講第3章的[[20201224 - 寫作是最好的自我投資#^1a3dd1|用戶思維]]。
|
||||
> 邏輯與文筆是第5章的[[20201224 - 寫作是最好的自我投資#5 如何寫好一個故事?]]。
|
||||
> 經營則是分享手機上的設定技巧。
|
||||
|
||||
### 9. 人人都能寫出爆款文
|
||||
- 「天才的唯一秘密,就在於刻意練習,用自己一套系統性的方法,不斷突破自己的邊界」 - 刻意練習,安德斯.艾瑞克森 ^7e896d
|
||||
- 不知道怎麼寫是因為看得太少,寫的不好是因為寫得太少。
|
||||
- 如果可以借助熱點,讓更多人看到我,讓我寫的有價值的東西更好的傳播出去,遠比我一昧死守不蹭熱點要強。
|
||||
- 跟風口
|
||||
- 成為風口 -> [[20201224 - 寫作是最好的自我投資#訂出好標題的方法]]
|
||||
- 尋找情緒能量匯集的點
|
||||
- 揮正拍消解情緒,反手拍引爆情緒
|
||||
- 觀點中庸,等於平庸
|
||||
- 角度決勝負
|
||||
- 標題是入口,主題是情緒推進 -> [[20201224 - 寫作是最好的自我投資#內文的特點]]
|
||||
- 幫讀者表達想法 -> [[20201224 - 寫作是最好的自我投資#^fc39a6]]
|
||||
- 讓讀者塑造自己的形象
|
||||
- 幫讀者進行比較,那怕是曬優越
|
||||
- 文章本身就能幫助別人 -> [[20201224 - 寫作是最好的自我投資#^8a2433]]
|
||||
- 標題定乾坤 -> [[20201224 - 寫作是最好的自我投資#內文的特點]] & [[20201224 - 寫作是最好的自我投資#提升文采]]
|
||||
- 立畫面
|
||||
- 有代入
|
||||
- 表情緒
|
||||
- 做鋪陳
|
||||
- 善用萬能框架 -> [[20201224 - 寫作是最好的自我投資#5 如何寫好一個故事?]]
|
||||
- 亮觀點
|
||||
- 說現象
|
||||
- 做分析
|
||||
- 下結論
|
||||
- 活用行文走筆 -> [[20201224 - 寫作是最好的自我投資#提升文采]]
|
||||
- 文字密度:不要囉嗦,精簡幹練
|
||||
- 畫面感:細節具體,案例鮮活
|
||||
- 情緒化:觀點一定要愛恨分明
|
||||
- 結尾刺激轉發
|
||||
- 找準發布時間
|
||||
- 騰訊統計的閱讀高峰時間
|
||||
- 上午7-9點
|
||||
- 中午12點-下午2點
|
||||
- 晚上6-8點
|
||||
- 晚上10點以後
|
||||
- 作者的統計
|
||||
- 上午10-12點
|
||||
- 晚上8-10點
|
||||
|
||||
> ### 心得
|
||||
> 這一章作者拿以前自己寫過的一篇文章來分析文章架構,用的也是前面幾章所用的技巧,可以看到好多段落都是前面章節的重新拆分組購,其實概念是一樣的。
|
||||
>
|
||||
> 這個作者利用這招式把寫文章的方法(第4章:[[20201224 - 寫作是最好的自我投資#4 如何寫出吸引人的好文章?]])不斷重新組構,用不同的方式講解一次,就變成一本書了,其實看到第7章就有點膩了,本著不要半途而廢的心態還是把它給讀完了。
|
||||
>
|
||||
> 雖然說很多部分是重複的,讀起來也有厭煩的感覺,但作者確實很會找金句,立金句,這一點是可以學習的。
|
||||
> 另外,作者也很會下提綱,他也是先立題綱,然後一題綱展開鋪陳,所以雖然很多部分概念相同,多有似曾相似的感覺
|
||||
50
05. 資料收集/讀書筆記/20210119 - 中產悲歌.md
Normal file
50
05. 資料收集/讀書筆記/20210119 - 中產悲歌.md
Normal file
@@ -0,0 +1,50 @@
|
||||
書名:中產悲歌
|
||||
日期:2021/01/19
|
||||
|
||||
# 第一章:我們談的中產階級究竟是什麼
|
||||
目前看到第一章,有些看不太懂,句子不適很流暢,或者說用詞有些饒舌。
|
||||
目前的感想是,作者認為中產階級並不存在,是資本主義、資本家所建構出來,用以說服勞動階級安心於工作的方法。作者認為中產階級這概念之所以能夠吸引工人,「財產私有化」是一個重要的因素,工人為了追求私人房屋、汽車,以及日後的生活保障,像是退休金、儲蓄,會更努力工作以追求更好的薪資,或是追求更好的學位以保障日後對於財產保護的能力。
|
||||
作者舉了很多例子來說明中產階級所追求的財產與投資其實都是被操弄的結果,資方所設計的金融商品看似對我們有利,但中產階級同時也因為這個遊戲規則而變得身陷其中,到後來,我們追求的投資利益與穩定,反過來變成自身的枷鎖,我們變成幫助資方剝削自身的人。作者認為中產階級其實不存在,它是一個概念,美好的概念,它說著「自我提升」的漂亮話,但自從資本主義誕生之後,我們的努力和投資就被動員與利用,用來幫忙資方創造盈餘而已。第一章的最後一句是:「我們不僅現在不是中產階級,設置從來都不是。」。
|
||||
|
||||
# 第二章:財產的低調魅力
|
||||
說到財產,說為什麼我們追求財產,我們希冀財產為我們帶來什麼,但也說了這個時代,財產是如何地變的波動、不穩定,以及財產面臨的風險。當然也說到了資本主義是如何引導我們,讓我們追求投資以累積財產,我們在資本主義的影響下,變得追求投資利潤大過於儲蓄(因為通膨)。而我們在面對風險的時候,又是如何在投資上分散風險來企圖降低損失,而我們所做的,到頭來又變成了另一種風險來危害我們。這說明了財產的基礎是多麼的脆弱。
|
||||
|
||||
# 第三章:太人性了
|
||||
作者再一次的批評資本主義,但是將討論點轉到教育上,作者認為,在資本主義中,我們的教育是要我們也成為資本中的一環,稱為「人力資本」。回到資本主義帶給我們的中產階級想像,中產階級認為自己有辦法藉著自身的努力來達成階級流動,反過來說,要是無法向上提升,那就是你自己不努力,而人力資本就是在這個基礎上將教育也「資本化」。
|
||||
|
||||
人力資本讓父母對自身與小孩的技能要求提高,進而將資源投入教育與證照之中,但是在資本化的教育市場下,環境的變化加快,生產變的靈活,也讓就業市場變得更不穩定,這表示投入在教育與證照的投資不一定會有預期的回饋。而教育市場為了因應不穩定與快速變化的市場,又推出更多更新更高階的證照,進一步提升就業的門檻與高度,而我們因為害怕脫節,為了不落人後,害怕就就業市場中輸掉競爭,只能再一次的追求更新更高階的「產品」,進一步地再次投資在教育裡面。
|
||||
|
||||
而人力資本不同於物質資本的一點在於:人力資本是無法傳承的。一個人可以藉由繼承家產來獲得金錢,但只要這金錢不足以讓他一輩子生活無虞,那他也勢必要培養自己的技能、文化、教養等等的,來培養自己的人力資本。
|
||||
|
||||
另外,資本家不停尋找更佳優秀的技術者來降低其生產成本,而其他同業也會跟進競爭、追趕,然後再下一次的科技與創新中又形成下一輪的競爭。
|
||||
|
||||
無法傳承與技術競爭造成人力資本的不斷投資,這項投資甚至可以說是無止盡的。這造成一種「滑坡」,停在原地不動是不可能的,要是不讓自己努力追上新的技術、潮流、文化,就會發現自己已經過時了。但是投資這些追求或是可以讓我們獲得短暫的地位,卻不一定能再在之後的時間上賺到錢,因為你將會再一次投資到另一個潮流裡。
|
||||
|
||||
但是在中產階級對於自我提升的追求之下,人力資本隱藏了投資沒有回報的事實,就像所有的金融投資都宣傳著賺錢的美好,隱藏背後虧損的風險。
|
||||
|
||||
人力資本就像其他資產一樣,其價值再過一段時間之後就會被抽離。
|
||||
|
||||
最後談到人力資本與家庭的關係,父母不只追求自身的人力資本,也被要求要培養子女的人力資本,但因為人力資本無法直接轉移,父母必須在子女的教育與培養上進行多年的投資,接下來還需要子女自身的進一步投資,而且受到子女個性與經濟潮流的影響,這些投資的成果,不一定能有明確的回報。隨著這種人力資本投資流傳了幾代,它塑造了家庭關係,也反過來被家庭關係塑造。
|
||||
|
||||
# 第四章:後會有期了價值觀,再見了政治
|
||||
第四章作者試著再一次的論述資本主義與政治家是如何建構出「中產階級」這個價值觀。資本主義將工作者從市場性質中的生計分離出來,是他們在就業、住房;教育等重要議題上互相競爭。資本主義讓這些資源維持在足夠稀缺的狀態來維持高報酬率。同時又讓工作者以投資者的身份加入,讓他們甘願的「維護自身利益」以維護已經擁有的東西(並設法獲得更多),這也激發了工作者一種「個人自由」的感覺,並藉著鼓勵投資再一次的強化這種感覺。
|
||||
|
||||
投資的報酬讓餐與投資的工作者嘗到了自由,並受到了鼓舞。但一旦他們的投資回報受到了風險,他們也往往無能為力,他們的策略也因為物質壓力與動機糾纏而受挫,工作者或許會積極採取行動,參加抗爭,但這些抗爭往往並不是要求工作者在政治賞或結構上的勝利,而只要一個秩序和穩定(以確保工作者的投資),但其結果都會造成集體的脆弱性和不利情勢。普遍的不安全感愈高,競爭壓力愈猛烈,而這又讓投資行動愈顯合理。
|
||||
|
||||
# 結論
|
||||
作者再一次重申了中產主義意識形態是處於資本主義操作下的結果,藉由讓「自認為中產階級」的人們,對於控制自己人生這件事產生滿族,並熱衷於投資,讓這些「自認為中產階級」的人們有一種「一切操之在我」的感覺,促使他們不斷的進行投資,即使在虧損之後仍持續投入,這行為促使了資本主義所需要的持續性,並讓這主意更加盛行與根深蒂固。
|
||||
|
||||
作者一再強調至些是對於我們的剝削,我們進行的投資只會讓我們更身不由己地繼續參加這個資本主義的遊戲,我們投資於無法肯定有報酬的項目(包括學習、資產、金融),卻又認為它會在未知的某一天產生報酬,但又對報酬的多寡無法肯定。雖然作者在文末說這種矛盾終將引發我們自身的反省,但卻沒有說明應該如何來對抗這種困境,反倒是讓人覺得作者反對資本主義,認為資本主義用制度與意識形態將我們操作於中,但又不知應該如何改變,讓人有一種就是討厭資本主義的厭世感。
|
||||
|
||||
但是對於書面的副標題:「面對薪資停滯、金融危機、稅賦不公,中產階級如何改寫未來?」這個問號卻沒有有所回答,這讓我讀完之後仍然有一種茫茫不知所以然的困惑感。
|
||||
|
||||
# 發現
|
||||
雖然說作者沒有對於中產階級的困境提出一個解法,但確實說出了目前中產階級的問題:不停的競爭,包括職場上的競爭、教育的競爭、以及為了維護日後失去工作時所進行的儲蓄與投資,這都是現代人不得不(也覺得理所當然)要進行的事項。這也是作者在書中一再提起的。這生活與過去緩慢以及一分耕耘一分收獲的農村生活已經大不相同,而生活步調更是再也回不去了。我想我們能做的應對不多,我們無法從這個環境中脫離,但我們可以在某個程度叛逆一下,例如讓工作與假日徹底分離,為自己有興趣投入時間,陪伴孩子更多,而不只限於要求他們有更好的功課與競爭力。當然我還還是無法避免在工作競爭力上面持續投資加強以避免日後失業的可能性,但我們可以多注重一下生活,讓激烈競爭的氛圍降低一些,這需要大家一起行動,這必須一項全民運動才會有效果。
|
||||
|
||||
# TODO
|
||||
- 生活不是只有競爭,也要試著享受生活。
|
||||
- 在追求作競爭力提升的同時,也要讓心靈感到充實。
|
||||
- 孩子的人生不只是為了他們長大之後的競爭,也應該享受當下的生活,學會放鬆與愛人。
|
||||
|
||||
-----
|
||||
- [博客來-中產悲歌:面對薪資停滯、金融危機、稅賦不公,中產階級如何改寫未來?](https://www.books.com.tw/products/0010874434?sloc=main)
|
||||
36
05. 資料收集/讀書筆記/20210220 - 最高學習法.md
Normal file
36
05. 資料收集/讀書筆記/20210220 - 最高學習法.md
Normal file
@@ -0,0 +1,36 @@
|
||||
書名:最高學習法
|
||||
日期:2021/02/20
|
||||
|
||||
# 筆記
|
||||
- 電影打從落幕那一刻才是正式開始
|
||||
- 04:以寫感想為前提來閱讀。
|
||||
- 要是先有「寫」感想的預設的話,在讀書的時候,就更容易注意到想要、可以寫下的東西或材料。
|
||||
- 帶著隨意的心態是無法認真吸收的。
|
||||
- 具體閱讀方法:
|
||||
- 看到重點處立刻畫線做記號
|
||||
- 在之後想重新閱讀或做引用的地方貼上標籤
|
||||
- 閱讀過程中有任何發現或衍生的想法,全都要寫下來
|
||||
- 在書中選出一句「最佳名言」
|
||||
- 寫下從書中得到的「最大的發現」
|
||||
- 寫下今天就想實踐的「做想做的事」
|
||||
- 每讀完一本書,一定要寫出感想,即便只是短文也好
|
||||
- 43:資訊和知識的最佳比例是3:7,收集來的資訊,經過消化之後還能用的就叫「知識」。就像超商特價的食物一樣,吃不完的食物買再多也沒有用,資訊也一樣,太多的資訊只是之後又忘記而已,不如吸收剛好可以消化的資訊,將之吸收之後變成知識。
|
||||
- 79:睡前喝酒是造成睡眠障礙的原因。喝酒雖然多少可以幫助入睡,但是卻會妨礙持續睡眠。在適量的情況下,作者認為**「開心」的喝酒**,把喝酒當成溝通的潤滑劑也是很好的一件事。
|
||||
- P246:輸入之後馬上做輸出。最好的輸出時刻就是輸入的當下。
|
||||
- 把大腦濟助的東西,什麼都不要看的直接寫出來,這種行為稱為「提取練習」(retrieval practice)。
|
||||
- 這說法跟[[20201201 - 學習如何學習#^da7fba|積極回想]]一樣。
|
||||
- 「全面輸出」包含了「附加」、「關聯」、「整理」、「彙整」、「審查」等所有「精緻化」的要素,因此可以捯到強烈的增強記憶的效果。
|
||||
- 開會和討論也一樣,結書之後馬上把想到的所有東西,全部寫在筆記上。包括「問題點」、「疑問」、「未解決事項」、「提議」等。
|
||||
- P248:使用曼陀羅計畫表來打造「腦內情報圖書館」。
|
||||
|
||||
|
||||
# 心得
|
||||
這本算是學習工具書,作者將很多心法轉化為行動,直接告訴你直接這樣做最有效,也因此這本書的編排就像是一部準則一樣,洋洋灑灑的列出數十條的「分類方法」,讓讀者可以依據想要改進的方向來查閱。身為讀者,想要一口氣實踐所有的方法也是很不實際的,這時候作者在「貪心學習」(P254)的方法就可以派上用場了。雖然也是有不少是我們熟知的老生常談,但這樣再一次重新複習也是讓自己有再一次審視自我的機會,藉著書中所列出的種種行動方針,再看看是否有可以加強補足的地方,讓自己變得更有效率、比昨天更好。
|
||||
|
||||
# TODO
|
||||
- 建立的新的讀書筆記樣板,加入了:
|
||||
- 書名
|
||||
- 日期
|
||||
- 心得
|
||||
- TODO
|
||||
這些欄位
|
||||
19
05. 資料收集/讀書筆記/20210320 - 最高學以致用法.md
Normal file
19
05. 資料收集/讀書筆記/20210320 - 最高學以致用法.md
Normal file
@@ -0,0 +1,19 @@
|
||||
書名:最高學以致用法
|
||||
日期:2021-03-20(週六)
|
||||
|
||||
# 筆記
|
||||
這本書基本上內容跟[[20210220 - 最高學習法]]是差不多的,但是一本強調「輸出」的書,整本書為了讓讀者有所改變,能夠採取行動去「輸出」,整本書提供了很多方法,連「自我介紹」都變成了其中一個方法了,當然很多方法我們身為大人可能早就知道了,像是列出代辦事項啦,隨時用筆記本紀錄靈感啦,等等我們已經聽過很多次的技巧。作者透過一連串的方法轟炸無非就是希望我們能夠採取行動,那怕只用了幾個方法也好。所以不要再想了,輸出是為了變得更好,而行動才是第一步。
|
||||
|
||||
# 心得
|
||||
像準則一樣的書,光是看過一次是不夠的,也不可能一次就學會、採用書中的每一個方法,這種書必須先從最有可能的方法來實踐,然後不停地回頭翻閱與修正,然後再使用下一個方法,只要可以這樣逐步實踐,應該就會變得跟作者一樣厲害吧。
|
||||
|
||||
海因利奇法(Heinrich’s law)法則很有趣,這個運用在勞動傷害的法則,說明的是如果有1件重大的事故,就代表其背後有29件較輕微的事故,甚至它的背景是300件「有驚無險的事件」(讓人感到緊張害怕或嚇一跳的事件)。
|
||||
|
||||
這是由美國工程師赫伯.海因利奇(Herbert William Heinrich)根據勞動傷害的統計數據導出的法則。
|
||||
|
||||
這個法則,經常運用在失誤或客訴等負面事件上。
|
||||
|
||||
舉個例子,如果有1件很嚴重的失誤,那麼其背後就有29件小失誤以及300件一邊覺得「糟了」一邊先含混過去的事件。
|
||||
|
||||
# TODO
|
||||
- 是該認真地的把讀書筆記變成BLOG了吧!
|
||||
27
05. 資料收集/讀書筆記/20210406 - 精準購買.md
Normal file
27
05. 資料收集/讀書筆記/20210406 - 精準購買.md
Normal file
@@ -0,0 +1,27 @@
|
||||
書名:
|
||||
日期:2021-04-06(週二)
|
||||
|
||||
# 筆記
|
||||
- Herman Miller是cradle-to-creadle認證的廠商。
|
||||
- Fisher Space Pen Infinium.
|
||||
- 模組化洗衣機:L'increvable。
|
||||
|
||||
# 心得
|
||||
精準購買用一種永續的精神來勸導我們持續消費的壞處,我對於這點其實很有感,我自己也是一個很喜歡買東西,尤其買到好用精巧東西的時候更是感到沾沾自喜,覺得自己找到了一個省時省力或是值得賞玩賞味的好東西,但往往在一陣子之後,那東西就慢慢地失去了當初的新鮮感,或者不在那麼有耐性地去維護它,漸漸的,它就被冷落了。
|
||||
|
||||
另外,也許是年紀大了,腦袋漸漸地不喜歡記太多東西,「阿~太久沒充電壞掉了」、「這件事用剪刀也可以吧,為什麼還要多維護一個工具阿」、「哀阿,又多一個規格,全部都type-c不行嗎」,腦袋對於簡化事情這件事愈來愈熱烈,甚至可以說強烈的希望周遭的事情簡單就好,這也讓我再買新的東西(尤其是科技產品)不在那麼衝動,譬如說,我會希望新買的3C都是type-c接頭,如果我屬意的產品還沒有type-c,沒關係,那我就等等吧,如果在我等待的過程中退燒了,那更好,這筆錢就省下來了。
|
||||
|
||||
這種觀念延續到生活周遭的其他東西的話,那就更容易發現其他的冗餘物品,像是忍不住多買的抱枕、在遊樂場換回來的廉價玩具、因為肚子餓而多買的麵包、一時衝動多買的隨身碟等等,諸如此類你用過幾次(有些甚至只用過一次)就束之高閣的東西,你會發現其實它們不存在對你也不會有什麼影響。精準購買其實像是「斷、捨、離」的進階功夫,如果我們買的東西都是對我們有用的,必須的,那我們又何必在之後進行「斷、捨、離」整理術呢?
|
||||
|
||||
在精準購買這本書中,強調的不只是購買想的「必須性」,也強調了產品的「永續性」,書中不是要讀者一昧的省錢,只買便宜的東西,而是要讀者買使用上可以「最大化」的東西,「最大化」包含了耐用性、必須性,也包含了我們製造與回收的能源消耗與物料消耗,也包含了產品維修的可能性。所以作者認為多花一點錢,甚至多花上一大筆錢,來買一個可以用上一輩子的東西得很值得的。譬如說鍋子、可維修的家電、雨傘、可以升級的智慧型手機,作者在書中舉了一些例子,也給初這些推薦產品的價錢,讀者可以自己衡量有沒有道理。我自己是滿認同的,我一直認為使用熟悉的工具與物品可以簡化我們的生活邏輯,讓我們不必花太多時間在找東西,穿衣服,查說明書,甚至因為對於新東西的不習慣而操作錯誤,相對的,我們可以有更多時間來把工作做好、陪家人、進修,簡單來說,我們可以把時間花在更有意義的地方。
|
||||
|
||||
我認為精準購買所傳達的觀念跟筆記整理、「斷、捨、離」整理術、極簡生活這些書所傳達的觀念是類似的,如果我們不需要維護太多東西,我們可以對身邊的事物瞭若指掌,我們對於它們的使用就可以最大化,我們的心理負擔與幸福感就會更高,時間上也可以更充裕,對於人生意義的追尋也會更容易吧!
|
||||
|
||||
文中有介紹一些作者認為可以「終身受用」的品牌與產品,在此紀錄一下:
|
||||
- [Fisher Space Pen infinium鉻色系列](https://24h.pchome.com.tw/prod/CBAP2V-A64532635?fq=/S/DXBH0L)
|
||||
- [Sennheiser HD 25 專業型監聽耳機](https://24h.pchome.com.tw/prod/DCAYMP-A900AJCLM?gclid=CjwKCAjwjbCDBhAwEiwAiudBy_Wws3XJxCeAaUpjlNy_2YrTrhjkLNL1q2xFH1D8jGOBDyaQMbdNWhoC7H4QAvD_BwE)
|
||||
- [Buy Fairphone 3+](https://shop.fairphone.com/en/fairphone-3-plus)
|
||||
- [永續智慧型手機 Fairphone 3 登場,環保又方便維修](https://technews.tw/2019/08/31/ethical-smartphone-fairphone-3/)
|
||||
|
||||
# TODO
|
||||
- [x] 把5.11 UCR賣掉吧。 ✅ 2022-06-01
|
||||
21
05. 資料收集/讀書筆記/20210723 - 高手學習.md
Normal file
21
05. 資料收集/讀書筆記/20210723 - 高手學習.md
Normal file
@@ -0,0 +1,21 @@
|
||||
書名:高手學習
|
||||
日期:2021-07-23(週五)
|
||||
|
||||
# 筆記
|
||||
- eudaimonia,希臘詞,意指一種特殊的幸福,透過從事某種有意義的活動,把自己的全部潛能都發揮出來。
|
||||
- 也許你身上真的有某種創作天賦。帶著這個天賦默默死去,是很遺憾的事情;能把這樣的天賦充分發揮出來,那就很幸福。
|
||||
- 大腦負責認知的兩個區域
|
||||
- 前扣帶迴皮質(ACC)
|
||||
- 負責監控
|
||||
- 外側前額葉皮質(LPFC)
|
||||
- 大腦中的決策系統
|
||||
- 當ACC發現異常便向LPFC發出警告,讓大腦能夠直接介入,而不是用潛意識的方法來處理。
|
||||
|
||||
# 心得
|
||||
這種書看了幾本以後,會發現其實中心思想都是類似的,例如說「練習」,就會提到要練習不會的,而不是一直練習你已經熟悉的。其實這部份就和[[20201201 - 學習如何學習]]中所提到的[[20201201 - 學習如何學習#9 腦連結]]是一樣的,也就是所謂的刻意練習。刻意練習在[[20201224 - 寫作是最好的自我投資]]也有提到。
|
||||
|
||||
再來說創造力,書中提到的發散思維其實也跟[[20201201 - 學習如何學習]]中提到的[[20201201 - 學習如何學習#^1c4ddf|發散模式]]是一樣的。
|
||||
|
||||
也就是說概念上都相同,只是作者用一種更加通俗與心靈雞湯的方式講給你聽,如果你已經熟悉了這些方法,其實是老調重彈的,有點無聊的。不過這也是看書的一個樂趣,戲法人人會變,巧妙各有不同,有時候我們就是難以在一本書裡面去理解作者的所有解釋與觀念,與抱著同一本書反覆推敲而不得其道,有時倒不如換個老師講給你聽。如果你也喜歡說書式的口吻,甚至權威口吻,那這本書還滿適合的。
|
||||
|
||||
# TODO
|
||||
11
05. 資料收集/讀書筆記/20220526 - 深入淺出設計模式.md
Normal file
11
05. 資料收集/讀書筆記/20220526 - 深入淺出設計模式.md
Normal file
@@ -0,0 +1,11 @@
|
||||
書名:深入淺出設計模式 第二版
|
||||
日期:2022-05-26(週四)
|
||||
Link:[深入淺出設計模式, 2/e (Head First Design Patterns: Building Extensible and Maintainable Object-Oriented Software, 2/e)](https://www.tenlong.com.tw/products/9789865029364?list_name=srh)
|
||||
|
||||
# 筆記
|
||||
紀錄在[[Design Pattern]]。
|
||||
|
||||
# 心得
|
||||
|
||||
|
||||
# TODO
|
||||
16
05. 資料收集/讀書筆記/20220619 - 精確的力量.md
Normal file
16
05. 資料收集/讀書筆記/20220619 - 精確的力量.md
Normal file
@@ -0,0 +1,16 @@
|
||||
書名:
|
||||
日期:2022-06-19(週日)
|
||||
Link:[精確的力量](https://www.books.com.tw/products/0010839555)
|
||||
|
||||
# 筆記
|
||||
|
||||
|
||||
# 心得
|
||||
作者從精度最不要求的部份開始說,從大英帝國對於帆船滑輪的需求開始說起,然後槍枝、汽車、鏡片,最後不可避免的講到了IC的製程。然而我覺得最有意思的是蒸汽機與哈伯望遠鏡。
|
||||
雖然一直知道瓦特發明了蒸汽機進而引發工業革命,也進一步改變了世界,但讓蒸氣機能夠穩定運作且能夠實用化的關鍵原因是威爾金森的活塞工藝,威爾金森在製造加農砲時所發明的加工挖孔技術適時的幫上了瓦特的忙,才讓蒸汽機的效率能夠實用化。
|
||||
|
||||
再來是哈伯望遠鏡的初期失敗是源自於鏡片製造商的失誤,而鏡片製造商的失敗又來自於多個失誤的累積,這些失誤都不是一下子造成的,而是一個一個慢慢累積的,這讓我又再次感覺到生活上培養習慣的重要性,壞習慣的積累往往也是讓某個失誤在某個時間爆發的原因,只是累積的時間太長,讓我們又無法一次看到事情發生的根本,而又讓相同的錯誤一再發生。
|
||||
|
||||
再來,從書中所寫的各個精密製造的發展過程,可以看到近日我們習以為常的產品、標準,其實都是由很多優秀、天才的人貢獻、累積而來的,沒有什麼橫空出世的天才,憑一人之力改變世界這種事。每個人都是站在前人的肩膀上,一步一步的改進而來,扎實的研究與實作才是最重要的。
|
||||
|
||||
# TODO
|
||||
2
05. 資料收集/軟體工具/IPFS.md
Normal file
2
05. 資料收集/軟體工具/IPFS.md
Normal file
@@ -0,0 +1,2 @@
|
||||
- Source code: https://github.com/ipfs/ipfs
|
||||
- Document: https://docs.ipfs.io/
|
||||
29
05. 資料收集/軟體工具/MkDocs.md
Normal file
29
05. 資料收集/軟體工具/MkDocs.md
Normal file
@@ -0,0 +1,29 @@
|
||||
|
||||
https://www.mkdocs.org/
|
||||
|
||||
## Commands
|
||||
`mkdocs new [dir-name]` - Create a new project.
|
||||
`mkdocs serve` - Start the live-reloading docs server. Goto `http://127.0.0.1:8000` to view WEB pages.
|
||||
`mkdocs build` - Build the documentation site.
|
||||
`mkdocs build --clean` - Clean the output folder.
|
||||
`mkdocs -h` - Print help message and exit.
|
||||
|
||||
## Theme
|
||||
#### Change theme to [mkdocs-material](https://squidfunk.github.io/mkdocs-material/getting-started/)
|
||||
1. Install by pip
|
||||
```
|
||||
pip install mkdocs-material
|
||||
```
|
||||
2. Modify `mkdocs.yml`
|
||||
```
|
||||
site_name: RobotRunDoc
|
||||
nav:
|
||||
- Home: index.md
|
||||
- 'User Guide':
|
||||
- 'Installation': 'Installation/installation.md'
|
||||
- 'APIs': 'APIs/Kong.md'
|
||||
- About: about.md
|
||||
|
||||
theme:
|
||||
name: material <-- HERE
|
||||
```
|
||||
63
05. 資料收集/軟體工具/Obsidian.md
Normal file
63
05. 資料收集/軟體工具/Obsidian.md
Normal file
@@ -0,0 +1,63 @@
|
||||
## 使用
|
||||
### 操作
|
||||
- `Ctrl-Enter`: 可以增加TODO的框框,或是用來更改框框的狀態
|
||||
|
||||
### 自訂快速鍵
|
||||
- `Alt+Insert`: 插入樣板
|
||||
- `Ctrl + Shift + <-`: 摺疊所有標題 ^e897a3
|
||||
- `Ctrl + Shift + ->`: 展開所有標題 ^5587cd
|
||||
|
||||
### 搜尋
|
||||
用 `file:` 開頭來指定指**只搜尋檔名**
|
||||
用 `content:` 開頭來指定**只指搜尋內容**
|
||||
用 `tag:` 開頭來搜尋標籤,例: `tag:#mydata`
|
||||
用 `path:` 來搜尋特定路徑下的檔案,路徑必須要用`""`包圍,例:`path:"path/to/foder" search_name`
|
||||
|
||||
## 設定
|
||||
目前所使用的theme是`Obsdn-dark-rmx`
|
||||
CSS路徑:`<vault>/obsidian.css`
|
||||
|
||||
### CSS
|
||||
#### 讓中文字型使用**微軟正黑體**
|
||||
```
|
||||
.CodeMirror pre.CodeMirror-line {
|
||||
font-size: 14px;
|
||||
font-family: Fira Code, Microsoft JhengHei, Source Code Pro, monospace;
|
||||
}
|
||||
```
|
||||
不用照抄,重點是在`font-family`裡面,加入`Microsoft JhengHei`,愈前面優先順序愈大。
|
||||
|
||||
#### 顯示**Bullet Point Relationship Lines**
|
||||
|
||||
```
|
||||
/*=== Bullet Point Relationship Lines ===*/
|
||||
.cm-hmd-list-indent, ul ul {
|
||||
position: relative;
|
||||
}
|
||||
.cm-hmd-list-indent::before, ul ul::before {
|
||||
content:'';
|
||||
border-left: 1px solid rgba(0, 122, 255, 0.55);
|
||||
position: absolute;
|
||||
}
|
||||
.cm-hmd-list-indent::before {
|
||||
left: 0;
|
||||
top: -5px;
|
||||
bottom: -4px;
|
||||
}
|
||||
ul ul::before {
|
||||
left: -11px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
```
|
||||
在`obsidian.css`最後端加入上面的CSS就可以顯示**Bullet Point Relationship Lines**,如:
|
||||
![[Pasted image 20201206094618.png]]
|
||||
|
||||
來源:
|
||||
- https://www.youtube.com/watch?v=ea9hkXem1f4
|
||||
- https://gist.github.com/emisjerry/36d1d115ae22cd0902fc528875f86414
|
||||
|
||||
|
||||
## Plugin
|
||||
### Dataview
|
||||
- [Source code](https://github.com/blacksmithgu/obsidian-dataview)
|
||||
- [介紹:[Obs#26] Dataview外掛: 製作索引筆記利器;動態查詢筆記資料 - YouTube](https://www.youtube.com/watch?v=dkWA7Qd0CLA&list=PLWg9zacwOnwfcpVm5pAKgOHms7PntsgJS&index=18)
|
||||
25
05. 資料收集/軟體工具/docker.md
Normal file
25
05. 資料收集/軟體工具/docker.md
Normal file
@@ -0,0 +1,25 @@
|
||||
## Container
|
||||
### list container
|
||||
`docker ps`會列出執行中的container(但是停止的不會)
|
||||
```bash
|
||||
sudo docker ps
|
||||
```
|
||||
|
||||
如果也要列出已停止的container
|
||||
```bash
|
||||
sudo docker ps -a
|
||||
```
|
||||
|
||||
### 刪除container
|
||||
Container必須是停止狀態才可以刪除
|
||||
```bash
|
||||
sudo docker rm <CONTAINER_ID>
|
||||
```
|
||||
|
||||
## Image
|
||||
### list images
|
||||
```bash
|
||||
sudo docker image ls
|
||||
or
|
||||
sudo docker images
|
||||
```
|
||||
36
05. 資料收集/軟體工具/git/apply.md
Normal file
36
05. 資料收集/軟體工具/git/apply.md
Normal file
@@ -0,0 +1,36 @@
|
||||
|
||||
## apply
|
||||
`git diff` 生出一個 diff 檔,而 `git apply` 把這個 diff 檔 apply 到某個 branch 上。
|
||||
```
|
||||
git diff ${A_COMMIT_HASH} ${B_COMMIT_HASH} > xxx.patch
|
||||
git apply xxx.patch
|
||||
```
|
||||
- 如果在 `git apply` 的過程中遇到 trailing whitespace error 的話,可以參考這篇文章:[git - My diff contains trailing whitespace - how to get rid of it? - Stack Overflow](https://stackoverflow.com/questions/14509950/my-diff-contains-trailing-whitespace-how-to-get-rid-of-it),透過加入 `--whitespace=warn` 或 `--whitespace=nowarn` 參數來解決。
|
||||
- [^1]
|
||||
|
||||
|
||||
[^1]: [(2018 iThome 鐵人賽) Day 11: 使用 Git 時如何做出跨 repo 的 cherry-pick - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天](https://ithelp.ithome.com.tw/articles/10194972)
|
||||
|
||||
|
||||
### Trouble shooting
|
||||
- 如果在Windows上git clone遇到,例如:`error: invalid path`、`fatal: unable to checkout working tree`
|
||||
```
|
||||
$ gclogi git@github.com-logi:LogiVideoFW/VC_Bolide_TableHub.git
|
||||
Cloning into 'VC_Bolide_TableHub'...
|
||||
remote: Enumerating objects: 159, done.
|
||||
remote: Counting objects: 100% (159/159), done.
|
||||
remote: Compressing objects: 100% (134/134), done.
|
||||
remote: Total 85001 (delta 71), reused 84 (delta 21), pack-reused 84842
|
||||
Receiving objects: 100% (85001/85001), 599.21 MiB | 6.18 MiB/s, done.
|
||||
Resolving deltas: 100% (17824/17824), done.
|
||||
error: invalid path 'zynqLNX/kernel-source/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c'
|
||||
fatal: unable to checkout working tree
|
||||
warning: Clone succeeded, but checkout failed.
|
||||
You can inspect what was checked out with 'git status'
|
||||
and retry with 'git restore --source=HEAD :/'
|
||||
```
|
||||
有可能是因為檔名與NTFS規則有所衝突,解法:
|
||||
```
|
||||
cd <REPO_NAME>
|
||||
git config core.protectNTFS false; git reset --hard HEAD
|
||||
```
|
||||
27
05. 資料收集/軟體工具/git/submodule.md
Normal file
27
05. 資料收集/軟體工具/git/submodule.md
Normal file
@@ -0,0 +1,27 @@
|
||||
## 建立 Git Submodule
|
||||
```
|
||||
git submodule add <repository> [<local_path>]
|
||||
```
|
||||
新增之後,用 git status 會發現多了兩個東西需要 commit:
|
||||
![[20220608152709_git_submodule.png|450]]
|
||||
|
||||
第一個檔案 .gitmodules,裡面紀錄 submodule 的對應關係,內容大概像這樣:
|
||||
```
|
||||
[submodule "RobotRunQA"]
|
||||
path = RobotRunQA
|
||||
url = git@github.com-logi:JuiwenHsu/RobotRunQA.git
|
||||
```
|
||||
|
||||
接下來剩3個步驟:
|
||||
1. 提交 `.gitmodule`:`git add .gitmodule ; git push origin master`
|
||||
2. 跟git說我們有新增一個submodule:`git submodule init`
|
||||
3. 把submodule pull下來:`git submodule update`
|
||||
|
||||
## Clone repository and submodule
|
||||
當clone一個有submodule的repo的時候,我們還需要 `git submodule init` 跟 `git submodule update` ,例如:
|
||||
```
|
||||
git clone https://xxx/xxx.git
|
||||
cd xxx
|
||||
git submodule init
|
||||
git submodule update
|
||||
```
|
||||
30
05. 資料收集/軟體工具/youtube-dl.md
Normal file
30
05. 資料收集/軟體工具/youtube-dl.md
Normal file
@@ -0,0 +1,30 @@
|
||||
## youtube-dl
|
||||
### List format
|
||||
```shell
|
||||
youtube-dl -F <YOUTUBE_URL>
|
||||
```
|
||||
|
||||
e.g.
|
||||
```shell
|
||||
youtube-dl -F https://www.youtube.com/watch?v=Pbzn79TSRO0
|
||||
```
|
||||
|
||||
### Download
|
||||
```shell
|
||||
youtube-dl -f <FORMAT_ID> <YOUTUBE_URL>
|
||||
```
|
||||
|
||||
### Download video-only & audio-only & merge to MKV
|
||||
```shell
|
||||
youtube-dl -f <VIDEO_ONLY_ID>+<AUDIO_ONLY_ID> --merge-output-format mkv <YOUTUBE_URL>
|
||||
```
|
||||
|
||||
e.g.
|
||||
```shell
|
||||
youtube-dl -f 313+251 --merge-output-format mkv https://www.youtube.com/watch?v=Pbzn79TSRO0
|
||||
```
|
||||
|
||||
### Download video to MP3
|
||||
```shell
|
||||
youtube-dl -i --extract-audio --audio-format mp3 --audio-quality 0 https://www.youtube.com/watch?v=IruVsWrfPqs
|
||||
```
|
||||
1
05. 資料收集/面試準備/技术面试最后反问面试官的话.md
Normal file
1
05. 資料收集/面試準備/技术面试最后反问面试官的话.md
Normal file
@@ -0,0 +1 @@
|
||||
- [技术面试最后反问面试官的话](https://github.com/yifeikong/reverse-interview-zh)
|
||||
Reference in New Issue
Block a user