script 嵌入 binary 檔案

下載的一些工具安裝檔案, 有時候是一個檔案頗大的 shell script. 這麼大的原因是 script 有塞入 binary file 的關係. 而這樣的好處應該就是可以把檔案集中成一個. 之外我覺得就是省去記檔案名稱吧 XDD. 此文章紀錄如何實作封裝與安裝的 script.

實作

這邊分兩個部分, 一個是負責封裝 install template script 與 binary 檔案的 pack script. 另一個則是 install template script. 這的 binary file 以 tar 檔案為例子.

Pack script

pack script 的流程主要是以 install template script 為樣板, 產生一個 install script. 接著在後面加入類似標籤的字串. 並在”下一行“塞入 tar 檔案.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/bin/sh
read -p "Input a tar file path: " file

# is file exsted >
if [ ! -f ${file} ]
then
    echo "no such file"
    exit 1
fi

# check file extension
extension=$(basename ${file} | tr "[:upper:]" "[:lower:]" | tr '.' '\n' | tail -n 1)
if [ ${extension} != "tar" ]
then
    echo "only support tar file"
    exit 1
fi

# append install.sh first
echo "packing...."
cat install_script.sh > install.sh
echo "PAYLOAD:" >> install.sh

# append tar file
cat ${file}  >> install.sh
echo "done...."

line 2 取得想要塞入 script 的 tar 檔案路徑. line 5-9 判斷輸入的檔案是否存在. line 12-17 判斷輸入的檔案是否為 tar 檔案. 擷取副檔名的部分由 line 12 得到. 接下來就是 install script 與 tar 檔案的部分. line 20-21 透過 cat 指令把 install template script 內容輸出到 install.sh, 接著 line 22 塞入 PAYLOAD: 標籤. 最後透過 cat 指令, 把 tar 檔案附加於 script 後面.

Install template script

主要是負責安裝的部分, 會去尋找 install script 裡面的標籤 PAYLOAD:. 把下一行的部分都視為 tar 來做處理.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/bin/sh

unpack()
{
    file=$1
    match=$(($(grep --text --line-number -m1 '^PAYLOAD:$' ${file} | cut -d ':' -f 1) + 1))
    echo "extract payload after line ${match}"
    echo "create destination folder \"unpack\""
    mkdir unpack
    echo "extracting...."
    tail -n +${match} $0 | tar -xvf - -C unpack
}


read -p "install ? (y/n) " ans
result=`echo ${ans} | tr "[:upper:]" "[:lower:]"`

# exit installation
if [ ${result} != "y" ]
then
    echo "exit installation"
    exit 0
fi

# start to install
unpack $0
exit 0

主要解說 unpack 函數. line 3-12 unpack 函數負責解壓以及安裝. line 6 在尋找 script 內的標籤 "PAYLOAD:". 利用 grep 指令去尋找開頭 PAYLOAD: 和 PAYLOAD: 結尾字串. -m1 表示搜尋到之後就可以停止搜尋了. line 9-11 則是把檔案解壓縮到所建立的 unpack 目錄底下.

執行

hayashiyoshihitoshis-MacBook-Pro:temp yijyun$ ls
folder.tar  install_script.sh pack.sh
hayashiyoshihitoshis-MacBook-Pro:temp yijyun$ sh pack.sh
Input a tar file path: folder.tar
packing....
done....
hayashiyoshihitoshis-MacBook-Pro:temp yijyun$ ls
folder.tar  install.sh  install_script.sh pack.sh

這邊有三個檔案, 分別為 tar 檔案, 負責封裝的 pack.sh 以及負責安裝 install_script.sh 樣板. 先使用 pack.sh 來封裝 install_script.sh 與 tar 檔案來成為一個 install.sh 檔案

hayashiyoshihitoshis-MacBook-Pro:temp yijyun$ sh install.sh
install ? (y/n) y
extract payload after line 29
create destination folder "unpack"
extracting....
x dir/
x dir/temp.2
x dir/temp.3
x dir/temp.1

hayashiyoshihitoshis-MacBook-Pro:temp yijyun$ ls . unpack/*
.:
folder.tar  install_script.sh unpack
install.sh  pack.sh

unpack/dir:
temp.1 temp.2 temp.3

這邊執行 install.sh 來進行安裝. 這邊會先建立一個 unpack 目錄. 接著把 script 內的 tar 檔案解壓縮於 unpack 目錄裡.

Reference

  1. Add a Binary Payload to your Shell Scripts

留言

這個網誌中的熱門文章

yocto recipe : (1) 撰寫 recipe

yocto recipe : (2) 撰寫 bbappend

yocto recipe : (3) 使用 External Source 來編譯軟體