2020年11月18日 星期三

[韓劇] 返回18歲 / 18 again / 18 어게인

圖片來源:wiki - 重回18歲

前陣子登入愛奇藝回顧一下方案(雙11方案),就被這韓劇吸引,當然,就是被女主角 金荷娜 吸引啦,看了幾齣她演的韓劇,印象深刻,像是某些情境會使出招牌的咬唇 (誤) 不過在返回18歲裡頭很少,我只有印象中看到一次。

後來發現以前公司的女同事也在看,當然,看法就不一樣,就是看帥哥男主角 XD 我一開始有點難適應那誇張燦爛的笑容 XDD

回過頭來,這齣戲是著重在親情戲的,剛好很適合我的年紀,提醒自已對小孩要多包容、多把握一起相處的時機。對年過35的來說,看的很有滋味,且愛情戲也不重,恰到好處,十分完美。

後來還在 NETFLIX 觀看了美國 2009 年的熱門電影 17 again (回到17歲),是返回18歲改編的來源。最後也研究了一下這部戲劇是不是很紅,好像是普通,平均收視 2.7%,因為同時段有 Penthouse 收視率可以衝破 10% ,也有青春紀錄等隨便也都 4% 收視率的。可能 TA 群不同吧,恰好給中年人回顧一下對家庭的時間投資。

2020年11月17日 星期二

[書] 彼得原理

幾個月前趁著 kobo 特價活動時,買了數本電子書,其中一本就是彼得原理。

這本書一開始閱讀時,對我而言像是八卦書,把自己已經在職場上看過的人事物統整起來,比較像複習,大概看完七成時都還是差不多的心得。

舉例來說,以前加入過五千人規模的公司,裡頭的文化氣息步調緩慢,再加上非營利的經營路線,考績跟年終影響沒那麼明顯,例如很努力可以得到 2個月年終獎金,而過的混混的可以拿到 1.5 年終,再加上彼此的薪資水準都是法定,範圍差距很小。

通常都是年紀大的比較懂文化,再加上年資高的月薪自然又被新鮮人高,這樣算年終下來,懂生活的老前輩不見得會輸給衝勁十足的新鮮人,就像彼得原理提到的人物一樣 XD 下一刻呢?有衝勁的年輕人習得文化後,要嘛一起享受生活,要嘛就離開此處。算是個劣幣驅除良幣的現象。

再來一個案例,我也曾碰過握有權力的前輩,本身也有才華,卻因為做事有自己偏好,很多苦勞都會刻意避開,實在聰明。有時都會覺得真是可惜,若那些苦勞都扛下來後,肯定會長出美好的果實的。再說一個案例,那就是老闆愛將模式下,會替愛將規劃一些政治圈,包括產生一些並非適合公司現狀的階級制度等等,這個叫做很得老闆愛 XD 

回過頭來,有人的地方就有政治,我覺得 彼得原理 可以提醒如何審視週遭人的現狀,為何有人明明很聰明,為何做事的成效不佳,在沒有利害關係下,可以當作很有趣的現象觀察。當然,有工作前後關係時,就會是個痛苦 XD 而書裡最後提到的章節,也等於讓讀者在審核自己的身心狀態,因此,假設這本書的養分有 100 分的話,我大概只需要其中的 20-30 分而已,比較好玩的是在教導如何避免不適任的現象,像是讓不適任的員工去做他們適任的工作內容,甚至避開衝突,只是對外商企業來說,除非有老闆愛,不然砍人是比較常見的解法 XD 

2020年11月6日 星期五

[Linux] 使用 uClibc-ng 製作 x86_64 開發測試環境,以編譯 curl / libcurl 為例 @ Ubuntu 20.04

由於硬體要限縮資源,這時會把常見的 glibc 換成 uclibc 節省空間,而過程包括要建置 toolchain 等等。由於部分程式在 embedded linux 運作不如預期,大家擔心可能是 uclibc 產生的問題,就出現在 x86_64 運行 uclibc 作檢驗的念頭

實作上也是要建置 x86_64 的 toolchain 出來,此例就用 curl / libcurl 為例。此篇工作記錄參考 编译工具链制作-x86_64-linux-uclibc 文章,建議先拜讀這篇,裡頭編譯參數的項目都有說明,佛心啊。此處筆記是設法把開發環境都用最新環境,包括:

  • Ubuntu 20.04.1 LTS server
  • uClibc-ng-1.0.36
  • binutils-2.35
  • gcc-9.3.0 
  • mpfr-4.1.0
  • mpc-1.2.1 
  • gmp-6.1.2
  • linux-2.6.39

而後面編譯 curl 採用以下資源:

  • tiny-curl-7.72.0
  • zlib-1.2.11
  • openssl-1.1.1h 

採用 gcc-9.3.0 的主因是 ubuntu 20.04 預設 apt install gcc 就是 9.3 版。以下連續動作:

$ wget https://ftp.gnu.org/gnu/binutils/binutils-2.35.tar.gz
$ wget https://ftp.gnu.org/gnu/gcc/gcc-9.3.0/gcc-9.3.0.tar.gz
$ wget https://ftp.gnu.org/gnu/gmp/gmp-6.1.2.tar.bz2
$ wget https://ftp.gnu.org/gnu/mpc/mpc-1.2.1.tar.gz
$ wget https://ftp.gnu.org/gnu/mpfr/mpfr-4.1.0.tar.gz
$ wget http://ftp.ntu.edu.tw/linux/kernel/v2.6/linux-2.6.39.tar.gz
$ wget https://downloads.uclibc-ng.org/releases/1.0.36/uClibc-ng-1.0.36.tar.gz

並全在 user 家目錄解壓縮,解壓縮後把 open source 包都移到 resource 目錄中保存:

user@buildserver:~$ tree -L 1 
.
├── binutils-2.35
├── gcc-9.3.0
├── gmp-6.1.2
├── linux-2.6.39
├── mpc-1.2.1
├── mpfr-4.1.0
├── resource
└── uClibc-ng-1.0.36

安裝一些工具:

$ sudo apt install make cmake gcc g++ libncurses-dev libncurses5-dev
$ gcc -v
...
Thread model: posix
gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04) 
$ g++ -v
...
Thread model: posix
gcc version 9.3.0 (Ubuntu 9.3.0-17ubuntu1~20.04) 
$ make -v
GNU Make 4.2.1
Built for x86_64-pc-linux-gnu
$ cmake --version
cmake version 3.16.3

建置環境變數,預計都安裝在家目錄的 tarball 裡,此例就是 /home/user/tarball:

$ cat ~/uclibc-init.sh 
export ARCH=x86
export TARGET=x86_64-linux-uclibc
export PREFIX=/home/user/tarball
export TARGET_PREFIX=$PREFIX/$TARGET
export PATH=$PREFIX/bin:$PATH

 

$ source ~/uclibc-init.sh
$ mkdir -p $TARGET_PREFIX

編譯 binutils 環境:

$ cd binutils-2.35 && mkdir -p $TARGET && cd $TARGET
$ ../configure \
--prefix=$PREFIX \
--with-lib-path=$PREFIX/lib:$PREFIX/lib64 \
--disable-multilib \
--disable-werror \
--disable-nls \
--enable-gold \
--target=$TARGET
$ make && make install

 

$ x86_64-linux-uclibc-ld --verbose | grep SEARCH
SEARCH_DIR("/home/user/tarball/x86_64-linux-uclibc/lib64"); SEARCH_DIR("/home/user/tarball/lib"); SEARCH_DIR("/home/user/tarball/lib64"); SEARCH_DIR("/home/user/tarball/x86_64-linux-uclibc/lib");

這邊增加 --enable-gold 用於 gcc-9.3 的編譯時會踩到的需求,通常就是缺一些 header files 就是要找找看躲在 binutils, uclibc 等等

安置 linux header files:

$ linux-2.6.39/
$ make ARCH=$ARCH INSTALL_HDR_PATH=$TARGET_PREFIX headers_install

編譯跨平台 gcc 工具:

$ cd gcc-9.3.0/
$ ln -s ../mpc-1.2.1/ mpc
$ ln -s ../mpfr-4.1.0/ mpfr
$ ln -s ../gmp-6.1.2/ gmp
$ mkdir -p $TARGET && cd $TARGET
$ ../configure \
--prefix=$PREFIX \
--with-sysroot=$PREFIX \
--with-local-prefix=$PREFIX \
--with-native-system-header-dir=/$TARGET/include \
--enable-languages=c,c++ \
--enable-linker-build-id \
--disable-multilib \
--disable-werror \
--without-headers \
--with-newlib \
--disable-shared \
--disable-nls \
--target=$TARGET
$ make all-gcc
$ make install-gcc

安置 uclibc 相關檔案們(startfiles/headers):

$ cd uClibc-ng-1.0.36
$ make menuconfig
Target Architecture
    --> x86_64
Target Architecture Features and Options
--> [*] Enable full C99 math library support  
--> [*] Enable C99 Floating-point environment
--> Linux kernel header location (/home/user/tarball/x86_64-linux-uclibc/include)
General Library Settings
--> [*] Dynamic linker stand-alone mode support
--> Thread support (Native POSIX Threading (NPTL))
--> [*] utmpx based support for tracking login/logouts to/from the system
--> [*]   utmp support (XPG2 compat, SVr4 compat) 
--> [*] Enable SuSv3 LEGACY functions
--> [*] Enable SuSv3 LEGACY macros
--> [*] Enable SuSv4 or obsolescent functions
Advanced Library Settings
--> [*] Enable SVr4 deprecated functions
Networking Support
--> [*] IP version 6 support
--> [*]   Use netlink to query interfaces 
--> [*]     Support the AI_ADDRCONFIG flag
--> [*] DNS resolver functions
String and Stdio Support
--> [*] Wide Charater Support
Big and Tall
--> [*] Support the wordexp() interface
Libray Installation Options
--> uClibc runtime library directory(/home/user/tarball/x86_64-linux-uclibc)
--> uClibc development envirment directory(/home/user/tarball/x86_64-linux-uclibc)
Development/debugging options
--> Cross-compiling toolchain prefix (x86_64-linux-uclibc-)
--> (-D__NR_setns -D__NR_syncfs) Extra CFLAGS
$ make startfiles
$ PREFIX="" make install_startfiles
$ PREFIX="" make install_headers

其中我開啟了不少項目都是後邊在編譯 gcc-9.3 和 curl 會用到的項目,像是缺 ifaddrs.h 而開啟 Support the AI_ADDRCONFIG flag 又相依要開啟 Use netlink to query interfaces 選項等等。過程常見的都是編譯期間缺 header files 而反覆在 uclibc 開啟資源,可以把缺的 header files 在 uclibc 中靠 find 或 grep 搜尋

繼續編譯跨平台 libgcc:

$ cd ~/gcc-9.3.0/$TARGET
$ make all-target-libgcc
$ make install-target-libgcc

編譯和安裝 uclibc :

$ cd ~/uClibc-ng-1.0.36/
$ make
$ PREFIX="" make install

最後一次 gcc 編譯:

$ cd ~/gcc-9.3.0/$TARGET
$ ../configure \
--prefix=$PREFIX \
--with-sysroot=/ \
--with-local-prefix=$PREFIX \
--with-native-system-header-dir=$TARGET_PREFIX/include \
--enable-languages=c,c++ \
--enable-linker-build-id \
--disable-libsanitizer \
--disable-multilib \
--disable-werror \
--disable-nls \
--target=$TARGET
$ make all
$ make install

如此,就可以有基本的環境運行了,例如編譯 main.c:

$ cat main.c 
#include <stdio.h>
int main(int argc, char *argv[]) {
        printf("Hello\n");
        return 0;
}
$ x86_64-linux-uclibc-gcc main.c 
$ ./a.out 
-bash: ./a.out: No such file or directory
$ file a.out 
a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld64-uClibc.so.0, BuildID[sha1]=c243334b7550adf7ef5342019c444d6762da738b, not stripped

 

$ ~/tarball/x86_64-linux-uclibc/lib/ld64-uClibc-1.0.36.so --library-path /home/user/tarball/x86_64-linux-uclibc/lib/:/home/user/tarball/x86_64-linux-uclibc/lib64:/home/user/tarball/lib ./a.out
Hello

緊接著編譯 curl 來用,因為他相依 openssl, libssh2, zlib ,所以過程要先把這些函示庫都編好:

$ wget https://zlib.net/zlib-1.2.11.tar.gz
$ tar -xvf zlib-1.2.11.tar.gz && cd ~/zlib-1.2.11
$ CC=x86_64-linux-uclibc-gcc  CXX=x86_64-linux-uclibc-g++  ./configure --prefix=$PREFIX
$ make && make install  

 

$ wget https://www.libssh2.org/download/libssh2-1.9.0.tar.gz
$ tar -xvf libssh2-1.9.0.tar.gz && cd libssh2-1.9.0
$ CC=x86_64-linux-uclibc-gcc  CXX=x86_64-linux-uclibc-g++  ./configure --prefix=$PREFIX --host x86_64-linux-uclibc
$ make && make install

 

$ wget https://www.openssl.org/source/openssl-1.1.1h.tar.gz
$ tar -xvf openssl-1.1.1h.tar.gz && cd ~/openssl-1.1.1h
$ CC=x86_64-linux-uclibc-gcc  CXX=x86_64-linux-uclibc-g++ ./config --prefix=$PREFIX -latomic no-threads no-shared no-rc5  enable-camellia  enable-mdc2 no-tests no-fuzz-libfuzzer no-fuzz-afl zlib
$ make && make install

 

$ wget https://curl.haxx.se/tiny/tiny-curl-7.72.0.tar.gz
$ tar -xvf tiny-curl-7.72.0.tar.gz && cd tiny-curl-7.72.0
$ mkdir build && cd build
$ CC=x86_64-linux-uclibc-gcc CXX=x86_64-linux-uclibc-gc++ cmake .. -DCMAKE_PREFIX_PATH=~/tarball -DCMAKE_INSTALL_PREFIX=~/tarball
$ make && make install

 

$ /home/user/tarball/bin/curl
-bash: /home/user/tarball/bin/curl: No such file or directory
$ ~/tarball/x86_64-linux-uclibc/lib/ld64-uClibc-1.0.36.so --library-path /home/user/tarball/x86_64-linux-uclibc/lib/:/home/user/tarball/x86_64-linux-uclibc/lib64:/home/user/tarball/lib  /home/user/tarball/bin/curl --version
curl 7.72.0 (Linux) libcurl/7.72.0 OpenSSL/1.1.1h zlib/1.2.11 libssh2/1.9.0
Release-Date: 2020-08-27
Protocols: dict file ftp ftps gopher http https imap imaps pop3 pop3s rtsp scp sftp smb smbs smtp smtps telnet tftp
Features: AsynchDNS HTTPS-proxy IPv6 Largefile libz NTLM SSL UnixSockets

收工!

2020年11月1日 星期日

[動漫] 鬼滅之刃 一口氣看完 26 集動畫和 205 話漫畫

鬼滅之刃

沒想到幼稚園萬聖節可以看到 禰豆子 裝扮,拿到的小禮物又是這動漫。於是乎,就毛起來來了解!這動漫風格感覺應該是國中以上的分級吧 XDD

若要說第一次接觸是 Yahoo 首頁右邊旁的影片推薦,那時我有印象,某天晚上滑過去看了一下野豬跟主角第一次碰面在打鬥,不小心我也看完全部 XD 打鬥場面對男生真的有吸引到,但我那次也只是閒著才看,完全沒印象是啥卡通,只覺得怎麼那麼血腥。

後來這週末一口氣先在愛奇藝看了 26集動畫,用兩倍數花不到300分鐘就看完了!撐過去並適應血腥風格後,果真故事內容很吸引人的,看完動畫才發現目前上映的動漫電影 無限列車 非常有規劃的串在一起!不過我的作息太難去看電影了,於是乎,我開始看漫畫了。漫畫大概就略過前53話動畫的以描述的內容,從無限列車任務開始看起。

將近 150話的漫畫,大概看了有6小時吧,看完後很佩服作者的安排,意猶未盡,可能熬夜快速地看也有點對戰鬥內容麻痺 XD 反而沒有很享受後期大量的打鬥 XDD 

原本想收藏漫畫的,台灣全21冊配合雙11活動,一線線上購物平台只賣 1600 左右,可是家裡空間好像有點不足啊 Orz 透過鬼滅之刃讓人想起小時候老爸出差時,買了幾本漫畫給我們看,那時都隨便買兩三本單行本漫畫,如亂馬二分之一、幽遊白書第八冊,甚至一些尚不有名的作者畫得全一冊等等,真是懷念小時看漫畫的單純感。

2020年10月21日 星期三

處理 Adsense 政策中心 帳戶問題 廣告放送量受限 無效流量疑慮

Adsense-政策中心-帳戶問題-廣告放送受限-無效流量疑慮

負責幫公司經營流量變現不知不覺也三年了?時間過得真快。這個題目說真的是好玩的,運作原理不複雜,但變化無窮。如何幫公司從流量轉換現金是需要許多智慧的。這個題目也是任何做服務的終極目標,如何產生現金流來養活團隊!

近一年半來,月初結算才能發現上個月被扣了多少無效流量,緊接著要去拆解為何導致這個現象。這點一直以來都沒標準答案,尚未深入此領域的同事,總是認為這一定要有標準答案才對,殊不知 Google Adsense 就是不告訴你為什麼,連 Adsense 客服也不會跟你說,好心一點只會模糊的指導,甚至像遊戲 NPC 一樣,永遠只會說固定的對話。因為告訴你怎樣判斷無效流量後,有心人士就拿它吃 Google 豆腐的,這也是一條完全沒有標準答案的生活模式,趣味無限。

這幾年累積的經驗,常見處理無效流量的方式:

  • 降低廣告被誤點
  • 避免手機內 webview 被過早初始化(如 android TabHost 在背景初始化了網頁及 adsense 內容)
  • 避免在無使用版權的內容網頁上投放廣告(無內容)
  • 遵守 Adsense 廣吿政策

由於本就正派經營沒在買流量,一直認為無效流量的判定大多是 Google Adsense 誤判(過去也曾收過 google adsense 事後補償),直到最近在政策中心直接顯示有帳戶問題,廣告放送量受限。這招很恐怖,一刀見骨不給廣告投放。跟之前面對的無效流量不同,以前是正常拿到廣告來投放,月底在減去無效投放。而這次是一開始就不給廣告,涵蓋率約 2% 水準。

解法呢?回歸原理,除了重新檢視廣告投放是否符合 adsense 政策外,請記得多去思考無效流量的定義,真的快走到冥想階段 XD

Adsense - 營利和廣告 - 無效流量的定義

ref: https://support.google.com/adsense/answer/16737?hl=zh-Hant

當頭棒喝的句子:發布商仍有義務確保自己的廣告流量有效!

一直以來都正派經營,完全忘了無效流量可能來自既有的客戶,甚至有心人士!因此,需要花心思去抓可能的兇手,這時就回歸自身廣告投放的情境是如何,規劃怎樣抓出異常行為。

最後,我偷懶設計了一些 GA event 且設法紀錄 IP 資訊(例如把 IP 記錄在 event label,正規一點應當掃 web server access logs)。透過簡單的機制,就可以發現異常行為。例如期待正常的使用者一週使用服務最高只會瀏覽 50次,那單週超過百次的就很有可能是異常。再搭配 ipinfo.io/ip 去察看基本資訊,有時會找到一些相關訊息。對症下藥實現 IP 黑名單管理法,該名單內的 IP 在使用服務時就不會投放廣告,就能達成自身過濾無效廣告流量。

最終無效流量議題,仍回歸到避免在無效用戶上投放廣告!每一則廣告都是買家的錢, Google 要確保廣告投放是有意義的,這樣買家才會繼續在 Google Ads 買廣告,而邪惡的事件就是...有心人士可以故意一直去點擊廣告消耗掉別人(競爭對手)廣告預算。

我想,這無效流量的戰鬥還是會持續下去的。