astdb bug

asterisk 1.6.2 有個 bug 會使硬碟產生不必要的頻繁的 IO load

註:在 asterisk 10.x.x 版本以後 astdb 檔名改了,改成 astdb.sqlite3 和 astdb.sqlite3-journal 這兩個檔案,所以底下的程式碼也要相應的修改才行。

雖然我們在這兒看到有人有貼出修正檔出來,但我還不知要怎麼安裝那個修正檔,所以我用我自己的方式來解決這個 bug ,就是採用 ramdisk。 依據前面的 bug 回報,我們得知 /var/lib/asterisk/astdb 此檔會有頻繁的寫入動作,就是它引起頻繁的 IO load ,故底下是要介紹如何將它移到 ramdisk 。

1 掛載 ramdisk

vim /etc/fstab
貼上以下內容

/dev/shm /tmp tmpfs defaults 0 0

重開機後 /tmp 便會成了 ramdisk

底下步驟2開機自動執行的設定方法比較笨,而且容易發生一個問題,就是你設定的ramdisk裡的檔案,若是在開機啟動時的順序比asterisk 還要慢的話,那麼就會造成asterisk無法正常的啟動,因為它找不到 /tmp/asteriskdb 這個資料夾裡面的東西

1.5 修改asterisk啟動檔
一般來說,你若是使用apt-get 或 aptitude 來安裝asterisk的話,那麼它會自動幫你設定好開機啟動檔案,若你是使用原始碼安裝asterisk的話,而且參照我這一篇來安裝的話,也會有一個asterisk開機啟動檔。

我們現在就要編輯asterisk開機啟動檔,讓它啟動和關閉時都能自動的處理好ramdisk裡的資料
vim /etc/init.d/asterisk
重點是要找到 start) 和 stop) 這兩個區段加入一點程式碼

....................
....................
....................
case "$1" in
  start)
        ###########以下為我加進的程式碼#################
        #底下這行是比較精簡的寫法
        #test -d /tmp/asteriskdb || mkdir /tmp/asteriskdb && cp -a /var/lib/asterisk/db/* /tmp/asteriskdb && chown -R asterisk.asterisk /tmp/asteriskdb
        #底下這段程式碼是比較正規的寫法,兩者可擇一用之。
        if [ -d /tmp/asteriskdb ];then
                #上面那行是檢查 /tmp/asteriskdb 此資料夾是否存在
                echo "ramdisk db exist, nothing to do!"
                else
                #若不存在則,設定ramdisk 4 asterisk
                mkdir /tmp/asteriskdb
                cp -a /var/lib/asterisk/db/* /tmp/asteriskdb
                chown -R asterisk.asterisk /tmp/asteriskdb
        fi
        ###########以上為我加進的程式碼#################
        # Check if Asterisk is already running.  If it is, then bug out, because
        # starting up Asterisk when Asterisk is already running is very bad.
        VERSION=`${DAEMON} -rx 'core show version' || ${TRUE}`
        if [ "`echo $VERSION | cut -c 1-8`" = "Asterisk" ]; then
                echo "Asterisk is already running.  $0 will exit now."
                exit 0
        fi
 
....................
....................
....................
  stop)
        log_begin_msg "Stopping $DESC: $NAME"
        # "start-stop-daemon --oknodo" returns 0 even if Asterisk was already stopped (as LSB expects):
        start-stop-daemon --stop --oknodo --exec $DAEMON
        log_end_msg $?
        #關機設定備份 asterisk db
        cp -a /tmp/asteriskdb/* /var/lib/asterisk/db
        ;;
....................
....................

執行 1.5 此步驟之後,底下的第2步驟就可以略過,直接跳往第3步驟

2 開關機自動執行

此步驟2的方法不建議使用,請使用步驟1.5 的方法。

由於 ramdisk 的特性,重開機之後檔案會消失,所以我們要寫個小程式讓它在開關機時能自動回存

vim /home/backup/script/astdb-ram.sh
貼上以下內容

#!/bin/bash
#開機設定ramdisk給 asterisk用
mkdir /tmp/asteriskdb
cp -a /var/lib/asterisk/db/* /tmp/asteriskdb
chown -R asterisk.asterisk /tmp/asteriskdb

vim /home/backup/script/save-astdb.sh
貼上以下內容

#!/bin/bash
#關機設定備份 asterisk db
cp -a /tmp/asteriskdb/* /var/lib/asterisk/db

chmod 755 /home/backup/script/astdb-ram.sh
chmod 755 /home/backup/script/save-astdb.sh

設定開機執行
vim /home/backup/script/startup.sh
貼上底下內容

### BEGIN INIT INFO
# Provides:          iptables.sh
# Required-Start:    $remote_fs $syslog
# Required-Stop:    
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Start daemon at boot time
# Description:       自製開機程式
### END INIT INFO
#/bin/bash
bash /home/backup/script/astdb-ram.sh


chmod 755 /home/backup/script/startup.sh
ln -s /home/backup/script/startup.sh /etc/init.d/startup.sh
update-rc.d startup.sh defaults 19

設定關機回存
把這個檔連結到 /etc/rc0.d/下面 (專司halt) 以及 /etc/rc6.d/下面 (專司reboot)
ln -s /home/backup/script/save-astdb.sh /etc/rc0.d/save-astdb.sh
ln -s /home/backup/script/save-astdb.sh /etc/rc6.d/save-astdb.sh

3 修改路徑

vim /etc/asterisk/asterisk.conf
修改底下內容

[directories] (!); remove the (!) to enable this
;要移掉上面那行的 (!) 底下的設定才會生效
;astdbdir => /var/lib/asterisk
astdbdir => /tmp/asteriskdb

vim /etc/asterisk/res_config_sqlite.conf
修改底下內容

;dbfile => /var/lib/asterisk/sqlite.db
dbfile => /tmp/asteriskdb/sqlite.db

PS:後來發現 sqlite.db 似乎沒有那麼高的 IO 可以不用把它搬到 ramdisk 去,另外你需要注意一下若sqlite.db此檔案很大的話,就不適合放到 ramdisk裡去。

4 搬檔案、重開機


mkdir /var/lib/asterisk/db
#cp -a /var/lib/asterisk/astdb /var/lib/asterisk/db
cp -a /var/lib/asterisk/astdb.* /var/lib/asterisk/db
cp -a /var/lib/asterisk/sqlite.db /var/lib/asterisk/db
sync;sync;sync;reboot

重開機後,你可以觀察一下 /tmp/asteriskdb 裡面的檔案的時間,尤其時 astdb 此檔,它每分鐘都會更新一次。
這樣就是設定無誤了,然後你可以把這兩個檔案刪除了

rm /var/lib/asterisk/astdb
rm /var/lib/asterisk/sqlite.db

最後再用 iotop 工具去看, io load 是否真有減輕許多。

參考資料:AstDB介紹(英文)

本篇發表於 voip。將永久鏈結加入書籤。

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *