basics
Environment variable
SHELL: 系統使用了哪種 shell
確認 OS Version
# 印出所有 release 版本
# * 是指 wildcard
ls /etc/*release*
# 印出當前版本細節
cat /etc/*release*
package managers
RPM (Red Hat Package Manager)
- RPM 不管 dependency
- CentOS
- Red Hat Enterprise Linux
- Fedora
package 會被包裝成 <檔名>.rpm
# install package
rpm -i telnet.rpm
# uninstall package
rpm -e telnet.rpm
# query package
rpm -q telnet.rpm
# query all installed package
rpm -qa
YUM 包裝過 rpm,會順便安裝 dependency
- 底層是 rpm
- 透過
/etc/yum.repos.d
決定 yum 要去哪邊載 package
# install package
yum install ansible
# -y flag 代表預設都同意
yum install -y ansible
# 列出 repo list
yum repolist
# 列出 repositories 在哪裡被 configured
ls /etc/yum.repos.d
# 印出對應的 repo 路徑 (以 CentOS-Base.repo 為例)
cat /etc/yum.repos.d/CentOS-Base.repo
# 印出安裝的 package
yum list
# 搜尋安裝的 package
yum list <package name>
# 移除 package
yum remove <package name>
# -y flag 代表預設都同意
yum remove -y <package name>
# - 可以指定版本
yum install ansible-2.8.11
services
安裝後的軟體或程序,在執行的時候 (可能在背景) 稱為 service
# 可能會需要提供 sudo 權限來操作
# start httpd service
service httpd start
# or
systemctl start httpd
# stop httpd service
systemctl stop httpd
# check httpd service status
systemctl status httpd
# configure httpd to start at startup
systemctl enable httpd
# configure httpd to not start at startup
systemctl disable httpd
範例:
# 原本的呼叫方式
/usr/bin/python3 /opt/code/my_app.py
# 希望調整成能夠透過 systemctl 簡易呼叫或停止
# 或是可以再開機時被呼叫
# 需要透過 systemd
systemctl 是用來控管 systemd service 的指令
systemd service 透過 systemd unit file 控管
路徑可能為 /etc/systemd/system/
my_app.service
[Unit]
Description=My python web application
[Service]
ExecStart=/usr/bin/python3 /opt/code/my_app.py
ExecStartPre=/opt/code/configure_db.sh
ExecStartPost=/opt/code/email_status.sh
Restart=always
[Install]
WantedBy=multi-user.target
ExecStartPre
是指說在跑 service 之前要執行什麼
ExecStartPost
是指說在跑 service 之後要執行什麼
[Install]
區段會讓電腦開機的時候自動開啟
# 重新載入 systemd configuration
systemctl daemon-reload
# 接下來即可透過 systemctl 正常呼叫 service
systemctl start my_app
# 查看組態設定
systemctl cat my_app
Virtual Box networking
當裝置的網路介面連接到網路的時候,都會獲取一個 ip
# 顯示 ip 資訊
ip addr show
Network adapter
- Host Only Network
- 以電腦為 host,把所有的 virtual machine 網路都接起來
- 例: 1台 電腦內開了 4個 virtual machine
- 透過 Host-Only network 192.168.5.0
- 電腦 host ip 為 192.168.5.1
- virtual machine 1 -> 192.168.5.2
- virtual machine 2 -> 192.168.5.3
- virtual machine 3 -> 192.168.5.4
- virtual machine 4 -> 192.168.5.5
- 電腦和 virtual machine 可互通
- 無法對外連線
- 電腦對外的 ip 為 192.168.1.10
- 電腦外部 LAN 的 ip 為 192.168.1.0
- NAT network (Network Address Translation)
- 讓 host 內的 virtual machine 可以對外連線
- virtual machine 彼此間也可以溝通
- virtual machine 192.168.5.2 送出 request 給 192.168.1.11 時
- 先把 FROM IP 從 192.168.5.2 轉成 192.168.1.10 後送出
- 192.168.1.11 資料庫收到 request 後回應 response
- NAT 收到 response 後再把 FROM IP 從 192.168.1.10 轉回 192.168.5.2
- 外部服務不會注意到是 192.168.1.10 的內部 virtual machine,即從外部無法存取內部資訊
- NAT
- host 內的 virtual machine 可以對外連線
- 但無法對內部的 virtual machine 彼此連線
- Bridge Network
- 視為外部網段 LAN 對內的 extension
- 內部 virtual machine 不會有自己的網段,直接使用外部網段 192.168.1.0
- virtual machine 1 -> 192.168.1.12
- virtual machine 2 -> 192.168.1.13
- virtual machine 3 -> 192.168.1.14
- virtual machine 4 -> 192.168.1.15
Port Forwarding
- 就是在 host 開一個 port,可以把進來的 request 對應到 內部的 virtual machine 的 port
Vagrant
# create vagrant file with os
vagrant init centos/7
# start a virtual machine
vagrant up
# 連線進 vagrant virtual machine
vagrant ssh
# shutdown
vagrant halt
# 查看狀態
vagrant status
# 重新載入 vagrant file for virtual machine
vagrant reload
Network basics
Switching
Switch 是用來讓 多台裝置彼此之間可以溝通連線的裝置
假設有 A B 兩台裝置,中間透過一台 switch 設定即可溝通
# 取得 裝置的 網路介面 (拿到 eth0)
# 列出清單 和 調整 host 上的 interface
ip link
# 查看 IP address assign 給 interface 的對應
ip addr
# 假設 switch 網段為 192.168.1.0
# A 裝置設定
ip addr add 192.168.1.10/24 dev eth0
# B 裝置設定
ip addr add 192.168.1.11/24 dev eth0
要注意 ip addr add 的指令如果重開機的話就失效了
要保留的話要寫到 etc network interface file
Routing
Router 是讓兩個不同 switch 網路的裝置可以互相溝通
假設有兩組 switch,一組為 192.168.1.0 (裝置A,B),一組為 192.168.2.0 (裝置C,D)
則在 Router 的端口 ip 第一組設定為 192.168.1.1,另一組為 192.168.2.1
Gateway
如果 network 是房間的話,gateway 就是對外的門
系統需要知道那個門是去哪的
# 顯示 routing table
route
假設 B 192.168.1.11 要連去 C 192.168.2.10
# 在 B 那台下指令
ip route add 192.168.2.0/24 via 192.168.1.1
# C 那台也要下指令
ip route add 192.168.1.0/24 via 192.168.2.1
# 假設 C 那台要連去網際網路 172.217.194.0 的話
ip route add 172.217.194.0/24 via 192.168.2.1
# 假設 C 那台要連去任何網際網路的話
# default 和 0.0.0.0 一樣意思
ip route add default via 192.168.2.1
# 檢查 ip forwarding 是否在 host 上啟用
cat /proc/sys/net/ipv4/ip_forward
# host 是否可以在 interface 之間做 forward 溝通,設定在 /proc/sys/net/ipv4/ip_forward
# default 是 0,代表 no forward
cat /proc/sys/net/ipv4/ip_forward
# 可以自己改數字
echo 1 > /proc/sys/net/ipv4/ip_forward
因為重啟後 ip_forward 設定就沒了,所以要寫到對應的 file 設定
檔名 /etc/sysctl.conf
欄位 net.ipv4.ip_forward = 1
DNS
本機的 IP 對 host 的 mapping 表放在 /etc/hosts
內
透過設定 /etc/hosts
的設定方式稱為 Name Resolution
但每台機器都要設定的話,很不彈性,萬一某個 ip 換了很麻煩
所以把這個對應表拉出去獨立的機器上 就稱為 DNS
每台機器都知道 DNS 在哪邊,設定在 /etc/resolv.conf
優先權 /etc/hosts
> /etc/resolv.conf
但可以在 /etc/nsswitch.conf
設定優先順序
/etc/resolv.conf
上面的 nameserver 不一定涵蓋全部的 domain
所以可以自己加上 nameserver (認得出這個 domain 的)
==
www.google.com
拆分
.
是 rootcom
是 top level domaingoogle
是 domain namewww
是 subdomain,其他如mail
,drive
,maps
,apps
… 等等
透過 search 方式 mapping 名稱
# dns
192.168.1.10 web.mycompany.com
# 如果不想要用這麼長的名字連線
# 只想用 web 字串的話
# 要在 /etc/resolv.confg 另外設定
search mycompany.com
# 這樣子ping web 等同於 ping web.mycompany.com
ping web
ping web.mycompany.com
Record Types
A
: ip to hostAAAA
: ipv6 to hostCNAME
: one name to another name
nslookup 用來測試 dns 解析
要注意的是這會忽略本機的 hosts 設定
nslookup www.google.com
dig 也是用來測試 dns 解析的
dig www.google.com
Application Basics
Language:
- compiled:
- Java, C, C++, …
Develop Source Code
->Compile
->Run
- interpreted:
- Python, node, Ruby, …
Develop Source Code
->Run
IPs and Ports
假設今天有一台電腦 開了兩個 IP 入口對外
若要開放不指定 IP 的話,就用 0.0.0.0
網路介面 l0
是指 127.0.0.1
SSL & TLS Basics
非對稱金耀 asymmetric encryption
- Private Key
- Public Lock (或可稱 public key)
以 SSH 為例
- 在遠端機器上放入 public lock
- 只有有 private key 的人可以連線進入
- 放在遠端機器的 ~/.ssh/authorized_keys
以 HTTPS 為例
- 遠端機器自己先建立好一組金鑰對 (asymmetric的)
- 假設
my-bank.key mybank.pem
- 使用者只需要 對稱金鑰
- 遠端機器 (server) 有 非對稱金鑰
- CA 使用非對稱金鑰
- CA 的 public key 在每個 browder 都有
- 遠端機器請求 CA 幫忙驗證自己是合法的 (送出 CSR)
- CA 確認後用
CA 的 private key
簽名 - 遠端機器拿到簽名後的 certificate後,設定在機器上 (configuration)
- 當使用者要存取遠端機器的網頁時,遠端機器送出 certificate 和 遠端機器的 public lock
- 使用者的瀏覽器用
CA public key
解開簽證,確認遠端機器的 public lock
是合法的 - 之後使用者用
遠端機器的 public lock
鎖住使用者的 key
傳給遠端機器 - 如此只有遠端機器可以用
遠端機器的 private key
解開遠端機器的 public lock
拿到使用者的 key
- 之後 遠端機器就用
使用者的 key
鎖住要給使用者的資料傳出去 - 使用者可以用
自己的 key
解密得到資料 - 使用者都用
自己的 key
加密後傳給 遠端機器 - 遠端機器用
使用者的 key
解密
- 假設
這樣在溝通中,使用者的 key 都不會裸露出來
現在的瀏覽器都內建了 驗證 certificate 的機制 (Certificate Authority 組織會把他們的 public key 安裝到瀏覽器上)
可以知道連線安不安全
遠端機器如何確認 client 是同一個?
- 提出 client 要提供 certificate
- 然後 client 就要生成 非對稱金鑰 且也要對 CA 提出 CSR 並拿到 CERT
- client 把自己的金鑰和 CERT 傳給 遠端機器
PKI (Public Key Infrastructure)
非對稱金鑰只能一把加密 另一把解密
同一把鑰匙不能同時做到加解密
Convention
Certificate (Public Key) 通常用 *.crt 或 *.pem
Private Key 通常用 *.key 或 *.key.pem
JSON path
JSON path 是對 JSON 的 query 語法 (dictionary)
就像 SQL 是對資料庫一樣
最外層的 {}
是指 root element 用 $
代表
而 JSON path query 的結果都是在 []
內,用中括號包起來
{
"car": {
"color": "blue",
"price": "$20000"
},
"bus": {
"color": "white",
"price": "$120000"
}
}
Query
- Get car details:
$.car
[
{
"color": "blue",
"price": "$20000"
}
]
- Get bus details:
$.bus
[
{
"color": "white",
"price": "$120000"
}
]
- Get car’s color:
$.car.color
[
"blue"
]
另一個範例 for 陣列
[
"car",
"bus",
"truck",
"bike"
]
- Get the 1st element
$[0]
// result
[
"car"
]
- Get the 4th element
$[3]
// result
[
"bike"
]
- Get the 1st and 4th element
$[0,3]
// result
[
"car",
"bike"
]
另一個範例
[
12,
43,
23,
12,
56
]
// 要找出大於 40 的
$[ ? ( @ > 40 ) ]
// 結果
[
43,
56
]
@
是指 item in loop
@ == 40
@ in [40,43,45]
@ != 40
@ nin [40,43,45]
複雜的 query 例子
$.car.wheels[?(@.location == "rear-right"].model