Skip to main content

16 posts tagged with "System"

View All Tags

· One min read

刪除特定一行

sed '/^keywords:/d' input > output

刪除符合字串後的所有行數

sed '/^keywords/,$d' input > output

搭配 Find 達到大量修改所有檔案

統一刪除所有檔案

find . -type f -exec sed -i '' '/^authors:/d' {} +

Append 一行新的,換行要特別注意處理

find . -type f -exec sed -i '' '/^title/a\
authors: hwchiu\
' {} +

大量換名稱 https://hackmd.io/_uploads 變成 ./assets/

find *.md -type f -exec sed -i '' -e 's/https:\/\/hackmd\.io\/_uploads\//\.\/assets\//g' {} +

假設環境中有大量檔案需要改名稱,透過 rename 這個工具可以快速達成 譬如以下範例會先用正規表達式找尋所有符合的檔案名稱,接者將所有 read-notes 都改名為 reading-notes

rename 's/read-notes/reading-notes/' *read-notes-*

· 7 min read

blktrace is a block layer IO tracing mechanism which provide detailed information about request queue operations up to user space.

blkparse will combine streams of events for various devices on various CPUs, and produce a formatted output the the event information. It take the output of above tool blktrace and convert those information into fency readable form.

In the following, We will use those tools blktrace and blkparse to help us to observe sector numbers which has been written by fio requests. We will use the fil to generate two diffenrt IO pattern requests, sequence write and random write.

Environment

OS: Ubuntu 14.04 Storage: NVME FIO: fio-2.19-12-gb94d blktrace: 2.0.0 blkparse: 1.1.0

you can use following commands to install blktrace and blkparse

apt-get install -y blktrace

Experiment

Step1

In order to make the output of blkparse more easily to read, we set the numjobs to 1. Following is my fio config

[global]
iodepth=256
numjobs=1
direct=1

time_based
runtime=120
group_reporting
size=5G
ioengine=libaio

filename=/dev/nvme1n1
[rw]
bs=4k
rw=randwrite

[sw]
bs=64k
rw=write

After we setup the fio config, use the fio to generate the IO request. In this example, we ask the fio to generate the IO via sequence write pattern.

fio ${path_of_config} section=sw

During the experiment, you can use the tool iostat to monitor the I/O information about the device we want to observe.

Step2

Open other terminal and use blktrace to collection the data, there are two parameter we need to use, First one is -d, which indicate what target device blktrace will monitor to. Second, is -w, we use it to limit the time (seconds) how long blktrace will run. So, our final command looks like below.

blktrace -d /dev/nvme1n1 -w 60

In the end of blktrace, you can discover some new files has created by blktrace and its prefix name is nvme1n1.blktrac.xx The number of files is depends how may CPUs in your system.

-rw-r--r--  1 root     root         821152 Jun  2 10:39 nvme1n1.blktrace.0
-rw-r--r-- 1 root root 21044368 Jun 2 10:39 nvme1n1.blktrace.1
-rw-r--r-- 1 root root 462864 Jun 2 10:39 nvme1n1.blktrace.10
-rw-r--r-- 1 root root 737960 Jun 2 10:39 nvme1n1.blktrace.11
-rw-r--r-- 1 root root 865872 Jun 2 10:39 nvme1n1.blktrace.12
-rw-r--r-- 1 root root 755248 Jun 2 10:39 nvme1n1.blktrace.13
-rw-r--r-- 1 root root 4675176 Jun 2 10:39 nvme1n1.blktrace.14
-rw-r--r-- 1 root root 4471480 Jun 2 10:39 nvme1n1.blktrace.15
-rw-r--r-- 1 root root 5070264 Jun 2 10:39 nvme1n1.blktrace.16
-rw-r--r-- 1 root root 5075040 Jun 2 10:39 nvme1n1.blktrace.17
-rw-r--r-- 1 root root 5062104 Jun 2 10:39 nvme1n1.blktrace.18
-rw-r--r-- 1 root root 5586936 Jun 2 10:39 nvme1n1.blktrace.19
-rw-r--r-- 1 root root 3718848 Jun 2 10:39 nvme1n1.blktrace.2

Step3

Now, we can use the blkparse to regenerate human-readable output form the output we get via blktrace before.

We need to indicate source files, you can just use the device name without .blktrace.xx, for example, nvmen1, it will search all files which match the pattern nvmen1.blktrace.xx and put together to analyze. Then, the -f option used to foramt the output data, you can find more about it via man blkparse

OUTPUT DESCRIPTION AND FORMATTING
The output from blkparse can be tailored for specific use -- in particular, to ease parsing of output, and/or limit output fields to those the user wants to see. The data for fields which can be output include:

a Action, a (small) string (1 or 2 characters) -- see table below for more details

c CPU id

C Command

d RWBS field, a (small) string (1-3 characters) -- see section below for more details

D 7-character string containing the major and minor numbers of the event's device (separated by a comma).

e Error value

m Minor number of event's device.

M Major number of event's device.

n Number of blocks

N Number of bytes

p Process ID

P Display packet data -- series of hexadecimal values

s Sequence numbers

S Sector number

t Time stamp (nanoseconds)

T Time stamp (seconds)

u Elapsed value in microseconds (-t command line option)

U Payload unsigned integer

For our observation, we use %5T.%9t, %p, %C, %a, %S\n to format our result containing timestamp, command, process ID, action and sequence number.

Since the data I/O contains many action, such as complete, queued, inserted..ect. we can use option -a to filter actions, you can find more info via man blktrace. In this case, we use the write to filter the actions.

In the end, use the -o options to indicate the output file name.

barrier: barrier attribute
complete: completed by driver
fs: requests
issue: issued to driver
pc: packet command events
queue: queue operations
read: read traces
requeue: requeue operations
sync: synchronous attribute
write: write traces
notify: trace messages
drv_data: additional driver specific trace

The command will look like below and it will output the result to file output.txt.

blkparse nvme1n1 -f "%5T.%9t, %p, %C, %a, %S\n"  -a write -o output.txt

open the file, the result looks like

    0.000000000, 22890, fio, Q, 1720960
0.000001857, 22890, fio, G, 1720960
0.000005803, 22890, fio, I, 1720960
0.000009234, 22890, fio, D, 1720960
0.000036821, 0, swapper/0, C, 1996928
0.000067519, 22890, fio, Q, 1721088
0.000068538, 22890, fio, G, 1721088
0.000071531, 22890, fio, I, 1721088
0.000073102, 22890, fio, D, 1721088
0.000093464, 0, swapper/0, C, 1994624
0.000123806, 0, swapper/0, C, 1785472
0.000147436, 22892, fio, C, 1784576
0.000159977, 22891, fio, C, 1997312
0.000166653, 22891, fio, Q, 2006912
0.000167632, 22891, fio, G, 2006912
0.000169422, 22891, fio, I, 2006912
0.000171178, 22891, fio, D, 2006912
0.000188830, 22892, fio, Q, 1817728
0.000189783, 22892, fio, G, 1817728
0.000191405, 22892, fio, I, 1817728
0.000192830, 22892, fio, D, 1817728
0.000202367, 22891, fio, Q, 2007040
0.000203160, 22891, fio, G, 2007040
0.000205969, 22891, fio, I, 2007040
0.000207524, 22891, fio, D, 2007040
0.000227655, 22892, fio, Q, 1817856
0.000228457, 22892, fio, G, 1817856
0.000231936, 22892, fio, I, 1817856
....

Since the fio will fork to two process to handle the process, we use the grep to focus on one specific process (pid=22892).

grep "22892, fio" output.txt | more

Now, the result seems good, we can discover the sequence number (fifth column) is increasing. One thing we need to care about is the row which action is "C", which means the completed, since we don't know how NVME handle those request and reply to upper layer. we only need to focus on other action. such as "Q (queued This notes intent to queue i/o at the given location. No real requests exists yet.)" or "I (inserted A request is being sent to the i/o scheduler for addition to the internal queue and later service by the driver. The request is fully formed at this time)".

    0.000147436, 22892, fio, C, 1784576
0.000188830, 22892, fio, Q, 1817728
0.000189783, 22892, fio, G, 1817728
0.000191405, 22892, fio, I, 1817728
0.000192830, 22892, fio, D, 1817728
0.000227655, 22892, fio, Q, 1817856
0.000228457, 22892, fio, G, 1817856
0.000231936, 22892, fio, I, 1817856
0.000233530, 22892, fio, D, 1817856
0.000360361, 22892, fio, Q, 1817984
0.000361310, 22892, fio, G, 1817984
0.000364163, 22892, fio, I, 1817984
0.000366696, 22892, fio, D, 1817984
0.000536731, 22892, fio, Q, 1818112
0.000537758, 22892, fio, G, 1818112
0.000539371, 22892, fio, I, 1818112
0.000541407, 22892, fio, D, 1818112
0.000670209, 22892, fio, Q, 1818240
0.000671345, 22892, fio, G, 1818240
0.000673383, 22892, fio, I, 1818240
0.000676260, 22892, fio, D, 1818240
0.001885543, 22892, fio, Q, 1818368
0.001887444, 22892, fio, G, 1818368
0.001891353, 22892, fio, I, 1818368
0.001895917, 22892, fio, D, 1818368
0.001934546, 22892, fio, Q, 1818496
0.001935468, 22892, fio, G, 1818496
0.001936891, 22892, fio, I, 1818496
0.001938742, 22892, fio, D, 1818496
0.001965818, 22892, fio, Q, 1818624

Now, we can do all above command again and change the section to rw for fio using the randon write pattern. The blkparse result will show the random sequence number.

Summary

In this article, we try to use tools blktrace and blkparse to analysiz the block level I/O for fio request. We observe the filed sequence number to make sure thhat the fio can generate the sequence or random according to its config.

Reference

· 5 min read

本文主要嘗試分析 drbd(9.0) 於 kernel運行時的效能分析,希望藉由 perf 這個 tool 來分析整個程式運行的狀況,藉此觀察其運行時各 function 的比例。

Testing Environment

為了進行效能上的分析,首要條件就是先將 DRBD 給衝到效能瓶頸才有機會去觀察,所以本文採用下列的環境與工具來進行這項作業

Environment

CPU: Intel(R) Xeon(R) CPU E5-2695 v3 @ 2.30GHz Storage: Non-Volatile memory controller(NVME) Tool: fio OS: Ubuntu 16.04 with linux 4.4.0-78-generic

Setup

為了更方便觀察 drbd 的運行,我們將 drbd 創造的 kernel thread 都分別綁在不同的 cpu 上,這樣可以讓每隻 kernel thread 盡可能去使用cpu。

  1. 透過 ps or htop 取得 kernel thread 的 pid,這邊可以關注的有
    • drbd_s_r0 (sender)
    • drbd_r_r0 (receiver)
    • drbd_as_r0 (ack sender)
    • drbd_a_r0 (ack receiver)
    • drbd_w_r0 (worker)
  2. 透過 taskset 這個指令將上述程式分別綁到不同的 cpu 上
taskset -p 0x100 18888
...

Stress

本文使用 fio 來進行資料的讀取,下方提供一個簡易的 fio 設定檔,可依照自行的環境變換修改。

[global]
iodepth=512
numjobs=3
direct=1

time_based
runtime=30
group_reporting
size=5G
ioengine=libaio

filename=/mnt/beegfs/fio1.test
[rrw]
bs=4k
rw=randrw
rwmixread=75

[rr]
bs=4k
rw=randread

[rw]
bs=4k
rw=randwrite

[sr]
bs=64k
rw=read

[sw]
bs=64k
rw=write

我們 fio 採用 client/server 的架構,要是可支援多台 client 同時一起進行資料讀取,提供更高的壓力測試。

假設該設定檔名稱為 fio.cfg,並且放置於 /tmp/fio.cfg 則首先在 node-1 上面執行下列指令以再背景跑一個 fio server

fio -S &

接下來要運行的時候,執行下列指令來運行 fio,其中若想要改變測試的類型,可透過 --secion進行切換。

/fio --client=node-1 /tmp/fio.cfg --section=rw

這時候可以透過 htop 以及 iostat 的資訊去觀察,如下圖 當前透過 iostat 觀察到的確對 drbd0 有大量的讀寫動作 同時由 htop (記得開啟 kernel thread觀察功能),可以看到 drbd_s_r0 以及 drbd_a_r0 都各自吃掉一個 cpu,大概都快接近 100% 的使用率。

Profile

有了上述的環境後,我們就可以準備來分析 drbd 程式碼運行狀況。

Environemnt

這邊使用 perf 這套程式來分析,基本上 kernel 新一點的版本都已經內建此功能了,比較舊的 kernel 則需要自己重新開啟該 kernel config然後重新 build kernel,所以這邊使用 Ubuntu 16.04 with linux 4.4.0-78-generic 相對起來非常簡單。

直接執行 perf 這個指令,若系統上有缺少 linux-tools-4.4.0-78 相關 tool 的話會有文字提示你,如下所示,按照提示使用 apt-get 將相關的套件安裝完畢後,就可以使用 perf 了。

WARNING: perf not found for kernel 4.4.0.78

You may need to install the following packages for this specific kernel:
linux-tools-4.4.0-78-4.4.0-78
linux-cloud-tools-4.4.0-78-4.4.0-78
Run

perf 的功能非常強大,可以參考 wiki, 這邊我們使用 perf top 的方式來觀察結果。 為了可以順便觀看 call graph 的過程,再執行perf的時候要多下-g這個參數

指令為 perf top -g -p $PID,如 perf top -g -p 18888

在這邊我嘗試觀察 drbd_a 這隻,結果如下列

drbd_a

這邊可以觀察到三隻吃比較兇的 function 都吃很兇,分別是 native_queue_spin_lock_slowpathtr_release 以及 idr_get_next

這邊比較麻煩的是你看這個只能知道就是卡在 spin_locK,系統上是不是 multithread,然後有太多的資料要搬移導致 spin_lock ? 這些搬移的資料是誰放進去的?,這些資料是什麼?

以及更多的問題都必須要看程式碼去理解其整體設計架構,才有辦法講出一套完整的流程說明這個結果。

這部份等之後能夠完整理解整個 drbd 的 write-path 或是 read-path 時再重新來看一次這張圖,到時候應該會有完全不一樣的思維。

· 2 min read

不久前有一篇文章https://daniel.haxx.se/blog/2017/04/22/fewer-mallocs-in-curl/指出, curl 開發者嘗試將 malloc 呼叫的次數減少,結果對整體的影響帶來的顯著的提升

使用 curl http://localhost/512M 當作第一個比較 原始版本的 curl 關於 malloc 相關數據如下

Mallocs: 33901
Reallocs: 5
Callocs: 24
Strdups: 31
Wcsdups: 0
Frees: 33956
Allocations: 33961
Maximum allocated: 160385

而修改後的版本為

Mallocs: 69
Reallocs: 5
Callocs: 24
Strdups: 31
Wcsdups: 0
Frees: 124
Allocations: 129
Maximum allocated: 153247

比較起來可以發現, malloc 呼叫的次數有急遽的下降,從 33901 降落到 69,而整體使用的記憶體也少了 7KB 左右 此外,若比較兩者傳輸的速度,抓取一個 80GB 的檔案

Original: 2200MB/sec
Modified: 2900MB/sec

在傳輸方面提升了 30% 左右的速率,非常驚人 若使用 time 指令來比較新舊版本抓取 80G 檔案的差別

Old code:

real 0m36.705s
user 0m20.176s
sys 0m16.072s
New code:

real 0m29.032s
user 0m12.196s
sys 0m12.820s

修改相關的 commit 如下

簡單來說就是將 malloc 的部分都拔除,盡量使用 stack 來提供記憶體,藉此減少呼叫 malloc 的部分。 主要是因為 curl 在傳輸的過程中,會有非常大量且小空間的 malloc 被呼叫到,這部分拖慢的整體的運行速度

· 6 min read

還記得以前在工三讀書時,常常看到 Chun Norris 坐在我前面,然後畫面上是一張一張的卡片在不停地翻動,每張卡片上面都標記者一個日文單字, 看他快速地翻閱這些卡片,感覺就是在背頌單字,那時候也就沒有去想太多了。

沒想到過了幾年後,Chun Norris 竟然出書了!!! 英、日語同步Anki自學法:我是靠此神器,最短時間通過日檢N1、多益975分

看到這個消息後,就馬上預購了一本這個書,不但捧朋友的場,同時也順便瞭解看看到底 Anki 是什麼樣的東西。

對於想瞭解 Anki 基本操作的,可以參考這邊 經過了一陣摸索後,也開始使用了 Anki 來幫助我背單字,不過由於內建的一些卡片集(Deck)大都偏向特定主題,如托福、多益等 ,所以我後來也自己創建了一個卡片集給我自己使用。 在卡片編輯的部分,原本都是透過Anki application上面的 GUI 去操作編輯,填寫正反兩面的卡片資訊。 所以本來的流程是這樣

  1. 我看小說/文章
  2. 使用手機的 APP 去查詢單字
  3. 定期開啟 Anki 將 APP 內的歷史單字一個一個透過線上字典服務去查詢
  4. 將查詢的結果複製貼上到 Anki內,並轉成Anki的卡片

上面第三步驟最花費時間,當卡片數量一多的時候,其實要非常可怕的 那時候APP內大概有五六百個查詢過的單字,每個單字花20秒去填寫,也要整整三個小時不間斷才有辦法處理完畢。

有鑑於未來單字量只會愈來愈多,這樣手動下去實在不是辦法,因此腦筋就轉了彎一下,看有沒有辦法讓上面的步驟簡單化 上述(1),(2)這兩個步驟是不可避免的,那(3),(4)這兩個步驟就是主要處理的對象了。

針對我的目標,我將其拆成兩部分

  1. 給定一個單字,想辦法自動獲得其發音解釋
  2. 從上述的輸出中,將其自動變成 Anki 的卡片,然後塞到我的卡片集(Deck)中

針對第一點,我使用 python 作為我的程式語言,然後很偷懶的就拿了 yahoo 字典當作我的搜索來源 於是用了 python + BeautifulSoup + urllib 來爬網頁, 於是就網頁爬阿爬~就爬出了發音解釋了,這邊一切搞定

再來第二點,想要自動加入倒 Anki 的資料庫中,於是就到github去翻一翻,還真的翻到有人寫好已經可以用的工具 addToAnki,這個作者使用 python 撰寫,提供一個 tool 讓第三方可以將卡片的內容輸入進去後,自動轉為卡片並且塞到對應的卡片集中。 雖然我個人是更偏向去呼叫 library 而不是只接呼叫 tool 來處理,不過我的目的能達成就好,所以就將我前面的程式碼跟他的結合起來。目前將此結果放在這邊 同時我也發送了一個 pull request 到原先作者那邊,把我的使用情境當作一個多的範例使用,不過我看作者也兩三年沒碰了,應該也不會去接收我的 PR XDD

最後我的流程就是

  1. 遇到不會的單字
  2. 使用手機查詢單字
  3. 定期將查詢過的單字匯出成一個文字檔
  4. 將該文字檔送給我的 python 去處理,等他自動處理好即可。

上次一口氣加了四百多個單字,總共花費十五分鐘左右,大部分的時間應該都是消耗再去爬 yahoo dict這邊,目前這樣已經滿足我的需求。

· 2 min read

Basic

  • commit所使用的編輯器會依照下列優先度去選擇,

    1. GIT_EDITOR 環境變數
    2. core.editor 的設定
    3. VISUAL 環境變數
    4. EDITOR 環境變數
    5. vi 指令
  • 變動檔案請用 git mv,使用git rm要注意檔案系統內的檔案會被真的刪除。

  • git log可以列出簡略的coommit資訊

  • git show [commit id] 可以看詳細的commit資訊,可以加上commit ID來指定特定的commit

  • git show-branch --more=10 可以看當前bracnh的詳細commit資訊,由--more控制數量

Configuraion

總共有三種設定方式,優先度如順序

  • .git/config, 可以用 --file或是預設的方式操作
  • ~/.gitconfig, 可以用 --global操作
  • /etc/gitconfig,可以用 --system操作
git config --global user.name "hwchiu" (2)
git config user.email "[email protected]" (1)
  • 可以透過 git config -l列出當前所有的設定
  • 可以透過 --unset來移除設定
git config --unset --global user.name

· 3 min read

本篇文章是用來記錄以前修課關於 Shell Script 的作業

Introduction

用Unix的指令,透過pipe的方式完成下列要求

  • 計算當前目錄底下資料夾的總數
  • 計算當前目錄底下檔案總數
    • 只有計算regular file.不考慮FIFO、LINK
  • 計算所有檔案大小和 (Byte)
  • 顯示前五大的檔案名稱
  • 只能使用PIPE,不能使用 $$ ; || & > >> <

Implement

  • 使用ls來取得所有資料夾跟檔案的資訊
    • -l 可以顯示詳細資訊,這邊我們要取得的是 檔案大小
    • -R 遞迴的往每個資料夾繼續往下找
    • -A 不要把...給顯示出來,因為這種當前目錄的東西我們不需要
  • 使用sort來幫忙排序,找出檔案大小前五個
    • -r 排序結果反過來,由大到小排序
    • -n 排序的時候,採用數字的方式去排序,不使用字母大小去排序
    • -k 指定第幾個欄位要排序
  • 使用awk作最後的處理,找出前五大,印出所有檔案大小和
    • 因為再ls -l的結果中,會有很多資訊,包含 ./cs/.svn/pristine/74: 或者 total 28,所以awk再處理的時候,先用NF判斷該行的欄位數,至少要有9個欄位才處理 if(NF>=9)
    • 接下來針對檔案是資料夾還是檔案,做全部的計數,可以由 -rw-r--r-- 的第一個欄位來決定,如果是d就代表資料夾,否則就是檔案。 這邊我使用 regular expression來判斷 ($1 ~/^d/)? (dir=dir+1) : (file=file+1)(size=size+$5),此外如果是檔案得話,就順便把大小也計算一下
    • 執行過程中,因為剛剛已經排序過了,所以 前六行都把大小印出來, if(NR<6) print NR": "$5" "$9}
    • 最後就把所有資訊都列印出來

ls -RlA | sort -rnk 5 | awk '{ if(NF>=9) ($1 ~/^d/)? (dir=dir+1) : (file=file+1)(size=size+$5); if(NR<6) print NR": "$5" "$9} END{ print "Dir = "dir"\n" " File = " file"\n" "total = "size}'

· 4 min read

之前機器因為ZFS空間滿了,因為平常有再作snapshot的緣故,導致東西都刪除不了 因為刪除的時候都會有一些metadata的寫入,導致整個zfs動彈不得,這時候就花了很多時間再研就怎麼處理 這邊稍微記錄一下ZFS相關得操作。 ZPOOL的來源可以是device也可以是files,這邊就用兩個檔案當作來源。

Files

  • sudo dd if=/dev/zero of=/zfs1 bs=1M count=256
  • sudo dd if=/dev/zero of=/zfs2 bs=1M count=256

Zpool

  • create a mirror pool
    • zpool create ftphome mirror /zfs1 /zfs2
  • destroy a pool
    • zpool destroy ftphome
  • check zpool status
    • zpool status <pool>
  • export pool ( 把某些pool export出去,暫時不使用)
    • zpool export ftphome
  • import pool ( 把被export 的pool 重新import回來)
    • zpool import -d / ftphome (用-d指定你檔案的位置,預設會去吃/dev/)
    • 以我的範例來說,當import回來後,名稱會變成 //zfs1, //zfs2,多了一個/,原因不明中。
  • attach ( 只能對mirror使用)
    • zpool attach ftphome /xxx
  • detach ( 只能對mirror使用)
    • zpool detach ftphome /zfs1

還有offline,online,remove...,剩下的就要用的時候去man zpool,還滿詳細說明的。

ZFS database

  • set attributes zfs set key=value <filesystem|volume|snapshot>
    • zfs get compression ftphome
    • zfs set mountpoint=/home/ftp ftphome
  • get attributes zfs get key <filesystem|volume|snapshot>
    • zfs get compression ftphome
  • snapshot
    • zfs snapshot ftphome@today
    • zfs list -t snapshot

其他

  • 假如你的ZFS有使用snapshot同時空間又滿的話,這時候會發現所有檔案都會刪除失敗,都會得到空間不足的訊息,這邊稍微模擬一下該情況,並且想辦法解決此問題。

模擬情況

snatshot 該zfs

  • zfs snapshot ftphome@today
  • zfs list -t snapshot 看一下是否有成功

塞爆該空間

  • zfs list 看一下還剩下多少空間
  • dd if=/dev/random of=/home/ftp/file bs=1M count=256
  • cd /home/ftp
  • rm file => 應該會得到 No space left on device空間不足的訊息。

解決問題

ZFS 變大容易(多塞個硬碟即可),變小困難(幾乎無法),因此當ZFS的硬碟滿的時候,有兩種做法

  1. 再加入兩個新的硬碟,然後合併到目前的zpool,可是這樣就會變成有兩份mirror。
  2. 準備兩個更大的硬碟,把原本的zpool內的data全都複製過去。 這邊使用第二種做法

先幫本來的pool加入一個檔案,增加本來的空間,如此一來才可以做更多操作

  • dd if=/dev/zero of=/zfs5 bs=1M count=128
  • dd if=/dev/zero of=/zfs6 bs=1M count=128
  • zpool add ftphome mirror /zfs5 /zfs6
  • zfs list (此時可以看到本來的空間變大了)

創造一個更大的zpool來取代

  • dd if=/dev/zero of=/zfs3 bs=1M count=512
  • dd if=/dev/zero of=/zfs4 bs=1M count=512
  • zpool create ftphome3 mirror /zfs3 /zfs4
  • zfs set compression=gzip-9 ftphome2

把資料複製過去

  • zfs snapshot ftphome@send
  • zfs send ftphome@send | zfs receive -F ftphome2
  • zfs list 看一下大小是否相同

mount新的,舊的砍掉

  • zfs umount ftphome
  • zfs set mountpoint=/home/ftp/ ftphome2
  • zpool destroy ftphome

做到這邊,就算完成了,成功的把本來的資料複製過去。 如果想要改變zpool的名稱,可以用exportimport來改名稱。

· 3 min read

最近重新整理vim的設定檔,意外的發現 http://yoursachet.com/ 這個網站滿好用的,可以根據你的需求來自動打造vim設定檔,對於不想動腦去研究設定檔而言的人來說是滿好用的工具 用滑鼠輕鬆點點就可以產生堪用的VIM了!!

vimrc 設定

set encoding=utf-8
set fileencodings=ucs-bom,utf-8,big5,latin1
set fileencoding=utf-8
set termencoding=utf-8
set number " 行號
set statusline=%<\ %n:%f\ %m%r%y%=%-35.(line:\ %l\ of\ %L,\ col:\ %c%V\ (%P)%)
set ai " 自動縮排
syntax on " 色彩標示

set tabstop=4 " tab使用四個空白取代
set shiftwidth=4 " 縮排空白數,要搭配set cin使用
set cin
set cursorline " 該行的線
set t_Co=256 " 支援 256 色
set textwidth=0
set backspace=2 "按下backspace會後退,道行首後會刪除到前一行
set showmatch "顯示括號配對情況
set nocompatible "用vim的特性去運行,捨棄vi的特性

" Pathogen
call pathogen#infect()
call pathogen#helptags()

filetype plugin indent on

" Nerdtree
autocmd VimEnter * NERDTree
autocmd VimEnter * wincmd p
let NERDTreeShowBookmarks=1
let NERDTreeChDirMode=0
let NERDTreeQuitOnOpen=0
let NERDTreeMouseMode=2
let NERDTreeShowHidden=1
let NERDTreeIgnore=['\.pyc','\~$','\.swo$','\.swp$','\.git','\.hg','\.svn','\.bzr']
let NERDTreeKeepTreeInNewTab=1
let g:nerdtree_tabs_open_on_gui_startup=0


set background=dark "背景顏色
colorscheme wombat
nnoremap <silent> <F5> :NERDTree<CR>
"normal mode的時候+數字 可以切換tab
nnoremap <Esc>1 gt1
nnoremap <Esc>2 gt2
nnoremap <Esc>3 gt3
nnoremap <Esc>4 gt4
nnoremap <Esc>5 gt5
nnoremap <Esc>6 gt6
nnoremap <Esc>7 gt7
nnoremap <Esc>8 gt8

NERDTree

更改呼叫方式,使用F5

nnoremap <silent> <F5> :NERDTree<CR>

在各界面中移動

  • 按照順序往下移動 (crtl+w+w)
  • 上一個view (ctrl+w+h)
  • 下一個view (ctrl+w+l)

切割視窗

  • 水平切割 (在該檔案前按i)
  • 垂直切割 (在該檔案前按s) i :水平 s :垂直

tab使用

  • 開新tab並且切換過去 (t)
  • 開新tab但不切換過去 (T)
  • 下一個tab (gt)
  • 上一個tab (gT)

· 2 min read

Introducion

Cscope 是一個用來trace code還滿方便的工具 我通常都用他來trace linuxe kernel code,雖然說有網頁版的reference可以使用,但是用起來不順手,網頁會卡卡的 因此還是習慣使用這種互動式的trace tools

Install

sudo apt-get install cscope on Ubuntu

portmaster devel/cscope on FreeBSd

Usage

詳細的可以參考man page. 通常我只有使用 -R 來觀看而已

第一次執行的時候,會花比較久的時間去建立一個cscope.out的檔案,會把一些相關資訊放進去

下次執行的時候就會利用該out檔案來作查詢。

其他

預設的情況下,cscope只能讀取

  • .c
  • .h
  • .l
  • .y

想要讓他讀取java或是cpp的專案,就必須要先自己建置該資料庫

  • find ./ -name *.cpp > cscope.files
  • fine ./ -name *.java >> cscope.files
  • cscope -bkq

前面兩行會把所有的檔案路徑都寫入倒cscope.files裡面

  • b:建立索引文件
  • k:建立索引文件時不會去搜尋/usr/local/目錄
  • q:生成cscope.out,加速索引,該檔案包含
    • locate functions
    • function calls
    • macros
    • variables
    • preprocessor symbols

接下來只要使用cscope就可以了