Monday, December 31, 2018

在 FreeBSD 及 CentOS 下如何將 timestamp 轉回一般時間格式輸出

FreeBSD
$ date -jf "%s" "1541563268" +"%Y-%m-%d %H:%M:%S"
2018-11-07 12:01:08

CentOS
$ date -d @1541563268 +"%Y-%m-%d %H:%M:%S"
2018-11-07 12:01:08

加速 SSH 重複登入

這裡採用的是 ControlMaster 功能, 可設定持續時間.

$ mkdir -p ~/.ssh/cm_socket

$ vi ~/.ssh/config
Host *
ControlMaster auto
ControlPath ~/.ssh/cm_socket/%r@%h:%p
ControlPersist 5m

$ chmod 0600 ~/.ssh/config

如何在 bash 下解析 JSON 資料

以下是其中的三個方案

1. 使用 python
echo "$DATA" | python -c "import json, sys; obj=json.load(sys.stdin); print(obj['name'])";

# echo '{"test":"123","test2":[{"test21":"456"}]}' | python -c "import json, sys; obj=json.load(sys.stdin); print(obj['test'])"
123

# echo '{"test":"123","test2":[{"test21":"456"}]}' | python -c "import json, sys; obj=json.load(sys.stdin); print(obj['test2'])"
[{'test21': '456'}]

2. 使用 awk sed tr
echo "$DATA" | sed "s/[{}]//g" | tr '[]' ' ' | sed 's/^ //' | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}'

# echo '{"test":"123","test2":[{"test21":"456"}]}' | sed "s/[{}]//g" | tr '[]' ' ' | sed 's/^ //' | awk -v k="text" '{n=split($0,a,","); for (i=1; i<=n; i++) print a[i]}'
"test":"123"

"test2": "test21":"456" 

3. 使用 jq
# echo '{"test":"123","test2":[{"test21":"456"}]}' | jq -r '.test'

123

Ref:
https://stackoverflow.com/questions/1955505/parsing-json-with-unix-tools

ESXi 好用工具介紹 ghettoVCB

如果不是好野人家企業/公司, 沒有 VCenter 還有儲存裝置可以爽用 live migration.
可是 guest VM 又不能關機匯出 ova, 又必須搬/複製到另一台 ESXi VM host時, 這個超級好用工具就能幫上忙.
程式
https://github.com/lamw/ghettoVCB 

目前支援到 ESXi 6.x

匯出VM 說明文件
https://communities.vmware.com/docs/DOC-8760

匯入VM說明文件
https://communities.vmware.com/docs/DOC-10595

這個軟體利用 snapshot 匯出 VM, 不過用過幾次都只能完整空間匯出, 所以不適用超大硬碟空間使用率的 guest VM. 另外匯入時也無法指定新 guest VM 名稱, 所以會檢查是否有名稱衝突問題.

至於設定檔及測試範例將在下一篇說明.

在 R 進行 K-Means clustering 分析

之前說了好久的 K-Means clustering 分析終於趁過年放假公佈指令.
使用 R 的好處是將這些複雜的數學計算簡化成指令, 而只要專注於資料分析及選擇正確的分析方法. 參考資料網站的詳盡程度值得讚許, 也值得各位好好仔細學習.

###
###  Load data and remove 1st and 2nd column
###
data <- DATA_SOURCE_NAME[-1]
data <- data[-1]
View(data)

###
### Normalization
###
scale(data, center = TRUE, scale = TRUE)
data <- scale(data, center = TRUE, scale = TRUE)
View(data)
write.table(data, file="DATA_Z-Score.csv", sep=",")

###
### K = 2
###
km <- kmeans(data, centers = 2, nstart = 10)
require(factoextra)
fviz_cluster(km, data = data, geom = c("point", "text"), ellipse.type = "norm")
(WSS <- km$tot.withinss) + (BSS <- km$betweenss) + (TSS <- BSS + WSS) + (ratio <- WSS / TSS)

> (WSS <- km$tot.withinss)
[1] 56253.93
> + (BSS <- km$betweenss)
[1] 22738.07
> + (TSS <- BSS + WSS)
[1] 78992
> + (ratio <- WSS / TSS)
[1] 0.7121472

outdata <- table(DATA_SOURCE_NAME$Label, km$cluster)
write.table(outdata, file="DATA_Z-Score-2.csv", sep=",")


###
### K = 3
###
km <- kmeans(data, centers = 3, nstart = 10)
require(factoextra)
fviz_cluster(km, data = data, geom = c("point", "text"), ellipse.type = "norm")
(WSS <- km$tot.withinss) + (BSS <- km$betweenss) + (TSS <- BSS + WSS) + (ratio <- WSS / TSS)

> (WSS <- km$tot.withinss)
[1] 40904.54
> + (BSS <- km$betweenss)
[1] 38087.46
> + (TSS <- BSS + WSS)
[1] 78992
> + (ratio <- WSS / TSS)
[1] 0.5178315

outdata <- table(DATA_SOURCE_NAME$Label, km$cluster)
write.table(outdata, file="DATA_Z-Score-3.csv", sep=",")

Ref:
R系列筆記

Sunday, May 20, 2018

用 RTL-SDR 聽 FM 是一種生活態度

請按照手冊 ( https://github.com/cjcliffe/CubicSDR/wiki/CubicSDR-Manual )
支援模組不是一定要安裝. 安裝過程很順利, 沒有什麼需要注意的地方.

啟動後, 一開始建議還是先聽 FM. 順便練習操作. FM 90.9 訊號強雜訊少拿來測試收聽.


這台筆電 x220 是第二代 i7, 平常 CPU 涼涼的. SDR 一上果真負載就上去惹.


以下是測試不同的取樣率. 從 3.2M ~ 1.5 M


當然不是只有 CubicSDR 可以玩. 
有名的 SDR# 也要玩玩.


再加碼 Gqrx


同場加映 SDR touch, 也可以將 SDR 接上手機.


接下來再將 RTL-SDR 硬體接到 Raspberry Pi zero w 上.

Saturday, April 28, 2018

用 cowsay 讓終端機充滿智慧

0. 準備工作
apt-get install fortune cowsay cconv

1. 程式碼 Cowsay.sh
#!/usr/bin/env bash

PATH=$PATH

SLEEP=6

declare -A CS

MAXEM=0
for e in `ls /usr/share/cowsay/cows/*.cow | sed 's/\.cow//' | awk 'BEGIN{FS="/"};{print $NF}'`
do
        CS[$MAXEM]="$e"
        MAXEM=$((MAXEM+1))
done

while [ 1 ];
do
        clear
        S=$(( RANDOM % 52 ))
        S=$((S+SLEEP))
        F="$S"
        FACE=""
        if [ $F -gt $MAXEM ]; then
                F=$(( F % MAXEM ))
                FACE=${CS[$F]}
        else
                FACE=${CS[$F]}
        fi
        date +"%Y/%m/%d %H:%M:%S"
        /usr/games/fortune | cconv -f UTF8-CN -t UTF8-TW | sed -r "s/\x1B\[[0-9;]*[mK]//g" | /usr/games/cowsay -f $FACE
        sleep $S
done

2. 執行
chmod a+x Cowsay.sh
./Cowsay.sh
bash Cowsay.sh

阿宅桌面時鐘 ASCII 版

請先安裝 toilet
# apt-get install toilet

然後執行
watch -n 1 "date +\"%Y-%m-%d %H:%M:%S\" | toilet"


Ubuntu 12 升級 16 意外直達 18 感想

話說之前將一台迷你筆電從 12 經過 14 升級 16 一切順利.
就來將自己的一號機筆電從好多年的 12 升級 16. 這台唯一的升級難度是有使用加密使用者目錄, 如果不小心就會毀掉使用者目錄, 這也是之前猶豫不升級版本的主因.

首先使用外接磁碟備份重要資料.

接著就使用 do-release-upgrade 從 12 升級 14. 一切順利登入而且正確輸入密碼解開使用者目錄. 一鼓作氣繼續升級到 16.

沒想到災難開始, 一路開始抱怨一堆套件不能安裝. 硬著頭皮繼續下去, 到最後還出現完成升級但是無法安裝一堆套件. 直接結束後重新開機就直接 kernel panic.

這時發揮堅持的精神, 放棄新安裝的核心改用舊版開機, 很好, 可以看到終端機登入畫面.
登入後發現無法自動連接網路, 這難不了我, 使用 ifconfig 大法手動來.
網路終於通了, 繼續堅持再執行 do-release-upgrade 還是一樣慘兮兮. 甚至想到之前將雲端VM從 14 升級 16 只改了 apt source 的方法, 然後 apt-get update; apt-get upgrade 後重新開機還是一樣.
這下傻了, 不會要重新安裝系統吧?!

還好此時靈光乍現, 不給升級就改用 update-manager -d. 可是現在是終端機界面哪來的 GUI WM. 死馬當活馬醫, 使用 startx 上場, 雖然 menu bar 通通失蹤, 可是有桌面啊! 立馬按下右鍵開個 GUI 下的終端機執行 update-manager -d. 看到有新版可以更新, 太讚了. 直上 18.04 LTS.
一切順利完成. 重新開機後看到登入畫面一整個感動. 而且大部分安裝的套件都沒消失, 只有 VirtualBox 等已在二號機安裝完成的套件不見蹤影. 更重要的是加密使用者目錄沒消失.

就這樣消耗兩個晚上, 最後想起來之前順利完成是使用更新管理員.
請愛用 update-manager -d

安裝簡易的電報送訊息機器人 Telegram bot

0. 安裝 telegram 設定帳號 UACCT

1. 加入 @BotFather
BotFather is the one bot to rule them all. Use it to create new bot accounts and manage your existing bots.

About Telegram bots:
https://core.telegram.org/bots
Bot API manual:
https://core.telegram.org/bots/api

Contact @BotSupport if you have questions about the Bot API.


UACCT:
/start

BotFather:
I can help you create and manage Telegram bots. If you're new to the Bot API, please see the manual.

You can control me by sending these commands:

/newbot - create a new bot
/mybots - edit your bots [beta]
/mygames - edit your games [beta]
...

2. 新增 bot
UACCT:
/newbot

BotFather:
Alright, a new bot. How are we going to call it? Please choose a name for your bot.

UACCT:
p****y

BotFather:
Good. Now let's choose a username for your bot. It must end in `bot`. Like this, for example: TetrisBot or tetris_bot.

UACCT:
botusername_bot

BotFather:
Done! Congratulations on your new bot. You will find it at t.me/pipboy88_bot. You can now add a description, about section and profile picture for your bot, see /help for a list of commands. By the way, when you've finished creating your cool bot, ping our Bot Support if you want a better username for it. Just make sure the bot is fully operational before you do this.

Use this token to access the HTTP API:
5*******2:A*********************************w

For a description of the Bot API, see this page: https://core.telegram.org/bots/api

3. 測試 API
3.1. 查詢我是誰
https://api.telegram.org/bot5*******2:A*********************************w/getMe
回應
{"ok":true,"result":{"id":5*******2,"is_bot":true,"first_name":"p****y","username":"botusername_bot"}}

3.2. 加入 bot 聊天並取得聊天室編號
https://api.telegram.org/bot5*******2:A*********************************w/getUpdates
{
  "ok": true,
  "result": [
    {
      "update_id": 5*******0,
      "message": {
        "message_id": 41,
        "from": {
          "id": CHAT_ID,
          "is_bot": false,
          "first_name": "UACCT_DESCRIPTION",
          "username": "UACCT",
          "language_code": "zh-TW"
        },
        "chat": {
          "id": CHAT_ID,
          "first_name": "UACCT_DESCRIPTION",
          "username": "UACCT",
          "type": "private"
        },
        "date": 1524858545,
        "text": "hbbvoebbvebwber"
      }
    }
  ]
}

3.3. 送出第一則訊息
https://api.telegram.org/bot5*******2:A*********************************w/sendMessage?chat_id=CHAT_ID&text=Hello+World

3.4. 送訊息 script
3.4.1. 先安裝 packages
apt-get install jq cconv fortune fortune-zh

3.4.2. 送訊息程式 tgsendmsg.sh
#!/usr/bin/env bash

PATH=$PATH

TS=`date +"%s.%N"`
LOGPATH="/PATH/to/tglog"
LOG="$LOGPATH/LogFilename.log"

BOTTK="5*******2:A*********************************w"
CHATID="CHAT_ID"

mkdir -p $LOGPATH
touch $LOG
chown -R 0755 $LOGPATH

if [ -n "$1" ]; then
        MSG="$1"
        shift
else
        echo "Usage: $0 \"Message\""
        exit 1
fi

TM=`curl --progress-bar --data-urlencode "chat_id=$CHATID" --data-urlencode "text=$MSG" "https://api.telegram.org/bot$BOTTK/sendMessage"`
echo "$TM" | jq
echo "$TS $TM" >> $LOG

3.4.3. 呼叫送出訊息 MyMSG.sh
#!/usr/bin/env bash

PATH=$PATH

Z="Asia/Taipei"

HR=`TZ=":$Z" date +"%H"`
HR=`echo "$HR" | sed 's/^0//'`
echo $HR

if [ $HR -eq 6 ]; then
        /root/tgsendmsg.sh "Good Morning 早安"
        FTZH=`/usr/games/fortune-zh | cconv -f UTF8-CN -t UTF8-TW`
        MSG=""
        for d in $FTZH
        do
                MSG="$MSG $d"
        done
        MSG=`echo "$MSG" | sed -r "s/\x1B\[[0-9;]*[mK]//g"`
        /root/tgsendmsg.sh "$MSG"
fi

if [ $HR -eq 12 ]; then
        /root/tgsendmsg.sh "Good Afternoon 午安"
        FT=`/usr/games/fortune | cconv -f UTF8-CN -t UTF8-TW`
        FT=`echo "$FT" | sed -r "s/\x1B\[[0-9;]*[mK]//g"`
        /root/tgsendmsg.sh "$FT"
fi

if [ $HR -eq 18 ]; then
        /root/tgsendmsg.sh "Good Night 晚安"
        FT=`/usr/games/fortune | cconv -f UTF8-CN -t UTF8-TW`
        FT=`echo "$FT" | sed -r "s/\x1B\[[0-9;]*[mK]//g"`
        /root/tgsendmsg.sh "$FT"
fi

接下來就發揮想像力把能串接的掛上去, 也能多開幾隻 bot 送不同類型的訊息.