2013年9月2日 星期一

PHP Extension (1) - 環境準備與Hello World

下列所有實作均以Ubuntu為範例,視不同distribution或版本可能指令與路徑均有不同

準備環境

$sudo apt-get install apache2 php5 php5-dev

Hello World

傳統PHP function要達到輸出hello world的方式
<?php
function hello_world() {  
  return 'Hello World';  
}
echo hello_world();
?>

若要使用PHP extension開發,要使用c語言實作出相同的function

test_hello_world.h
#ifndef PHP_TEST_HELLO_WORLD_H  
#define PHP_TEST_HELLO_WORLD_H  

extern zend_module_entry test_hello_world_module_entry;  
#define phpext_test_hello_world_ptr &test_hello_world_module_entry  

#ifdef PHP_WIN32  
#define PHP_TEST_HELLO_WORLD_API __declspec(dllexport)  
#else  
#define PHP_TEST_HELLO_WORLD_API  
#endif  

#ifdef ZTS  
#include "TSRM.h"  
#endif  

PHP_MINIT_FUNCTION(test_hello_world);  
PHP_MSHUTDOWN_FUNCTION(test_hello_world);  
PHP_MINFO_FUNCTION(test_hello_world);  

PHP_FUNCTION(hello_world);  

/*  
    Declare any global variables you may need between the BEGIN 
    and END macros here:      

    ZEND_BEGIN_MODULE_GLOBALS(test_hello_world) 
    long  global_value; 
    char *global_string; 
    ZEND_END_MODULE_GLOBALS(test_hello_world) 
 */  

#ifdef ZTS  
#define TEST_HELLO_WORLD_G(v) TSRMG(test_hello_world_globals_id, zend_test_hello_world_globals *, v)  
#else  
#define TEST_HELLO_WORLD_G(v) (test_hello_world_globals.v)  
#endif  

#endif  /* PHP_TEST_HELLO_WORLD_H */  

test_hello_world.cc
#ifdef HAVE_CONFIG_H  
#include "config.h"  
#endif  

#include "php.h"  
#include "php_ini.h"  
#include "ext/standard/info.h"  
#include "test_hello_world.h"  
#include "string"  

using namespace std;  

/* If you declare any globals in php_test_hello_world.h uncomment this: 
   ZEND_DECLARE_MODULE_GLOBALS(test_hello_world) 
 */  

function_entry test_hello_world_functions[] = {  
    PHP_FE(hello_world, NULL)  
    {NULL, NULL, NULL}  
};  

zend_module_entry test_hello_world_module_entry = {  
#if ZEND_MODULE_API_NO >= 20010901  
    STANDARD_MODULE_HEADER,  
#endif  
    "test_hello_world",  
    test_hello_world_functions,  
    PHP_MINIT(test_hello_world),  
    PHP_MSHUTDOWN(test_hello_world),  
    NULL, //RINIT  
    NULL, //RSHUTDOWN  
    PHP_MINFO(test_hello_world),  
#if ZEND_MODULE_API_NO >= 20010901  
    "$Revision: 1.5 $",  
#endif  
    STANDARD_MODULE_PROPERTIES  
};  

extern "C" {  
#ifdef COMPILE_DL_TEST_HELLO_WORLD  
    ZEND_GET_MODULE(test_hello_world)  
#endif  
}  

PHP_MINIT_FUNCTION(test_hello_world)  
{  
    return SUCCESS;  
}     

PHP_MSHUTDOWN_FUNCTION(test_hello_world)  
{  
    return SUCCESS;  
}     

PHP_MINFO_FUNCTION(test_hello_world)  
{  
    php_info_print_table_start();  
    php_info_print_table_header(2, "test_hello_world support", "enabled");  
    php_info_print_table_end();  
}     

PHP_FUNCTION(hello_world)  
{  
    string ret("hello world");  
    RETURN_STRING(const_cast(ret.c_str()), 1);  
}  

config.m4
PHP_ARG_ENABLE(test_hello_world, whether to enable test_hello_world support,  
Make sure that the comment is aligned:  
[  --enable-test_hello_world           Enable test_hello_world support])  

if test "$PHP_TEST_HELLO_WORLD" != "no"; then  
    PHP_SUBST(TEST_HELLO_WORLD_LIBADD)  
    PHP_NEW_EXTENSION(test_hello_world, test_hello_world.cc, $ext_shared)  
    PHP_REQUIRE_CXX  

    PHP_ADD_INCLUDE(/usr/include)  
    PHP_ADD_LIBRARY_WITH_PATH(stdc++, /usr/lib, TEST_HELLO_WORLD_LIBADD)  
    OS=`uname`;  
    if test $OS = "FreeBSD"; then  
        CPPFLAGS="$CPPFLAGS -Wno-error -Wall -g"
    else  
        CPPFLAGS="$CPPFLAGS -Wno-error -Wall -g -m32 -lstdc++"
    fi  
fi  

編譯
$ phpize

$ ./configure

$ make
如果編譯成功,可以看到如下畫面



將設定檔放入下列路徑/etc/php5/conf.d/test_hello_world.ini,php才知道需要載入此模組
extension = test_hello_world.so

將編譯完成的.so放入php的library中
/usr/lib/php5/20090626+lfs/test_hello_world.so



重起apache服務
$ service apache2 restart

重新測試test.php
<?php
echo hello_world();
?>

若需要清除編譯結果,指令如下
$ make clean
$ phpize --clean











 
疑難排解
如果遇到錯誤訊息undefined symbol: _ZNSs4_Rep20_S_empty_rep_storageE

PHP Warning: PHP Startup: Unable to load dynamic library '/usr/lib/php5/20090626+lfs/yahoo_hello_world.so' - /usr/lib/php5/20090626+lfs/yahoo_hello_world.so: undefined symbol: _ZNSs4_Rep20_S_empty_rep_storageE in Unknown on line 0

解決方法
加上-lstdc++在CPPFLAGS中

參考: http://stackoverflow.com/questions/11939934/c-apache-module-fails-on-znss4-rep20-s-empty-rep-storagee



2013年8月23日 星期五

Ubuntu 13.04安裝筆記

SSD硬碟開啟TRIM功能

確認SSD硬碟是否支援TRIM
$ sudo hdparm -I /dev/sda | grep "TRIM supported"


編輯/etc/fstab

需要加上TRIM的磁區,於errors前加入noatime,nodiratime,discard,
並將log相關的設定放入tmpfs減少SSD存取

將SSD trimming放入daily job
編輯/etc/cron.daily/trim,寫入如下設定








更改權限
$ sudo chmod +x /etc/cron.daily/trim

參考資料:
http://yblog.org/archive/index.php/11734
http://www.webupd8.org/2013/01/enable-trim-on-ssd-solid-state-drives.html

gcin

加入repository
$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 835AB0E3




安裝
$ sudo apt-get update
$ sudo apt-get install gcin

到語言設定去設定輸入法,之後登出再登入

解決icon消失的問題,可啟動gcin-tools,進入"外觀設定"=>"面板狀態(tray)"=>"Unity indicator"叫出

參考資料:
http://hyperrate.com/thread.php?tid=28044


Gnome-do

安裝
$ sudo apt-get install gnome-do
手動啟動後,調整熱鍵跟開機自動啟動選項,登出再登入即可生效

Pidgin

安裝
$ sudo add-apt-repository ppa:pidgin-developers/ppa
$ sudo apt-get update
$ sudo apt-get install pidgin

支援右上角訊息
$ sudo apt-get install pidgin-libnotify

設定支援office communicator
需要使用SIPE
http://sipe.sourceforge.net/
$ sudo apt-get install libglib2.0-dev intltool build-essential libnss3-dev libxml2-dev libgtk2.0-dev libpurple-dev
$ tar -xzvf pidgin-sipe-1.6.2.tar.gz
$ cd pidgin-sipe-1.6.2
$ ./configure --prefix=/usr
$ make
$ sudo make install
重新啟動pidgin就會看到office communicator的選項
記得不需要特別設定server等等,只需要設定username跟login都用mail即可

Dropbox

安裝
$ sudo apt-key adv --keyserver pgp.mit.edu --recv-keys 5044912E
新增 deb http://linux.dropbox.com/ubuntu/ raring main
$ sudo apt-get update
$ sudo apt-get install dropbox

Font
複製到ttf檔案到/usr/share/fonts/truetype/裏面 fc-cache -f -v

PCman
$ sudo apt-get install pcmanx-gtk2

Perforce
下載後,將bin內檔案放入/usr/bin,lib內p4v目錄放入/usr/lib/ 設定p4v.desktop放入/usr/share/applications/

[Desktop Entry]
Type=Application
Name=P4V
Comment=Perforce Visual Client
Icon=/usr/lib/p4v/P4VResources/icons/p4v_48_high.png
Exec=/usr/bin/p4v
Terminal=false
Categories=Development

VMWare

安裝
$ chmod 755 VMware-Player-5.0.2-1031769.x86_64.bundle
$ sudo ./VMware-Player-5.0.2-1031769.x86_64.bundle

kernel升級完掛點,直接重裝最快
$ sudo vmware-installer --uninstall-product vmware-player


移除惱人的menu bar
$ sudo apt-get autoremove appmenu-gtk appmenu-gtk3 appmenu-qt

關閉按到alt會跳出command的設定法
到keyboard的shortcut設定,將key to show the HUD設定為Disabled (使用backspace按鈕)

參考資料
http://askubuntu.com/questions/122209/how-do-i-modify-or-disable-the-huds-use-of-the-alt-key

Java
$ sudo add-apt-repository ppa:webupd8team/java
$ sudo apt-get update
$ sudo apt-get install oracle-java8-installer
$ sudo update-java-alternatives -s java-7-oracle

Chrome
$ wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add - deb http://dl.google.com/linux/chrome/deb/ stable main
$ sudo apt-get update
$ sudo apt-get install google-chrome-stable

Gnome
$ sudo add-apt-repository ppa:webupd8team/gnome3
$ sudo apt-get update
$ sudo apt-get install gnome-shell-extensions-gpaste compiz
$ sudo apt-get install gnome-session-fallback

2013年7月9日 星期二

Mac使用老式USB掃瞄器(以Mustek 1200 UB為例)

安裝軟體

1. libusb
2. SANE backends
3. SANE Preference Pane
4. TWAIN SANE Interface

下載處: http://www.ellert.se/twain-sane/

下載驅動程式

下載相對應的驅動程式放入/usr/local/share/sane/gt68xx/目錄

下載處: http://www.meier-geinitz.de/sane/gt68xx-backend/

以Mustek 1200 UB為例,需要下載sbfw.usb
放置於/usr/local/share/sane/gt68xx/,並修改權限為777

$ sudo cp sbfw.usb /usr/local/share/sane/gt68xx/
$ sudo chmod 777 /usr/local/share/sane/gt68xx/sbfw.usb

確認掃瞄器是否有無抓到

使用下列兩個指令確認是否能正常抓到掃瞄器
1. scanimage --list-devices
2. sane-find-scanner

掃描

使用scanimage指令掃描

$ sudo scanimage --format=tiff --mode=Color --resolution=300 > result.tiff

若對scanimage指令有疑問可以man一下










$ man scanimage

參考文件

http://nepkertkft.hu/en/mustek-ub-plus-1200-scanner-under-mac-os-x

2013年6月3日 星期一

Shell Scripting常用範例說明

建議開頭
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
export LANG="en_US.UTF-8"
註解
#user comment
定義變數與列印變數
VAR="hello world"
echo $VAR

printf "\33[1;31m"
printf "Color Version: $VAR"
printf "\33[0m\n"
正常結束
exit 0
if-else判斷式
if [ "$INPUT" == "Yes" ]; then
  echo "result is Yes"
elif [ "$INPUT" == "No" ]; then
  echo "result is No"
else
  echo "wrong input"
fi
讀取argument
if [ ! -z "$1" ]; then
  ARGS=$1
fi
echo $ARGS
檢查執行者身份
whoami_ret="$(whoami)"
if [ "$whoami_ret" != "root" ]; then
  echo "This script must be run as root"
  exit
fi
使用者輸入
read -p "Please input (Y/N), default is N:" ANSWER
if [ "$ANSWER" == "Y" -o "$ANSWER" == "y" ]; then
  echo "result is Yes"
fi
執行指令的結果
pyOpenSSL_ret="$(rpm -q python-openssl | grep install | wc -l)"
if [ "$pyOpenSSL_ret" == "1" ]; then
  echo "python-openssl is not installed, please install python-openssl"
  exit
fi  
類似traverse陣列
SERVER_LIST=(192.168.0.1 192.168.0.2 192.168.0.3)
for IP in ${SERVER_LIST[@]}
do
  echo "IP address: $IP"
done
Switch case
case $CAR in
  AUDI | audi)
    echo "audi"
  ;;
  VOLVO | volvo)
    echo "volvo"
  ;;
  BENZ | benz)
    echo "benz"
  ;;
  *) 
    echo "wrong role type"
    exit
  ;;
esac
Loop
until [ "$ANSWER" == "yes" ]
do
  read -p "Please input \"yes\":" ANSWER
done

i=0
while [ "$i" != "10" ]
do
  i=$(($i+1))
  echo $i
done

for CAR in AUDI VOLVO BENZ
do
 echo ${CAR}
done

for i in $(seq 1 10)
do
  echo ${i}
done

for (( i=1; i<=10; i=i+1 ))
do
  echo $i
done
等候某個事件發生
FILE_EXISTED=0;
while [ $FILE_EXISTED -ne "1" ]; 
do
  if [ -z "/root/test_file" ];then
    FILE_EXISTED=1
  fi
  sleep 1;
done
Function
function PRINT_FUNCTION(){
  echo "args is $1"
}

PRINT_FUNCTION "first_args"
參考 http://tldp.org/LDP/abs/html/ http://linux.vbird.org/linux_basic/0340bashshell-scripts.php

2013年5月29日 星期三

screen基本指令教學

screen是個簡單方便的terminal console管理工具,大概有幾個主要的優點:
  • 在一個terminal軟體中開啟許多子console視窗
  • 可以dettach出來、之後又reattach回去
  • 有scrollback的功能
  • console視窗間複製貼上
  • 切割console視窗

安裝

在Ubuntu上直接 $ sudo apt-get install screen就可以了

Command-line指令

$ screen
  • 直接開啟新的session
$ screen -list
  • 列出目前有哪些已經存在的session可以attach進去
$ screen -R
  • reattach回session。如果目前沒有session存在,直接就地開啟一個新的session。如果有好幾個不同的session,使用screen -R
$ screen -U
  • 以utf-8 mode執行
$ screen -d
  • 強制將某個正在被attach中的session給detach掉
$ screen -wipe
  • 將廢棄的screen清除

Key-Binding指令

screen預設是以Ctrl-a(同時按住鍵盤Ctrl跟a兩個按鈕,如果您能理解控制字元,這就是等同於"^A")來啟動console視窗管理,接著同時鬆開Ctrl與a鍵,按下另一按鍵或下達指令來進行操作。

Ctrl+a c
  • 開啟一個新的console視窗
Ctrl+a Ctrl+a
  • 連續兩次,回到上一個console視窗
Ctrl+a [1~9]
  • 切換到1號至9號的某個console視窗
Ctrl+a "
  • 列出目前所有視窗,可用上下方向鍵選擇要進入的console視窗,按下enter進入
Ctrl+a k
  • 刪除目前的console視窗
Ctrl+a d
  • 將目前session給detach掉
Ctrl+a Esc
  • 進入copy mode,可用上下左右操控或進行scrollback。/或?用來搜尋(類似vim)。空白鍵可進行選取,決定範圍後按下第二次空白鍵就會複製入buffer中。之後使用Ctrl+]就可以將剛剛screen放入buffer中的內容貼上
Ctrl+a :sessionname [name]
  • 設定session的名稱,之後在comman-line模式執行screen -list方便檢視
Ctrl+a v
  • [Ctrl+a] 輸入控制字元Ctrl+a(因為Ctrl+)
Ctrl+a S
  • 將目前所在區域,水平分割成另外兩個區域
Ctrl+a Q
  • 關閉分割區域
Ctrl+a Tab
  • 切換分割區域

進階議題

  • 在screen的vim中輸入控制字元^A,需要在vim中進入insert模式,然後按下Ctrl+A,再按下a,就可以了
  • 因為screen畫面有些單調,有時無法辨別目前console視窗的狀態與session的狀態。如果需要像bash一樣有客製化的畫面,可以透過設定編輯~/.screenrc這個檔案來得到自己想要的效果。只要上Google搜尋screenrc就有許多範本可以下載,有空我再來寫篇screenrc教學。
  • 垂直分割screen區域(需要拿git版screen重make自己build)
    • $ git clone git://git.savannah.gnu.org/screen.git
    • $ cd screen/src
    • $ ./autogen.sh
    • $ ./configure
    • $ make
    • $ make install
    • 使用Ctrl+a | 來垂直分割區域
    • 參考 http://savannah.gnu.org/projects/screen/

2013年5月28日 星期二

Ubuntu Distribution版本

通常要得知Linux核心的版本,使用uname -a指令就可以了。

不過要得知Distribution版本,這個指令還不太夠。這時候只要檢視/etc/os-release或/etc/issue就可以了。


2013年4月29日 星期一

在Ubuntu環境設定ctags

  • 安裝ctags
    • $ sudo apt-get install exuberant-ctags
  • 設定~/.ctags (支援python)
    •  --python-kinds=-i
    • 如果有需要放入過濾清單, 加入--exclude=
      • ex. --exclude=*/build/*
  • 設定~/.vimrc
    • 加入:set tags=~/.myctags
  • 手動執行ctags
    •  $ ctags -R -o ~/.myctags ~/src
  • 自動執行ctags (每分鐘執行一次)
    • $ sudo /etc/crontab
    • */1 * * * * account /usr/bin/ctags -R -o /home/howard/.myctags ~/src
    • $ service cron restart
  • vim中指令
    • ctrl+] 跳入該function
    • ctrl+t 跳出該function
    • :tselect 或 :stselect 選擇同名的其他function
    • :tnext 或 :tprev 往前或往後跳往同名的其他function
    • :help tags 得到更多訊息

2013年1月11日 星期五

在terminal中MySQL欄位太多時呈現資料的另一方式

當我們在terminal中連入MySQL時,有時會因為欄位過多,導致select出來的結果亂七八糟。


有個很簡單的方法就可以讓顯示的結果改成以一筆一筆資料秀出為主,就是在select的query最後加上\G即可。


2012年10月17日 星期三

ssh Authentication refused

今天公司有台環境不知道為什麼ssh-key一直無法通行,怎麼登入都還是需要打密碼。後來試著在client用ssh -vvv 去看訊息,得到了

debug3: load_hostkeys: loading entries for host "172.16.15.139" from file "/root/.ssh/known_hosts"
debug3: load_hostkeys: found key type RSA in file /root/.ssh/known_hosts:21
debug3: load_hostkeys: loaded 1 keys
debug1: Host '192.168.0.1' is known and matches the RSA host key.
debug1: Found key in /root/.ssh/known_hosts:21
debug2: bits set: 512/1024
debug1: ssh_rsa_verify: signature correct
debug2: kex_derive_keys
debug2: set_newkeys: mode 1
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug2: set_newkeys: mode 0
debug1: SSH2_MSG_NEWKEYS received
debug1: Roaming not allowed by server
debug1: SSH2_MSG_SERVICE_REQUEST sent
debug2: service_accept: ssh-userauth
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug2: key: /root/.ssh/id_rsa (0x7f91407b54f0)
debug2: key: /root/.ssh/id_dsa ((nil))
debug2: key: /root/.ssh/id_ecdsa ((nil))
debug1: Authentications that can continue: publickey,gssapi-with-mic,password
debug3: start over, passed a different list publickey,gssapi-with-mic,password
debug3: preferred publickey
debug3: authmethod_lookup publickey
debug3: remaining preferred:
debug3: authmethod_is_enabled publickey
debug1: Next authentication method: publickey
debug1: Offering RSA public key: /root/.ssh/id_rsa
debug3: send_pubkey_test
debug2: we sent a publickey packet, wait for reply
debug1: Authentications that can continue: publickey,gssapi-with-mic,password
debug1: Trying private key: /root/.ssh/id_dsa
debug3: no such identity: /root/.ssh/id_dsa
debug1: Trying private key: /root/.ssh/id_ecdsa
debug3: no such identity: /root/.ssh/id_ecdsa
debug2: we did not send a packet, disable method
debug1: No more authentication methods to try.
Permission denied (publickey,gssapi-with-mic,password).


似乎是跟permission有關,但看了半天包括client上的private key跟server上面的public key檔案都是正常。後來上網稍微搜尋了一下,看到這個文章提到可以看server上的/var/log/secure來得到確切的error log。

Authentication refused: bad ownership or modes for directory /root

在仔細看了一下,才發現原來不知道誰把/root權限由750改為755,而sshd設定檔(/etc/init.d/sshd)有個參數StrictModes跟這個有關,只要整條path有任何目錄權限不對就會阻止public key使用。

結果花了一個小時查原因,但畢竟是共同開發環境,難免遭遇這種狀況就是。

2012年10月4日 星期四

Pidgin安裝msn-pecan

如果有需要在Ubuntu的Pidgin中安裝msn-pecan模組,直接輸入
$ apt-get install msn-pecan 
即可完成安裝

接著關閉pidgin並重起後,將原本MSN的帳號停用
改成使用WLM的方式重新加入並啟動MSN帳號即可



2012年8月7日 星期二

Linux Shell Command Logger

1. 新增下列到/etc/bashrc中
export PROMPT_COMMAND='RETRN_VAL=$?;logger -p local6.debug "$(whoami) [$$]: $(history 1 | sed "s/^[ ]*[0-9]\+[ ]*//" ) [$RETRN_VAL]"'
若您使用的是ubuntu,則檔案為/etc/bash.bashrc。若使用centos,檔案為/etc/profile
ps. /etc/profile或/etc/bashrc等檔案要視順序設定,可參考http://www.51testing.com/?uid-225738-action-viewspace-itemid-216622

2. 新增下列到/etc/syslog.conf
local6.*                /var/log/commands

3. 若需要log rotate,則新增/var/log/commands這行到/etc/logrotate.d/rsyslog中 (以ubuntu為例,若您使用centos則是/etc/logrotate.d/syslog)

4. 參考資料
http://blog.kxr.me/view/classic
http://efreedom.com/Question/6-93566/Log-Bash-Commands-Users-Server

2012年6月22日 星期五

Pylons profiling工具 -- repoze.profile

repoze.profile可以針對WSGI進行完整的profiling,本文特別針對Pylons的使用做簡單說明

1. 安裝
只要使用
$ easy_install repoze.profile
下完指令即可安裝完成
 
2. 設定
直接在pylons的middleware.py修改如下

from repoze.profile.profiler import AccumulatingProfileMiddleware

# ...

def make_app(.....):
    load_environment(global_conf, app_conf)
    app = PylonsApp()

    app = AccumulatingProfileMiddleware(
        app,
        log_filename='/tmp/profiling.log',
        cachegrind_filename='/tmp/cachegrind.out',
        discard_first_request=True,
        flush_at_shutdown=True,
        path='/__profile__'
    )

    app = RoutesMiddleware(app, config['routes.map'])
    app = SessionMiddleware(app, config)
    app = CacheMiddleware(app, config)

    #.....
 

log_filename代表profiling log檔案存放位置
cachegrind_filename代表要給KCachegrind工具觀看的profiling log檔案存放位置
discard_first_request代表要不要忽略第一次檢視的結果,因為通常第一次的數據都會比較不正常而影響了整體的結果
flush_at_shutdown代表middleware instance不存在時是否要將profiling結果刪掉
path顧名思義就是利用browser檢視profile結果的URI
 
設定完成後重起httpd server
 
3. 確認結果
確認 http://localhost/__profile__ 能否存取
理論上可以看到畫面如下
 
 
4. 使用KCachegrind檢視
 
5. 參考資料

http://pypi.python.org/pypi/repoze.profile
http://docs.repoze.org/profile/#viewing-the-profile-statistics
http://nickmurdoch.livejournal.com/392632.html

2012年6月7日 星期四

Perforce Console 版本教學

以下教學同時適用於mac版與linux版

1. 下載perforce console版

請至 http://www.perforce.com/downloads/complete_list 下載The Perforce Command-Line Client (P4),檔案會是一個執行檔。下載後請放置於/usr/bin/並修改檔案權限。

sudo chmod 755 /usr/bin/p4

2. 設定環境變數

修改~/.bashrc,加入下列資訊
export P4HOST={SERVER HOSTNAME}
export P4PORT={PORT}
export P4CLIENT={WORKSPACE NAME}
export P4USER={USERNAME}
unset P4CHARSET


P4CHARSET參數視client與server之間的編碼版本決定,細節可見 http://www.perforce.com/perforce/doc.current/manuals/cmdref/env.P4CHARSET.html

其他環境變數可參見 http://www.perforce.com/perforce/doc.current/manuals/p4guide/02_config.html 說明

接著重新載入.bashrc後直接執行p4看看是否與server連結正常。如果出現Perforce client error等字樣,代表環境變數設定還有問題。若成功就會出現相關的help指令說明。


3. 登入perforce

接著輸入p4 login,就會詢問登入密碼,登入後就會顯示成功登入的訊息。如果實在嫌每次都要登入登出麻煩,可以直接在.bashrc中間指定P4PASSWD參數(但因為放置於.bashrc等於是明碼儲存,並不建議)


p4 login 


4.  建立workspace


若此台電腦尚未開啟過workspace,只要執行p4 client即可,便會跳出一個vim文字編輯畫面,讓您修改此workspace相關訊息,儲存後就會在server上建立一個新的workspace。比較重要的參數就是Client、Root與View這幾個參數,Client就是屆時在清單會看到的workspace名稱,Root則是程式碼儲存的根目錄,View則是會決定你要同步出來的路徑深度。

p4 client

接著可用 p4 workspaces -u 確認目前此user的workspace狀態,並檢查剛剛的workspace是否有建立 

p4 workspaces -u {USERNAME}



若要看更詳細的workspace訊息,可用 p4 client -o 指令把前面vim編輯的訊息倒出來

p4 client -o {WORKSPACE NAME}

若要刪除workspace,執行 p4 client -d 即可

p4 client -d {WORKSPACE NAME}


5. 倒出程式碼

p4 sync {PATH ON SERVER}/...
目錄會幫忙開好


強制sync到最新版
p4 sync -f {PATH ON SERVER}/...


p4 sync -n 沒有真的同步,只是把結果先倒出來

p4 sync -n ./... 列出目前路徑下還有哪些檔案沒有up-to-date


如果出現Request too large代表此路徑下檔案太多,需要縮小範圍來sync


6. 確認檔案狀況

p4 have {FILENAME} 確認該檔案在client端的目前版本。可用p4 have *

p4 files {FILENAME} 確認該檔案在server端的最新版本。可用p4 files *  

p4 fstat {FILENAME} 確認該檔案更詳細的訊息。其中還可以看到誰也開了這檔案。可用p4 fstat *


p4 changes {FILENAME} 列出檔案各個版本與歷史紀錄


p4 changes -m {MAX} {FILENAME} 只列出該檔案最近的幾個版本與紀錄

p4 changes -i ./... 列出目前目錄下所有子目錄所有檔案的 各個版本與歷史紀錄


p4 filelog {FILENAME} 列出更詳細的版本與歷史紀錄

7. 修改檔案 

p4 add {FILENAME} 新增檔案


p4 diff {FILENAME} 假設你正在修改revision #4,就會比較你現在改的跟原本revision #4的差別


p4 diff {FILENAME}#{REVISION} 比較你現在改的跟特定revision


p4 diff {FILENAME}#HEAD 比較你現在改的跟特定revision跟server上最新的revision

p4 diff2 {FILENAME}#{REVISION1} {FILENAME}#{REVISION2} 比較server上兩個revision

p4 diff -se 列出你自己沒有先edit就強制編輯的檔案

p4 diff -se | p4 -x -edit 將上述的檔案通通edit開

p4 diff -sd 察看哪些檔案不是用p4 delete而是自己手動在本地刪除的 

p4 edit {FILENAME} 將程式碼check-out出來


p4 submit {FILENAME} 將程式碼check-in進去

p4 submit -d {DESC} 將程式碼check-in進去並補上說明

p4 revert {FILENAME} 直接將檔案倒回編輯時check-out的原樣 

p4 revert 直接將所有開啟的檔案全部倒回

p4 delete {FILENAME} 刪除特定檔案


p4 sync {FILENAME}#{REVISION} 將本地檔案倒回某個版本 


p4 sync ./... 更新該目錄與子目錄下所有的檔案至server的的最新revision


p4 opened 列出目前已經check-out的檔案

p4 move {FILENAME} {NEW FILENAME or NEW FILEPATH} 搬移或rename某個檔案 (更名亦可用p4 rename {OLD FILENAME} {NEW FILENAME})


p4 restore {FILENAME}#{REVISION} 將某個檔案倒回到特定版本


p4 resolved 解決某個檔案的衝突


8. 進階用法


p4 tag -l {LABEL} {FILENAME} 將某個檔案加入特定label



p4 label {LABEL} 建立或編輯label


p4 labels -u {USERNAME} 列出該user所有的label

p4 labels ./... 列出此路徑下存在的label


p4 sync @{LABEL}
同步該label中的所有文件


p4 files @
{LABEL}
查看該label所包含的文件列表


p4 branch {BRANCHNAME} 建立branch


p4 branches -u {USERNAME} 顯示該使用者擁有的branch


p4 integrate -b
{BRANCHNAME}
合併該brach中的文件

p4 dirs -H .
顯示當前目錄



9. 求助

p4 help 列出重要指令說明


p4 help commands 列出所有指令的說明


p4 help {COMMAND} 針對特定指令的更詳細說明


p4 help revisions 列出針對檔案版本的指令說明,例如#rev或@change的意義

2011年12月8日 星期四

Mac OS 10.7 Lion新增Windows網路芳鄰印表機

雖然我已經脫離Windows作業系統許久了,但就算投靠Ubuntu與Mac OS多年,要在非Windows新增印表機還是相當麻煩。方法無非就是找到印表機本體,透過上面的小按鈕跟小螢幕中進入設定尋找印表機的IP、或者列印設定頁出來後再看上面的IP是啥。最近發現在Mac OS上有更快速的方法可以新增印表機。

1. 首先進入"系統偏好設定" => "列印與掃描",然後點選選單下方的+號"新增印表機"
2. 接著按著鍵盤的Control鍵點選"預設值"按鈕,會跳出隱藏版的選單,點選"自定工具列"


3.將"進階"往上拖拉到工具列後點選"完成"


4. 接著在"類型"中選擇"Windows....",並在URL中填上該印表機在網路芳鄰上的位置後即可加入


參考資料:
Mac OS X: How to manually add a Windows shared printer

2011年12月5日 星期一

Mac OS 10.7雙網卡設定

由於公司內網與外網切開,但我手頭上又只有一台電腦,只能採用雙網卡的策略。之前這方法在Windows與Ubuntu都是無往不利,然而卻在Mac OS上踢到鐵板,不知為何路由似乎總是被Mac OS牢牢抓住沒辦法修改,或者是路由不通。

理論上理想的設定方式應該是預設gateway是外網的gateway,而內網則指定特定的網段走內網的gateway,但Mac OS不論如何都會硬塞一個預設的gateway。在Mac OS中如果超過一個以上的網路設備時,就需要設定設定服務順序,否則可能會導致routing錯亂,而且這個服務順訊還會影響到使用DNS Server的順序。

所以正確的作法就是將內網的網路卡設定為優先權最高。設定方式就是進入到"系統偏好設定"的"網路"中,點選網路設備清單下面的選項按鈕,選擇"設定服務順序",然後將內網的網路卡拉到外網的網卡上面。


接著在終端機下指令將所有default gateway通通刪除。

sudo route delete default <內網gateway ip>
sudo route delete default <外網gateway ip>

這時候輸入netstat -rn指令看routing table會看到還殘留著一個default gateway無法刪除,理論上在調整完服務順序後這個default gateway應該會是外網的gateway。

接著輸入指令新增內網的路由

sudo route add -net <內網的網段/netmask> <內網的gateway ip>

這時候應該已經可以正常存取內網跟使用內網的domain name了。但外網還無法連線,原因在於這個default的gateway的Refs小於內網gateway的Refs。因此還需要手動在將外網的default gateway加回去。


sudo route add default <外網的gateway ip>

理論上應該就大功告成了

2011年11月29日 星期二

如何把右邊的Alt鍵在ubuntu中改為Win (Super)鍵


有用過IBM鍵盤的人都會著迷於那舒適的回饋手感以及獨家秘方小紅點,然而IBM的鍵盤卻有著一個最大的致命缺陷,就是這鍵盤缺乏著Win (Super)鍵。在Windows環境中頂多只是少了一個叫出"開始"的快速鍵而已,然而在ubuntu環境中Win (Super)鍵卻是擔任著許多重要的任務,包括切換視窗等等重要的快捷鍵,都需要搭配Win (Super)鍵搭配服用。

在這種狀況下我也試圖尋找解決方案,無意間發現有高手拿右邊的Alt鍵來轉換為Win (Super)鍵使用。這真是相當聰明的辦法,畢竟若要將左邊的Alt鍵拔除實在不太可能,但我相信絕大多數的人卻都很少使用到右邊的Ctrl鍵以及Alt鍵,因此拿右邊的Alt鍵當作Win (Super)鍵使用再聰明不過了。

在ubuntu中我們需要使用到xmodmap這個程式來修改X Window中的鍵盤與滑鼠對應。

1. 安裝xmodmap
首先確認您目前是否已經安裝好xmodmap,但通常ubuntu安裝好以後預設都是已經有安裝了。如果在terminal中沒有xmodmap可以執行,就需要安裝x11-xserver-utils。
sudo apt-get install x11-xserver-utils

2. 確認目前的keymap
先在terminal中執行xmodmap確認ALT_R是落在mod1中(如果不是,稍候的.Xmodmap設定檔就需要做相對應的調整)。


接著確認你右邊的Alt鍵的keycode是108(轉為十六進位就是上圖看到的0x6C),需要透過xev這個程式。在終端機執行xev後會跳出一個白色視窗,內有一個黑色小框。接著按下右邊的Alt後終端機就會跳出相對應的資訊,而其中的keycode欄位應該要出現108(如果不是108,稍候的.Xmodmap設定檔就需要做相對應的調整)。


3. 設定.Xmodmap如下


接著將此檔案存放在使用者目錄下,只要每次開機就會自動生效。若要馬上生效,直接執行xmodmap指令讀取設定檔亦可。
$xmodmap .Xmodmap

參考資料
xmodmap man page
xev man page
Ubuntu and my favourite keyboard IBM SK-8835
How to set right Alt to work as a Win(Super) key?

2011年11月11日 星期五

Ubuntu 12.04安裝之後遇到的各式各樣問題

本篇持續新增與更新中.......


1. 沒有終端機
安裝gnome-shell
$ sudo apt-get install gnome-shell

2. 需要設定字型
$ sudo apt-get install gnome-tweak-tool
安裝後尋找進階設定值(Advanced Settings)程式並開啟就可以找到相關字型設定
3. VMWare Player有問題
參考http://ved-antani.com/?p=30

4. 找回Dropbox等等系統列圖示
參考http://jonny.ubuntu-tw.net/2011/04/gcin-on-ubuntu-1104.html

5. 安裝hime
新增repository如下(參考)
$ sudo add-apt-repository -y ppa:hime-team/hime
deb http://debian.luna.com.tw/debian ./
deb http://debian.luna.com.tw/ubuntu ./

$ sudo apt-get install hime
$ sudo im-switch -s hime
$ update-alternatives --config xinput-zh_TW

選擇hime

在"系統設定值"的"語言支援"選擇"鍵盤輸入法系統"







然後登出重新登入即可生效

如果發生ctrl + space無法切換輸入法這點,我Google查了很久都找不到原因也無法解決,後來無意間發現只要別將EN英數設定為預設輸入法即可

6. Pidgin在使用Alt + Tab切換應用程式時都沒有出現
這個是ubuntu目前已知bug,可用下列work-around解開(參考)
在Pidgin設定中將"系統工作匣圖示"開起來就可以了(忘記要不要登出重新登入才會生效)

7. 安裝GIMP 2.8
由於Ubuntu預設都是使用GIMP 2.6,想使用2.8就需要重新安裝
新增下列repository
$ sudo add-apt-repository ppa:otto-kesselgulasch/gimp 
$ sudo apt-get update
$ sudo apt-get install gimp

8. APT相關
如果出現"W: GPG error: http://ppa.launchpad.net intrepid Release: The following ...the public key is not available: NO_PUBKEY 3B81A3FBA47394CE" 類似的錯誤訊息,只要重新取得key就好
$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3B81A3FBA47394CE

如果要刪除某把key
$ sudo apt-key del 3B81A3FBA47394CE

如果出現"gpg: no default secret key: secret key not available" 類似的錯誤訊息,就把快取清光重拿
$ cd /var/lib/apt
$ sudo mv lists lists.old
$ sudo mkdir -p lists/partial
$ sudo apt-get clean
$ sudo apt-get update

另一種作法
$ gpg --keyserver pgpkeys.mit.edu --recv-key  1C1E55A728CBC482    
$ gpg -a --export 1C1E55A728CBC482 | sudo apt-key add -
參考: http://blog.wu-boy.com/2012/05/how-to-resolve-apt-get-no_pubkey-gpg-error/ 

若是出現 "W: GPG error: http://ppa.launchpad.net precise InRelease: File /var/lib/apt/lists/....... doesn't start with a clearsigned message" 
通常都是中間的proxy擋住或是gateway有動手腳,嘗試看看
$ sudo rm /var/lib/apt/lists/* -vf
$ sudo apt-get -o Acquire::http::No-Cache=True -o Acquire::BrokenProxy=true update
或者是換台proxy

如果試了半天還是不行,就乾脆直接到Ubuntu軟體中心(Ubnutu Software)裏面, 設定軟體來源(Software Sources)的下載自(Download From)改為主要伺服器(Select Best Server)

Ubuntu 10.04設定雙螢幕的主螢幕

進入Monitors設定
今天終於把Ubuntu的雙螢幕(dual-monitor)弄起來,但卻發現按照系統的設定無法設定哪一邊是主螢幕。一般在Windows環境中,各顯示卡廠商出廠的驅動程式都可以設定主螢幕的選項。

沒有主螢幕的選項可以選擇
因此稍微在網路上搜尋了一下找到了解決方法,只要透過xrandr指令就能搞定。

1. 先使用xrandr找到目前有的顯示卡輸出選項
$ xrandr
目前有VGA1與HDMI1兩個螢幕
2.透過xrandr設定主螢幕,指令下完結果馬上就會生效了
    $ xrandr --output HDMI1 --primary

3.如果還要調整解析度、螢幕位置、或者鏡面螢幕等等,就直接在Monitors Preferences裏面設定就好
參考資料:
http://ubuntuforums.org/showthread.php?t=998591
xrandr man page

2011年10月17日 星期一

Apple Mac as client of synergy by using QuickSynergy

本來Mac OS上最受推荐的Synergy軟體當屬SynergyKM,然而自從Lion問世以後似乎災情慘重,在我的環境確實也是有同樣的問題,看來在新的問題被修正之前可能還是得回頭用QuickSynergy了。

然而今天不知為何怎麼弄就是無法讓QuickSynergy在Mac上能夠乖乖的作為一個正常的client工作。經過了一番搜尋,才找到原因,這問題不知道是系統的限制或是個bug。

原來不知為何,Mac版的QuickSynergy沒辦法讓使用者在client端自行指定Screen name,才會怎麼連都連不上server。因為Mac的QuickSynergy會強迫指定hostname作為client,所以必須反過來設定server端,讓server的設定"屈就"於client的hostname。

要得知Mac的hostname,就是先打開"系統偏好設定" => "共享"



看到上方的"電腦名稱",旁邊有個"編輯",直接點開


包含後面這段.網域的,整段加起來就是要放在server端設定的screen name



以Ubuntu作為Synergy的server為例,大概就是需要像這樣,接著執行server。回到作為cient端的Mac,就是直接執行就可順利連上server了。



參考資料
如何設定Mac上的QuickSynergy Client設定

2011年9月30日 星期五

iperf3測試網路負載

iperf是一個透過tcp測試系統網路能力的工具,由於可以專門測試tcp層不管application layer的干擾,因此特別適合用於針對系統底層網路能力來測試,例如網路卡、驅動程式、作業系統等等。

目前iperf已經出到3.0版,還在beta中,不過根據經驗之前版本的iperf反而不是很穩定,因此建議還是以iperf3作為測試的工具。

安裝
可以到此處下載
解開後經過編譯與安裝就可使用

註解: 如果使用ubuntu,需要先安裝build-essential uuid-dev,然後才能編譯與安裝
apt-get install build-essential uuid-dev
./configure
make
make install

執行
執行架構可分為client與server兩端

在server端執行如下指令即可
iperf3 -s

在client端執行下列指令
iperf3 -c -t -i

進階參數設定
還有下列幾個進階的參數可以設定,但若要使用下列參數,則server與client都要同時下一樣的參數值才行
-w n[KM]  指定 TCP window size
-l n[KM] 指定 read/write buffer 大小(預設為 8k)
-Pn (大寫的P) client 端指定同時 (parallel) 跑幾個的 threads

結果
在server端與client端都會有結果出現,兩者會不太一樣,但相當接近
最後cilent的結果如下
[ ID] Interval       Transfer     Bandwidth
      Sent
[  5] 0.00-20.00 sec  80.6 GBytes  34.6 Gbits/sec
      Received
[  5] 0.00-20.00 sec  80.6 GBytes  34.6 Gbits/sec 
分別代表執行時間、總下載數(單位為byte)與平均傳輸速度(單位為bits)

參考資料
iperf3官方網頁
iperf2官方網頁
更詳細的教學網頁
Windows版本的教學網頁