2021/07/26

如何查看遠端機器的 mnesia

要先知道 remote erlang node 的 cookie 值

在 local 機器先啟動一個 erlang node, setcookie 的部分要設定跟 remote erlang node 一樣

erl -setcookie cookievalue -sname obs1
% 啟動 observer
(obs1@cmbp)1> observer:start().

在上面選單的 Nodes -> Connect to Node,輸入遠端 nodename@hostname

larzio1@larzio

就可以查看遠端的 mnesia 資料了

Note: 只要點 Application 頁籤就會 crash,不知道原因

2021/07/19

Distributed OTP Applications

OTP application 可以轉換為 distributed application,用途是在多個 erlang cluster nodes 之間,distributed application 能夠在這些節點中間,只運作一個 application。

OTP distributed application 能夠設定為一個運作的主節點,其他節點則是在該主節點失效時,能夠接手選擇產生另一個 application 繼續運作,這是 failover。當主節點恢復時,這個 application 會重新在主節點啟動,原本接手的節點會停止該 application,這是 takeover。運作的細節可參考 Distributed OTP Applications

以該文章的 8ball 實例,測試三個節點運作 OTP distributed application 的狀況。

產生 app

# 透過 rebar 產生 app
rebar create-app appid=m8ball

修改 src 裡面的檔案

m8ball.app.src

{application, m8ball,
 [{vsn, "1.0.0"},
  {description, "Answer vital questions"},
%%  {modules, [m8ball, m8ball_sup, m8ball_server]},
  {applications, [stdlib, kernel, crypto]},
%%  {registered, [m8ball, m8ball_sup, m8ball_server]},
  {mod, {m8ball, []}},
  {env, [
    {answers, {<<"Yes">>, <<"No">>, <<"Doubtful">>,
               <<"I don't like your tone">>, <<"Of course">>,
               <<"Of course not">>, <<"*backs away slowly and runs away*">>}}
  ]}
 ]}.

m8ball.erl

-module(m8ball).
-behaviour(application).
-export([start/2, stop/1]).
-export([ask/1]).

%%%%%%%%%%%%%%%%%
%%% CALLBACKS %%%
%%%%%%%%%%%%%%%%%

%% start({failover, Node}, Args) is only called
%% when a start_phase key is defined.
%% application:which_applications().
start(normal, []) ->
    io:format("application normal start m8ball~n"),
    m8ball_sup:start_link();
start({takeover, OtherNode}, []) ->
    io:format("application takeover m8ball from ~p~n", [OtherNode]),
    m8ball_sup:start_link().

stop(_State) ->
    io:format("application stop m8ball~n"),
    ok.

%%%%%%%%%%%%%%%%%
%%% INTERFACE %%%
%%%%%%%%%%%%%%%%%
ask(Question) ->
    m8ball_server:ask(Question).

m8ball_server.erl

-module(m8ball_server).
-behaviour(gen_server).
-export([start_link/0, stop/0, ask/1]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
         code_change/3, terminate/2]).

%%%%%%%%%%%%%%%%%
%%% INTERFACE %%%
%%%%%%%%%%%%%%%%%
start_link() ->
    gen_server:start_link({global, ?MODULE}, ?MODULE, [], []).

stop() ->
    gen_server:call({global, ?MODULE}, stop).

ask(_Question) -> % the question doesn't matter!
    gen_server:call({global, ?MODULE}, question).

%%%%%%%%%%%%%%%%%
%%% CALLBACKS %%%
%%%%%%%%%%%%%%%%%
init([]) ->
    % <<A:32, B:32, C:32>> = crypto:strong_rand_bytes(12),
    % rand:seed(A,B,C),
    <<I1:32/unsigned-integer, I2:32/unsigned-integer, I3:32/unsigned-integer>> = crypto:strong_rand_bytes(12),
    rand:seed(exsplus, {I1, I2, I3}),
    {ok, []}.

handle_call(question, _From, State) ->
    {ok, Answers} = application:get_env(m8ball, answers),
    Answer = element(rand:uniform(tuple_size(Answers)), Answers),
    {reply, Answer, State};
handle_call(stop, _From, State) ->
    {stop, normal, ok, State};
handle_call(_Call, _From, State) ->
    {noreply, State}.

handle_cast(_Cast, State) ->
    {noreply, State}.

handle_info(_Info, State) ->
    {noreply, State}.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.

terminate(_Reason, _State) ->
    ok.

m8ball_sup.erl

-module(m8ball_sup).
-behaviour(supervisor).
-export([start_link/0, init/1]).

start_link() ->
    supervisor:start_link({global,?MODULE}, ?MODULE, []).

init([]) ->
    {ok, {{one_for_one, 1, 10},
          [{m8ball,
            {m8ball_server, start_link, []},
            permanent,
            5000,
            worker,
            [m8ball_server]
          }]}}.

config files

a.config

[{kernel,
  [{distributed, [{m8ball,
                   3000,
                  [a@cmbp, {b@cmbp, c@cmbp}]}]},
   {sync_nodes_mandatory, []},
   {sync_nodes_optional, [b@cmbp, c@cmbp]},
   {sync_nodes_timeout, 5000}
  ]
 }
].

b.config

[{kernel,
  [{distributed, [{m8ball,
                   3000,
                  [a@cmbp, {b@cmbp, c@cmbp}]}]},
   {sync_nodes_mandatory, []},
   {sync_nodes_optional, [a@cmbp, c@cmbp]},
   {sync_nodes_timeout, 5000}
  ]
 }
].

c.config

[{kernel,
  [{distributed, [{m8ball,
                   3000,
                  [a@cmbp, {b@cmbp, c@cmbp}]}]},
   {sync_nodes_mandatory, []},
   {sync_nodes_optional, [a@cmbp, b@cmbp]},
   {sync_nodes_timeout, 5000}
  ]
 }
].

startup script

runa.sh

# erl -sname a -config a.config -pa ebin -eval 'application:start(crypto), application:start(m8ball)'

erl -sname a -config a.config -pa ebin -eval 'application:ensure_all_started(m8ball)'

runb.sh

# erl -sname b -config b.config -pa ebin -eval 'application:start(crypto), application:start(m8ball)'

erl -sname b -config b.config -pa ebin -eval 'application:ensure_all_started(m8ball)'

runc.sh

# erl -sname c -config c.config -pa ebin -eval 'application:start(crypto), application:start(m8ball)'

erl -sname c -config c.config -pa ebin -eval 'application:ensure_all_started(m8ball)'

compile

rebar compile

測試

先啟動 node a,因為 b, c 還沒有啟動,這時候, a 在啟動時,會等 5s,看看 b, c 是不是有啟動。 5s 後,才會進入 console。

application:which_applications(). 可以查詢目前運作的 applications

./runa.sh

Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [kernel-poll:false]

Eshell V9.3  (abort with ^G)
(a@cmbp)1> application:which_applications().
[{m8ball,"Answer vital questions","1.0.0"},
 {crypto,"CRYPTO","4.2.1"},
 {stdlib,"ERTS  CXC 138 10","3.4.4"},
 {kernel,"ERTS  CXC 138 10","5.4.3"}]

如果啟動 b,一樣會等 5s。但如果同時再啟動 c,就會直接進入 console。

./runb.sh
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [kernel-poll:false]

Eshell V9.3  (abort with ^G)
(b@cmbp)1> application:which_applications().
[{crypto,"CRYPTO","4.2.1"},
 {stdlib,"ERTS  CXC 138 10","3.4.4"},
 {kernel,"ERTS  CXC 138 10","5.4.3"}]
./runc.sh
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [kernel-poll:false]

Eshell V9.3  (abort with ^G)
(c@cmbp)1> application:which_applications().
[{crypto,"CRYPTO","4.2.1"},
 {stdlib,"ERTS  CXC 138 10","3.4.4"},
 {kernel,"ERTS  CXC 138 10","5.4.3"}]

透過 application 查詢,可得知 m8ball 運作在 node a

如果把 node a 關掉,等待 5s 後,進行 application 查詢,可發現 m8ball 運作在 node b

(b@cmbp)2> application:which_applications().
[{m8ball,"Answer vital questions","1.0.0"},
 {crypto,"CRYPTO","4.2.1"},
 {stdlib,"ERTS  CXC 138 10","3.4.4"},
 {kernel,"ERTS  CXC 138 10","5.4.3"}]

再把 node b 關掉,等待 5s 後,進行 application 查詢,可發現 m8ball 運作在 node c。

重新啟動 node a,這時候 node c 的 application 會被停止

(c@cmbp)6>
=INFO REPORT==== 26-Mar-2021::15:45:28 ===
    application: m8ball
    exited: stopped
    type: temporary

但是並沒有回到 node a 運作。這邊認為有可能是 erlang 的問題。

(a@cmbp)1>
=INFO REPORT==== 26-Mar-2021::15:45:28 ===
    application: m8ball
    exited: {{already_started,<5269.88.0>},
             {m8ball,start,[{takeover,c@cmbp},[]]}}
    type: temporary

=INFO REPORT==== 26-Mar-2021::15:45:28 ===
    application: crypto
    exited: stopped
    type: temporary

在 takeover 時, b,c 兩個 node 如果少了一個,就會發生問題。

再重新執行一次 a

$ ./runa.sh
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [kernel-poll:false]

Eshell V9.3  (abort with ^G)
(a@cmbp)1> application:which_applications().
[{m8ball,"Answer vital questions","1.0.0"},
 {crypto,"CRYPTO","4.2.1"},
 {stdlib,"ERTS  CXC 138 10","3.4.4"},
 {kernel,"ERTS  CXC 138 10","5.4.3"}]

Note:如果只做兩個 Node,這時候就沒有發生上面 takeover 的問題。


在任意一個節點,只要 m8ball 有在某一個節點運作,就可以使用 m8ball

(b@cmbp)3> m8ball:ask("Questions?").
<<"*backs away slowly and runs away*">>
(b@cmbp)4> m8ball:ask("Questions?").
<<"No">>
(b@cmbp)5> m8ball:ask("Questions?").
<<"Of course">>

References

Distributed OTP Applications

2021/07/12

當上主管後,難道只能默默崩潰?

當上主管後,難道只能默默崩潰? 作者 Julie Zhuo 在 Facebook 晉升設計主管後,以他自己的個人經驗,告訴大家一個管理職應該/不應該做什麼事情,並提出了許多實用的建議,重點在於有關「人」的工作,必須不斷地檢討調整做法。

什麼是管理?

想辦法讓一群人合作,得出更好的結果。

管理者每天要處理的事情,分為三大類:目標 purpose、人 people、流程 process

目標:why

​ 為什麼這項工作很重要

​ 確保團隊知道成功的狀況,而且想要成功

人:who

​ 團隊成員有成功的條件、技能、動力嗎?

流程:how

​ 如何一起工作

優秀經理是後天培養出來的。

管理者的成就,在於團隊的表現,工作內容是協助團隊成功。願意視情況扮演不同的角色。

隨機應變:目標轉向、成員異動、流程改變...

管理者要花大量時間與人相處。能夠在充滿情緒的情境下,依然穩若泰山。

領導者與管理者不同

領導是特質,要能影響他人,不是工作

管理是被指派

新官上任

接下管理職的途徑:

  1. 學徒:成長的團隊,需要有人分擔管理工作

    可得到舊主管的引導,知道什麼可以做、什麼不行

    • 該從哪裡下手
    • 要如何跟團隊溝通職務變化
    • 被管理者,有哪些要注意的事
    • 有哪些重要團隊目標或流程
    • 前3~6個月,要完成哪些事情
    • 兩個人如何協調、分工

    大家開始用不同的方式對待你,或是不再分享更多資訊

  2. 開拓者:新團隊的創始成員

    打造出自己要的團隊,跟大家協調目標、價值觀、流程

    • 希望團隊成員具備哪些特質
    • 希望成員具備哪些技能
    • 這個團隊一年後將會如何運作
    • 自己的角色與責任

    背後沒有太多支援

  3. 新進主管:進入已經運作的團隊

    一開始有蜜月期 -> 該問的就要問

    努力建立新關係

    不了解工作 -> 跟上司溝通

  4. 繼任者:原管理者離開

    責任大增

    原本平行的同事建立新互動會尷尬

    大家期待你要跟前主管一樣

帶領小型團隊

團隊成長至八人時,開始每週 critique 互評會議

妨礙人把工作做好的原因

  1. 不知道如何能做好工作
  2. 沒有動力

信任是重要元素

信任:人們覺得可以告訴你自己犯的錯、遇到的挑戰、心中的恐懼

如果連續幾週,大家都說「每一件事都很好」,那就可能有問題

指標:我帶的人願意再當我的部屬

尊重與關心你管理的人:管理就是關懷

花時間協助你管理的人

  • 討論優先事項
  • 協調什麼叫「優秀表現」
  • 分享回饋意見
  • 檢討現況

用這些問題引導對話

  • 找出癥結
    • 你現在最煩心的事情是什麼
    • 你打算先處理哪些事
    • 你認為今天這個時間應該討論什麼
  • 理解
    • 你理想中的結果是什麼樣子
    • 得出那樣的結果難在哪裡
    • 你真正在意的事是什麼
    • 你認為最理想的辦法是什麼
    • 你最擔心的情況是什麼
  • 支持
    • 你希望我怎麼幫你
    • 我怎麼做能讓你更成功
    • 我們今天的對話,最有用的地方是哪裡

誠實告知部屬的表現

承認自己也會犯錯,依然有成長的空間

人們會忘記你說過什麼、做過什麼,但永遠不會忘記你帶來的感受

發生問題時,最重要的不是建議或答案,而是同理心

協助他人發揮長處

團隊中不該容忍的事:有優秀孤狼

沒必要永遠都要「解決問題」:如果真有不對盤的人,就不要放在一起

快刀斬亂麻:當你決定讓某人離開,態度要直接,但也要表現出尊重

提供回饋的技巧

有很多人不擅長給回饋意見

理想的回饋

一開始就清楚設定期待

一有機會就給「特定任務的回饋」:對事不對人

仔細思考後,定期分享「行為回饋」

蒐集「360度回饋」,力求客觀

重大失望的起因都是沒有設定期待

事情有改善,回饋才算數

1. 回饋要越明確越好
2. 說明成功的樣貌與感受
3. 建議接下來的步驟

給批評性的回饋或宣布壞消息:不要用好聽的話包裝壞消息

「三明治評論法」:先講正面觀察,然後提出建議,最後拍肩膀鼓勵

Feedback is a gift.

管理自己

每個人偶爾都會感到自己是冒牌者

冒牌者症候群 imposter syndrome:每個主管偶爾都會感到自己是冒牌者

  1. 人們經常仰賴你提供答案
  2. 你得不斷做從前沒做過的事

完全對自己誠實:找出自己的優點與缺點

了解自己表現最好與最糟的情境

陷入谷底時找回自信

​ 不要怪自己心情低落

​ 跟著說「我腦中的聲音不夠理性」

​ 閉上眼睛想像

​ 讓你能卸下心防的人協助

​ 小事也要慶祝

​ 區分上下班,照顧自己

努力變得更優秀

​ 請他人提供回饋

​ 把主管當教練

​ 人人都能成為導師

​ 找時間反省與設定目標

​ 利用正式訓練

精彩會議

好的會議簡單明瞭

會議的結果

​ 作出決定

​ 分享資訊

​ 提供回饋

​ 想出點子

​ 強化關係

邀請正確人選

給人機會,準備好再出席

讓與會者能安心發言

​ 明確說出原則

​ 改善會議形式,增加參與程度

​ 讓每個人都有平等的發言時間

​ 請大家提供會議回饋

不需要參加每一個會議

雇用正確人選

事先想好如何規劃你的團隊

​ 找人是你的責任

​ 描述理想中的人選,越明確越好

​ 擬定找人策略

​ 提供令人驚豔的面試體驗

​ 讓應徵者感受到你求才若渴

雇用是一場賭博

​ 檢視應徵者過去做過的類似工作

​ 找可信人士推薦

​ 多找幾位面試官

​ 一個熱心的打包票掛保證,勝過大家覺得普通也沒人反對

​ 事先備妥面試題目

​ 不收會讓工作環境烏煙瘴氣的人

​ 打造具備多元視野的團隊

​ 雇用具備成長空間的人

​ 要對流程有信心

如果需要雇用五人、十人、數百人

​ 成功的聘僱關鍵在於肯下功夫

​ 主管級的聘僱要先做功課

​ 招募頂尖人才,目光要放遠

​ 建立堅強的板凳陣容

​ 培養把找到人才當成第一要務的文化

讓事情發生

先有明確的願景

​ 擬定可信的行動方案

​ 依據團隊的長處制定計劃

​ 專心做好一兩件事

​ 分配好哪些是由誰負責

​ 把大目標拆成小目標

完美執行比完美策略重要

​ 衡量短期與長期效益

​ 立下長期願景,接著往回推

​ 採取「組合法」

​ 說明每一件事與願景之間的關聯

理想的流程一直在變動

帶領成長中的團隊

大團隊 vs 小團隊

​ 直接管理轉變為間接管理

​ 人們以不同方式待你

​ 每天隨時都得轉換心境

​ 挑選自己要投入的戰役

​ 關鍵技能越來越與「人」有關

授權的程度不好拿捏

委以重任象徵著信任

不同層級的主管要統一願景

當主管表現不佳時,要怎麼辦

努力讓自己「沒工作」

培養文化

Nothing at Facebook Is Somebody Else's Problem.

找出你想成為哪種團隊的一份子

​ 了解目前的團隊

​ 了解你渴望擁有的文化

​ 找出差異

重要的是可以隨時提醒

身體力行

製造正確誘因

建立宣揚你的價值觀的傳統

2021/07/05

RPA: Robotic Process Automation

RPA: Robotic Process Automation 是 2018 年開始的一個新興領域,用來取代辦公室內的人力,目標是,只要是電腦能夠處理的重複性工作,因為 RPA 能夠模擬我們操作電腦的動作,例如打開 Browser,在網頁擷取資料,打開 email,登入應用程式等等,都可透過 RPA Tool 重複運作。目前 RPA 領域中的領導者是 UiPath。

目前 RPA 的產品有

  1. UiPath
  2. Automation Anywhere
  3. blueprism
  4. WorkFusion
  5. PEGA
  6. RedWOOD

RPA 分析

淺談RPA: Robotic Process Automation

https://miro.medium.com/max/700/0*DMRvUjFQv_QENu1b.jpeg

以前有個名詞 OA 辦公室自動化,這個階段是要利用 IT 技術開發一些工具,簡化工作流程與時間,節省人力。RPA 是因為 IT 系統太多樣化,又有許多工具跟資料各自獨立,沒有整合在一起。RPA 是一個能在電腦中跨越多個系統互相傳遞資訊的工具。

RPA的目標『模擬』人工操作電腦的行為,解決過往跨系統資料串連不易、跨平台資料比對問題,讓原本人工作業的流程變得自動化,並減少人為疏失或錯誤。在討論到跨系統整合,一般都會從系統資料串接的角度來想,但這樣一個跨系統整合專案,不僅耗時,成本高,而且無法因應系統的升級或更新,立刻做調整與改變。

RPA 是從使用者與成本的角度產生的,等於是認為目前資訊系統的異質性與多樣性是無法解決與處理的,乾脆從各系統的既有介面為出發點,讓 RPA 直接模擬操作過程,已達到低成本跨系統的整合目的。

IA

從流程機器人(RPA)進階到智能自動化(IA)

智能自動化是流程機器人與認知科技(Cognitive Technology)的結合,能處理較複雜的作業情境,並針對各種結構化與非結構化的資料進行擷取、重組、分析及驗證,以下列舉三項可將複雜的作業流程進行自動化的情境:

  1. 圖像資訊轉為文字訊息的工作,例如:從不同格式的紙本發票擷取收據內容,並轉為文字清單。
  2. 語音訊息轉為文字訊息的工作,例如:將客戶透過電話預約的通話內容,轉為文字記錄。
  3. 統整與分析結構鬆散的巨量資料,例如:將每月收支產生的紙本單據轉為數位資料後,擷取特定的欄位數據,彙整成當月的結算報告。

隨著圖像辨識與語意識別的技術逐漸成熟,結合這些科技能將過去不易處理的資料型態進行辨識與轉換,進一步達到智能自動化。相較於流程機器人擅長將重複性高、帶有固定規則的作業內容自動化;智能自動化則是強調能夠識別不同的作業情境,並將資料結構鬆散、具複雜邏輯的作業內容自動化(圖2)。

IA 智能自動化,是下一個階段的目標。最終目標當然是 AI,但這應該還離我們很遠。

UiPath

UiPath Tutorial 10 - Real Time Project in UiPath | Data Scraping | Send Email with Attachment

類似 巨集 Editor

【UiPath課程】沒有程式背景,花2天上課的心得筆記(Day1)

UiPath的平台架構主要有三部分

  • UiPath Studio:設計工作室,用來設計流程的工具。(製作Robot)
  • UiPath Robot:那個幫你做事的機器人,實際執行自動化流程的機器人。(執行Robot)
  • UiPath Orchestrator:中控管理平台,當機器人越來越多的時候,需要集中管理這些每天做事的機器人,可以排程、安全控管、監控與分析效能等。(管理Robots)

Automation Anywhere

https://www.automationanywhere.com/tw/rpa/robotic-process-automation

機器人能夠複製貼上、抓取網頁資料、進行計算、開啟和移動檔案、剖析電子郵件、登入程式、連接到 API,以及擷取非結構化資料。而且,由於機器人可以適應任何介面或工作流程,因此無需變更業務系統、應用程式或現有流程,即可實現自動化。


https://medium.com/alexchanglife/什麼是rpa機器人流程自動化-robot-process-automation-d6c6de75f28d

Automation Anywhere的設計架構主要包含三個元件:Control Room、Bot Creator、Bot Runner。

1. Control Room 中控室

Control Room做為Automation Anywhere架構設計的核心,負責管理、維護從Bot Creator開發後上傳的各式機器人,並根據自動化排程的設定,分派這些機器人至Bot Runner中,執行自動化任務。

2. Bot Creator 機器人開發者

主要負責開發、設計各種執行自動化任務的機器人。

Bot Creator可以於本機電腦上進行機器人的開發(客戶端),開發完成後,透過網路傳輸的方式,將其開發的機器人上傳至Control Room(伺服端),讓Control Room可以根據預先設定好的執行排程,分配這些機器人於Bot Runner中,執行自動化任務。此外Bot Creator也可以從Control Room上下載已開發完成的機器人,進行調整、優化機器人的作業。

3. Bot Runner 機器人執行者

主要負責執行從Control Room分派下來的各種自動化機器人。

Control Room會依據設定好的執行排程(伺服端),經由網路傳輸的方式,將機器人分派至Bot Runner上執行自動化任務(客戶端),Bot Runner可同時執行多個自動化機器人,已完成不同的類型的任務腳本,但無法新增、更新自動化機器人

而當Bot Creator完成機器人開發,並上傳至Control Room的機器人,其機器人會被儲存至Bot Repository中,搭配如同Git的版本控制功能(Version Control),讓Control Room的管理者可以追蹤過往此機器人的修改歷程,清楚知道要使用哪個版本的機器人,做為執行自動化任務使用。

此外我們先前提到Control Room是經由網路的方式,連結Bot Creator與Bot Runner,為了防止於分派任務的過程中產生資料外泄的風險,Control Room於傳送前,會採用AES-256的資料加密方式,並搭配TLS 1.2的資料傳輸規格,確保資訊安全無虞。

最後Control Room也提供Single-Sign on的登入功能,提供系統管理者可經由帳號綁定的方式快速登入Automation Anywhere進行監控、管理、安排自動化機器人等任務。

AI + RPA

智慧文件辨識2.0應用,AI+RPA 發票/文件處理自動化

利用 RPA Tool 裡面內建的 OCR,做到自動化

但實務上下游關係的所有電子表單格式不同,文件掃描後的解析度,位置可能會稍微不同,傳統的 OCR Engine 無法處理非結構化的資料。因為 RPA 還無法處理不同範本的文件檔案,具有 AI 能力的 OCR Engine,可以解決這樣的問題。