pv 控制 pipe 的速度
因為想控制某些程式的傳輸速度, 所以想找找看有沒有 linux 命令 能像節流閥那樣串在管道中就能限制通過的流量, 就找到一個叫 pv 的小工具, 不只是節流閥,還可以做流量統計。 隔天想想其實也可以自己用 shell script 寫一個土炮版本的。
透過 wifi 傳檔案但手機和筆電不合
我習慣用筆電開熱點,把有線網路分享給手機無線上網。 然後就能用 ftp 或 adb 傳檔案,省去 usb 線的麻煩。 但我的筆電好像和手機不合,如果 wifi 流量太大手機會自動斷線。 所以要嘛用 ftp 的斷點續傳,要嘛手動控制傳輸速度。
ftp 斷點續傳
ftp 支援斷點續傳,所以可以無腦重傳,
用 shell script 控制只要斷線就重傳的無窮迴圈就好了。
其實我用的是 sftp,然後我習慣把手機寫到 ssh_config
裡,
就能用 alias 連線。
while echo 'reput -r my-file/' | sftp atom
do
sleep 1s
done
用 adb 傳送檔案的二種方法
另一招就是用 adb,我的手機有 root, 所以能 用 app 設定透過 wifi 連結 adb。 連上後可以用 adb push 傳檔案,或是用 shell 傳。 adb push 我不會控制速度,以我的經驗就是速度會吃滿, 然後手機就斷線了。 shell 就是之前提過用 pipe 傳, 我就想如果中間加個管道命令,像節流閥那樣就能控制速度了。
# 用 adb
adb push my-file/ /sdcard/
# 用 shell
tar -zcf - my-file/ | adb shell tar -C /sdcard/ -zxf -
# 如果有節流閥
tar -zcf - my-file/ \
| pipe-speed-controll --max-per-second 200k \
| adb shell tar -C /sdcard/ -zxf -
管道哲學的好處就是,可以方便的內嵌各種工具。 像如果要做壓縮,就在收發端各加個 gzip 命令, (不過上面的 tar 已經在打包時壓縮了。) 要用 ascii 傳,就加個 base64。
# 手動用 gzip 壓縮
tar -cf - my-file/ \
| gzip -c - \
| adb shell 'zcat - | tar -C /sdcard/ -xf -'
# base64
tar -cf - my-file/ \
| base64 - \
| adb shell 'base64 -d - | tar -C /sdcard/ -xf -'
流量工具 pv
於是 google 後就找到一個叫 pv 的工具, 全名是 pipe-view,不只有節流閥功能,還有流量統計。 基本上和 cat 相同都是把輸入轉到輸出, 但就是多了流量控制、統計的功能。
例如限制流量為 200k/s, 同時 pv 會自動統計流量,輸出到 standard error:
tar -zcf - my-file/ \
| pv --rate-limit 200k \
| adb shell tar -C /sdcard/ -xf -
# 輸出
# 2.05MiB 0:00:07 [ 301KiB/s] [ <=> ]
另外也可以改成控制 buffer 大小。
總之是個實用的小工具,
在 debian 可以直接用 apt install pv
安裝。
用 shell script 徒手實現 pv
隔天發白日夢時,忽然想到 pv 的功能其實可以用 shell script 實現, 只要用 sleep 控制一秒讀一次,head 則控制讀多少資料。 或說每 sleep 一秒,就用 head 讀固定量的資料。
my_pv() {
local byte=$1
while sleep 1s
do
head -c $byte
done
}
yes | my_pv 8
但這樣在流量慢時會一直卡在 sleep 那邊, sleep 整整一秒後才開始讀資料。 改善方式是可以把 sleep 丟到背景執行, 就能馬上在一秒期間內 sleep 的同時執行 head, 再用 wait 確保上一次 sleep 退出後再開始下一次讀取。
my_pv() {
local byte=$1
while wait
do
head -c $byte
sleep 1s &
done
}
yes | my_pv 200