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 買廣告,而邪惡的事件就是...有心人士可以故意一直去點擊廣告消耗掉別人(競爭對手)廣告預算。

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

2020年9月26日 星期六

塑膠年年的 塑膠黏黏的 老化氧化的解救方式

塑膠 黏黏 老化 氧化 處理方式

以前買到一個螢幕沒有內建喇叭時,買了一個飛利浦特價的藍牙小音箱,當時覺得外型還滿可愛的就下手了。隨著時間,已經被我晾在旁邊兩年了,原本想拿來跟投影機搭配,卻發現整個機身黏到不行又沾滿灰塵。透過用膠帶沾黏處理,還是沒解決。甚至一度想說拿膠帶包一身算了 XD

後來,還是敲敲關鍵字研究一下大家的解法,有很多種,其中應景的解法就是家家戶戶在 COVID-19 疫情下都早已配有酒精!只需拿乾淨的小布,用酒精噴濕拿來擦拭機殼,即可解決。

在研究資料時,也才發現常見的環保塑膠會隨著時間如此,因此有些3C產品會進行特惠清庫存,以免買家拿到後,整個黏到不行而退貨

2020年9月18日 星期五

台灣社群行銷年會 2020 團拜

台灣社群行銷年會 2020

今年報名參加 taiwan social marketing 2020 活動,擴充一下自己行銷領域知識、順便建立關鍵字索引,沒想到這場有 2800 人!記得上一次來這種地方好像是 n 年前的 Awsome Day,每次來都背著筆電,結果筆電都沒用到,接著不知中午要吃啥,輪迴著每次都想吃超商卻又發現超商要走很遠,然後隨便找一間吃完,才想起來旁邊不是有世貿餐廳,不是有 101 美食街,不是有 ATT4Fun !! 這次活動的彩蛋大概是認識旁邊的高手,哈拉了幾句,受益良多。

回過頭來,說一下會讓我期待的題目是 PopDaily 波波黛莉的異想世界 近況。近幾年我也在負責流量變現,有觀察到 Alexa.com 的 Top Sites in Taiwan 的排名變化,因此對這間感到興趣。雖然我還是把他歸類在內容農場的思維,但近幾年內容農場已經開始收斂,而透過 copy 思維的產文方式在 SEO 或 Social Network 已經佔不到什麼便宜,還活著服務絕大多數都進入 PGC 領域,因為 UGC 水準很難控制,沒有分潤機制也吸引不到別人貢獻,所以,挽起袖子,自己養!

很高興聽到 PopDaily 在 2017 年起開始軸轉,朝向經營 PGC 社群。我記得前幾年有關注到公司資本額的變化,那時以為單純賣掉公司,這次聽講才發現,公司經營者很大膽的向股東們論述未來走法,將全部利潤再投入經營公司核心,陸續在 2020 年初也看到在各個常見的工程粉絲團張貼聘請一些數據分析的職缺,非常努力地往前邁進。

再次回顧,再次敬佩這間公司。

接下來記憶深刻的是 TikTok 吧!原先一直覺得年紀已大,跟不上時代。近半年還是設法安裝 TikTok/小紅書/IG/Snapchat ,強迫自己一週播一點時間去滑幾下。後來看來看去核心都是 TikTok 機制。我認為 TikTok 營造出讓眾人可以快速/低門檻的加入表演,透過樣版/快速上手模仿,讓整個社群瘋狂起來,甚至濾鏡什麼都不是太重要的開始。

令我驚訝的是 TikTok 原來跟中國境內的抖音模式不同,抖音有直播帶貨等服務變現機制,而 TikTok 沒有這種極度噁心的機制(未來說不定也會有?畢竟網購經營還是最佳的變現手段)。跟創作者沒有分潤機制,但在台灣沒推廣的機制下,還是產生了 400萬 MAU 呢!甚至在推廣未來想找資料,就上 TikTok 搜尋 hashtag!!

TikTok 關鍵數字:

  • 每月有 700萬支影片
  • 平均一人一天會打開 8 次 app
  • 平均一人一天會觀看 45分鐘!!
  • 請重視影片觀看數,而非粉絲數,就算沒有粉絲的,也很可能靠推薦機制讓很多人看到
  • 用戶其實是先看推薦影片,而非追蹤的用戶

此外 TikTok 的核心還是跟推薦系統脫不了關係,正是從內容農場起家的今日頭條,透過收集大量有趣的事物,再搭配 SEO 跟推薦系統瘋狂搶佔眼球。

剩下跟本業相關的,其實是 91APP ,畢竟自身就是在公司負責數據收集/系統建置/服務變現相關應用,只是隨著年紀的增加,越來越能體會何謂團體戰!就像其他講者公司也都採用 91APP 的方案,賺錢的公司應當關注自己的核心事業,把系統整合的交給專業的來 XD 不要太貪心都自己做,這樣可以切割風險管控,更可以專注在自己的強項。

其餘演講內容也都很精實,但跟我的本業就相距較遠,像是明星代言的成本跟效果、直播帶貨等等。但對岸基本上是網購/直播的大聯盟等級,其實已經有一些翻出牆外再說書的 Youtuber 可以略知一二,有興趣可以看看:


可以觀看一下此活動的 社群行銷年會 舉辦者龍哥的 影片剪影,感受一下 2800 位聽眾的氣勢。其餘的課程文字筆記,可以瀏覽社群的文字記者,都還滿仔細的: