Google 的新程式語言Carbon

Google 最近發表了新的程式語言 Carbon, 其主要的目的是用來作為C++的後繼語言;從目前的資訊可以知道,它的角色比較像是 Kotlin 之於 Java, 除了強調現代化的編程方式以外,且能夠繼續支援舊有的C++程式庫(這點其實蠻吸引人的XD)。

通常看到C++程式語言的繼任者,現在大概都會想到Rust吧,但其實定位不太一樣…

Rust 在設計之初主要是作為更安全的系統語言為出發點而設計的,所以它並不相容於既有的C++程式,所以對於已經有許多C++ 程式的組織而言,使用Rust 就相當於要改寫許多內部的程式…

Carbon在這邊則採用類似於Kotlin的模式,新的語法但又可與公司現有的C++程式一起編譯的特性,想必正式GA之後應該可以有不錯的發展…

Reference:

Mac上遇到的warning: setlocale: LC_CTYPE: cannot change locale (UTF-8)

這個問題之前遇到過幾次,每次都是透過iTerm2連接到remote linux server時跳出警告… 雖然問題不大,但昨天連到自家的機器又遇到一樣的問題時,還是決定來找一下解決方式!

這個警告主要影響的是使用者在iTerm2上的畫面顯示,只要用到UTF-8的地方會一直出現警告 !

解決方式

網路上找了一下相關的解決方式以後,大概可以分為兩種方式處理:

Server 端的解決方式

將下列的設定加入到 /etc/environment 裡面

LANG=en_US.utf-8
LC_ALL=en_US.utf-8

Client 端的解決方式(Mac)

將下列兩行環境變數加入到使用者的 ~/.bashrc~/.zshrc(基本上看client端這邊的shell環境)

export LC_ALL=en_US.UTF-8
export LANG=US.UTF-8

我目前採用Client端的解決方式,再重新做 source ~/.zshrc以後,目前就沒在遇到問題了!

Reference:

透過SQLite3 來用一指令實現SQL讀取CSV檔

看到DK的文章上提到這個功能覺得也太有趣了, 沒想到會有這麼簡單方式來從CSV檔中讀取想要的內容…

使用方式

將sqlite3 透過memory的方式讀取了以後, 就可以透過SQL來找到其中想要的內容了…

sqlite3 :memory: -cmd '.mode csv' -cmd '.import mds_content_status.csv temp' -cmd '.mode column' 'SELECT * FROM temp'

為了讓使用方式更方便, 還可以在.bashrc.zshrc中把上面的cli 指令包裝成 shell function 如下:

function query_csv() {
    local CSV_FILE=$1
    local TABLE=$2
    local QUERY=$3

    sqlite3 :memory: -cmd '.headers on' -cmd '.mode csv' -cmd ".import ${CSV_FILE} ${TABLE}" -cmd '.mode column' "${QUERY}"
}

然後我們就可以用下面的方式去query了…

query_csv users.csv user_table 'SELECT id, name FROM user_table where id=17807'

reference

Linux中網路界面速度的調整方式

最近剛好工作上有需要, 需要針對一些網路情況不佳的裝置去做一些實驗; 但問題來了, 要在實務上去真的找到這種裝置其實蠻難的, 這時候Linux 提供了一些很好模擬的方式來對特定的網路界面模擬上述情境…

限制網路界面的速率

再做了一些快速的瀏覽以後, 看起來在Linux中主要是透過 tc 這個指令來做 traffic control, 不過社群中有人提供了一個更簡便的方式 wondershaper, 如果OS是ubuntu 的話可以用 sudo apt-get install wondershaper 就可以安裝了.

一些常見的指令範例有:

設定eth1 的download=256kbps, upload=128kbps

sudo wondershaper eth1 256 128

清除 eth1的流量設定

sudo wondershaper clear eth1

設定網路界面的packet lost 機率

這個情境下, 我們可以模擬網路掉包在不同嚴重程度的情況下的情境; 主要是透過 iptables 來達成, 可以參考以下範例:

設定來源ip為 123.123.123.123 且封包到這台電腦的 local port為 3000時, 其packet drop的機率為 5%

sudo iptables -I INPUT -s 123.123.123.123 -p tcp --dport 3000 -m statistic --mode random --probability 0.05 -j ACCEPT

reference:

調低EBS 的磁碟大小

前言

最近收到AWS的個人帳單以後, 突然發現我帳單上的金額與我的想像有些落差, 也因為這樣子, 開始來對一下是哪些項目在吃錢…

大概對了一下, 發現主要的花費在EC2 instance 與 EBS 兩個項目上面, EC2 instance 這邊的花費就是題外話了, 但EBS這邊就慢讓我意外的… 細看了以後才發現當初不知道為什麼把使用的EBS 成 使用30GB, 但我實際上的使用也才6GB左右…
(雖然這也不是什麼大錢, 但每個月給它這樣扣也是覺得還不如把錢省下來去訂閱其他有用服務….)

第一次實驗

原本想說把root volume EBS 調低應該不是件難事, 結果沒想到AWS預設上是不支援這件是的, 它可以往上調高, 但不支援調低…

在網路上找了不少相關的教學文, 主要的作法都是, 大概都是…

  • 先建立一個較小的EBS volume
  • 再把這個新的 EBS volume 掛到我們的EC2上面以後, 做好格式化以及 rsync 的資料拷貝
  • 最後設定好 /boot 以後, 就可以把新的EBS volume來取代原有的 EBS root volume.
    (題外話, 要把EBS volume 設定為 EC2 上面的 /dev/sda1 才會成為那台EC2上的root volume)

第一次實驗結果

經由上述步驟的教學文實際嘗試以後, 都會卡再做出來的EBS volume是無法當成是原本這一台EC2的root volume, 它會直接讓那台EC2開不起來. (機器顯示 running, 但是ssh 連不到…)

上述的測試其實我參考了不少文章, 但最後卡的點都是一樣的, 做出來的 EBS volume是不能用的… (我這邊使用的EC2 t4g family, 不太確定跟ARM 版本的 grub-install 有關??? 也許今天使用的是x86的機器就可以? 之後有機會再來試試)

另一種Workaround的方式

因為上面測試也花了不少時間, 所以最後就自己做了一些流程上的調整如下:

  • 建立一台新的EC2, 並設定root volume為我想要的大小 (6GB), 並且OS的版本也是用與就機器一樣的 ubuntu 20.04
  • 接著, 將舊機器的EBS 掛到新的EC2機器上.
  • 透過 rsync 將舊的EC2 資料都複製到新的EC2上. (基本上除了 /boot, /tmp, /mnt, /dev以外, 都要sync 到新的EC2的對應資料夾)
  • 如果先前有設定route53, elastic IP 等等相關的設定, 最後都指定到這台新的EC2機器上.

最後靠這個方式成功把 EBS size降下來了, 不過靠這個方式比較像是duplicate出一台新的EC2, 而不是clone出一模一樣的機器…

Reference:

在GNUMakefile 中使用if-else的方式

主要是我想要針對某些build target做些條件判斷,只有當某些條件成立時,才可以繼續build target中的其他步驟,不然的話就中斷。

最基本的使用範例如下︰

build.target:
    if [ ! -d /home/ubuntu ]; then echo "ERROR: folder not exist"; exit 1; fi

# OR
build.target2:
    if [ ! -d /home/ubuntu ]; then \
        echo "ERROR: folder not exist"; \
        exit 1; \
    fi

Reference:

ansible 加載relative path role的方式

對ansible還不是很熟, 大概知道可以把ansible scripts寫得很模組化, 但就遇到一個問題是如何加載我們剛寫的task role呢?

在ansible 中, 預設的 role 的讀取路徑會是如下:

  • ${playbook_dir}/roles/...
  • ${HOME}/.ansible/roles/...
  • /usr/share/ansible/roles/...
  • /etc/ansible/roles/...
  • ${playbook_dir}/...

如果在上面的路徑下, 都找不到對應的role時, ansible就會無法執行對應的playbook…

但除了上面的role搜尋路徑以外, 其實我們可以在paybook中直接透過相對路徑去指定role的對應位址.

舉例來說:

我的playbook 資料夾結構為

my-playbook/
    roles/
        my-role
    playbook1
        /main.yml

main.yml 的內容中, 可以透過相對路徑來指定我另外撰寫的 my-role

- hosts: all
  vars:
    foo: "bar"
  roles:
    - role: "../roles/my-role"

Reference:

Linux的cpu/power自動省電工具

剛好在Hacker News 上看到,記錄一下,也許以後會用得到。

有人分享了一個開源的cpu/電源自動化管理工具(auto-cpufreg),讓Linux的筆電的cpu可以電池模式下降件cpu的負載,而在插電模式下,又可以自動的提高cpu的運算能力。

如果有人有Linux的筆電,剛好也可以試試。

Reference:

常用指令 – awk

awk 是個很強大的工具, 透過其特製的語法可以在很多變化上處理pipe或檔案內容;之前一段時間不碰後,又忘了之前使用過awk語法,趁最近又開始接觸來重新複習這個工具。

測試用檔案 – log.txt

假設一個log檔的檔名為log.txt,且內容如下:

2 this is a test 
3 Are you like awk 
This's a test
10 There are orange,apple,mongo

基本搭配print做格式化輸出

NOTE:

  • 值得注意的是,$0awk中代表的是整行文字
# 在print使用逗號,可以在輸出時用空白隔開$1與$4
awk '{print $1,$4}' log.txt

(上述指令針對每一行的log,截取第1個與第4個讀取到的文字)

2 a
3 like
This's
10 orange,apple,mongo

透過-F 更改分割字元

由於預設awk是使用空白當分割字元來處理同一行文字的,若要改變分割字元,則可以使用-F 這個flag。

aws -F , '{print $1,$2}' log.txt

(上述指令針對每一行的log,透過,分隔以後,截取分割後的第1個與第2個讀取到的文字)

2 a
3 like
This's
10 orange apple

(以這個log檔來看,只有最後一行才會被分割成多個arguments)

透過-v 來代入自訂的變數

透過預先定義好的變數

awk -v a=1 -v b=2 '{print $1,$1+a,b}' log.txt

(上述指令定義了a, b 2個變數與值,且在print時使用它們)

2 3 2
3 4 2
This's 1 2
10 11 2

透過運算符號來使用awk

支援的運算符號可以參考這裡

對每一行文字,過濾只有第一個參數大於2
awk '$1>2' log.txt

# output
3 Are you like awk
This's a test
10 There are orange,apple,mongo
對每一行文字,過濾只有第一個參數大於2,且第二個參數必須是"Are"
awk '$1>2 && $2=="Are" {print $1,$2,$3}' log.txt

# output
3 Are you
對每一行文字,列出只有字元數大於20的行
awk 'length>20 {print $0}' log.txt

# output
10 There are orange,apple,mongo

搭配Regular expression使用

awk中,可以透過運算符號~!~來去搭配正規表示法使用。

對於每一行文字,當第一組參數不是數字時才會被print出來
awk '$1 !~ /[0-9]/ {print $0}' log.txt

# output
This's a test

對於每一行文字,只有當第一組參數是數字時才會被print
awk '$1 ~ /[0-9]/ {print $0}' log.txt

# output
2 this is a test
3 Are you like awk
10 There are orange,apple,mongo

對於每一行文字,只有符合正規表示法時才會被print

如果只是要對整行文字作匹配的話,則可以直接用這方式

awk '/re/ ' log.txt

#output
3 Are you like awk
10 There are orange,apple,mongo

或加個!來過濾掉匹配到的每一行文字

awk '!/re/ ' log.txt

#output
2 this is a test
This's a test

搭配awk的進階使用

awk常見可以使用的keyword可以參考這裡

過濾掉第一行的文字(通常可用於csv檔拿掉header)
awk 'NR != 1' log.txt

# output
3 Are you like awk
This's a test
10 There are orange,apple,mongo

(我猜NR指的應該是Nnumb of Row)

對文字檔的特定參數做數字加總,並且print出來
awk '{sum+=$1} END {print sum}' log.txt

# output
15

(如果每一行的第一個參數是數字的話,就會對它做加總並暫存在sum這個變數上)

針對文字檔中的每一行,來做分組與處理

假設我們有個文字檔如下,然後我們想要針對每個Category的值串起來在印出來

Category: OS
Windows
Liux
Unix
Category: CPU
x86
arm64
amd64
Category: RAM
1GB
2GB
4GB
8GB
16GB

awk '/Category/ {header=$0; if (v) print v; v=""; next} { v=(!v) ? header"="$0 : v","$0;} END {print v;}' support_sepcs.txt

# output
Category: OS=Windows,Liux,Unix
Category: CPU=x86,arm64,amd64
Category: RAM=1GB,2GB,4GB,8GB,16GB

這個指令用了到幾個進階的功能:

  • /Category/ 用來匹配當遇到Category那一行的文字時,會在{header=$0 ...;next}中處理。(結尾的next是指說跳過後面的{v=(!v)…}相關的工作)
  • () ? : 用三元運算符號來去給v這個變數值。
  • END 用來處理最後的收尾。
  • 整個指令的邏輯是,當如果遇到文字中含Category時,則那行的文字會當作是接下去的header,然後如果v 目前是有值的情況下,則print v
    (這個情況v會是前面的字串組成的結果, 例如處理Category: CPU時,v這時會有值,且值會是Category: OS=Windows,Liux,Unix)。
    若沒遇到Category的話,則繼續append 目前的這一行文字到v這個變數上。
    最後一個Category: RAM則是透過 END { print v}來去print出來。
  • 如果在header後想要多處理else的話,會是這樣的語法:
    {header=$0; {if (v) { print v; v=""; next } else {v="";next}}

總結

整個awk的進階使用還更複雜,尤其是它支援許多語法,透過它的語法可以寫成另一個awk的script了,然後在指令中讀取來使用,像是awk -f cal.awk log.txt

reference

常用指令 – xargs

基本上常搭配其它linux指令 (find, awk, sed, grep…)一起使用,主要是因為一些linux的指令是沒直接支援pipe,所以可以透過xargs將前面pipe的輸出當成input arguments 給下一個指令使用;

xargs 後面沒有接任何的指令時,預設是以 echo 來進行輸出喔

將find的結果,透過xargs 來當作grep 主要要找的對象

find . -name "*.go" -print | xargs grep "src"

-0 flag

-0 flag主要是用來讓xargs 來讓可以去處理需要escape的字元,像是空白字元…

-n flag

-n flag 是用來指定每隔多少個要切割成一個pipe的arguments,也就是目前的pipe經過xargs以後會產生N/n 個pipe(N為目前pipe的argument數量)。如果沒有設定的話預設為把所有xargs 當下截取到的內容全部收集到目前這個pipe中。

舉例來說,一個env檔的內容如下:

FOO=123
BAR=456
LOCAL=127.0.0.1
PORT=3000

如果我們沒加-nflag時,用下面的指令:

cat env| xargs

則輸出結果會是 (env檔中的4個環境變數會被當成目前這個pipe的argument)

FOO=123 BAR=456 LOCAL=127.0.0.1 PORT=3000

但如果指令改成是下面這樣時

cat env| xargs -n 2

則輸出結果會是 (env檔的4個環境變數被切割成每2個是一組argument, 並且丟到下一個pipe中,所以這樣就fanout成2個pipe了)

FOO=123 BAR=456
LOCAL=127.0.0.1 PORT=3000

-I flag

-I 主要是可以用來將截取到的內容,暫存成一個變數名稱,來方便下個指令使用。

以下面的例子來說,會將所有找到的 *.conf檔案,透過xargs暫存到變數{}中,所以接下來的ls -al {}就可以這樣用…

find /etc/ -name "*.conf" | xargs -I{} ls -al {}

另個例子則是像是備份所有的.conf檔,則可以透過-I flag

find /etc/ -name "*.conf" | xargs -I{} cp {} {}.bk

integrate with bash

更彈性的用法是,它可以直接當作bash的輸入arguments;若一樣以前面的env 檔來當例子,透過以下指令我們可以透過一個簡短的bash來處理其中的第3個($2)環境變數。

cat env| xargs bash -c 'export $2'

Reference: