2009年10月3日 星期六

TIPTOP案例探討- 系統管理table斷開synonym


案例緣由

客戶:柚子的爸實業公司有台中廠和花蓮廠,可是兩端都有各自的IT人員及ERP開發人員,想要在TIPTOP上做到各別獨立控管;也就是台中廠的IT人員不可以去異動花蓮廠的權限、系統帳號…等等的設定。因此IT人員就將台中廠﹝資料庫為 DSTC﹞與系統資料庫﹝DS﹞的synonym全部斷開,開成實體存在的table
台中廠的Alex君某日突然發現,在啟用使用者登入帳號編碼﹝說明:TIPTOP GP 5.x後support﹞作業後突然發生異常無法登入…
案例說明

由於TIPTOP GP出現第一個畫面至使用者登入帳號、密碼輸入完成並驗證成功的過程中,系統真的也還不知道是哪個user要進來,此時當然更不會知道將進入的這個user是台中廠還是花蓮廠的。因此系統的作法是一律指定在系統資料庫﹝DS﹞內作業,直到我可以辨識user真實身份為止。
因此,若斷開各別資料庫與DS系統資料庫的synonym時,很可能就會發生基本設定不同而出現登入異常的情形。
應有作法

TIPTOP GP版本內,z*_file﹝z開頭的﹞及ga*_file / gb*_file / gc*_file 等table均屬系統基本資料表的範圍,切勿隨意移除synonym。否則很容易發生莫名其妙的系統性錯誤。
各廠間的IT人員應該相戶合作,共同維護基本資料,而從設定多組zw資料來進行管理上的切分。
又或者可以將zy_file 及 zxw_file 的synonym斷開,維護不同Database間各群組可用程式不同即可:其它系統table則仍須維持synonym。
若真的要做到完全拆開﹝連作業系統帳號都要做到互不隸屬管理﹞,那是否應該拆成兩組license並分裝在兩台機器上為宜。

Genero技轉沒教的事(03) – base.channel讀取外部執行指令結果

Genero語言中其實提供的Built-in函式與可應用的API並不多,因此,有時需要一些支援功能就顯的比較麻煩一些。若要用combine C/C++,程序上又較為麻煩,因此可以考慮利用base.channel的功能,在外部﹝shell上﹞執行後再由程式將執行結果讀入系統中。

01 MAIN
02     DEFINE fn CHAR(40)
03     DEFINE ex CHAR(10)
04     DEFINE ch base.Channel
05     LET ch = base.Channel.create()
06     CALL ch.setDelimiter(".")
07     CALL ch.openPipe("ls -l","r")
08     WHILE ch.read([fn,ex])
09         DISPLAY fn, "   ", ex
10     END WHILE
11     CALL ch.close()
12 END MAIN

04: 使用base.channel當然需要先進行DEFINE的動作
05: 利用LET channel_name = base.channel.create( )來創建channel
06: 設定分隔符號,讀取狀態下可設可不設
07: 如果是要讀外部指令的回傳結果,請用channel.openPipe(“指令",”r”),第二參數『r』是表示要讀取
      請注意若指令的輸出是在std err(error畫面輸出),則請導向到標準輸出﹝2>1&﹞
08: 利用ch.read讀到結束為止
11: 用完的channel請記得close否則會引發不可預期的錯誤

當然channel可以用來讀執行指令的結果,更可以用來讀取檔案

01 MAIN
02     DEFINE i INTEGER
03     DEFINE s STRING
04     DEFINE ch base.Channel
05     LET ch = base.Channel.create()
06     CALL ch.openFile("file.txt","r")
07     LET i = 1
08     WHILE TRUE
09         LET s = ch.readLine()
10         IF ch.isEof() THEN EXIT WHILE END IF
11         DISPLAY i, " ", s
12         LET i = i + 1
13     END WHILE
14     CALL ch.close()
15 END MAIN

06: 讀取檔案時要改用openFile,並且指定檔名、指定屬性【r:read only/ w:write only(一定是開空檔案)/ a:append only(一定不是空檔案,不可讀只能寫)/ u: update檔案 / b:binary file only】
09: 此處用readLine( )表示一次讀一整行進來,注意在Genero2以上版本就要定意由string型態的變數來接
10: isEOF( )讀到檔尾符號出現
14: ch.close( )還是要記得關channel

base.channel的使用很多元,詳細資料也可參考Genero線上說明。

2009年10月2日 星期五

RHEL 5.4版的telnet service


日前在Hyper-V R2上安裝了一套RHEL 5.4版的Linux,當然了,從上一個大版起telnet service預設就沒有安裝,因此就自作聰明的做了以下的調整來開啟telnet:
  1. chkconfig krb5-telnet on
  2. 把pts/1 – pts/20 加到 /etc/securetty 裡
好了,系統可以 telnet 了,可是 issue.net 好像一直沒有出來,登錄畫面就是很怪
後來終於瞭解,原來 krb5-telnet 是有安全性的 telnet service,不是傳統明碼傳遞的那種telnet service,因此要打掉重練
正確的步驟記錄如下:
  1. 取出安裝光碟,mount /dev/cdrom /mnt掛載並到 /mnt/Server 下以 rpm –i telnet-server-0.17-39.el5.x86_64.rpm 安裝 service
  2. chkconfig telnet on
  3. service xinetd restart
依照這樣的動作,/etc/issue.net 才可以生效

Genero 技轉沒教的事 (02) – 與環境變數的互動

Genero 語言從2.0版開始,提供2個與環境變數互動的function。

讀取環境變數fgl_getenv
Sample: CALL fgl_getenv("windir") RETURNING ls_string

依照上述的語法,我們即可將系統內的環境變數值讀進來使用,這些對於需要跨程式連結的需求上,有很大的幫助,因為可以不用再靠著寫暫存檔或變數檔的方法,達到不同的兩支程式﹝PID不同﹞互拋簡易資料的工作。從而避免了若『沒有讀寫權』之類的尷尬事件發生。

設定環境變數fgl_setenv
Sample: CALL fgl_setenv("windir","C:\\windows")

程式開發人員,可以利用這樣的語法,『即時的』改變現在執行的環境變數值﹝立即套用生效﹞,當然也可搭配上面的fgl_getenv,作出兩支獨立程式互串執行時拋接簡單變數的功用。
原廠文件內特別提到,當使用fgl_setenv時要特別注意,不要去異動一些系統需要用的環境變數﹝應該是指fglserver之類的﹞,以免造成程式的異常中止情形發生。

搭配RUN指令使用

當在程式內使用CALL fgl_setenv設定,又於接下來的程式段使用RUN來執行下一支作業﹝不管有沒有WITHOUT WAITING﹞,系統都會把設定的參數傳入並套用。

註:RUN…WITHOUT WAITING和『沒有WITHOUT WAITING』都一樣是用folk新process的方式啟動,只是一個不會等,一個會等…

Genero 技轉沒教的事 (01) – 檔案系統處理

先把之前寫過的整理整理,讓大家有個管道可以更瞭解Genero語言。

Genero在2.0版之後,增加一些外掛的函式庫,以擴展原有不足的部份。這些函式﹝function﹞,必需用『IMPORT』的方式將函式庫掛載到程式裡面來,才可以使用。利用這種技法開發出來的項目越來越多,如本文介紹的檔案系統處理﹝os﹞、Web Service及一些數學函式庫。

使用之前

在使用這些函式之前,需要在4gl啟始處﹝DATABASE指令之前﹞寫入『IMPORT os』

使用當下

使用此類函式時,必需用『os.Path.METHODS﹝METHOD請參照下表﹞』的方式來使用,例如copy,就是 CALL os.Path.copy(source, target) RETURNING li_success

Methods ﹝下表引用自 4JS 網頁:http://www.4js.com/online_documentation/fjs-fgl-2.11.01-manual-html/User/Ext_os_Path.html﹞以下紅字部份表示在TIPTOP GP程式內常見,沒翻譯的部份則比較少用到。

function 說明
separator

回傳path的分隔符號,Windows為 \ ,UNIX為 / 通常可以用來判斷系統是在哪個平台下運行,如 IF os.Path.separator() = "/" THEN….

pathseparator 類似上一個,回傳用在環境變數 (如 %PATH% 或 $PATH) 裡的路徑分隔符號
Windows為:,UNIX為;

basename

回傳『主要檔名』部份

dirname

回傳『目錄部份』檔名

rootname

回傳主要檔名﹝以上三組,請參照下方對照表即可瞭解﹞join 合併路徑用,如:LET ls_dir = os.Path.join ( "/etc", "passwd") 此時 ls_dir = /etc/passwd

extension Returns the file extension.
exists

檢視檔案是否存在
IF os.Path.exists(ls_filename) THEN…存在則回傳TRUE,沒有檔案即為FALSE

chrwx

變更UNIX上的rwx屬性,要計算對應值,而且只能用在UNIX 例如希望變更屬性為 777,則計算式為 64* 7 + 8* 7 + 1 * 7 = 511
CALL os.Path.chrwx(ls_filename, 511) RETURNING li_success (回傳TRUE / FALSE)

dirsort (搭配diropen/dirnext等) 如果要執行 ls / dir 指令來 check 檔案列表,請參考標準程序進行
chdir 變更目錄
mkdir mkdir
delete 刪除檔案或目錄
rename 更新目錄名或檔名
copy 複製檔案
atime 回傳檔案上次被讀取時間
mtime 回傳檔案上次被修改時間
readable 檢查檔案是否可被讀取
writable 檢查檔案是否可被寫入
executable 檢查檔案是否可被執行
isfile 檢查是否為一個檔案路徑
isdirectory 檢查是否為一個目錄路徑
islink 檢查是否為UNIX的soft link
isrootpath 檢查是否為根路徑
size 回傳檔案大小
chvolume 更換Windows的工作磁碟機

os.Path 指令操作範例對照表

原始資料 dirname basename rootname extension
. . .   NULL
.. . .. . NULL
/ / / / NULL
/usr/lib /usr lib /usr/lib NULL
/usr/ / usr /usr/ NULL
usr . usr usr NULL
file.xx . file.xx file xx
/tmp.yy/file.xx /tmp.yy file.xx /tmp.yy/file xx
/tmp.yy/file.xx.yy /tmp.yy file.xx.yy /tmp.yy/file.xx yy
/tmp.yy/ / tmp.yy /tmp.yy/ NULL
/tmp.yy/. /tmp.yy . /tmp.yy/ NULL

當可以善用這一些函式時,程式就可以和檔案系統進行一些互動,增加操作上的便利性。