2020-05-18

無廢話 crontab 設定


[排程]
* 檔案位置
nano /etc/crontab

* 內容格式
# ┌───────────── 分鐘   (0 - 59)
# │ ┌─────────── 小時   (0 - 23)
# │ │ ┌───────── 日     (1 - 31)
# │ │ │ ┌─────── 月     (1 - 12)
# │ │ │ │ ┌───── 星期幾 (0 - 7,0 是週日,6 是週六,7 也是週日)
# │ │ │ │ │
# * * * * *
# 台灣時間半夜3點15分 (系統為格林威治時間)
15 19 * * *  root  /bin/mysqldump -umyname -p密碼 mytest_db | gzip > /aws/share/mysql/mytest_db_auto_bak_`date '+\%Y\%m\%d'`.sql.gz




goofsy 的設定與自動/手動掛載

安裝

$ go get github.com/kahing/goofys
$ go install github.com/kahing/goofys


掛載 AWS S3 bucket 的 package

[goofsy 設定]
在 [HOME]/.aws/ 下有兩個檔案要設,格式如下 (參考 https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html)
1. ~/.aws/credentials
[default]
aws_access_key_id=AKxxxxxxx12345QCQCEE 
aws_secret_access_key=y8lkHqIxxxxxxxzq54dd
2. ~/.aws/config
[default]
region=us-west-2
output=json

3. 手動 mount 指令
$ $GOPATH/bin/goofys <bucket> <mountpoint>
例如
$ $GOPATH/bin/goofys my-s3-bucket /aws/s3

4. 手動 umount 指令
指令記得離開該目錄,然後 umount 該目錄
$ umount /aws/s3

5. copy goofys 至系統目錄(path for all users)以供執行
$ cp ~/go/bin/goofys /usr/bin

6. 掛入 fstab
  * 安裝 fuse (Filesystem in Userspace) 
  $ yum install fuse
  * 位址 /etc/fstab
  * 格式
    goofys#bucket   /mnt/mountpoint        fuse     _netdev,allow_other,--file-mode=0666,--dir-mode=0777    0       0
  * 實例
    goofys#aws-share   /aws/share        fuse     _netdev,allow_other,--file-mode=0666,--dir-mode=0777    0       0
  * 掛載
  $ mount -a

其它注意事項,可參考 https://github.com/kahing/goofys/issues/433#issuecomment-512903339

go 安裝及資訊


[go 安裝]
* 下載位置
$ wget https://dl.google.com/go/go1.14.3.linux-amd64.tar.gz
* 解壓至 /user/local
tar -C /usr/local -xzf go1.14.3.linux-amd64.tar.gz
* 將 go 註冊於系統路徑
export PATH=$PATH:/usr/local/go/bin
* 測試

檔案 hello.go
package main

import "fmt"

func main() {
   fmt.Println("Hello, World!")
}

執行
$ go run hello.go
Hello, World!



[資訊]
* 安裝位置
/usr/local/go/
* bin
/usr/local/go/bin/go
* go env
GOPATH="/root/go"
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"

2020-04-28

regular expression 的 Lookahead 與 Lookbehind

[regular expression]
這裡不教導簡單的 regular expression, 首先你必需瞭解一些基本的 RE。例如 g 是指全域尋找,[56]是指 5 或 6,[2-8]是指 2 到 8。
基本的 RE 很簡單,到處都有資料,要瞭解沒有任何困難。

【開始】

所謂 regular expression 的 expression 是指表達式,也就是說尋找「符合整個表達式的規則」的資料的意思。
對程式設計師來說落落長的「說明」是沒太大用處的,程式碼才能表達一切。但是上面這句話卻是例外,不領會這句話的意義就代表不懂或一知半解 regular expression 的意思。

0. 基礎說明

在這裡我們將 RE 的格式 (?=c)m 中,c 我們稱其為「條件表達式」或「條件式」,而 m 稱之為「主表達式」
各種格式例如以下:
(?=c)m、m(?=c)、(?<=c)m、m(?<=c)

Lookahead符合條件時從前面開始抓資料。當條件式在主表達式「前面」時則取值判斷時包含該條件式,在後面時則看取多少「長度」。
Lookbehind符合條件時從後面開始抓資料。 當條件式在主表達式「後面」時則取值判斷時包含該條件式,在後面時則看取多少「長度」。
positive: 要符合條件式,「必需」符合條件式
negative: 要不符合條件式, 「不可」符合條件式(限制不能同條件式所述)
front: 條件式在主表達式「前面」的這種 expression
behind: 條件式在主表達式「後面」的這種 expression

RE 條件比對順序:RE 條件比對順序為由左至右比對,所以前後順序很重要

1. lookahead 及 lookbehind

   很多人跟你說 lookahead 就是往前看,所以格式 m(?=c) 就是找 m 後面有 c 的資料。
   誰跟你說的?
   包含外國人都跟你說 m followed by c, 其實這是大大的誤解了。
   難道我不能這樣找 (?=c)m ,意指找 c 在 m 前的「符合這個表達式規則」的資料? 這時後難道要叫「往後看」?lookbehind?
   很顯然的並不是這樣的,因為 lookbehind 在 RE 裡是另一個意思。
   RE 最重要的是「表達式順序」,
   lookahead 意指若條件式(c)在前面時,則取值判斷時要包含 c 值,但條件式若在後面時取值判斷時則不包含 c值。即符合條件時從前面開始抓資料。相反的,
   lookbehind 意指若條件式(c)在前面時,則取值判斷時不包含 c 值,但條件式若在後面時取值判斷時則要包含 c值。即符合條件時從後面開始抓資料。

2. 用例子證明一切

所以到這裡我們總共有 lookahead/lookbehind, positive/negative, condition position front/behind 共 2 x 2 x 2 = 8 種狀況,
再加上我們再用長度 1 及 2 讓觀念更清楚,於是共有 8 x 2 = 16 種狀況
# Lookahead
## positive Lookahead (positive ?=)
### positive Lookahead, 1 char, condition in front
"01234567890".match(/(?=[5])[2-8]/g)
結果: ["5"]
分析: 因為 lookahead 在 front 時取值判斷要包含其值,又我們只要1個字元,故直接只有 5 符合其值,毫無懸念。
### positive behind, 1 char, condition in behind
"01234567890".match(/[2-8](?=[5])/g)
結果: ["4"]
分析: 因為 lookahead 在 behind 時取值判斷"不"包含其值,又我們只要1個字元,因 4 的下1位5符合,取值不取5,故答案為 4
### positive Lookahead, 2 chars, condition in front
"01234567890".match(/(?=[5])[2-8]{2}/g)
結果: ["56"]
分析: 因為 lookahead 在 front 時取值判斷要包含其值,取2個字元,故直接只有 [5]6 符合其值
### positive behind, 2 chars, condition in behind
"01234567890".match(/[2-8]{2}(?=[5])/g)
結果: ["34"]
分析: 因為 lookahead 在 behind 時取值判斷"不"包含其值,取2個字元,故答案為 34[5]
## negative lookahead (negative ?!)
### negative lookahead, 2 chars, condition in front
"01234567890".match(/(?![6])[2-8]{2}/g)
結果: ["23", "45", "78"]
### negative lookahead, 2 chars, condition in behind
"01234567890".match(/[2-8]{2}(?![6])/g)
結果: ["23", "56", "78"]
## negative 1
### negative lookahead, 1 char, condition in front
"01234567890".match(/(?![5])[2-8]/g)
結果: ["2", "3", "4", "6", "7", "8"]
### negative lookahead, 1 chars, condition in behind
"01234567890".match(/[2-8](?![5])/g)
結果: ["2", "3", "5", "6", "7", "8"]


# Lookbehind
## positive
### positive 2 front
"01234567890".match(/(?<=[5])[2-8]{2}/g)
結果: ["67"]
分析: 因為 Lookbehind 在 front 時取值判斷"不"包含其值,取2個字元,5為前置不取,[5]67,故答案為 67
### positive 2 behind
"01234567890".match(/[2-8]{2}(?<=[5])/g)
結果: ["45"]
分析: 因為 Lookbehind 在 behind 時取值判斷要包含其值,取2個字元,故答案為 4[5] (含5)
### positive 1 front
"01234567890".match(/(?<=[5])[2-8]/g)
結果: ["6"]
### positive 1 behind
"01234567890".match(/[2-8](?<=[5])/g)
結果: ["5"]
## negative
### negative 2 front
"01234567890".match(/(?<![5])[2-8]{2}/g)
結果: ["23", "45", "78"]
分析: 因為 Lookbehind 在 front 時取值判斷不包含其值,這裡取2個字元,故第1組23,第2組45,第3組67時因前面為5,故不符合,跳至下一字元78
### negative 2 behind
"01234567890".match(/[2-8]{2}(?<![5])/g)
結果: ["23", "56", "78"]
分析: 因為 Lookbehind 在 behind 時取值判斷要包含其值,這裡取2個字元,故第1組23,當第2組45中遇到 5不符規則,跳至下一位元,第2組變56,第3組78 
### negative 1 front
"01234567890".match(/(?<![5])[2-8]/g)
結果: ["2", "3", "4", "5", "7", "8"]
分析: 因為 Lookbehind 在 front 時取值判斷不包含其值,這裡僅取1個字元,故「前值為5的6不合規則」
### negative 1 behind
"01234567890".match(/[2-8](?<![5])/g)
結果: ["2", "3", "4", "6", "7", "8"]
分析: 因為 Lookbehind 在 behind 時取值判斷要包含其值,這裡取1個字元,故當 「非5」 時即為答案




2018-10-01

MySQL server has gone away 解法,無廢話


MySQL gone away 就是 MySQL 斷線了,最大的原因在於操作時間大於設定。記住,是「操作」時才應該有這種事發生,不應該出現在你的 "run time" application。例你需要批次匯入大量動態更新資料。

你可以在 mysql (or phpmyadmin) 執行以下命令查看你的 timeout 設定
show global variables like '%timeout%'





Variable_nameValue
connect_timeout60
delayed_insert_timeout300
innodb_flush_log_at_timeout1
innodb_lock_wait_timeout50
innodb_rollback_on_timeoutOFF
interactive_timeout60
lock_wait_timeout31536000
net_read_timeout30
net_write_timeout60
rpl_stop_slave_timeout31536000
slave_net_timeout3600
wait_timeout60

這裡我們發現 interactive_timeout, wait_timeout 都只有 60秒,也就是說60秒內都沒動作將會導致連線中斷

解決方法有
1. 直接修改my.cnf文件
2. my sql 在建立連線時傳入參數修改 interactive_timeout, wait_timeout
3. 只在某個連線,某個動作時直接改變 interactive_timeout, wait_timeout

第1種方式將會導致整個 mysql 都會延長連線時間,你可能有很多 database,有不同應用。這種設定在用戶端一多時(例如website)就會導致無法建立新連線的問題

第2種方式則是在某個應用啟動連接 mysql 時修改 timeout, 並第1種會少很多無法連線問題

第3種方式則是只在執行你知道的某個已知需要較長久功能時才修改interactive_timeout, wait_timeout。這個方式是最有效率的,不會影響其它功能。因為你修改的 timeout 只在該 child process 有效,每次重新 fork 一個新 process 都是重載的預設參數。而且你一定知道哪些功能會需要較長時間連線,若你不知道,那表示問題大了,且問題在你身上。

修改 timeout 指令如下:
set interactive_timeout=900
set wait_timeout=900

php 例子:

$sql = "set interactive_timeout=900; set wait_timeout=900";
$GLOBALS['db']->query($sql);
....
需要等長時間的程序




2018-09-14

Angular package.json 版本中 tilde(~) 跟 caret(^) 的意思

tilde(~) and caret(^) in package.json

我們在 Angular 的 package.json 會看到以下結構,結構中版本號碼前有 ^ 或 ~ 的符號,這兩個符號是什麼意思呢?


"dependencies": {
    "@angular/animations": "^5.2.11",
    "@angular/common": "~5.0.0",
    "@angular/compiler": "5.0.0",
    "@angular/compiler-cli": "5.0.0",
    "@angular/core": "5.0.0",
    "@angular/forms": "5.0.0",
    "@angular/http": "5.0.0",
    "@angular/platform-browser": "5.0.0",


不廢話,我簡單歸納其意思如下:

首先,我們在此定義版本的欄位格式: 1.2.3 三欄分別為 (major, minor, patch)
~:表示更新 patch 版本到最新,但止於 minor 版本,如 ~1.2.3 表示 1.2.x 等版本都會update,但 1.3.0 則不會更新

^:表示更新 minor 版本到最新,但 major 版本會忽略,如 ^1.2.3 表示 1.x.x  等版本都會update,包含 1.3.0, 終止於最大版本 2.0.0 ,不會更新。

【參考資料】
https://docs.npmjs.com/misc/semver#caret-ranges-123-025-004
https://stackoverflow.com/questions/22343224/whats-the-difference-between-tilde-and-caret-in-package-json...

2018-04-06

安裝 opencc 1.0.4 到 MAC 跟 CENTOS 平台下


[opencc 1.0.4 安裝]
1. 下載 opencc 1.0.4 => https://github.com/BYVoid/OpenCC
2. 解壓到你的程式下某目錄(自行依喜好安排)
3. 再來就是進到 opencc 的目錄執行
# cd opencc1.0.4
# mkdir build
# cd build
  產生 makefile, 以下分兩個平台, MAC 不能打開  GETTEXT
  CENTOS 執行以下命令
# cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release LE_GETTEXT:BOOL=ON  ..
  MAC 執行以下命令
# cmake -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_BUILD_TYPE=Release -D ENABLE_GETTEXT:BOOL=OFF  -DCMAKE_OSX_ARCHITECTURES=x86_64  .. 
# make
# sudo make install

4. 最後,用 pip 安裝 OpenCC 即可
$ pip install OpenCC==0.2


5. 若遇到 libopencc.so.2: cannot open shared object file: No such file or directory
那是因為build 出來的 library 是 32bit, centos 64bit 是放在 /usr/lib64/ 故建個捷徑連到 /usr/lib 即可

#sudo ln -s /usr/lib/libopencc.so.2 /usr/lib64/libopencc.so.2


[測試]
$ opencc --version

Open Chinese Convert (OpenCC) Command Line Tool
Version: 1.0.4



[python 測試]
$ python
Python 3.4.3 (default, Jul 13 2015, 03:19:09)
[GCC 4.8.3 20140911 (Red Hat 4.8.3-9)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import opencc
>>> opencc.convert("开放中文转换", config='s2tw')
'開放中文轉換'
>>>




[內建可轉換檔有]
Conversions include 轉換包含:
'hk2s': Traditional Chinese (Hong Kong standard) to Simplified Chinese
's2hk': Simplified Chinese to Traditional Chinese (Hong Kong standard)
's2t': Simplified Chinese to Traditional Chinese
's2tw': Simplified Chinese to Traditional Chinese (Taiwan standard)
's2twp': Simplified Chinese to Traditional Chinese (Taiwan standard, with phrases)
't2hk': Traditional Chinese to Traditional Chinese (Hong Kong standard)
't2s': Traditional Chinese to Simplified Chinese
't2tw': Traditional Chinese to Traditional Chinese (Taiwan standard)
'tw2s': Traditional Chinese (Taiwan standard) to Simplified Chinese
'tw2sp': Traditional Chinese (Taiwan standard) to Simplified Chinese (with phrases)