2017年5月5日 星期五

理解 iptables 的使用


網路上的文章幾乎都使用舊版說明,雖然過時,但仍然可以學點常識.
iptables 資訊:  http://www.iptables.info/en/iptables-contents.html
各鏈條流程圖:  http://www.iptables.info/files/tables_traverse.jpg

列出 iptables 指令的使用方式:
        iptables   --help

        iptables   -h

常用的命令列格式:
      iptables   規範命令   鏈條名稱   規範選項
或     
      iptables   規範選項   規範命令   鏈條名稱

其中 規範選項  的各項順序只要處理得當,可以依照喜好自由調換位置.iptables 鏈條(chain)的規範命令是以"-大寫簡稱"或"--小寫全名"擇ㄧ使用:
   -A 或 --append  用於附加鏈條規則
   -C 或 --check  用於檢查鏈條規則是否存在
   -D 或 --delete  用於刪除鏈條規則, 以數字 1 為基準當第一條鏈條
   -I 或 --insert  用於插入鏈條規則, 若沒設定插入位置, 預設是插入當作第一條規則
   -L 或 --list  用於詳細列出鏈條規則
   -S 或 --list-rules  用於顯示鏈條簡表
   -N 或 --new   用於自訂鏈條規則
   -P 或 --policy  用於鏈條的預設政策,當鏈條的具體行動沒指定時將啟用(ACCEPT 或  DROP)
   -E 或 --rename-chain  用於改變鏈條名稱
   -R 或 --replace  用於改變鏈條的順序
   -F 或 --flush  用於刪除鏈條的規則
   -X 或 --delete-chain  用於刪除自訂鏈條
   -Z 或 --zero   用於鏈條計數器歸零

目前版本(version 1.6.0) iptables 內部共有五個表格(filter, mat, mangle,raw,security)可由規範選項 -t 來指定),每個表格各有不同的鏈條名稱,使用 -L 可以列出各表格的鏈條規則:
         $iptables    -t    filter    -L
由此來看 filter 有  INPUT,   FORWARDOUTPUT   3個鏈條,接著看:
         $iptables    -t   nat     -L
因此 nat 應該有  REROUTINGINPUTOUTPUTPOSTROUTING   4個鏈條,再來看:
         $iptables    -t   mangle    -L
所以 mangle 有  PREROUTINGINPUTFORWARDOUTPUTPOSTROUTING   5個鏈條
另外兩個 raw, security 似乎比較少用,詳細可上網找文章閱讀看看.

規範選項部份除了版本(-V--version)以外,都是以"-小寫簡稱"或"--小寫全名"擇ㄧ使用,有些選項可以使用驚嘆號 ! (反邏輯),將選項的邏輯允以反向(也就是在原本用意加上'非'這個字眼),例如:
  !  -p 或 --protocol  用於網路協定,像是  tcp 或 udp 或 icmp 或 all
  !  -s 或 --source  用於來源網址或網域, 像是  ipaddress 或 ipaddress/mask 之類的位址
  !  -d 或 --destination 用於目標網址或網域,像是 ipaddress 或 ipaddress/mask之 類的位址
  !  -i  或  --in-interface  用於來源網路界面, 像是 lo eth0 之類的名稱
  !  -o 或 --out-interface  用於目標網路界面, 像是 lo eth0 之類的名稱
  !  -f 或  --fragment  用於像是片狀的封包 ???
 只要不加驚嘆號, 就如字面上意義(正邏輯).

只能用正邏輯的規範選項有 :
   -j 或  --jump  指定目標(target), 可用 ACCEPT 或 REJECT 或 DROP
   -g 或 --goto  直接跳進指定的鏈條規範不返回
   -m 或 --match  使用指定模組來拓展匹配
   -t 或 --table   指定表格,可有 filter 或 nat 或 mangle 來過濾封包, 若未指定,則內定用 filter
   -w 或  --wait  等待表格鎖定時間,以秒為單位
   -v 或  --verbose  顯示冗餘資訊,像是目前計數器的數值... 等等

其它正邏輯選項還有:
   -4 或 --ipv4   用於 ipv4  的封包 ???
   -6 或 --ipv6  用於 ipv6 的封包 ???
   --modprobe=載入外部模組 ???
   -n 或 --numeric   網路位址(ip address/netmask)及端口(port)使用數字展開
   -x 或 --exact  展開數字 ???
   --line-numbers  當顯示列表時,前面附加行數的順序.

在 linux mint 系統上執行 iptables 必須要有 superuser 權限,自行定義一個變數(例如 iptables) 便於重複利用並簡化輸入:
    iptables='sudo iptables'
 
將鏈條名稱與規範選項合併就成為該鏈條的一個規則, iptables 如果定義規則時沒用選項 -t 來指定來表格,將會用 filter 當作內定表格.而且不同的表格將有不同的規範選項,因此底下說明可能只適用於 filter 表格(等同使用了 -t filter).

假設要設定 filter 表格內 OUTPUT 鏈條的規範,使用選項匹配模組(-m owner )去匹配是否等同指定的使用者(--uid-owner   $USER),如果選項匹配成功,執行指定目標(-j   REJECT ).將上述規則定義成一個變數 rule 方便後續使用:
    rule="OUTPUT   -m   owner   --uid-owner   $USER  -j   REJECT"

鏈條規範的執行流程會從所有設定規則的第一條開始一個個往下匹配,直到匹配成功去執行具體行動,如果在規則中沒有用 -j 設定目標,則會往下一條規則繼續匹配,如果全部規則都匹配不成,也就無具體行動,因此該鏈條的預設政策就會啟用(預設政策的規範選項僅可以是 ACCEPTDROP),要改變預設政策,使用規範命令 -P,例如:
     $iptables -P INPUT ACCEPT
     $iptables -P FORWARD  DROP
     $iptables -P OUTPUT  ACCEPT

使用  -A 添加規則到最後一條:
    $iptables   -A   $rule

如果認為規則很重要,可以使用 -I 插隊變成第一條規則:
    $iptables   -I   $rule

-L 可以詳細列出表格鏈條的規則,附加 --line-numbers 會將規則的順序一起列出:
    $iptables   -L   --line-numbers

或是用 -S 顯示表格鏈條的簡表:
    $iptables   -S

只要語法正確,就會被加入到鏈條的規則內, 因此相同的規則可能會重複,因此先檢查再添加可以防止重複添加,使用 -C 可以先檢查想啟用的規則是否存在,若存在只要輸出該規則的訊息:
    $iptables   -C   $rule   &&  echo Exist:$rule  ||  $iptables   -A   $rule

如果上述規則設定成功, 使用瀏覽器試試看,應該無法上網了.用 -D 可以刪除剛剛設定的規則:
    $iptables   -D   $rule

-D 只刪除第一個匹配到的規則,如果規則有重複,只會刪除第一個.如有需要可以執行 -D 多次直到刪除為止,或是用 -F 一次清除內部鏈條(但不含自訂名稱)所有的規則
    $iptables   -F  OUTPUT

-N 可以在表格自訂新鏈條,例如自訂一個有意義的鏈條名稱 OUTtcp:
     $iptables   -N   OUTtcp

一旦自訂鏈條名稱定義完成,就可以像正規鏈條一樣去定義規則:
     $iptables    -A   OUTtcp    -j   DROP

在相同表格內的自訂鏈條經由鏈條規範,使用選項 -j 當成目標(target)跳進去,例如:
     $iptables    -A   OUTPUT   -p   tcp   -j   OUTtcp

-X 可以清除自訂的鏈條(由 -N 指令去定義的鏈條),連同自訂鏈條名稱及規則都一併清除,如果 -X 後面不指定鏈條名稱,則清除全數自訂的鏈條:
    $iptables   -X   OUTtcp

用  -F  可以清除鏈條的規則,如果後面不指定表格,則只清除預設表格(-t filter)的鏈條規則(但不會清除自訂鏈條的名稱):
     $iptables   -F   OUTPUT

通常一開始設定 iptables 時,不僅要清除所有鏈條(包含自訂的)規則,連計數器也都一併清除為零,避免被無端的規則所干擾.
清除預設表自訂鏈條:
    $iptables   -X
清除預設表鏈條規則:
    $iptables   -F
清除預設表鏈條計數器:
    $iptables   -Z 

要注意的是 -P 所設定的預設政策(預設是全數鏈條 ACCEPT 開放)並不會因為清除而重設,只要之前有設定好,它就會持續有效.常用的伺服器端口,可以檢查 /etc/services 檔案內容,就可以略知一二,它包含有 tcp 及 udp 兩種通信協定:
    cat /etc/services | more

在 linux mint 系統,有些內部的 porcess 可能會使用 udp 端口相互溝通,如果全擋,怕會無法運作,可以用 ifconfig 查一下對外 ip 的界面,目前查到的是 enp2s0,因此管制該網路界面的輸出鍊,就能抵擋大部分的網路運作了.先清除所有規則,設定好預設政策,再分別設定 tcp 及 udp 的規則,把不符合規則的端口都丟棄:
    $iptables   -F
    $iptables   -P   INPUT   ACCEPT
    $iptables   -P   OUTPUT   ACCEPT
    $iptables   -A   OUTPUT   -o  enp2s0   -p    tcp     -j    DROP
    $iptables   -A   OUTPUT   -o  enp2s0   -p    udp    -j    DROP 

這樣子就阻擋了對外所有網路第三層的 tcp/udp 通信協定.執行 ping www.google.com.tw 看看,應該無法得到回應.但若直接用 ping 168.95.192.1 卻是可以的, 那是因為 ip 屬於第二層通信協定.只要插隊設定一條輸出鏈(-I   OUTPUT)的規則,管制網路界面(-o   enp2s0)的通信協定(-p   udp),比對端口(--dport   53),確認行動(-j   ACCEPT):
   $iptables   -I   OUTPUT -o   enp2s0   -p   udp   --dport   53   -j    ACCEPT

把 udp 端口 53 打開,主機就能向DNS(Domain Name Server)查詢到 ip 位址,接著就會得到 ip/icmp 回應,但此時仍無法用瀏覽器瀏覽網頁, 因為 http 是用 tcp 端口 80, 而 https 是用 tcp 端口 443.為了一次開放多個 tcp 端口,可以插隊設定一條輸出鏈(-I OUTPUT)的規則,管制通信協定(-p tcp),調用匹配模組(-m multiport),比對離散端口(--dport 80,443),確認行動(-j ACCEPT):
   $iptables   -I  OUTPUT  -o   enp2s0   -p   tcp -m multiport   --dport   80,443   -j  ACCEPT

此時用瀏覽器上網應該就能暢行無阻了,對於其它 tcp  端口,例如 ssh 端口 22, ftp 端口 21 等都可依樣畫葫蘆自行設定規則,總結這次瀏覽網頁所需設定的規則,使用預設表格(-t filter):
    iptables='sudo iptables'
    $iptables   -F
    $iptables   -P  INPUT   ACCEPT
    $iptables   -P  OUTPUT   ACCEPT
    $iptables   -A  OUTPUT   -o  enp2s0   -p  tcp     -j    DROP
    $iptables   -A  OUTPUT   -o  enp2s0   -p  udp    -j    DROP
    $iptables   -I   OUTPUT   -o  enp2s0   -p  udp   --dport   53   -j    ACCEPT
    $iptables   -I   OUTPUT   -o  enp2s0   -p  tcp -m  multiport   --dport   80,443   -j  ACCEPT

nat 表格的轉向(REDIRECT)的功能.由插入 nat 表格事前輸入鍊(-I PREROUTING  -t nat)當範例,當從外部(-i   enp2s0)接收到的封包時,原本要傳給 tcp 端口 80(-p  tcp  --dport 80)的,事先改成(REDIRECT)端口 3128(--to-port  3128),之後才進主機作後續鏈條的處理(可先參考網址有關鏈條的流程會比較清楚脈絡: http://www.iptables.info/files/tables_traverse.jpg)
    $iptables -I  PREROUTING   -t   nat  -i   enp2s0  -p  tcp   --dport  80   -j   REDIRECT   --to-port   3128 

送出去的封包更換端口也可以透過轉向的功能,由插入 nat 表格的輸出(-I OUTPUT -t nat)當範例,將原本要送出 tcp 端口 8888(-p tcp --dport 8888)的封包,換成(REDIRECT)端口 80(--to-port  80)後直接丟出去:
    $iptables -I  OUTPUT  -t   nat  -p   tcp  --dport   8888  -j   REDIRECT   --to-port   80

上述端口轉向並不一定會用到 ip 路由(Route)的功能,如果只是轉向特定端口,就不必將 /proc/sys/net/ipv4/ip_forward 打開.要將 linux 當作 ip 分享器,需利用超級使用者的權限開啟 ip_forward 的功能,再用 iptables 設定 nat 表格的事後鍊(POSTROUTING)把送出封包的來源位址(soure  ip)直接替換成主機位址,有兩種方式可以達成 ip 分享的目的:

第一個,當主機的位址是動態取得時,簡單設定 nat 表格的事後鍊(-A  POSTROUTING  -t  nat)讓 linux 內核把要送出去的封包(-o   enp2s0)自動改裝(-j MASQUERADE),變成 ip 分享器:
    sudo su
    echo 1 > /proc/sys/net/ipv4/ip_forward
    iptables  -A 
POSTROUTING  -t  nat    -o   enp2s0    -j   MASQUERADE


另一個是當主機固定位址時,把要送出去的封包(-o   enp2s0),直接用主機位址(假設 ip = 10.0.0.1)替換掉來源位址( -j SNAT --to-source),雖然麻煩一點,但速度較快:
    iptables  -A  POSTROUTING  -t  nat   -o   enp2s0   -j  SNAT --to-source 10.0.0.1 

如果要處理經 nat 改裝的封包,可以設定事前(-A PREROUTING -t nat),由網路界面收到的封包(-i   enp2s0),事先更換封包的目標位址(-j  DNAT --to-desination)由主機(10.0.0.1)來取代,藉此將它轉給主機再作後續處理:
    iptables  -A  PREROUTING  -t  nat  -i   enp2s0   -j  DNAT --to-desination 10.0.0.1
.

2017年5月2日 星期二

Wine 利用 winepath 轉換 linux 系統上檔案位置到 Wine 系統上使用

為了要用滑鼠拖拉(drag and drop)的方式開啟檔案,首先執行檔要能接收檔案,若是用 bash script 可以使用 $1 接收第一個參數,經由命令變數 $(winepath -w %1)可以轉換給 Wine 應用程式使用.而使用副檔名 .desktop 的執行檔則可以用  %f 來接收滑鼠傳來的檔案位置,同樣也是利用命令變數 $(winepath -w %f) 轉換給 Wine 應用程式加以使用.類似像這樣:
[Desktop Entry]
Exec=env  WINEPREFIX=/home/mint/.wine  wine  'c:\\windows\\notepad.exe' $(winepath -w %f)
Type=Application

記得將它存檔並設定為可執行檔,這樣就可以利用滑鼠拖拉檔案到該執行擋上,Wine 應用程式就可以從滑鼠接收到檔案接著轉換檔案位置,最後在 Wine 系統中開啟檔案.

當然如果有建立 mswin  群組,並將 mint 加入該群組, 透過切換群組開啟檔案,只要將上述檔案稍微修改一下改用 sg 命令:
[Desktop Entry]
Exec=sg mswin "env  WINEPREFIX=/home/mint/.wine  wine  'c:\\windows\\notepad.exe' $(winepath -w %f)"
Type=Application

 Wine 已更新到 2.7 版了, 參考網站: https://wiki.winehq.org/Ubuntu

sudo dpkg --add-architecture i386
wget https://dl.winehq.org/wine-builds/Release.key
sudo apt-key add Release.key
sudo apt-add-repository 'deb https://dl.winehq.org/wine-builds/ubuntu/ xenial main'
sudo apt-get update
sudo apt-get install --install-recommends winehq-staging

2017年5月1日 星期一

避免 Wine 的應用程式開啟網路

參考文章: https://askubuntu.com/questions/19346/how-to-block-internet-access-for-wine-applications
有些 windows 應用程式太邪惡了, 許多病毒或是木馬甚至原版軟體都有可能偷偷上網傳遞資訊,使用者根本無法察覺,如果將它安裝成 Wine 的應用程式想必也不例外,因此有必要限制 Wine 的網路行為.在 linux mint 可以用 groupadd 產生新的群組,用 adduser 將使用者加入這新的群組,再透過 iptables 阻斷群組的網路行為:
       sudo groupadd  mswin
       sudo adduser  mint  mswin
       sudo iptables  -A  OUTPUT  -m  owner  --gid-owner  mswin  -j  REJECT

往後只要用 sg 先切換使用群組,之後才載入 Wine 的應用程式(例如內建瀏覽器 wine iexplore.exe),這樣就能徹底隔絕 Wine 應用程式的網路運作了.
       sg  mswin  "wine iexplore.exe"

如果要用滑鼠雙擊就可執行的 Wine 應用程式,可以編輯一個檔案副檔名用 .desktop 命名, Exec 指定內容則改用 linux 的 sg 切換群組並包住 env 命令,像這樣:
[Desktop Entry]
Exec=sg mswin "env  WINEPREFIX=/home/mint/.wine  wine  'c:\\windows\\notepad.exe'"
Type=Application

要注意的是 env 命令的部份要用引號括起來. 在 wine 的應用程式敘述用單引號而整個 env 部份則改用雙引號.單引號與雙引號的不同在於:單引號裡面內容,如果有$變數或執行()命令或者跳脫字元\時,並不會展開賦值(evaluate),而是一成不變的照實敘述,但如果放在雙引號裡面則會先展開變數才會執行後續動作.記憶口訣: 一層不變(一成不變), 二度就要(二度就樂一ㄠˋ)

2017年4月30日 星期日

執行備份的 wine 應用程式

安裝完 wine 的應用程式後,預設全都會放在 ~/.wine 底下, 可以先切換到家目錄(~)再將 .wine 目錄打包備份,之後把 wine.tgz 移至別處加以收藏,在終端機輸入以下命令將 .wine 打包:
       cd  ~
       tar  -zcvf  wine.tgz  .wine

如果有任何意外破壞了 .wine 的目錄結構,可以先刪掉該目錄(rm -rf .wine)再藉由回存指令(tar  -zxvf wine.tgz), 就可以恢復該目錄所有檔案,並不需要將應用程式重頭安裝.至於剛安裝完 wine 執行 winecfg 時,一開始會要求從網路下載穩定版本的 gecko 及 mono, 但使用備份檔的好處是因為先前已安裝過並備份到 wine.tgz 裡面了, 因此不用再從網路下載資源浪費時間.假設 /path_to 是 wine.tgz 想要解壓縮之位置,而 /path_from 是備份檔案 wine.tgz 所收藏之地方,在終端機輸入以下命令,用打包的檔案還原檔案:
        sudo  mkdir   /path_to
        sudo  chown  mint   /path_to
        cd   /path_to
        tar  -zxvf   /path_from/wine.tgz

如果 .wine 的目錄不是放在家目錄(~/.wine)底下,可以透過 linux 的 env 命令(設定環境變數並執行後續命令,相關用法使用 man env 就可以瞭解),先將環境變數 WINEPREFIX 指向 .wine 所在的位置,接著用 wine去 載入應用程式來執行.想要執行 windows 內建的 notepad.exe,在終端機輸入:
        env  WINEPREFIX="/path_to/.wine"   wine    "c:\\windows\\notepad.exe"

如果覺得用 env 執行命令很繁瑣,也可以先切換到家目錄(~), 再用符號連結(symbolic link)的方式去建立連結,在終端機輸入命令:
        cd  ~
        ln   -sf   /path_to/.wine    .wine

之後在終端機用 wine 就可以載入應用程式並執行:
      wine    "c:\\windows\\notepad.exe"

另外用 wine regedit 去手動設定 windows 的內建環境變數, 可以在裡面添加 path:
       REGEDIT4

       [HKEY_CURRENT_USER\Environment]
       "path"="%path%;c:\windows"

或將上述內容存成 winenv.reg 檔案, 在終端機輸入 wine regedit 檔名,把要註冊的內容放進 windows 環境變數內:
       wine regedit  winenv.reg

往後就不用再打一長串的路徑,直接在終端機用 wine 載入應用程式,windows 會自動用 path 所指定的目錄去找尋執行檔來執行,因此要執行內建的 notepad.exe 只要在終端機輸入 :
      wine notepad

在 linux mint上有更直接的用法,去編輯一個檔案,將副檔名以 .desktop 命名,在桌面進入點的段落 [Desktop Entry] 敘述中包含 Exec 及 Type 這兩個關鍵字,其中 Exec 讓它等於上述 linux 的 env 命令,將需要執行 wine 程式的相關參數隨後填入,而 Type 則直接等於 Application 這個字, 類似像這樣:
     [Desktop Entry]
     Exec=env  WINEPREFIX="/home/mint/.wine"  wine  "c:\\windows\\notepad.exe"
     Type=Application

將它存檔,先隨便取個名字(例如 notepad.desktop), 之後用滑鼠右鍵將它改成中文名,要執行時只要用滑鼠左鍵雙擊該檔案就能直接執行,相當方便.

2017年4月23日 星期日

用 nodejs 內建的 Promise 語法執行 child_process 外部程式 ffmpeg


定義 function ffmpeg,記得要將可執行檔 ffmpeg 放在目前目錄底下:
1. 這是原始function的定義,傳進來參數命名為 options,  檔名: child.js
      function ffmpeg(options) {
          const child = require('child_process');    // 調用內建child_process程式庫
          var cmd =__dirname+'/ffmpeg ' + options;   // 傳給child_process 時所需要的參數
          child.exec(cmd,function (err, stdout, stderr) { // child_proces開始處理指令
                  if( err )   console.log('出錯了:'+err+'\nstderr:'+stderr);
                  else       console.log('成功了:'+stdout);
           });  // end child_process
       } // end of ffmpeg
       ffmpeg('-version'); // 呼叫 ffmpeg 函式:

2. 這是將上述 function ffmpeg(options )轉化成 Promise 的用法, 檔名: child.js
      function ffmpeg(options) {
           return new Promise(function (ok,ng) {//回傳 closure,將會有兩個callback function
               const child = require('child_process');
               var cmd =__dirname+'/ffmpeg ' + options;
               child.exec(cmd, function (err, stdout, stderr) {
                   if(  err )  ng('出錯了:'+err+'\nstderr:'+stderr);// 回調(callback) ng
                   else       ok('成功了:'+stdout);   // 回調(callback) ok
               }); // end child_process
           }); // end of closure
       } // end of ffmpeg
      // 轉化成 Promise,就可以呼叫 then( ) 及 catch( ), 執行指令:
       ffmpeg('-version').then(console.log).catch(console.log);
      // 其中 then( ) 裡面的 callback 對應到 ok, 而 catch( ) 裡面的 callback 對應到 ng

3.  存檔用 nodejs 執行
       js  child.js


p.s. 轉檔時, 避免操壞硬碟, 改用 RAMDISK, linux 的 ramdisk 位置在 /dev/shm, 參考範例:
    var fs = require('fs'),
    var dirRAM='/dev/shm/hls'; // create a directory in ramdisk
    fs.mkdir(dirRAM, function(err) {
        fs.symlink(dirRAM, __dirname + '/hls', function(errlink ) { // create a symbolic link
            process.chdir(__dirname + '/hls'); // enter to the directory
            ffmpeg('-i '+ __dirname + '/oceans.mp4  -hls_flags delete_segments playlist.m3u8').then(console.log).catch(console.log); // media file transcode
        })
    })

2017年4月20日 星期四

下載 ffmpeg-3.3 自行編譯,讓它支援 pthreads, librtmp, libx264, libvpx, libx265, libvorbis, libmp3lame, libass 方便轉換影音檔

1. 上官網先下載原始碼(source code) 並解壓縮:
    wget http://ffmpeg.org/releases/ffmpeg-3.3.tar.bz2
    tar -xvf ffmpeg-3.3.tar.bz2
    cd ffmpeg-3.3
或是利用 git 複製出整個 repository:
    git clone https://git.ffmpeg.org/ffmpeg.git

2. 下載編譯環所需要的標頭檔:
sudo apt-get install librtmp-dev libx264-dev libvpx-dev libx265-dev libvorbis-dev libmp3lame-dev libass-dev yasm

3. 設定環境並開始編譯:
  ./configure --enable-gpl --enable-pthreads --enable-librtmp  --enable-libx264 --enable-libvpx --enable-libx265 --enable-libvorbis --enable-libmp3lame --enable-libass
  make

4. 複製 ffmpeg 到 /usr/bin
   sudo cp ffmpeg /usr/bin


5. 一些使用 ffmpeg 的範例:
   列出 webcam 支援的格式:
       ffmpeg -f v4l2 -list_formats all -i /dev/video0
   
   讓 ffmpeg 在背景擷取 webcam 影像,轉換產生 http live streaming (HLS) 所需要的檔案:
   ffmpeg -f v4l2 -i /dev/video0 -hls_flags delete_segments playlist.m3u8

   讓 ffmpeg 在背景擷取mp4檔案,轉換產生每個ts檔大約是10秒的HLS檔案:
   ffmpeg -i oceans.mp4 -hls_time 10 playlist.m3u8

   
   架設 http live streaming server 只要架設好 http server,再將轉換完成的HLS檔案放在讓 HLS client 可以下載到的地方,一旦下載完 playlist.m3u8 就可以隨後播放裡面的ts影片擋了.

bash 變數, 錢字符號 $, ${ }, $( ), $(( )) 不同點

參考文章: http://stackoverflow.com/questions/27472540/difference-between-and-in-bash-scripting
設定 bash 的變數 var 成為一個字串, 例如:  
     var = 'This is a test'
若要將變數內容取出來,在變數名稱前面加上錢字符號 $ 就可:
     echo $var
如果變數後面有跟隨其它字元時,用大括號刮起來以便區別成變數,因此 $ 與 ${ } 是相同用法.
     echo ${var}string,  append some string behind
但 $( ) 在小括號裡的是一個指令, 會被 bash 先取出來執行,執行完的輸出就是變數內容, 簡稱指令變數, 例如:
     echo  目前目錄是:$(pwd)
用雙小括號變數可以做簡單整數的加減乘除(+-*/)四則運算,:
   echo $(( 5-19+2*3 + 3/3 ))