2011年7月28日 星期四

Setup moinmoin wiki with lighttpd

OS: Arch Linux
Package:
  • python2: 2.7.2-2
  • moinmoin: 1.9.3-2
  • lighttpd: 1.4.29-1
Install Path: /srv/http/





# edit /etc/lighttpd/lighttpd.conf to enable fastcgi

cp -v /usr/share/moin/server/moin.fcgi /srv/http/bin_path/moin.fcgi

# edit moin.fcgi

cp -r /usr/share/moin/{data,underlay} /srv/http/wiki/

# in lighttpd.conf, server.username is "http", change directories owner to http
chown -R http /srv/http/wiki/{data,underlay}
cp -v /usr/share/moin/config/wikiconfig.py /srv/http/wiki/

# edit wikiconfig.py, add superuser account

# Start wiki, register superuser account
/etc/rc.d/lighttpd start

# go to http://localhost/wiki/, register superuser account
# http://localhost/wiki/LanguageSetup to install page packages

# Install theme
# Download theme from http://moinmo.in/ThemeMarket
# if using the built-in static server
# static files are stored in /usr/lib/python2.x/site-packages/MoinMoin/web/statc/htdocs/
# I prefer the moniker theme :)

mv theme file to /usr/lib/python2.7/site-packages/MoinMoin/web/static/htdocs/
mv theme.py to /srv/http/wiki/data/plugin/theme/

# test config
/etc/rc.d/lighttpd restart

2011年6月4日 星期六

Ignore tracked file in Mercurial without removing it

hgignore only ignore files that have not been tracked before, if you add some files to the repository at previous commits, then you changed your mind, don't want to track those files, list them in .hgignore won't stop Mercurial from tracking them, you need to use `hg rm -Af FILENAME` to remove files from the repository ( files will still exist in the directory ), after commit, Mercurial will really stop tracking those files.

Step by step:
  1. list files in .hgignore ( eg. echo "glob:FILENAME" >> .hgignore )
  2. hg rm -Af FILENAME
  3. hg ci -m "Stop track FILENAME"

My test:
[lefthaha@HOST work]$ mkdir test
[lefthaha@HOST work]$ cd test/
[lefthaha@HOST test]$ hg init
[lefthaha@HOST test]$ touch abc.txt
[lefthaha@HOST test]$ hg ci -Am 'abc.txt'
adding abc.txt
abc.txt
committed changeset 0:1949cce3893d

[lefthaha@HOST test]$ hg st
[lefthaha@HOST test]$ hg head
changeset: 0:1949cce3893d
tag: tip
user: left < lefthaha >
date: Sat Jun 04 17:18:02 2011 +0800
files: abc.txt
description: abc.txt

[lefthaha@HOST test]$ echo "glob:abc.txt" > .hgignore
[lefthaha@HOST test]$ echo ".hgignore" >> .hgignore
[lefthaha@HOST test]$ echo "cde" >> abc.txt

[lefthaha@HOST test]$ hg st
M abc.txt
[lefthaha@HOST test]$ hg ci -m "modify abc.txt"
abc.txt
committed changeset 1:76446b6f8d7f
[lefthaha@HOST test]$ ls
abc.txt
[lefthaha@HOST test]$ hg rm -Af abc.txt
removing abc.txt
[lefthaha@HOST test]$ hg st
R abc.txt
[lefthaha@HOST test]$ ls
abc.txt
[lefthaha@HOST test]$ hg ci -m "hg rm abc.txt"
committed changeset 2:b07e13f2dd28

[lefthaha@HOST test]$ echo "ijk" >> abc.txt
[lefthaha@HOST test]$ hg st
[lefthaha@HOST test]$ echo "ijk" >> abc.txt
[lefthaha@HOST test]$ hg st
[lefthaha@HOST test]$ cat abc.txt
cde
fgh
ijk
ijk
[lefthaha@HOST test]$ hg ci
nothing changed

[lefthaha@HOST test]$ cd ..

# clone the repository
[lefthaha@HOST work]$ hg clone test/ test2
updating to branch default
resolving manifests
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
[lefthaha@HOST work]$ cd test2/
[lefthaha@HOST test2]$ ls
[lefthaha@HOST test2]$ hg st
[lefthaha@HOST test2]$ hg head
changeset: 2:b07e13f2dd28
tag: tip
user: left < lefthaha >
date: Sat Jun 04 17:20:12 2011 +0800
files: abc.txt
description:
hg rm abc.txt

[lefthaha@HOST test2]$ hg log
changeset: 2:b07e13f2dd28
tag: tip
user: left < lefthaha >
date: Sat Jun 04 17:20:12 2011 +0800
files: abc.txt
description:
hg rm abc.txt

changeset: 1:76446b6f8d7f
user: left < lefthaha >
date: Sat Jun 04 17:19:34 2011 +0800
files: abc.txt
description:
modify abc.txt

changeset: 0:1949cce3893d
user: left < lefthaha >
date: Sat Jun 04 17:18:02 2011 +0800 1 123
files: abc.txt
description:
abc.txt

[lefthaha@HOST test2]$ hg update -r 1
resolving manifests
getting abc.txt
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
[lefthaha@HOST test2]$ ls
abc.txt



There is another trick on Mercurial wiki to ignore multiple files in one line command, not tried yet.

Tips and Tricks - 34. Remove files that are matched by .hgignore but were added in error


Reference:
superuser - Can you remove a file from Mercurial without removing it from the filesystem like Git?
hg(1)
hgignore(5)

2011年5月26日 星期四

sha1 hash encoded in base64

到了報稅的季節,幫家人安裝報稅軟體的時候發現有提供 SHA1 驗證檔,點進去一看,應該是以 base64 編碼,在 Windows 下有安裝 Python 2.7 ,就直接解碼看看( 沒想到 Python 內建的 IDLE 那麼難用,已經習慣 shell 裡按上下鍵叫出之前的指令了... ),解開一看發現真的是 hash (註一),沒有轉成一般可見的文字,跟以前看過的驗證碼(註二)不一樣 ,還以為是我下錯指令或編碼不是 base64 ,翻了說明文件才發現是我見識淺薄,用 hashlib 的 hash.digest() 就可以得到相同結果,使用 hash.hexdigest() 才會得到一般的驗證碼,但是這串文字又不能直接 decode("hex"),在 Python 裡面 decode("hex") 或 encode("hex") 都是已經轉碼好了(註三),身為一個懶得思考的傢伙,就直接跑去看人家 hashlib 原始碼是怎麼寫的,結果人家是用 C 寫的,後來又發現 binascii 這個 module 可以直接用 hexlify 這個 function 轉換字串,又跑去看原始碼,看到註解還真有點囧
/* make hex version of string, taken from shamodule.c */

for(i=j=0; i<sizeof(digest); i++) {
char c;
c = (digest[i] >> 4) & 0xf;
c = (c>9) ? c+'a'-10 : c + '0';
hex_digest[j++] = c;
c = (digest[i] & 0xf);
c = (c>9) ? c+'a'-10 : c + '0';
hex_digest[j++] = c;
}

沒想到我連這麼簡單的字元轉換都記不起來,還用
bin( ord("a") >> 4 & 0xf )
配合 ascii 表查了一下才瞭解這段程式
算 hash 的時候還忘記要用 binary mode 讀檔...Orz

後來寫了一小段 script 來比對驗證碼是否符合,如果明年幫忙安裝報稅軟體的時候可以拿來用 ( 感覺機會不大 XD ),最後要抱怨一下,這 "個人綜合所得稅電子結算申報程式" 真是他媽的難用,難用到我只是幫家人操作讀取檔案和列印單據就想摔滑鼠的程度。


註一\xe6@\x0e\x86\xdeD\xdeW\x87\xf8\t\x9c=o\xee\xd3\xdcw\xdc
註二
60e6400e86de44de5787f8099c3d6feed3dc77dc
註三"abc".encode("hex") == "616263"

2011年5月9日 星期一

Arch Linux Live USB

一直很想弄個 Live USB Stick 來玩玩,但是試了 UNetbootin 和 Universal USB Installer,不管是 GNOME 3 Live CD、Ubuntu、Xubuntu、Mint 都沒辦法成功開機,不然就是畫面有問題,進入 X 後變成模糊畫面,燒到 CD 來測試卻是正常,後來又看到了 Debian Live Project,翻了文件發現要搞定一套可以用的系統得花上更多的時間,乾脆就直接把 Arch Linux 安裝到 USB Stick 上面,對 Arch Linux 比較熟悉,操作起來會比較順手一點,要保存資料和設定也很方便

OS: Arch Linux
USB Stick minimal disk space: 4G ( About 3.1G after GNOME 3 installed )

因為希望這隨身碟還是能拿來存一些資料,所以有另外切一個 vfat 的分割,而且這個分割的順序必須是第一個,Windows 才讀的到
fdisk -l
Disk /dev/sdd: 8032 MB, 8032092160 bytes
248 heads, 62 sectors/track, 1020 cylinders, total 15687680 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xdacf2b24

Device Boot Start End Blocks Id System
/dev/sdd1 * 2048 1435647 716800 c W95 FAT32 (LBA)
/dev/sdd2 1435648 9824255 4194304 83 Linux
/dev/sdd3 9824256 15687679 2931712 83 Linux

系統安裝在 /dev/sdd2 ,type ext4,掛載的時候時候加上 noatime 這個 flag

這次是用 pacman -r /mnt/arch_live 的方式去安裝,要手動設定一些 /dev 的 nodes ,有點麻煩,不知道利用 CD Image 的 AIF 會不會比較簡單

裝完需要的 packages ,像 xorg-server、nvidia、gnome 後,要記得在 /etc/mkinitcpio.conf 裡的 HOOKS 加上 usb,因為 grub-install 失敗,所以是用手動安裝的方式,沒搞清楚設定檔,結果卡了一天都沒辦法進入系統...Orz

整體上來講,照著 wiki 上的指示安裝,再依 Beginner's Guide 做設定,應該是沒什麼大問題,另外網路頻寬也要夠,否則下個 pacman -Syu 大概會抓到睡著

常常用 sudo ,下指令和複製本機設定檔的時候要再三檢查路徑,搞錯的話就要跟太陽公公說再見了;還有之前沒試過 chroot ,每次 sudo mount proc, sys, dev 都有點怕打錯,也有寫個 bash script 來幫忙,倒是 umount 還要自己 key,還要再研究一下怎麼寫,最怕的就是沒辦法 umount ,就要回想剛剛是不是下了什麼指令動到 /dev 下面的東西...

碰到卡比較久的問題:
  1. GRUB 出現 Error 15: File not found:
    問題是在 menu.lst 的設定,當初安裝 GRUB 的時候是安裝到 MBR,設定的 root 是 (hd0,0) ,但是我的系統是安裝在第二個分割,所以必須要改成 (hd0,1);由於 /boot 沒有獨立一個分割區給他,所以 kernel 和 initrd 前面必須加上 /boot/ ,GRUB 才知道要到 boot 這個資料夾下尋找 kernel image
    ## /boot/grub/menu.lst
    # (0) Arch Linux
    title Arch Linux [/boot/vmlinuz26]
    root (hd0,1)
    kernel /boot/vmlinuz26 root=/dev/disk/by-uuid/544dccdf-2aaf-4843-973c-f04c305f5e1f ro vga=792
    initrd /boot/kernel26.img

  2. 開機後無法進入 X:
    錯誤訊息有好幾個,條列如下:
    # 開機以後進入 X ,畫面閃了幾下出現類似
    gdm-binary[3684]: WARNING: GdmDisplay: display lasted 0,858447 seconds
    gdm-binary[3684]: WARNING: GdmDisplay: display lasted 0,864611 seconds
    gdm-binary[3684]: WARNING: GdmLocalDisplayFactory: maximum number of X display failures reached: check X server log for errors
    # 進 console 裡下 `startx` 則是出現以下錯誤
    (EE) USB USB Keyboard failed to initialize for relative axes.
    # 在 Xorg.0.log 除了上面鍵盤的問題之外還有一些其他的錯誤訊息
    (WW) Open ACPI failed (/var/run/acpid.socket) (No such file or directory)
    (WW) `fonts.dir' not found (or not valid) in "/usr/share/fonts/X11/100dpi/".
    Entry deleted from font path.
    (Run 'mkfontdir' on "/usr/share/fonts/X11/100dpi/").

    ### 解決方法:不太確定是哪個方式解決的,只好把做過的修改一樣樣列出來 ###
    # 1.在 /etc/rc.conf 的 DAEMONS 中加入 hal 和 acpid
    DAEMONS=(syslog-ng dbus hal acpid @network netfs crond @openntpd @alsa)
    # 2.依錯誤訊息指示,在 /usr/share/fonts/X11/... 中執行 mkfontdir
    # 另外也安裝了一些字型像 ttf-fireflysung, wqy-zenhei, ttf-dejavu 之類...
    # 3.Reinstall xorg-server,gdm,並檢查 ~/.xinitrc 是不是有加上
    exec ck-launch-session gnome-session

  3. 網際網路無法連線:
    區網是使用 DHCP,一開機就會啟動,網際網路連線則是使用 PPPoE 手動啟用
    ping 區網上的電腦沒有問題,但是對外像 www.google.com, 168.95.1.1 都 ping 不到,後來才想到可能是 route table 的問題
    # 預設的 gateway 是 eth0 ,照理說 PPPoE 啟動應該會把預設改成 ppp0 才對
    [left]$ route -n
    Kernel IP routing table
    Destination Gateway Genmask Flags Metric Ref Use Iface
    h254.s98.ts.hin * 255.255.255.255 UH 0 0 0 ppp0
    192.168.1.0 * 255.255.255.0 U 0 0 0 eth0
    default * 0.0.0.0 U 0 0 0 eth0

    # 手動更改 gateway 就正常了
    [left]$ sudo route del default
    [left]$ sudo route add default ppp0

    # 測試確定是 route 的問題的話,可以在 /etc/ppp/ 下面新增名為 ip-pre-up 的 script
    # 這樣 pppd 在啟動的時候就會去執行它,內容如下 ( 記得要 chmod +x 才能執行)

    [left]$ cat /etc/ppp/ip-pre-up
    #! /bin/sh
    /sbin/route del default

    [left]$ sudo chmod +x /etc/ppp/ip-preup

在 bitbucket 上面開了 repository 放些設定檔,有興趣的可以參考看看。


Reference on Arch Linux Wiki:
Installing Arch Linux on a USB key
Install from Existing Linux
Change Root
Tips for Minimizing SSD Read/Writes
Beginners' Guide

2011年4月8日 星期五

log cron jobs output

之前在看 /var/log/crond.log 的時候常會看到以下類似的訊息
Mar 20 18:37:01 `hostname` crond[1234]: FILE /var/spool/cron/root USER root PID 9999 job sys-daily
Mar 20 18:37:16 `hostname` crond[5678]: mailing cron output for user root job sys-daily
Mar 20 18:37:16 `hostname` crond[5678]: unable to exec /usr/sbin/sendmail: cron output for user root job sys-daily to /dev/null
Arch Linux 預設不會安裝 sendmail,所以 cron jobs 所產生的訊息沒辦法傳給使用者,但是又懶得去安裝與設定 postfix ,乾脆就寫個 script 把這些訊息存到 /var/log/cron_output/ 這個目錄下面,沒想到這一寫也是花了不少時間,我果然是個遜泡...

因為 crond 執行 cron jobs 時會把權限切換到該使用者一樣,寫入 log 的時候會有權限問題,如果 root 沒有幫忙在 /var/log/cron_output/ 下面建立 ${USER}.cron_output.log,會改成存到使用者的家目錄。

開放讓使用者能寫入 /var/ 下的檔案雖然有點危險,如果帳號被盜可能會把硬碟空間吃光導致其他 log 寫不進去,雖然可以用 quota 或另外準備一個 cron job 來偵測硬碟剩餘空間判斷要不要砍掉這個檔案或拿掉寫入權限,但身為一個不喜歡分開看 log 檔的懶惰傢伙,就讓他隨風而去吧~
把這支 script 丟到 /var/log/cron_output/ 後

sudo mkdir -v /var/log/cron_output/
sudo touch /var/log/${USER}.cron_output.log
sudo chmod 600 /var/log/${USER}.cron_output.log
sudo chattr +a /var/log/${USER}.cron_output.log

再修改 /etc/conf.d/crond,將
CROND_ARGS="-S -l info"
改成
CROND_ARGS="-S -l info -M /var/log/cron_output/cron_output_to_log.sh"

順便利用 logrotate 來管理這些 log

結果隔天馬上就發現有兩個問題要改,還是去年的問題,一堆 pacnew 檔案到現在都還沒 merge XDD~

Reference:
dcron man package
鳥哥的 Linux 私房菜:登錄檔的輪替 (logrotate)