2020/08/19

初探 ansible

ansible 是一個基於 python 的工具,在 CI/CD 的世界挺受歡迎,可以做的事情很多,網路上很多 ansible 教學了,我這邊筆記一下一些比較常用的東西

deploy.yml
- hosts: localhost
  vars:
    NAME: chan

  tasks:
  - name: echo name
    command: "echo {{ NAME }}"
  
  - name: echo age from outside
    command: "echo {{ AGE }}"
    
  - name: echo name from env
    command: "echo {{ lookup('env', 'LBJ') }}"

這是一個最基礎的 ansible playbook 架構,只要把命令寫好,ansible 就會照 task name 一個一個執行,上面我的範例第一個是 echo 本地設定的 NAME,第二個 AGE 會從外部導入,第三個 LBJ 是抓取環境變數,因此要正確執行的話要這樣下

$ export LBJ=GOAT
$ ansible-playbook deploy.yml -e "AGE=40" -v

執行後可以依序看到 NAMEAGELBJ 的變數結果相繼印出,基本上架構瞭解,做的事情只是從 tasks 去變化,搭配 ansible 本身強大的 modules 可以幾乎沒有事情辦不到,也可以使用 role 來做群組管理,但如果想要簡單部署,接下來示範如何把上面的工作打散

/a.yml
- hosts: localhost
  vars:
    TARGET: a
  vars_files:
    - ./vars/var.yml

  tasks:
    - include_tasks: ./tasks/deploy.yml

    - name: echo self stuff
      command: "echo this is {{ TARGET }}"
/vars/var.yml
NAME: chan
/tasks/deploy.yml
- name: echo name
  command: "echo {{ NAME }}"

- name: echo age from outside
  command: "echo {{ AGE }}"

這樣的設定,如果要生另一個類似的流程只要複製 a.yml 改一下內容即可。

2020/01/15

jq

JSON 格式的應用現在已經隨處可見了,目前使用的程式語言都有相關支援的套件,如果要在 Linux 底下操作的話有一個非常好用的工具叫 jq,下面來展示應用範例

應用網址:https://jsonplaceholder.typicode.com/users

curl -s https://jsonplaceholder.typicode.com/users | jq .

我們會得到格式漂亮的結果

[
  {
    "id": 1,
    "name": "Leanne Graham",
    "username": "Bret",
    "email": "Sincere@april.biz",
    "address": {
      "street": "Kulas Light",
      "suite": "Apt. 556",
      "city": "Gwenborough",
      "zipcode": "92998-3874",
      "geo": {
        "lat": "-37.3159",
        "lng": "81.1496"
      }
    },
    "phone": "1-770-736-8031 x56442",
    "website": "hildegard.org",
    "company": {
      "name": "Romaguera-Crona",
      "catchPhrase": "Multi-layered client-server neural-net",
      "bs": "harness real-time e-markets"
    }
  }
]

而 jq 可以做 node 的搜尋,以上面那个例子

curl -s https://jsonplaceholder.typicode.com/users | jq .[0].name # "Leanne Graham"
curl -s https://jsonplaceholder.typicode.com/users | jq .[0].address.street # "Kulas Light"

使用 jq 的一些參數也可以達成 json encode 的功能:

test

	#!/bin/bash
 
NAME=$1
AGE=$2
 
JSON_STRING=$(jq -n \
    --arg name "$NAME" \
    --arg age "$AGE" \
    '{name: $name, age: $age}')
 
echo $JSON_STRING

./test chan 40 # { "name": "chan", "age": "40" }

jq 沒有驗證 json format 的功能,但我們可以利用一些 shell script 的特性辦到這件事

#!/bin/bash
 
function json_validator() {
    echo $1 | jq . &> /dev/null
 
    if [[ $? == 0 ]]; then
        echo "$1 is valid format"
    else
        echo "$1 is invalid format"
    fi
}
 
JSON='{"name": "chan"}'
json_validator "$JSON"
# {"name": "chan"} is valid format
 
JSON='{"name":}'
json_validator "$JSON"
# {"name":} is invalid format

jq 也可以使用自定義模組,在 ~/.jq 裡面可以將一些複雜但常用的內容先寫好

def blurry($f):
  ($f | ascii_upcase) as $ucf
  | to_entries[]
  | select((.key|ascii_upcase) | startswith($ucf))
  | .value;
 
 
def very_blurry($f):
  ($f | ascii_upcase) as $ucf
  | to_entries[]
  | select(.key | ascii_upcase | index($ucf))
  | .value;

這樣的話像搜尋 docker 的 config 的話就非常好用,像是 docker inspect test | jq '.. | blurry("config")?' | objects

搜尋語法

$ jq 'map(select(.id=="1234"))'
$ jq 'map(select(.id|index("1234")))'
$ jq 'map(select(.id|contains("1234")))'
$ jq 'map(select(.id|test("1234";"i")))'
$ jq 'map(select(.id|match("1234";"i")))'

docker inspect 出來的結果是 json format,假設我們今天要找 LogPath,但不記得他的層級的話,有個語法可以針對該 key 找出資料。

docker inspect <container_id> | jq -r '.. | .LogPath? // empty'

-r 是輸出 raw data 好複製,// empty 部分會讓沒搜到的結構不輸出,因此最終只會跑出我們要的結果。

2019/12/30

yum 套件管理

我在這篇文章寫過 yum 跟 apt 的使用差異比較,這篇來討論一下 yum 對於 repo 的管理方式,雖然很多方面 centos 都比 ubuntu 麻煩許多,但 centos 的 yum 在某些方面對於 repo 的管理更加的方便。

首先,如果你沒有這個指令,請先透過 yum 安裝,yum -y install yum-utils,一般我們會這樣操作。

$ yum repolist all # 查詢有哪些 repo
$ yum repolist enabled # 哪些 repo 有啟用
$ yum repolist disabled # 哪些 repo 沒有啟用

今天假設我的本機電腦 PHP 版本是 7.1,我有安裝 7.3 的 repo,我要更換版本到 7.3 的話指令如下:

$ sudo yum-config-manager --disable remi-php71
$ sudo yum-config-manager --enable remi-php73
$ sudu yum install php
$ php -v
PHP 7.3.13 (cli) (built: Dec 17 2019 10:29:15) ( NTS )

打完收工,至於 repo 怎麼安裝只要打上要裝的 package 加上 yum repo 等關鍵字幾乎都找的到。

如果你不想透過 config 設定,想在 runtime 的時候指定 repo,大概流程如下:

$ sudo yum repolist all | grep php

remi-php54                          Remi's PHP 5.4 RPM repositor disabled
remi-php55                          Remi's PHP 5.5 RPM repositor disabled
remi-php55-debuginfo/x86_64         Remi's PHP 5.5 RPM repositor disabled
remi-php56                          Remi's PHP 5.6 RPM repositor disabled
remi-php56-debuginfo/x86_64         Remi's PHP 5.6 RPM repositor disabled
remi-php70                          Remi's PHP 7.0 RPM repositor disabled
remi-php70-debuginfo/x86_64         Remi's PHP 7.0 RPM repositor disabled
remi-php70-test                     Remi's PHP 7.0 test RPM repo disabled
remi-php70-test-debuginfo/x86_64    Remi's PHP 7.0 test RPM repo disabled
remi-php71                          Remi's PHP 7.1 RPM repositor disabled
remi-php71-debuginfo/x86_64         Remi's PHP 7.1 RPM repositor disabled
remi-php71-test                     Remi's PHP 7.1 test RPM repo disabled
remi-php71-test-debuginfo/x86_64    Remi's PHP 7.1 test RPM repo disabled
remi-php72                          Remi's PHP 7.2 RPM repositor disabled
remi-php72-debuginfo/x86_64         Remi's PHP 7.2 RPM repositor disabled
remi-php72-test                     Remi's PHP 7.2 test RPM repo disabled
remi-php72-test-debuginfo/x86_64    Remi's PHP 7.2 test RPM repo disabled
remi-php73                          Remi's PHP 7.3 RPM repositor disabled
remi-php73-debuginfo/x86_64         Remi's PHP 7.3 RPM repositor disabled
remi-php73-test                     Remi's PHP 7.3 test RPM repo disabled
remi-php73-test-debuginfo/x86_64    Remi's PHP 7.3 test RPM repo disabled
remi-php74                          Remi's PHP 7.4 RPM repositor disabled
remi-php74-debuginfo/x86_64         Remi's PHP 7.4 RPM repositor disabled
remi-php74-test                     Remi's PHP 7.4 test RPM repo disabled
remi-php74-test-debuginfo/x86_64    Remi's PHP 7.4 test RPM repo disabled
remi-php80                          Remi's PHP 8.0 RPM repositor disabled
remi-php80-debuginfo/x86_64         Remi's PHP 8.0 RPM repositor disabled
remi-php80-test                     Remi's PHP 8.0 test RPM repo disabled
remi-php80-test-debuginfo/x86_64    Remi's PHP 8.0 test RPM repo disabled

# 透過上方找到了你想要裝的版本,獨立 enable repo 他
$ sudo yum install --enablerepo=remi-php74 php

2019/12/20

merge object

jQuery 有一個 $.extend 功能我覺得相當好用,假設你有兩個 object,{'name': 'chan', 'sport': 'basketball'},新的屬性是 {'sort': 'baseball'}, 透過 $.extend(object1, object2) 可以得到 {'name': 'chan', 'sport': 'baseball'},今天要在三個語言實現這個功能,但我要另外加一個內容是,如果新的內容是空字串就不覆蓋。

PHP
<?php  
  
$data = [  
    'name' => 'chan',  
    'sport' => 'basketball'  
];  
$newData = [  
    'name' => '',  
    'sport' => 'baseball'  
];  
$mergeObject = function($object1, $object2) {  
    return json_encode(  
        array_merge(  
            $object1,  
            array_filter(  
                $object2,  
                function($item) {  
                    return $item != '';  
                } 
            )  
        )  
    );  
}; 
  
echo $mergeObject($data, $newData); // {"name":"chan","sport":"baseball"}  
python
# coding=utf-8  
  
import json  
  
data = {  
    'name': 'chan',  
    'sport': 'basketball'  
}  
new_data = {  
    'name': '',  
    'sport': 'baseball'  
}  
  
  
def merge_object(object1, object2):  
    x = object1.copy()  
    n = {}
  
    for key, value in object2.items():  
        if value != '':  
            n[key] = value  
  
    x.update(n)  
  
    return json.dumps(x)  
  
  
print(merge_object(data, new_data)) # {"sport": "baseball", "name": "chan"}
node.js
let data = {  
    'name': 'chan',  
    'sport': 'basketball'  
};  
let newData = {  
    'name': '',  
    'sport': 'baseball'  
};  
let objectFilter = (object1, object2) => {  
    let n = {};  
  
    for (let i in object2) {  
        let value = object2[i];  
  
        if (value !== '') {  
            n[i] = value;  
        }  
    }  
  
    return JSON.stringify(Object.assign(object1, n));  
};  
  
console.log(objectFilter(data, newData)); // {"name":"chan","sport":"baseball"}

2019/07/23

Apache Docker 權限問題

最近在練習使用 docker 建立產品環境,遇到一個權限問題,container 的內容是隔離的,但我們網站有可能會修修改改,如果每次改好才 cp 進去的話很麻煩,所以我採用的方式是將 apache container 內的 /var/www/ 目錄掛出來,直接在本機編輯檔案,如果是靜態網站的話都還好,如果需要用到寫入權限的時候會發生問題。

本機檔案的權限是 root:root,但 container 內的 apache 的權限是 www-data:www-data,所以透過 apache 執行檔案遇到 root:root 時 755 是沒有作用的,開 777 又不妥,目前綜合網路的解法就是在本機建立一個帳號,確定他的 uid,然後將 container 內的 www-data 帳號 uid 改相同,就可以解決這件事,步驟如下

$ useradd -u 3000 docker -g docker
$ chown docker -R /var/www/

Dockerfile

FROM php-apache

RUN usermod -u 3000 www-data

這樣的話外部的檔案權限就是 docker:root,而 container 內會是 www-data:root,後面 root 可以忽略,寫入權限就完成了。

2019/07/10

Docker Compose Note

Docker Compose Document

version: '3'

services:
    redis:
      image: redis
      container_name: redis
      networks:
        default:
          ipv4_address: '172.18.0.12'
    nginx:
      image: nginx
      container_name: ngx
      volumes:
        - default:/data/
      networks:
        default:
          ipv4_address: '172.18.0.11'
      ports:
        - '8080:80'
      depends_on:
        - redis

networks:
  default:
    external:
      name: chan-network

volumes:
  default:
    external:
      name: chan-volume

2019/02/11

2019 NBA Tour Day 2

2019 NBA Tour Day 2

Universal Studios Hollywood -> in-n-out burger

Universal Studios Hollywood

第二天的行程排去環球影城玩,難得去一次的朋友記得買快速通關,我幾乎是全玩了,只要有快速通關你就不用看什麼攻略,只要照順序一路玩一圈就好,我幾乎是沒有排到隊,不是因為沒人喔,一般通關照樣大排長龍,但我是淡季去的所以只要四千出頭,旺季的話一張快速通關好像要近八千,我是去雄獅買的,剛好他們有年前優惠方案,所以挺划算的。

有這張真的走路有風

enter image description here
enter image description here

來環球一定要拍的球

enter image description here

Shrek
Harry Porter

Harry Porter 基本上就是商店街加兩個刺激的遊樂設施,街道充滿魔法的氣氛,連我不是波特迷都被感染,而且很多人都穿魔法袍,入戲相當深啊。

這邊有一個插曲,Harry Porter 那兩個刺激的設施我都沒玩到,在入口的時候他會有椅子讓你試坐,我太大隻了塞不進去,所以在外面乾等團友,不過非常多老美都不行,而且不是胖子,稍微有肉的都不行,美國健身的巨巨很多,這點讓我匪夷所思,難道英國也都是瘦子嗎,不過我猜是不能玩得人太多抱怨的人也很多,所以他有送一張可以選擇一個設施的快速通關卷作為補償。

可愛的動物表演
特效表演

超值得推薦的 show,非常精彩。

Universal Studio Tour

絕對要去的項目,有些時段是中文解說的,可以瞭解一下再去參加。

Transformer

超仿真的模仿,密卡登基本上就是嘴爆每個要跟他合照的人,我是當天唯一惹毛他的人。

in-n-out Burger

enter image description here

你去 LA 問十個大概有十個人跟你說要去吃 in-n-out,由於我有看劉沛 Piere 的影片所以我點出一番風味,連美國當地的人都問我這是怎麼點的,只要點一號餐 + animal style + grilled onion 即可,美國吃東西都很貴,隨便一家店都七鎂起跳未稅,in-n-out 算是不貴又吃的飽了,味道的話我會這樣形容,就是你用麥當勞的金額,預期吃到麥當勞的品質,但他卻是 Dan Ryan’s 那種貴森森的美式餐廳的漢堡水準,所以會非常驚艷。