顯示具有 伺服器管理 標籤的文章。 顯示所有文章
顯示具有 伺服器管理 標籤的文章。 顯示所有文章

Google Cloud Platform (GCP):主機類型之效能比較

使用 Wakacoin 開源碼 (20200927 釋出的版本) 測試,

區塊高度大約在 22,000 的情況,

運算速度的參數設定在未全速運轉的情況,

然後以相同的執行檔,在不同類型、相同地區的 GCP 主機上運作,

得到資料如下:


n1-standard-1 (1 個 vCPU,3.75 GB 記憶體)
標準永久磁碟 ( New 10 GB standard persistent disk )
$24.67 monthly




e2-medium (2 個 vCPU,4 GB 記憶體)
標準永久磁碟 ( New 10 GB standard persistent disk )
$24.86 monthly



n1-standard-1 (1 個 vCPU,3.75 GB 記憶體)
SSD 永久磁碟 ( New 10 GB SSD persistent disk )
$25.97 monthly






 


Google Cloud (GCP):Compute Engine 擴大硬碟空間

https://cloud.google.com/compute/docs/disks/add-persistent-disk?&_ga=2.123459599.-587591896.1554639132#resize_pd

https://snippetinfo.net/mobile/media/2770

執行之前先備份、製作快照

官方文件與參考文件交互參照,理解後再進行操作。


整理後結論:


(1) 先在網頁 UI 操作,加大硬碟容量

再進入 CLI 下指令 


(2) 如果需要在 CentOS 服务器上安装 growpart,运行:

(新的實例可能尚未安裝 growpart)

$ sudo yum -y install cloud-utils-growpart


(3) 使用 df -kh, df -Th, lsblk 這 3 個 CLI 指令

查看硬碟掛載的編號、確認結果等


(4) 擴大分割區

比如說 

$ sudo growpart /dev/sda 1

sda 跟 1 之間要有空格

sda 是指 設備 ID

1 這個編號 是 該設備的分區號

實際上的編號要透過上述使用  df -Th 和 lsblk 這兩個 CLI 指令查看


(5) 擴大檔案系統空間

如果是 ext2, ext3, ext4 的 file system,則用 resize2fs 

如果是 xfs,則用 xfs_growfs 

比如說

$ sudo resize2fs /dev/sda1

$ sudo xfs_growfs /dev/sda1


如何取得使用者 IP 的方法與資安探索

https://devco.re/blog/2014/06/19/client-ip-detection/

本文與留言區的討論


重點摘錄:

一、使用代理伺服器的情況下,HTTP Header 會有不同的行為。例如 Elite Proxy 如何隱藏客戶端的真實 IP。以下簡單介紹幾種常見的狀況給各位參考。

直接連線 (沒有使用 Proxy)
REMOTE_ADDR: 客戶端真實 IP
HTTP_VIA: 無
HTTP_X_FORWARDED_FOR: 無

Transparent Proxy
REMOTE_ADDR: 最後一個代理伺服器 IP
HTTP_VIA: 代理伺服器 IP
HTTP_X_FORWARDED_FOR: 客戶端真實 IP,後以逗點串接多個經過的代理伺服器 IP

Anonymous Proxy
REMOTE_ADDR: 最後一個代理伺服器 IP
HTTP_VIA: 代理伺服器 IP
HTTP_X_FORWARDED_FOR: 代理伺服器 IP,後以逗點串接多個經過的代理伺服器 IP

High Anonymity Proxy (Elite Proxy)
REMOTE_ADDR: 代理伺服器 IP
HTTP_VIA: 無
HTTP_X_FORWARDED_FOR: 無 (或以逗點串接多個經過的代理伺服器 IP)


二、攻擊者可以竄改 header 插入特殊字元,對網站進行 SQL Injection 或者 Cross-Site Scripting 攻擊。


三、從資安的角度,應留存下所有可能紀錄到真實 IP 的資料,記錄下所有相關的 header 欄位,包含「REMOTE_ADDR」「X-Forwarded-For」等等,真正有犯罪事件發生時,就可以調出所有完整的 IP 資訊進行人工判斷,從蛛絲馬跡中或許有機會找出真正的 IP。當然從 header 存入的數值也可能會遭到攻擊者竄改插入特殊字元嘗試 SQL Injection,因此存入值必須先經過過濾,或者使用 Prepared Statement 進行存放。

可以參考的 HTTP Header(依照可能存放真實 IP 的順序)

HTTP_CLIENT_IP
HTTP_X_FORWARDED_FOR
HTTP_X_FORWARDED
HTTP_X_CLUSTER_CLIENT_IP
HTTP_FORWARDED_FOR
HTTP_FORWARDED
REMOTE_ADDR (真實 IP 或是 Proxy IP)
HTTP_VIA (參考經過的 Proxy)

「駭客思維」就是找出網站任何可能竄改的弱點,從網頁上的元素到 HTTP Header 都是嘗試的對象。因此身為防禦者一定要清楚的知道哪些數值是不能信賴的。


四、REMOTE_ADDR 只能透過 Proxy、VPN 等方法來改變,沒辦法藉由竄改 Header 來假造。

五、用 Onion Routing 連線的 IP 有辦法被查出嗎? 沒有辦法,只能夠知道「Exit Node」的 IP。

六、一般來說不會透過 Onion Routing 來做 DDoS 攻擊。典型的 的 DDoS 攻擊也無法透過 Onion Routing。

七、Web Server 能夠取得的資訊就是那些欄位,包含 REMOTE_ADDR 以及其他 HTTP Header,因此能夠獲得的資訊有限。直接 TCP 連線的 IP 位置就是 REMOTE_ADDR。

如何在 Google Cloud 的 VM instance (CentOS) 上安裝與使用 rar 壓縮


先安裝 wget:
sudo yum -y install wget

確認系統是 32位元 還是 64位元:
uname -a

如果是 32位元:
sudo wget http://www.rarsoft.com/rar/rarlinux-4.0.1.tar.gz
sudo tar -zxvf rarlinux-4.0.1.tar.gz

如果是 64位元:
sudo wget http://www.rarlab.com/rar/rarlinux-x64-5.3.0.tar.gz
sudo tar -zxvf rarlinux-x64-5.3.0.tar.gz

進入到 rar 的資料夾:
cd rar

進行配置:
sudo make


解壓縮指令:
rar x test.rar

壓縮指令:
rar test.rar ./test/

MySQL 允許外部連入

google "mysql 8 remote access"
google "mysql 8 remote access ssl"
google "gcp mysql 遠程連接"


MySQL 8 的新特性與解決方式
http://www.manongjc.com/article/13483.html

* 創建用戶與授權方式的改變
* 遠程連結強制加密
* 預設為 caching_sha2_password



Mysql 允許外部連入
https://contemplator.github.io/blog/2018/06/06/Mysql-%E5%85%81%E8%A8%B1%E5%A4%96%E9%83%A8%E9%80%A3%E5%85%A5/

* 修改 Mysql 設定檔 - /etc/mysql/mysql.conf.d/mysqld.cnf
註解原本的 bind-address

* 修改後需要重啟 mysql
$ sudo service mysql restart

* 開通防火牆
如果是 Google Cloud ,就是去開通防火牆端口,
如果是其他的 VPS ,則可能是參考如下: 
$ /sbin/iptables -A INPUT -i eth0 -p tcp --destination-port 3306 -j ACCEPT
eht0 是 網路卡名稱,比如說查出來的結果是 ens3
查詢的方式,在 VPS server 輸入以下指令
$ ifconfig

* 測試是否可以連到 mysql,先不論帳號密碼和權限
telnet <your-mysql-ip> 3306



如何在 Google Compute Engine 上安裝最新版 MySQL

免費 Instance 的記憶體太小不足以運作 MySQL 8,需要先規劃虛擬記憶體 Swap 以增加記憶體,否則啟動 MySQL 伺服器時會失敗:
https://21st.each1.net/2018/03/swap.html

然後以官方文件為基礎:
https://cloud.google.com/solutions/setup-mysql?hl=zh-tw

再以下篇更完整的概念去客製化:
https://www.itread01.com/article/1535250863.html

在 CLI 查詢 MySQL/MariaDB 版本 (不需要登入 MySQL):
mysql -V

以 CentOS 7 安裝 MySQL 8 為例:

# 先查出 CentOS 7 預設的資料庫 MariaDB、以及可能已安裝的 MySQL
rpm -qa | grep mysql
rpm -qa | grep mariadb

# 通過下面的命令進行刪除
sudo yum remove mysql-xxx-xxx-

然後,

1. 更新套件管理員以納入 MySQL。
sudo rpm -Uvh http://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm

2. 安裝 MySQL。
sudo yum -y install mysql-community-server

3. 啟動 MySQL 伺服器。
sudo /usr/bin/systemctl start mysqld

# 啟動成功後可以檢視 初始化密碼 ,這是在安裝時隨機生成的
sudo cat /var/log/mysqld.log | grep password

# 提升 MySQL 安裝的安全性
sudo mysql_secure_installation


配置檔
在 Windows 上,位置是
C:\ProgramData\MySQL\MySQL Server 8.0/my.ini

在 Linux 上,位置是
/etc/my.cnf


Linux 作業系統比較

http://mitblog.pixnet.net/blog/post/41037058


適合一般使用者的:
--------------
(1) Ubuntu:簡單、易上手、很多人用。是 Linux 初學者相當推薦的一套入門 Linux 流通版。

(2) Fedora:會將最新版的軟體,在還沒穩定前就包入發行。適合喜歡嘗鮮的玩家。

(3) OpenSUSE:使用與 Red Hat Enterprise Linux、CentOS 等伺服器等級相同的核心,但卻包裝得非常簡單易用。適合喜歡穩定、不找麻煩作業系統的使用者。

(4) Arch Linux:特點是非~常小!除了必要的軟體外,不包含華而不實的任何套件。適合想把 Linux 安裝在 4GB 隨身碟上,到處執行的使用者。


適合系統管理員的:
-------------
(1) Debian:特點就是穩!缺點就是操作沒有其它 Linux 流通版那麼友善。適合不怕下繁複命令列指令的系統管理員,當成桌機或伺服器系統之用。

(2) Red Hat Enterprise Linux:穩定、支援叢集伺服器、雲端運算等企業用得到的特性。很適合拿來架設伺服器。不過想取得這個版本,是要收費的。

(3) CentOS:一套由 Red Hat Enterprise Linux 改造而來、但卻不用收費的 Linux 作業系統。特色也是穩到一個不行。有「萬年不掛伺服器」之美稱。適合想嘗試 Red Hat Enterprise Linux,卻無力負擔花錢購買該 Linux 的人使用。


為特殊用途而開發的:
---------------
(1) Gentoo:以支援軟體套件眾多、傲視所有 Linux 作業系統聞名。不過它很要求整套系統要提供原始碼這件事,導致安裝時,常常需要從「原始碼」編譯成「執行檔」後,才能使用。從另一面來看,這會迫使用它的人,培養出從原始碼編出執行檔的能力,也算是蠻好的教育訓練平台。因此,Gentoo 有「學其它 Linux 版本,你就是學會該版本而已。學會 Gentoo,你就學會所有的 Linux」之美稱。

(2) Damn Vulnerable Linux(DVL):從字面上翻譯,就是「他媽的超脆弱 Linux」。這個版本故意裝了老舊、破損、有臭蟲的各種軟體套件。因此你可以拿它來訓練系統管理員,將它修補到穩定為止。

(3) Kali Linux:由 Debian 改寫、前身是「Backtrack」、故意留下各種網路漏洞、讓你拿來訓練駭客「入侵技巧」之用的 Linux。它本身可以直接接受任何 Debian 的軟體,適合拿來做「入侵測試(Penetration Test)」之用。

TiDB 安裝部署

https://php.wiki/tidb

TiDB 是新一代开源分布式 NewSQL 数据库,模型受 Google Spanner / F1 论文的启发,实现了自动的水平伸缩,强一致性的分布式事务,基于 Raft 算法的多副本复制等重要 NewSQL 特性。TiDB 结合了 RDBMS 和 NoSQL 的优点,部署简单,在线弹性扩容和异步表结构变更不影响业务, 真正的异地多活及自动故障恢复保障数据安全,同时兼容 MySQL 协议,使迁移使用成本降到极低。

安装部署

TiDB 官方提供了支持 Linux 版本的二进制安装包,官方推荐使用 Redhat 7+、CentOS 7+ 以上版本的操作系统,不推荐在 Redhat 6、CentOS 6 上部署 TiDB 集群。
操作系统:Linux ( Redhat 7+,CentOS 7+ )
执行步骤:

下载压缩包

wget http://download.pingcap.org/tidb-latest-linux-amd64.tar.gz
wget http://download.pingcap.org/tidb-latest-linux-amd64.sha256

检查文件完整性

,返回 ok 则正确
sha256sum -c tidb-latest-linux-amd64.sha256

解开压缩包

tar -xzf tidb-latest-linux-amd64.tar.gz
cd tidb-latest-linux-amd64

单节点方式快速部署

在获取 TiDB 二进制文件包后,我们可以在单机上面,运行和测试 TiDB 集群,请按如下步骤依次启动 PD,TiKV,TiDB。
注意:以下启动各个应用程序组件实例的时候,请选择后台启动,避免前台失效后程序自动退出。
步骤一. 启动 PD:
./bin/pd-server --data-dir=pd --log-file=pd.log
步骤二. 启动 TiKV:
./bin/tikv-server --pd="127.0.0.1:2379" --data-dir=tikv --log-file=tikv.log
步骤三. 启动 TiDB:
./bin/tidb-server --store=tikv  --path="127.0.0.1:2379"   --log-file=tidb.log
步骤四. 使用 MySQL 客户端连接 TiDB:
mysql -h 127.0.0.1 -P 4000 -u root -D test

参考链接

MySQL Replication 主從式架構

https://blog.toright.com/posts/5062/

資料庫可以說是應用程式的核心,但關聯式資料庫 (RDBMS) 基於 ACID 設計原則,傳統架構導致在運算能力的擴展上,變得不容易實現。擴充上除了典型的 Scale-up (擴充單一硬體能力) 之外,最常使用的就是 Replication 技術,Replication 泛指資料複製模式,會把資料完整的複製到另一個 MySQL 節點上,這樣的方式並不是分散儲存喔。

目前常使用且成熟的關聯式資料庫,一般官方都會提供 Replication 機制,通常官方內建的 Replication 機制已經很成熟,不像幾年前 Open Source RDBMS 都要自己編譯第三方 Replication 功能,當然也有第三方像是 Percona 這樣的套件。透過 Replication 將資料同步複製到其他主機,可以實現運算的擴充與高可用架構。大部分的資料庫應用情境都是 SELECT 居多,最常用到的就是讀寫分離的「主從架構」,如下圖所示:


主要的 MySql Master 節點負責「讀寫」,寫資料會透過 Binlog Relay 機制,以非同步模式複製 Binlog 到每一台 Slave 執行 (正確一點的說法應該是 Slave 透過 REPLICATION 權限連線到 Master 去抓 Binlog 回來執行),運作時就好像讓 Slave 與 Master 進行資料同步。一般來說,Slave 不提供寫入功能,只負責分散 SELECT 運算,這也是最典型的擴充架構。實作時有一個地方很麻煩,就是應用程式必須自行實作「讀寫分離」的機制 (有些 Framework ORM 會內建),自行再程式邏輯將 SELECT Query 分散到 Slave 執行,除非有使用商業的 Proxy Connection Pool 機制,才有提供自動讀寫分離的機制。如果是使用 MariaDB 的話也可以搭配 MaxScale 實現讀寫分離機制,但 MaxScale 我沒玩過,只是打打嘴砲。

此外,建構 Replication 還有一個很重要的好處,就是可以順便備份!一般的情況我們都是用 mysqldump 進行資料備份對吧!?但是如果你的資料已經大到一定的程度,想要 Dump DB 絕對是 GG,搞不好跑個日備份就超過一天了....... 這時候就要借助 Replication 的能力。


透過 HAProxy 實現 MySQL 主備自動切換

上述說明的主從架構只能分散運算,並無法實現 HA 能力,如果採用 Master/Master 的配置方式就可以實現了,但是應用程式要如何判斷其他一台機器出問題呢?我們可以藉由 HAProxy 這個套件來實現。將其中一台機器上線,另一台基器備援 (Replication),當第一台機器發生問題時,自動由 HAProxy 轉接連線至備援機,以實現 HA 模式。HAProxy 的設定方式在 GitHub 上:https://github.com/samejack/blog-content/blob/master/mysql-replication/haproxy.cfg


MySQL 的日常管理

status;
show create database 資料庫名稱 ;
show create table 資料表名稱 ;
show table status ( from 資料庫名稱 ) ;
show columns from 資料表名稱 ;

select version();
show variables like 'have%ssl%';
show variables like 'port';
show variables like 'datadir';
sudo find / -name my.cnf
sudo mysql --help | grep my.cnf


檢視當前的工作狀態
mysql> show processlist
mysql> show full processlist

如果需要刪掉某個工作
mysql> kill 該工作的Id ;

檢視當前配置的最大連線數、當前使用過的最大連線數。
mysql> show variables like "max_c%";
mysql> show global status like "Max_%";

最大連線數設定為:使用過最大連線數/配置最大連線數≈85% 為比較合適,但使用過的最大連線數都受到配置最大連線數的應用,所以在配置最大連線數過少的情況下,儘可能的先配置大一點的連線數,過段時間獲取使用過的最大連線數後,再設定最優的最大連線數。

mysql> show variables like "%timeout%";

http://jeremy.zawodny.com/blog/archives/011421.html
無論如何都必須修改的四個 MySQL 預設值
max_connect_errors = 1844674407370954751
(並 running an occasional FLUSH HOSTS command)
connect_timeout = 20
skip-name-resolve

設置 max_connect_errors 的目的是預防暴力破解密碼,
所以是否應該如上建議的修改調高這個預設值,其實仍得端視實際應用場景的整體規劃,
比如防火牆是否有開放外部連結的埠號等等,
同理,調整每個預設值之前,應仔細思考實際應用場景的特殊需求,整體規劃考量。

mysql>
set GLOBAL max_connect_errors=1844674407370954751;
set GLOBAL max_connections=5000;
set GLOBAL connect_timeout=20;
set wait_timeout=600;
set interactive_timeout=600;


wait_timeout 預設值為 28800(8小時)
太長了會吃掉 mysql 的連線數

wait_timeout 和 interactive_timeout
這兩個參數要同時設定才會生效


mysql> show status
Show Status官網詳細文件:
https://dev.mysql.com/doc/refman/5.7/en/server-status-variables.html#statvar_Aborted_clients



網站的效能優化

作為通用的原則,雅虎的工程師團隊曾經給出過35個最佳實踐,這個列表請參考
Best Practices for Speeding Up Your Web Site
https://developer.yahoo.com/performance/rules.html

陳希章@中國
https://www.cnblogs.com/chenxizhang/archive/2013/05/20/3088196.html

Web API

2020年,預計全球有30萬個API生成;《財富》雜誌的100大公司,也都將要開放API;API驅動的行動應用,市場規模至2015年將增長到250億美元。大數據與雲端時代,API已成為串聯新應用的關鍵,將舊有服務加值,把商業模式更新,大企業、新創者,你不能不認識它。

何謂 Omni-Channel Retail 全通路零售 (全渠道零售):https://21st.each1.net/2018/07/omni-channel-retail.html


已經進入SaaS / PaaS / IaaS 時代已久,還在用舊時代想法規劃網站嗎?

「 以Google為例,透過 GoogleMapAPI,第三方開發者可以輕易的使用 Google Map 所提供的套件,串接Google的地圖資料,並鑲嵌在自己的網路。Twitter 利用 WebAPI 分享他們龐大會員的資訊。Amazon 則提供了一個代管主機的應用介面;微軟更是把傳統的Office變成了雲端服務的Office365 」

從上述案例來看,以雲端服務為導向的商業模式,正在這幾年蓬勃發展。但並非是透過網路就是所謂的雲端服務,從雲端機房到WebAPI,其中的學問可是大不相同,雲端服務的類型如下:


傳統方式:

過去的網路公司,主要都是以傳統方式建置產品和服務,不管是從Server硬體、網路、作業系統、機房等等,都由公司一手包辦。而為因應產品的類型,是否用多少頻寬的網路、作業系統、是否使用虛擬主機VM等...都會影響到產品的效能,這樣的建置方式不僅需要對每個技術環節,都有相當程度的了解和考究,投入的時間和人力成本也更是一大考量。

IaaS(Infrastructure as a Service),基礎建設即服務 :

將網路建置及server硬體採買、是否虛擬化過程交給廠商管理,而公司本身只要針對硬體設施以外的項目如作業系統、硬體上所需執行的服務及應用程式即可,或是我們可以解釋成僅和外部廠商租賃雲端機房、伺服器、網路環境等等,而不用像過去需要在公司內部自行建置機房,而大部分提供雲端機房的環境亦提供恆溫、24小時監控外、機房本身又具備高規格的防震等級,可以有效負擔掉企業內部機房的維運成本。

PaaS(Platform as a Service), 平台即服務:

除IaaS的項目之外,更把作業系統、開發程式環境都交給廠商管理,這樣公司只要專注在資料處理及服務(應用程式)的開發項目,就像Microsoft Azure所提供的Paas服務,像IaaS一樣提供包括基礎架構服務器,存儲和網路,而且還包括開發環境、開發工具,商業智能(BI)服務,數據庫管理系統等。以微軟Azure而言,PaaS旨在支援完整的Web應用程序生命週期:構建,測試,部署,管理和更新,並於Paas項目上提供更完善的維護及管理。


SaaS(Software as a Service),軟體即服務:

透過提供已經產品化的軟體服務是近年來營利的一大趨勢,使用者不再需要負擔自己的開發成本,只需要向廠商訂購該服務,就可以替企業省下大筆的資金。舉Google為例,它提供免費的電子郵件、日曆等服務給大眾使用外,還針對企業推出服務層級協定(SLA)較高的付費網路郵件服務,企業不需要另外採購應用電子郵件的軟體和硬體設備,只要訂購Google的Gmail服務,就能取代自建的電子郵件系統。

像Google Analysis & Adobe Sitecatalyst,也屬於SaaS的一種,提供以監控平台作為服務,透過Web方式登入並提供資料挖掘和商業數據分析。像是社群網站Facebook也可以算是SaaS的一種囉! (常見的SaaS例如 Gmail郵件、Zendesk線上客服、Codepen 線上程式編輯器)

補充說明:
這邊的SaaS與在網站開發CSS style 進階技術的Sass唸起來是一模一樣。
如果這口語上聽到這個詞必須要依照內容情境來推論對方在講什麼,商業上多半是講SaaS,網站開發規格則比較可能是Sass。

「從SaaS談到API,進入雲端產品的新世代」

以雲端產品為代表的新時代即將到來,大型企業在軟體上的開發、維護與消費上都出現了重大轉變,更代表著程式設計師在未來可以賦予產品上更高的服務價值,AWS,Facebook,Google,Twitter和數千家其他網路公司,都透過提供WebAPI的方式大打經濟戰,而服務與服務之間的互動,也從過去SaaS的接口,轉移到WebAPI身上,那API是什麼呢?

API全名叫做應用程式介面(英語:Application Programming Interface,簡稱:API),主要的概念就是把各家或是各種軟體系統的「服務」,做成一種可以「互相溝通」的一種介面,透過服務呼叫、串接的方式來進行產品與產品之間的合作與溝通,重點就在「服務」與「互相溝通」這兩個關鍵字上。

補充說明:
其實很多網路公司在內部討論的時候不用 WebAPI,而直接使用API來稱呼網路服務接口,但API 的全名 Application program interface 只是代表應用程式的使用介面/接口,遠在網際網路還不純熟的時代就已經存在,無論是C語言系列的header檔,到製作成動態函式庫,都可以使用這個名稱。因此本文以WebAPI來表達一般網站所提供的外部程式接口。

我們舉例來說吧

當我們要去大賣場買鞋子的時候,找到了心儀的鞋子卻找不到適合的尺寸,這時該怎麼作呢?

當然我們可以翻箱倒櫃的在賣場中去尋尋覓覓,但這通常不是一般人會做出的直覺選擇吧,其中花費的時間與體力都是無形中的一種成本,還未必可以找到想要的東西,所以我們通常都會選擇「請店員來協助我們」做為我們找鞋子的方式吧!

當你在呼喚了店員請他們協助時,無形中就是對「服務」的一種呼叫,而呼叫店員的這動作就是「API」,他提供的是一種服務,透過呼叫的方式來和另外一支服務「協助找尺寸」去做串接。

1.想找到想要的鞋子尺寸:服務的目的

2.呼叫店員請店員協助:與「協助找尺寸」 的服務進行呼叫與溝通

3.跟店員表示自己要的鞋子和尺寸:提出呼叫服務的需求與規格-我要什麼東西

4.拿到鞋子:完成你需要的服務

當然,主要透過Web作為介面的,就是WebAPI囉!


舉一個實際上在網站上的例子吧!

像 Uber 中使用 GoogleAPI 來當作地圖和導航的介面,不僅可以減少 Uber 團隊開發自己圖台及精算最佳路徑的成本,更可以把團隊的精力投注在優化產品服務及使用者體驗的項目上,無疑是對產品的一大助力。

而在一般我們看到的APP裡面,所有的動態資訊也都是透過WebAPI和後台DB去進行服務串接的,例如:連鎖咖啡店的會員APP,當你希望使用「檢視優惠」的服務時,就會透過WebAPI的方式,把APP後台上架的這些優惠活動、折扣等等,進行串接,而優惠活動更是動態且持續更新的,總不能每次都版本更新之後才把活動進行上架吧,光是 iOS 上架的那些繁瑣程序就會讓你心力交瘁了。

透過上述的例子,我們可以發現,一項集所有服務於一身的大型產品,不僅本身維運上的成本難以想象,其中對於所提供服務的彈性上更是較難突破,不如把服務切分成各種的WebAPI來做串接,不僅可以分散維護風險外,還可以透過「服務」來創造商機,例如以產品做接口來說,「電商網站」和「社群網站」就沒有達到有效的連想,但如果把電商網站的「搜索商品」、「推薦商品」做成一隻對外接口的廣告服務WebAPI,和Facebook的廣告WebAPI做對接,這樣不僅可以在瀏覽動態時做置入性行銷,透過社群間的串接後面產生的經濟效益,更是無法預期。

而一項項服務維護的費用,肯定比維護產品來的少許多,也許在產品草創的初期,有效的運用核心資源,把一些不必要的工作外包給這些雲端服務,並把軟體產品的功能「外包」給WebAPI,讓團隊專注在更快地創建和發布新的業務模式,來保持公司的業務彈性與競爭力,也許這也是快速開發的重要法則。

RESTful Web API

在HTTP協定中,定義了多種不同的method做為服務的請求方法,近年來由於行動裝置的普及化,越來越多的產品及網站,都提供了WebAPI服務,因此身為程式設計師的我們,在設計API為主的Web服務時,對於HTTP請求方式的認知,更是相當重要。

最常見的method,五種如下:
GET
POST
PUT
PATCH
DELETE

所有的字看起來既熟悉又陌生,因為在Http的協定下,每一種呼叫方式都會有一種他專屬的特殊定義,對於寫過網站的人來說,GET和POST絕對毫不陌生。

當Web service使用Web API進行介面介接時,每一串我們設計的URL,就會是一個專屬的服務『窗口』。

舉例來說,像是讀取及上傳的動作,就屬於完全不同的業務,所以當然也會用不同的呼叫方式來設計。

簡單說,不同的Method就是對同一件事情做不同的操作。

以搭買鞋子為例子做衍生吧!

GET:取得型錄,了解想要找的鞋子、型號、規格等。
POST/PUT:呼叫店員協助幫忙找鞋子,並買到想要的鞋子。
PATCH:結帳後向店員更換尺寸或加價購買其他配件如鞋帶、襪子等。
DELETE:跟店員說我不要了。

用生活化的例子講解完後,改以程式的角度來說明

GET:取得(想要的服務)的資料或是狀態。(safe & idempotent)
POST:新增一項資料。
PUT:利用更新的方式於"指定位置"新增一項資料。 (idempotent)
PATCH:在現有的資料欄位中,增加或部分更新一筆新的資料。
DELETE:指定資料刪除。 (idempotent)

這裡突然出現了兩個名詞 safe & idempotent,這兩個是HTTP狀態描述的專有名詞。

「safe」是指該操作不會改變原本的資源狀態,並且同樣的結果是可以被快取(Cache)的。

例如: 查看訂單是不會改變訂單本身紀錄。

「idempotent」是指該操作不管做1遍、2遍或多遍,都會得到同樣的資源狀態結果。

例如: 同一筆資料被DELETE了2次,雖然都是一樣的結果,但第二次發送會因為資料已經被刪除而失敗喔!

GET / POST 我們用得很多所以沒什麼問題,DELETE與字意上相符所以不難理解。

其中讓人困擾的是 PATCH & PUT,要解釋它們必須參考定義 (RFC 5789)。

https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5

依照 RFC 5789,
POST/PUT 都可以用來新增,
PATCH/PUT 都可以用來修改,
但其中的差別在哪裡呢?

POST的定義上屬於將原先沒有的資料去做一筆新增的動作,
PATCH就是一般常見的修改,
所以真的有問題的其實是PUT。

PUT在定義上(idempotent)無論做多少次,回傳結果都會一樣。

以POST來說,我要一雙鞋,我就會得到一雙鞋;
但是如果再用POST發一次我要一雙鞋,會出現兩種可能;
一種是我"再"得到一雙鞋,而且這雙鞋跟上一雙是不一樣的(以資料庫來說,就是ID不一樣);
或是我只能有一雙鞋,所以他會跟我說"錯誤"!! 我已經得到一雙鞋了。

但以PUT來說,無論我發多少次,他都會回我,我有一雙鞋,而我並不會變成兩雙鞋;
當然如果商店沒鞋,則變成我沒有鞋。

這點在很多程式框架裡面都有不完全正確,像 Ruby On Rails 的 PUT 與 PATCH 看起來是一件事(當然你可以自己修正)。

定義是絕對的,但應用是彈性的,所以你可以說這些框架做的與 RFC5789 不一樣,但或許這樣比較好用。
這就看個人取捨,當然,考試的時候通常需要寫 RFC5789 的定義。

另外,PUT 除新增外亦可以做更新請求,假設使用 PUT 做更新,不管是既有的資料或是覆蓋原先的資料,都會利用覆蓋的方式去更新,但假如你的資料裡面有圖檔的話,每 PUT 一次,圖檔就必須要再重新上傳一次,是相當耗費資源的。

而 PATCH 則可以針對已經存在的資料欄位去做部分更新,例如:我們在更新履歷表時,使用PATCH 就可以僅更新裡面的資料,如年齡、工作經歷等欄位,而 PUT 就像是把整份改好的履歷表重新上傳。

PATCH 也可以更新本身一開始 PUT 資料內沒有的欄位,故 PATCH 是非屬於 idempotent 的操作。

所以如果我們以電腦操作檔案來譬喻,建立一個新檔案是POST,修改檔案是PATCH,從別的地方複製檔案貼上就是PUT (無論你貼上幾次都是同一個檔案)。

當然Web API沒有一定要照著上面的定義敘述建立,但如果你符合的話,你可以將它稱作Restful API
(Rest化 = Restful,如果常常不知道講述的時候該用 Rest 或是 Restful 可以這樣去記,被轉化成 Rest架構 的 Web API = Restful API)

REST全名 Resource Representational State Transfer ,可譯為具象狀態傳輸,若是把各個單字拆開來解釋的話即如下:

Resource:資源。
Representational:表現形式,如 JSON,XML...
State Transfer:狀態變化。即上述講到的可利用HTTP動詞們來做呼叫。

簡單的說,就是一個單從發出的HTTP要求裡面所包含的資訊,就可以直接預期這要求會收到怎樣類型的資料。再更白話一點,就是人眼看得懂。

REST指的是網路中Client端和Server端的一種呼叫服務形式,透過既定的規則,滿足約束條件和原則的應用程式設計,對資源的操作包括獲取、創建、修改和刪除資源,這些操作就是依照我們前面所提到的HTTP Method: GET、POST、PUT、PATCH和DELETE。這正好會對應到資料庫基本操作CRUD。

CRUD 為 Create(新增)、Read(讀取)、Update(更新)與Delete(刪除)的縮寫。

接著我們繼續舉例來說,如果我們正在寫一隻商品的WebAPI,讓工程師隨便寫可能會有以下方式來作interface:

獲得商品資料 GET   /getAllItems
獲得商品資料 GET   /getItem/11
新增商品資料 POST /createItem
更新商品資料 POST  /updateItem/
刪除商品資料 POST  /deleteItem/

若是以使用 RESTful API 開發的話:

獲取商品資料 /GET     /items
獲取商品資料 /GET     /items/1
新增商品資料 /POST   /items
更新商品資料 /PATCH /items/1
刪除商品資料 /DELETE /items/1

PUT 則是比較特別一點,其實它並不直接對應CRUD裡面的任何一項。

在這樣的風格中最有名的,應該就是 Ruby on Rails了吧!

透過 HTTP 為基礎來設計 RESTful API,不僅可行,更可以更簡單扼要呢!

最後要提醒大家,我們沒辦法直接在 HTML的<form>裡面使用GET 與 POST以外的Method,因為瀏覽器都還不支援,如果想要發送 Restful request 一般都要後台程式的支援,而且必須要在<form>裡面藏一個<input name="_method" value="你的HTTP Request方法"> 才有辦法送出去。


資料來源:
https://progressbar.tw/posts/51
https://progressbar.tw/posts/53




虛擬記憶體 Swap

http://linux.vbird.org/linux_basic/0230filesystem/0230filesystem.php#swap
https://yungke.li/how-vultr-swap/


在設定之前,先檢查系統裡有沒有既存的 swap 文件。

swapon -s
free -m


如何在 Linux 裡建立 Swap file,步驟與解說如下:

1. 本範例建立一個 2G 大小的 swap 檔,命名為 swapfile 放在根目錄
$ sudo dd if=/dev/zero of=/swapfile bs=1M count=2048

2. 設定 swap
$ sudo mkswap /swapfile

3. 啟用 swap
$ sudo swapon /swapfile

4. 設定開機自動啟動 swap
$ sudo vi /etc/fstab

在 fstab 這個檔案裡頭加上這一行
/swapfile swap swap defailts 0 0


完整解說:

dd 是 convert and copy a file。

/dev/zero是一個特殊的檔案,當讀取它的時候,它會提供無限的空字元 ( NULL, ASCII NUL, 0x00 )。
一個典型用法是用它提供的字元流來覆蓋資訊,另一個常見用法是產生一個特定大小的空白檔案。

if 是輸入文件,of 是輸出文件,
dd 可以轉換類型,然後把這些 0x00 寫入一個 swapfile。

bs 是區塊大小,count 是數量,所以本範例建立了 2048 個 1M 大小的區塊,共計 2G。

做完這一步以後,可以用如下指令查看一下:
$ file /swapfile

接著,mkswap 可將磁盤分區或文件設為 Linux 的交換區。

因此,基本的流程就是:
以 dd 指令來建立 swapfile ;
以 mkswap 來將 swapfile 格式化為 swap 的檔案格式;
以 swapon 來啟動該檔案,使成為 swap。


刪除swap file
     Step 1 . sudo swapoff /swapfile

     Step 2 . 將 /etc/fstab 中的設定移除

     Step 3 . sudo rm /swapfile

在 shell 中常用的特殊符號

在shell中常用的特殊符號:

# ;    ;;       .       ,        /        \        'string'|        !    $    ${}    $?       $$    $*        "string"*      **    ?       :        ^       $#    $@        `command`{}     []       [[]]      ()     (())         ||    &&        {xx,yy,zz,...}~    ~+    ~-     &    \<...\>    +        -         %=    ==    !=                    

输出/输入重导向
>       >>    <    <<    : >    &>    2&>    2<>>&    >&2                         

# 井号 (comments)
这几乎是个满场都有的符号,除了先前已经提过的"第一行"
#!/bin/bash
井号也常出现在一行的开头,或者位于完整指令之后,这类情况表示符号后面的是注解文字,不会被执行。
# This line is comments.
echo "a = $a" # a = 0
由于这个特性,当临时不想执行某行指令时,只需在该行开头加上 # 就行了。这常用在撰写过程中。
#echo "a = $a" # a = 0
如果被用在指令中,或者引号双引号括住的话,或者在倒斜线的后面,那他就变成一般符号,不具上述的特殊功能。

~ 帐户的 home 目录
算是个常见的符号,代表使用者的 home 目录:cd ~;也可以直接在符号后加上某帐户的名称:cd ~user
或者当成是路径的一部份:~/bin;~+ 当前的工作目录,这个符号代表当前的工作目录,她和内建指令 pwd 的作用是相同的。
# echo ~+/var/log~- 上次的工作目录,这个符号代表上次的工作目录。
# echo ~-/etc/httpd/logs

; 分号 (Command separator)
在 shell 中,担任"连续指令"功能的符号就是"分号"。譬如以下的例子:cd ~/backup ; mkdir startup ; cp ~/.* startup/.

;; 连续分号 (Terminator)
专用在 case 的选项,担任 Terminator 的角色。
case "$fop" inhelp) echo "Usage: Command -help -version filename" ;;version) echo "version 0.1" ;;esac

. 逗号 (dot)
在 shell 中,使用者应该都清楚,一个 dot 代表当前目录,两个 dot 代表上层目录。
CDPATH=.:~:/home:/home/web:/var:/usr/local
在上行 CDPATH 的设定中,等号后的 dot 代表的就是当前目录的意思。
如果档案名称以 dot 开头,该档案就属特殊档案,用 ls 指令必须加上 -a 选项才会显示。除此之外,在 regular expression 中,一个 dot 代表匹配一个字元。

'string' 单引号 (single quote)
被单引号用括住的内容,将被视为单一字串。在引号内的代表变数的$符号,没有作用,也就是说,他被视为一般符号处理,防止任何变量替换。
heyyou=homeecho '$heyyou' # We get $heyyou

"string" 双引号 (double quote)
被双引号用括住的内容,将被视为单一字串。它防止通配符扩展,但允许变量扩展。这点与单引数的处理方式不同。
heyyou=homeecho "$heyyou" # We get home
`command` 倒引号 (backticks)
在前面的单双引号,括住的是字串,但如果该字串是一列命令列,会怎样?答案是不会执行。要处理这种情况,我们得用倒单引号来做。
fdv=`date +%F`echo "Today $fdv"
在倒引号内的 date +%F 会被视为指令,执行的结果会带入 fdv 变数中。

, 逗点 (comma)
这个符号常运用在运算当中当做"区隔"用途。如下例
#!/bin/bashlet "t1 = ((a = 5 + 3, b = 7 - 1, c = 15 / 3))"echo "t1 = $t1, a = $a, b = $b"

/ 斜线 (forward slash)
在路径表示时,代表目录。
cd /etc/rc.dcd ../..cd /
通常单一的 / 代表 root 根目录的意思;在四则运算中,代表除法的符号。
let "num1 = ((a = 10 / 2, b = 25 / 5))"

\ 倒斜线 (
)
在交互模式下的escape 字元,有几个作用;放在指令前,有取消 aliases 的作用;放在特殊符号前,则该特殊符号的作用消失;放在指令的最末端,表示指令连接下一行。
# type rmrm is aliased to `rm -i'# \rm ./*.log
上例,我在 rm 指令前加上 escape 字元,作用是暂时取消别名的功能,将 rm 指令还原。
# bkdir=/home# echo "Backup dir, \$bkdir = $bkdir"Backup dir, $bkdir = /home
上例 echo 内的 \$bkdir,escape 将 $ 变数的功能取消了,因此,会输出 $bkdir,而第二个 $bkdir 则会输出变数的内容 /home。

| 管道 (pipeline)
pipeline 是 UNIX 系统,基础且重要的观念。连结上个指令的标准输出,做为下个指令的标准输入。
who | wc -l
善用这个观念,对精简 script 有相当的帮助。

! 惊叹号(negate or reverse)
通常它代表反逻辑的作用,譬如条件侦测中,用 != 来代表"不等于"
if [ "$?" != 0 ]thenecho "Executes error"exit 1fi
在规则表达式中她担任 "反逻辑" 的角色
ls a[!0-9]
上例,代表显示除了a0, a1 .... a9 这几个文件的其他文件。

: 冒号
在 bash 中,这是一个内建指令:"什么事都不干",但返回状态值 0。
:
echo $? # 回应为 0
: > f.$$
上面这一行,相当于 cat /dev/null > f.$$。不仅写法简短了,而且执行效率也好上许多。
有时,也会出现以下这类的用法
: ${HOSTNAME?} ${USER?} ${MAIL?}
这行的作用是,检查这些环境变数是否已设置,没有设置的将会以标准错误显示错误讯息。像这种检查如果使用类似 test 或 if 这类的做法,基本上也可以处理,但都比不上上例的简洁与效率。
除了上述之外,还有一个地方必须使用冒号
PATH=$PATH:$HOME/fbin:$HOME/fperl:/usr/local/mozilla
在使用者自己的HOME 目录下的 .bash_profile 或任何功能相似的档案中,设定关于"路径"的场合中,我们都使用冒号,来做区隔。

? 问号 (wild card)
在文件名扩展(Filename expansion)上扮演的角色是匹配一个任意的字元,但不包含 null 字元。
# ls a?a1
善用她的特点,可以做比较精确的档名匹配。

* 星号 (wild card)
相当常用的符号。在文件名扩展(Filename expansion)上,她用来代表任何字元,包含 null 字元。
# ls a*a a1 access_log
在运算时,它则代表 "乘法"。
let "fmult=2*3"
除了内建指令 let,还有一个关于运算的指令 expr,星号在这里也担任"乘法"的角色。不过在使用上得小心,他的前面必须加上escape 字元。

** 次方运算
两个星号在运算时代表 "次方" 的意思。
let "sus=2**3"echo "sus = $sus" # sus = 8

$ 钱号(dollar sign)
变量替换(Variable Substitution)的代表符号。
vrs=123echo "vrs = $vrs" # vrs = 123
另外,在 Regular Expressions 里被定义为 "行" 的最末端 (end-of-line)。这个常用在 grep、sed、awk 以及 vim(vi) 当中。

${} 变量的正规表达式
bash 对 ${} 定义了不少用法。以下是取自线上说明的表列
    ${parameter:-word}    ${parameter:=word}    ${parameter:?word}    ${parameter:+word}    ${parameter:offset}    ${parameter:offset:length}    ${!prefix*}    ${#parameter}    ${parameter#word}    ${parameter##word}    ${parameter%word}    ${parameter%%word}    ${parameter/pattern/string}    ${parameter//pattern/string}

$*引用script 的执行引用变量,引用参数的算法与一般指令相同,指令本身为0,其后为1,然后依此类推。引用变量的代表方式如下:
$0, $1, $2, $3, $4, $5, $6, $7, $8, $9, ${10}, ${11}.....
个位数的,可直接使用数字,但两位数以上,则必须使用 {} 符号来括住。
$* 则是代表所有引用变量的符号。使用时,得视情况加上双引号。
echo "$*"
还有一个与 $* 具有相同作用的符号,但效用与处理方式略为不同的符号。

$@
$@ 与 $* 具有相同作用的符号,不过她们两者有一个不同点。
符号 $* 将所有的引用变量视为一个整体。但符号 $@ 则仍旧保留每个引用变量的区段观念。
$#
这也是与引用变量相关的符号,她的作用是告诉你,引用变量的总数量是多少。
echo "$#"

$? 状态值 (status variable)
一般来说,UNIX(linux) 系统的进程以执行系统调用exit() 来结束的。这个回传值就是status值。回传给父进程,用来检查子进程的执行状态。
一般指令程序倘若执行成功,其回传值为 0;失败为 1。
tar cvfz dfbackup.tar.gz /home/user > /dev/nullecho "$?"$$
由于进程的ID是唯一的,所以在同一个时间,不可能有重复性的 PID。有时,script 会需要产生临时文件,用来存放必要的资料。而此script 亦有可能在同一时间被使用者们使用。在这种情况下,固定文件名在写法上就显的不可靠。唯有产生动态文件名,才能符合需要。符号$$ 或许可以符合这种需求。它代表当前shell 的 PID。
echo "$HOSTNAME, $USER, $MAIL" > ftmp.$$
使用它来作为文件名的一部份,可以避免在同一时间,产生相同文件名的覆盖现象。
ps: 基本上,系统会回收执行完毕的 PID,然后再次依需要分配使用。所以 script 即使临时文件是使用动态档名的写法,如果 script 执行完毕后仍不加以清除,会产生其他问题。

() 指令群组 (command group)
用括号将一串连续指令括起来,这种用法对 shell 来说,称为指令群组。如下面的例子:(cd ~ ; vcgh=`pwd` ; echo $vcgh),指令群组有一个特性,shell会以产生 subshell 来执行这组指令。因此,在其中所定义的变数,仅作用于指令群组本身。我们来看个例子
# cat ftmp-01#!/bin/basha=fsh(a=incg ; echo -e "\n $a \n")echo $a# ./ftmp-01incgfsh
除了上述的指令群组,括号也用在 array 变数的定义上;另外也应用在其他可能需要加上escape 字元才能使用的场合,如运算式。

(())
这组符号的作用与 let 指令相似,用在算数运算上,是 bash 的内建功能。所以,在执行效率上会比使用 let 指令要好许多。
#!/bin/bash(( a = 10 ))echo -e "inital value, a = $a\n"(( a++ ))echo "after a++, a = $a"

{} 大括号 (Block of code)
有时候 script 当中会出现,大括号中会夹着一段或几段以"分号"做结尾的指令或变数设定。
# cat ftmp-02#!/bin/basha=fsh{a=inbc ; echo -e "\n $a \n"}echo $a# ./ftmp-02inbcinbc
这种用法与上面介绍的指令群组非常相似,但有个不同点,它在当前的 shell 执行,不会产生 subshell。
大括号也被运用在 "函数" 的功能上。广义地说,单纯只使用大括号时,作用就像是个没有指定名称的函数一般。因此,这样写 script 也是相当好的一件事。尤其对输出输入的重导向上,这个做法可精简 script 的复杂度。
此外,大括号还有另一种用法,如下
{xx,yy,zz,...}
这种大括号的组合,常用在字串的组合上,来看个例子
mkdir {userA,userB,userC}-{home,bin,data}
我们得到 userA-home, userA-bin, userA-data, userB-home, userB-bin, userB-data, userC-home, userC-bin, userC-data,这几个目录。这组符号在适用性上相当广泛。能加以善用的话,回报是精简与效率。像下面的例子
chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}
如果不是因为支援这种用法,我们得写几行重复几次呀!

[] 中括号
常出现在流程控制中,扮演括住判断式的作用。
if [ "$?" != 0 ]thenecho "Executes error"exit 1fi
这个符号在正则表达式中担任类似 "范围" 或 "集合" 的角色
rm -r 200[1234]
上例,代表删除 2001, 2002, 2003, 2004 等目录的意思。

[[]]
这组符号与先前的 [] 符号,基本上作用相同,但她允许在其中直接使用 || 与 && 逻辑等符号。
#!/bin/bashread akif [[ $ak > 5 || $ak < 9 ]]thenecho $akfi

|| 逻辑符号
这个会时常看到,代表 or 逻辑的符号。

&& 逻辑符号
这个也会常看到,代表 and 逻辑的符号。

& 后台工作
单一个& 符号,且放在完整指令列的最后端,即表示将该指令列放入后台中工作。
tar cvfz data.tar.gz data > /dev/null &
\<...\> 单字边界
这组符号在规则表达式中,被定义为"边界"的意思。譬如,当我们想找寻 the 这个单字时,如果我们用
grep the FileA
你将会发现,像 there 这类的单字,也会被当成是匹配的单字。因为 the 正巧是 there 的一部份。如果我们要必免这种情况,就得加上 "边界" 的符号
grep '\' FileA

+ 加号 (plus)
在运算式中,她用来表示 "加法"。
expr 1 + 2 + 3
此外在规则表达式中,用来表示"很多个"的前面字元的意思。
# grep '10\+9' fileB109100910000910000931010009#这个符号在使用时,前面必须加上 escape 字元。

- 减号 (dash)
在运算式中,她用来表示 "减法"。
expr 10 - 2
此外也是系统指令的选项符号。
ls -expr 10 - 2
在 GNU 指令中,如果单独使用 - 符号,不加任何该加的文件名称时,代表"标准输入"的意思。这是 GNU 指令的共通选项。譬如下例
tar xpvf -
这里的 - 符号,既代表从标准输入读取资料。
不过,在 cd 指令中则比较特别
cd -
这代表变更工作目录到"上一次"工作目录。

% 除法 (Modulo)
在运算式中,用来表示 "除法"。
expr 10 % 2
此外,也被运用在关于变量的规则表达式当中的下列
${parameter%word}${parameter%%word}
一个 % 表示最短的 word 匹配,两个表示最长的 word 匹配。 

= 等号 (Equals)
常在设定变数时看到的符号。
vara=123echo " vara = $vara"
或者像是 PATH 的设定,甚至应用在运算或判断式等此类用途上。

== 等号 (Equals)
常在条件判断式中看到,代表 "等于" 的意思。
if [ $vara == $varb ]
...下略
!= 不等于
常在条件判断式中看到,代表 "不等于" 的意思。
if [ $vara != $varb ]
...下略

^
这个符号在规则表达式中,代表行的 "开头" 位置。

Linux 特殊符號

http://www.cnblogs.com/balaamwe/archive/2012/03/15/2397998.html

在shell中常用的特殊符号罗列如下:

#   ;   ;;      .      ,       /       \       'string'|       !   $   ${}   $?      $$   $*  "string"*     **   ?   :   ^   $#   $@    `command`{}  []   [[]]   ()    (())  ||   &&       {xx,yy,zz,...}~   ~+   ~-    &   \<...\>   +       -        %=   ==   != 

# 井号 (comments)
这几乎是个满场都有的符号,除了先前已经提过的"第一行"
#!/bin/bash
井号也常出现在一行的开头,或者位于完整指令之后,这类情况表示符号后面的是注解文字,不会被执行。
# This line is comments.
echo "a = $a" # a = 0
由于这个特性,当临时不想执行某行指令时,只需在该行开头加上 # 就行了。这常用在撰写过程中。
#echo "a = $a" # a = 0
如果被用在指令中,或者引号双引号括住的话,或者在倒斜线的后面,那他就变成一般符号,不具上述的特殊功能。


~ 帐户的 home 目录
算是个常见的符号,代表使用者的 home 目录:cd ~;也可以直接在符号后加上某帐户的名称:cd ~user或者当成是路径的一部份:~/bin
~+ 当前的工作目录,这个符号代表当前的工作目录,她和内建指令 pwd的作用是相同的。
# echo ~+/var/log
~- 上次的工作目录,这个符号代表上次的工作目录。
# echo ~-/etc/httpd/logs


; 分号 (Command separator)
在 shell 中,担任"连续指令"功能的符号就是"分号"。譬如以下的例子:cd ~/backup ; mkdir startup ;cp ~/.* startup/.


;; 连续分号 (Terminator)
专用在 case 的选项,担任 Terminator 的角色。
case "$fop" inhelp) echo "Usage: Command -help -version filename";;version) echo "version 0.1" ;;esac


. 逗号 (dot,就是“点”)
在 shell 中,使用者应该都清楚,一个 dot 代表当前目录,两个 dot 代表上层目录。
CDPATH=.:~:/home:/home/web:/var:/usr/local
在上行 CDPATH 的设定中,等号后的 dot 代表的就是当前目录的意思。
如果档案名称以 dot 开头,该档案就属特殊档案,用 ls 指令必须加上 -a 选项才会显示。除此之外,在 regularexpression 中,一个 dot 代表匹配一个字元。


'string' 单引号 (single quote)
被单引号用括住的内容,将被视为单一字串。在引号内的代表变数的$符号,没有作用,也就是说,他被视为一般符号处理,防止任何变量替换。
heyyou=homeecho '$heyyou' # We get $heyyou


"string" 双引号 (double quote)
被双引号用括住的内容,将被视为单一字串。它防止通配符扩展,但允许变量扩展。这点与单引数的处理方式不同。
heyyou=homeecho "$heyyou" # We get home

`command` 倒引号 (backticks)
在前面的单双引号,括住的是字串,但如果该字串是一列命令列,会怎样?答案是不会执行。要处理这种情况,我们得用倒单引号来做。
fdv=`date +%F`echo "Today $fdv"
在倒引号内的 date +%F 会被视为指令,执行的结果会带入 fdv 变数中。


, 逗点 (comma,标点中的逗号)
这个符号常运用在运算当中当做"区隔"用途。如下例
#!/bin/bashlet "t1 = ((a = 5 + 3, b = 7 - 1, c = 15 / 3))"echo "t1= $t1, a = $a, b = $b"


/ 斜线 (forward slash)
在路径表示时,代表目录。
cd /etc/rc.dcd ../..cd /
通常单一的 / 代表 root 根目录的意思;在四则运算中,代表除法的符号。
let "num1 = ((a = 10 / 2, b = 25 / 5))"


\ 倒斜线
在交互模式下的escape 字元,有几个作用;放在指令前,有取消 aliases的作用;放在特殊符号前,则该特殊符号的作用消失;放在指令的最末端,表示指令连接下一行。
# type rmrm is aliased to `rm -i'# \rm ./*.log
上例,我在 rm 指令前加上 escape 字元,作用是暂时取消别名的功能,将 rm 指令还原。
# bkdir=/home# echo "Backup dir, \$bkdir = $bkdir"Backup dir,$bkdir = /home
上例 echo 内的 \$bkdir,escape 将 $ 变数的功能取消了,因此,会输出 $bkdir,而第二个 $bkdir则会输出变数的内容 /home。


| 管道 (pipeline)
pipeline 是 UNIX 系统,基础且重要的观念。连结上个指令的标准输出,做为下个指令的标准输入。
who | wc -l
善用这个观念,对精简 script 有相当的帮助。


! 惊叹号(negate or reverse)
通常它代表反逻辑的作用,譬如条件侦测中,用 != 来代表"不等于"
if [ "$?" != 0 ]thenecho "Executes error"exit 1fi
在规则表达式中她担任 "反逻辑" 的角色
ls a[!0-9]
上例,代表显示除了a0, a1 .... a9 这几个文件的其他文件。


: 冒号
在 bash 中,这是一个内建指令:"什么事都不干",但返回状态值 0。
:
echo $? # 回应为 0
: > f.$$
上面这一行,相当于 cat /dev/null >f.$$。不仅写法简短了,而且执行效率也好上许多。
有时,也会出现以下这类的用法
: ${HOSTNAME?} ${USER?} ${MAIL?}
这行的作用是,检查这些环境变数是否已设置,没有设置的将会以标准错误显示错误讯息。像这种检查如果使用类似 test 或 if这类的做法,基本上也可以处理,但都比不上上例的简洁与效率。
除了上述之外,还有一个地方必须使用冒号
PATH=$PATH:$HOME/fbin:$HOME/fperl:/usr/local/mozilla
在使用者自己的HOME 目录下的 .bash_profile或任何功能相似的档案中,设定关于"路径"的场合中,我们都使用冒号,来做区隔。


? 问号 (wild card)
在文件名扩展(Filename expansion)上扮演的角色是匹配一个任意的字元,但不包含 null 字元。
# ls a?a1
善用她的特点,可以做比较精确的档名匹配。


* 星号 (wild card)
相当常用的符号。在文件名扩展(Filename expansion)上,她用来代表任何字元,包含 null 字元。
# ls a*a a1 access_log
在运算时,它则代表 "乘法"。
let "fmult=2*3"
除了内建指令 let,还有一个关于运算的指令expr,星号在这里也担任"乘法"的角色。不过在使用上得小心,他的前面必须加上escape 字元。


** 次方运算
两个星号在运算时代表 "次方" 的意思。
let "sus=2**3"echo "sus = $sus" # sus = 8


$ 钱号(dollar sign)
变量替换(Variable Substitution)的代表符号。
vrs=123echo "vrs = $vrs" # vrs = 123
另外,在 Regular Expressions 里被定义为 "行" 的最末端 (end-of-line)。这个常用在grep、sed、awk 以及 vim(vi) 当中。


${} 变量的正规表达式
bash 对 ${} 定义了不少用法。以下是取自线上说明的表列
   ${parameter:-word}   ${parameter:=word}   ${parameter:?word}   ${parameter:+word}   ${parameter:offset}   ${parameter:offset:length}   ${!prefix*}   ${#parameter}   ${parameter#word}   ${parameter##word}   ${parameter%word}   ${parameter%%word}   ${parameter/pattern/string}   ${parameter//pattern/string}


$* 
$* 
引用script的执行引用变量,引用参数的算法与一般指令相同,指令本身为0,其后为1,然后依此类推。引用变量的代表方式如下:
$0, $1, $2, $3, $4, $5, $6, $7, $8, $9, ${10}, ${11}.....
个位数的,可直接使用数字,但两位数以上,则必须使用 {} 符号来括住。
$* 则是代表所有引用变量的符号。使用时,得视情况加上双引号。
echo "$*"
还有一个与 $* 具有相同作用的符号,但效用与处理方式略为不同的符号。


$@
$@ 与 $* 具有相同作用的符号,不过她们两者有一个不同点。
符号 $* 将所有的引用变量视为一个整体。但符号 $@ 则仍旧保留每个引用变量的区段观念。

$#
这也是与引用变量相关的符号,她的作用是告诉你,引用变量的总数量是多少。
echo "$#"


$? 状态值 (status variable)
一般来说,UNIX(linux) 系统的进程以执行系统调用exit()来结束的。这个回传值就是status值。回传给父进程,用来检查子进程的执行状态。
一般指令程序倘若执行成功,其回传值为 0;失败为 1。
tar cvfz dfbackup.tar.gz /home/user > /dev/nullecho"$?"$$
由于进程的ID是唯一的,所以在同一个时间,不可能有重复性的 PID。有时,script会需要产生临时文件,用来存放必要的资料。而此script亦有可能在同一时间被使用者们使用。在这种情况下,固定文件名在写法上就显的不可靠。唯有产生动态文件名,才能符合需要。符号$$或许可以符合这种需求。它代表当前shell 的 PID。
echo "$HOSTNAME, $USER, $MAIL" > ftmp.$$
使用它来作为文件名的一部份,可以避免在同一时间,产生相同文件名的覆盖现象。
ps: 基本上,系统会回收执行完毕的 PID,然后再次依需要分配使用。所以 script 即使临时文件是使用动态档名的写法,如果script 执行完毕后仍不加以清除,会产生其他问题。

(   ) 指令群组 (command group)
用括号将一串连续指令括起来,这种用法对 shell 来说,称为指令群组。如下面的例子:(cd ~ ; vcgh=`pwd` ;echo $vcgh),指令群组有一个特性,shell会以产生 subshell来执行这组指令。因此,在其中所定义的变数,仅作用于指令群组本身。我们来看个例子
# cat ftmp-01#!/bin/basha=fsh(a=incg ; echo -e "\n $a \n")echo $a#./ftmp-01incgfsh
除了上述的指令群组,括号也用在 array 变数的定义上;另外也应用在其他可能需要加上escape字元才能使用的场合,如运算式。


((  ))
这组符号的作用与 let 指令相似,用在算数运算上,是 bash 的内建功能。所以,在执行效率上会比使用 let指令要好许多。
#!/bin/bash(( a = 10 ))echo -e "inital value, a = $a\n"(( a++))echo "after a++, a = $a"

{  } 大括号 (Block of code)
有时候 script 当中会出现,大括号中会夹着一段或几段以"分号"做结尾的指令或变数设定。
# cat ftmp-02#!/bin/basha=fsh{a=inbc ; echo -e "\n $a \n"}echo $a#./ftmp-02inbcinbc
这种用法与上面介绍的指令群组非常相似,但有个不同点,它在当前的 shell 执行,不会产生 subshell。
大括号也被运用在 "函数" 的功能上。广义地说,单纯只使用大括号时,作用就像是个没有指定名称的函数一般。因此,这样写 script也是相当好的一件事。尤其对输出输入的重导向上,这个做法可精简 script 的复杂度。

此外,大括号还有另一种用法,如下
{xx,yy,zz,...}
这种大括号的组合,常用在字串的组合上,来看个例子
mkdir {userA,userB,userC}-{home,bin,data}
我们得到 userA-home, userA-bin, userA-data, userB-home, userB-bin,userB-data, userC-home, userC-bin,userC-data,这几个目录。这组符号在适用性上相当广泛。能加以善用的话,回报是精简与效率。像下面的例子
chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}
如果不是因为支援这种用法,我们得写几行重复几次呀!


[   ] 中括号
常出现在流程控制中,扮演括住判断式的作用。if [ "$?" != 0 ]thenecho "Executes error"exit1fi
这个符号在正则表达式中担任类似 "范围" 或 "集合" 的角色
rm -r 200[1234]
上例,代表删除 2001, 2002, 2003, 2004 等目录的意思。


[[     ]]
这组符号与先前的 [] 符号,基本上作用相同,但她允许在其中直接使用 || 与&& 逻辑等符号。
#!/bin/bashread akif [[ $ak > 5 || $ak< 9 ]]thenecho $akfi


|| 逻辑符号
这个会时常看到,代表 or 逻辑的符号。


&& 逻辑符号
这个也会常看到,代表 and 逻辑的符号。


& 后台工作
单一个& 符号,且放在完整指令列的最后端,即表示将该指令列放入后台中工作。
tar cvfz data.tar.gz data > /dev/null&

\<...\> 单字边界
这组符号在规则表达式中,被定义为"边界"的意思。譬如,当我们想找寻 the 这个单字时,如果我们用
grep the FileA
你将会发现,像 there 这类的单字,也会被当成是匹配的单字。因为 the 正巧是 there的一部份。如果我们要必免这种情况,就得加上 "边界" 的符号
grep '\' FileA


+ 加号 (plus)
在运算式中,她用来表示 "加法"。
expr 1 + 2 + 3
此外在规则表达式中,用来表示"很多个"的前面字元的意思。
# grep '10\+9' fileB109100910000910000931010009#这个符号在使用时,前面必须加上escape 字元。


- 减号 (dash)
在运算式中,她用来表示 "减法"。
expr 10 - 2
此外也是系统指令的选项符号。
ls -expr 10 - 2
在 GNU 指令中,如果单独使用 - 符号,不加任何该加的文件名称时,代表"标准输入"的意思。这是 GNU指令的共通选项。譬如下例
tar xpvf -
这里的 - 符号,既代表从标准输入读取资料。
不过,在 cd 指令中则比较特别
cd -
这代表变更工作目录到"上一次"工作目录。


% 除法 (Modulo)
在运算式中,用来表示 "除法"。
expr 10 % 2
此外,也被运用在关于变量的规则表达式当中的下列
${parameter%word}${parameter%%word}
一个 % 表示最短的 word 匹配,两个表示最长的 word 匹配。


= 等号 (Equals)
常在设定变数时看到的符号。
vara=123echo " vara = $vara"
或者像是 PATH 的设定,甚至应用在运算或判断式等此类用途上。


== 等号 (Equals)
常在条件判断式中看到,代表 "等于" 的意思。
if [ $vara == $varb ]
...下略

!= 不等于
常在条件判断式中看到,代表 "不等于" 的意思。
if [ $vara != $varb ]
...下略


^
这个符号在规则表达式中,代表行的 "开头" 位置,在[]中也与"!"(叹号)一样表示“非”


输出/输入重导向
>      >>   <   <<   :>   &>   2&>   2<>>&   >&2 

文件描述符(File Descriptor),用一个数字(通常为0-9)来表示一个文件。
常用的文件描述符如下:
文件描述符          名称         常用缩写     默认值
     0               标准输入      stdin            键盘
     1               标准输出      stdout         屏幕
     2            标准错误输出   stderr          屏幕
我们在简单地用<或>时,相当于使用 0< 或 1>(下面会详细介绍)。
* cmd > file
把cmd命令的输出重定向到文件file中。如果file已经存在,则清空原有文件,使用bash的noclobber选项可以防止复盖原有文件。
* cmd >> file
把cmd命令的输出重定向到文件file中,如果file已经存在,则把信息加在原有文件後面。
* cmd < file
使cmd命令从file读入
* cmd << text
从命令行读取输入,直到一个与text相同的行结束。除非使用引号把输入括起来,此模式将对输入内容进行shell变量替换。如果使用<<- ,则会忽略接下来输入行首的tab,结束行也可以是一堆tab再加上一个与text相同的内容,可以参考後面的例子。
* cmd <<< word
把word(而不是文件word)和後面的换行作为输入提供给cmd。
* cmd <> file
以读写模式把文件file重定向到输入,文件file不会被破坏。仅当应用程序利用了这一特性时,它才是有意义的。
* cmd >| file
功能同>,但即便在设置了noclobber时也会复盖file文件,注意用的是|而非一些书中说的!,目前仅在csh中仍沿用>!实现这一功能。
: > filename      把文件"filename"截断为0长度.# 如果文件不存在, 那么就创建一个0长度的文件(与'touch'的效果相同).
cmd >&n 把输出送到文件描述符n
cmd m>&n 把输出 到文件符m的信息重定向到文件描述符n
cmd >&- 关闭标准输出
cmd <&n 输入来自文件描述符n
cmd m<&n m来自文件描述各个n
cmd <&- 关闭标准输入
cmd <&n- 移动输入文件描述符n而非复制它。(需要解释)
cmd >&n- 移动输出文件描述符 n而非复制它。(需要解释)
注意: >&实际上复制了文件描述符,这使得cmd > file 2>&1与cmd 2>&1 >file的效果不一样。

MySQL 加密傳輸

以 OpenSSL 實作 MySQL 加密傳輸:
http://www.netadmin.com.tw/article_content.aspx?sn=1609080004

Linux 使用 Let’s Encrypt 實現 SSL:
https://teddysun.com/454.html

MySQL 5.7 啟用 SSL 之實作與評估: https://tw.saowen.com/a/74b5871c8e4e380b9dbec9b7698a77339a9bfea6d4fe0770982dceedb92d995f

雖然 SSL方式使得安全性提高了,但是卻相對使得 MySQL 5.7 Queries per second (QPS) 降低 23% 左右,所以:

1、對於非常敏感核心的資料,或者 QPS 本來就不高的核心資料,建議採用 SSL方式保障資料安全。

2、對於採用短連結、要求高效能的應用,或者不產生核心敏感資料的應用,當效能和可用性才是首要時,建議不要採用SSL方式。

TLS/SSL 安全性憑證 與 HTTP/2

https://www.kingman.idv.tw/internet-genaration/180-what-ssl-how-choose.html

SSL依據驗證等級分為EV、OV、DV三種等級,不同等級驗證的項目不同,通常一個SSL證書給一個網站使用,但是也有部份CA單位簽發子網域通用、甚至跨不同網域的SSL證書,可以同時給多個網站使用。

如果是OV、EV等級的SSL,需要洽詢SSL簽證單位,付費申請SSL,常見的簽證單位有Comodo、Kaspersky等… 台灣則有TWCA提供SSL簽證服務。

如果是一般的個人Blog網站,或者小型、微型企業的官方形象網站,想要避免出現不安全警告、提供使用者安全瀏覽環境,並獲得SEO加分,有幾個辦法可以取得免費的DV SSL憑證:

Free SSL憑證:

AWS Certificate Manager
如果使用AWS的雲端主機服務,可以透過AWS Certificate Manager取得免費的SSL,Amazon申請成為CA機構,讓使用AWS的客戶都可以藉此獲德免費的SSL憑證,並免去安裝、管理的麻煩。

cPanel憑證
如果網站的虛擬主機使用cPanel公司的後台管理系統,在cPanel介面內可以設定、取得cPanel發出的憑證,或者建立虛擬主機的時候就會自動安裝、擁有網域憑證,要使用cPanel憑證請洽租賃虛擬主機的公司,基本上cPanel憑證不需要特別申請、安裝,只要虛擬主機建立好之後就會自動簽發、取得憑證,只需要將網站設定好就可以直接使用https連線。

Let's Encrypt
Let's Encrypt是由Google、Facebook、Cisco、Mozilla等單位贊助成立的CA憑證機構(ISRG),主旨是希望能夠有更安全的網路瀏覽環境,因此為每一個網域提供免費的DV SSL憑證。
Let's Encrypt的SSL安裝需要透過伺服器去設定、取得憑證,並自動展期、或者更新憑證,這部份比較麻煩,且需要一些技術基礎,如果會使用一般的CRT憑證安裝方式,可以去SSL For Free網站申請並取得SSL憑證安裝資料,SSL For Free透過網頁介面協助我們從Let's Encrypt取得SSL憑證,並導出CRT、KEY、CABUNDLE等SSL憑證安裝資料。唯一麻煩的是Let's Encrypt的憑證效期比較短,需要經常重設憑證。



https://ihower.tw/blog/archives/8489

HTTP/2 是 HTTP/1.1 從 1999 年發布以來,十六年來最重要的一次升級。HTTP/2 這項技術可以讓網站瀏覽更快、更安全、SEO 加分,而且網站工程師不需要改 code 就可以全站使用。

關於 HTTP/2 的歷史,由 SPDY 這個通訊協定開始。SPDY 是 Google 狹著 Chrome 瀏覽器龐大市佔率,在 2009-2016 年所進行的大規模網路實驗,在獲得了顯著的成功之後,進一步將 SPDY 推向網路標準,終於在 2015/5 正式發布。目前包括 Chrome、Safari、Firefox、IE/Edge 瀏覽器都已經支援,在不知不覺中,HTTP/2 已經進入使用者的生活。

為了能夠順利讓瀏覽器相容現存的 HTTP 網站 (使用通訊埠 Port 80),所以 HTTP/2 選擇佈署在 HTTPS (使用通訊埠 Port 443) 上,因此在安裝 HTTP/2 的步驟中,要先擁有 TLS/SSL 安全性憑證。

使用 HTTPS 加密連線的好處有:
  • 保護瀏覽器和伺服器之間的傳輸,不會被別人修改。這不一定指惡意的駭客進行中間人攻擊,也可能只是想插入廣告。例如有些咖啡店的免費 Wifi 會在網頁上面插入廣告。但是如果是 HTTPS 網站就沒辦法了。
  • 保護了使用者的隱私安全,不會被人竊聽。特別是需要登入的網站,沒有 HTTPS 加密,非常容易就可以被人竊取帳號密碼。
  • SEO 加分。
  • 方可與新技術或重要服務整合。很多新的瀏覽器功能已經把 HTTPS 當作必要條件,例如 Geolocation 定位、ServiceWorker 等。此外,所有 iOS app 的網路連線都必須使用加密連線 HTTPS。
為了推廣 HTTPS 安全連線,由許多團體共同贊助推出 Let's Encrypt 這個服務,免費發佈 TLS/SSL 憑證。中文使用說明可以參考 https://letsencrypt.tw,或是用 Certbot 這個工具。不過因為它的使用方式,跟一般我們在憑證機構網站上購買的步驟不太一樣,需要在主機上下指令來取得憑證,所以也有人設計了一個線上工具 SSL For Free 可以在線上就完成憑證申請。

第一步取得 TLS/SSL 安全性憑證,第二步設定 Web 伺服器,如果上述的兩個步驟還是太麻煩,也可以使用 CloudFlare 這個網站加速服務(CDN),它有免費方案提供 TLS/SSL 憑證以及 HTTP/2 連線。也就是說網站伺服器也可以什麼都不用改,只需要修改 DNS 讓使用者的連線先經過 CloudFlare 伺服器即可。使用者到 CloudFlare 的這一段傳輸,就會是有加密的 HTTP/2 連線。CloudFlare 在全球各地都有節點,所以網路速度非常好。

第三步:替換 HTTP 網址為 HTTPS

需要將所有 HTTP 網址都換成 HTTPS 網址。網頁上所有連到自己網站的超連結、圖片、JavaScript 和 CSS 等等網址,都必須修改成 https:// 開頭。而所有外部系統中自己的網址,例如 Facebook 廣告、Google Analytics 和其他網站分析追蹤工具,都必須把網址改成 https:// 開頭。

第四步:最後檢查

先檢查 TLS/SSL 安全性憑證安裝正確,可以使用 SSL Server Test 這個線上工具。接著啟用 HTTP/2 ,可以安裝 HTTP/2 and SPDY Indicator。線上測試工具則可以用 HTTP/2 Test。更多工具可以參考 Tools for debugging, testing and using HTTP/2。

第五步:全面啟用

檢查沒有問題後,可以設定 Web 伺服器只允許 HTTPS 連線,所有連線到 HTTP 的情求,全部轉址 (301 Redirect) 到 HTTPS 連線,並且打開 HSTS 這個 HTTP Header 強制使用者瀏覽器只能用 HTTPS 連線。

最後的成果就是會有一個綠色的 Icon 出現在網址列。




Golang 網頁伺服器 申請 Let's Encrypt 的 HTTPS 實現證書自動部署 (一個說明清楚的簡潔作法):https://www.golangnote.com/topic/211.html

手動模式申請Let's Encrypt萬用字元證書:https://itw01.com/QCJTFEH.html

利用golang申請Let's Encrypt的HTTPS實現證書自動部署:https://itw01.com/YB75DED.html

https://blog.wu-boy.com/2017/04/1-line-letsencrypt-https-servers-in-golang/

https://github.com/golang/go/issues/14374

https://golang.org/pkg/net/http/

https://studygolang.com/articles/10380

https://github.com/golang/go/issues/21890

https://stackoverflow.com/questions/37321760/how-to-set-up-lets-encrypt-for-a-go-server-application

https://stackoverflow.com/questions/37536006/how-do-i-rewrite-redirect-from-http-to-https-in-go?noredirect=1&lq=1



Let’s Encrypt 相關備忘

Let's Encrypt 终于支持通配符证书了
https://studygolang.com/articles/12599

什么是通配符证书
在没有出现通配符证书之前,Let’s Encrypt 支持两种证书。

1)单域名证书:证书仅仅包含一个主机。

2)SAN 证书:一张证书可以包括多个主机(Let’s Encrypt 限制是 20),也就是证书可以包含下列的主机:www.example.com、www.example.cn、blog.example.com 等等。

证书包含的主机可以不是同一个注册域,不要问我注册域是什么?注册域就是向域名注册商购买的域名。

对于个人用户来说,由于主机并不是太多,所以使用 SAN 证书完全没有问题,但是对于大公司来说有一些问题:

子域名非常多,而且过一段时间可能就要使用一个新的主机。
注册域也非常多。
读者可以思考下,对于大企业来说,SAN 证书可能并不能满足需求,类似于 sina 这样的网站,所有的主机全部包含在一张证书中,而使用 Let’s Encrypt 证书是无法满足的。

Let’s Encrypt 通配符证书
通配符证书就是证书中可以包含一个通配符,比如 .example.com、.example.cn,读者很快明白,大型企业也可以使用通配符证书了,一张证书可以防止更多的主机了。

这个功能可以说非常重要,从功能上看 Let’s Encrypt 和传统 CA 机构没有什么区别了,会不会触动传统 CA 机构的利益呢?

如何申请 Let’s Encrypt 通配符证书
为了实现通配符证书,Let’s Encrypt 对 ACME 协议的实现进行了升级,只有 v2 协议才能支持通配符证书。

在了解该协议之前有几个注意点:

1)客户在申请 Let’s Encrypt 证书的时候,需要校验域名的所有权,证明操作者有权利为该域名申请证书,目前支持三种验证方式:

dns-01:给域名添加一个 DNS TXT 记录。
http-01:在域名对应的 Web 服务器下放置一个 HTTP well-known URL 资源文件。
tls-sni-01:在域名对应的 Web 服务器下放置一个 HTTPS well-known URL 资源文件。

註解:tls-sni-01 將於 February 13th, 2019 完全停用。取而代之的是 HTTP-01, DNS-01 or TLS-ALPN-01 三種。

而申请通配符证书,只能使用 dns-01 的方式




解析 Certbot(Let's encrypt) 使用方式
https://andyyou.github.io/2019/04/13/how-to-use-certbot/

Golang 配置 Let's encrypt
https://stackoverflow.com/questions/37321760/how-to-set-up-lets-encrypt-for-a-go-server-application

2019 年因為安全理由需要升級 Golang 配置  Let's encrypt 的方法
https://github.com/golang/go/issues/21890

實作解決方案 => Golang 官方網站:
https://godoc.org/golang.org/x/crypto/acme/autocert#example-Manager

對官方網站實作的中文解說 (代碼有誤) 與關於這個包的設計的英文討論:
https://colobu.com/2017/09/30/use-letsencrypt-in-go/
https://github.com/golang/go/issues/17053

其他參考資料:
https://community.letsencrypt.org/t/help-with-golang-autocert/75806
https://ericchiang.github.io/post/go-letsencrypt/
https://studygolang.com/articles/10380
https://studygolang.com/articles/16463
https://itw01.com/YB75DED.html
https://github.com/mholt/certmagic


程式語言編年史

程式語言編年史原文 下面這張圖片描繪了整個程式語言的歷史。包括各種程式語言的發明人、程式語言的特點和適用領域、被什麼網站或公司使用等 (檢視 完整高清圖 )。 之所以會有那麼多不同的程式語言是因為設計程式語言的初衷不同、對語言學習曲線的追求不同、不同程式之間的執行成本差異...