發表文章

由Oracle PL/SQL中寄信

我有時候會使用Oracle的PL/SQL來寫一些程序,可以提供給前端的程式來叫用,或者使用Oracle的排程器來叫用,就可以做到許多原本要用C#或PB等開發工具才能做到的事。PL/SQL可以提供很好的效能,配合SQL Developer工具就可以跨平台在Windows或Mac OSX,Linux等不同電腦上寫程式。 最近在寫一個定期檢查的功能,想要在程式檢查到某些特別狀況時,希望可以寄送信件通知。找了一些資料,先稍作整理: 1. PL/SQL寄email的方式由早期的UTL_TCP,UTL_SMTP,到10g之後主要是推UTL_MAIL, 但是UTL_MAIL預設沒有安裝,必須由DBA先行安裝並設定一個指定郵件主機的初始參數。 $cd $ORACLE_HOME/rdbms/admin $sqlplus / as sysdba > @ utlmail.sql > @ prvtmail.plb > grant execute on UTL_MAIL to public; > alter system set smtp_out_server='xxx.xxx.xxx.xxx' 然後就可以很簡單的叫用一個程序來寄信了。 utl_mail.send(sender, recipients, cc, bcc, subject, message, mine_type); 我直接在SQL Developer裡測試正常,但是將此程式包在另一個程序裡叫用時,卻出現ORA-24247的錯誤。Google了一下找到這篇 ORA-06502 ORA-24247 calling UTL_MAIL from Oracle 11gR2  說要再建立一個ACL,然後要利用此ACL指派權限可以存取該郵件主機。不過,我在建立ACL時,卻又出現另一個錯誤訊息:function-based index XDB.XDB$ACL_XIDX is disabled並告訴我可以重建或啟用該索引。我直接在SQL Developer中重建該索引,卻一直失敗。再去Google後找到另一篇 Fine-grained access to network services ,發現他也是同樣的情況,而且他說他重建索引後就可以了。我才想到自己雖然具有DBA的權限,但是...

又被垃圾信攻擊了

最近做例行主機檢查時,發現郵件閘道主機異常的大量在往外寄信,但都無法寄出去。看了一下mailq, 果然發現有很大量的信在/var/spool/mqueue中。 直覺的先在mail log裡查看問題,但只看到一大堆由A主機寄到B主機的訊息,而B主機則是一大堆由A主機寄來信件以及試著要寄出,但無法寄出的訊息。 我們的架構是預設由A主機來寄信,如若寄不出去,則轉到B主機,由B主機來試著寄看看。所以真的寄不出去的信,都會queue在B主機。由初步看到的現象,我判斷(假設)攻擊者很有可能已經猜到我們使用者的帳號及密碼,然後由A主機大量的寄信進來。 我必須印證這個想法,並且若真為此情況,則必須找到是那個帳號被利用了。 但要如何印證呢?當然可以由mail log來查看,一定可以看到誰在那個時候,使用那個帳號進入,然後寄了多少信。這表示我必須查看大量的log訊息了,其實未必,我想到一個方法,在B主機裡queue了大量無法寄出的垃圾信,正好提供我重要的資訊。 #cd /var/spool/mqueue #ls * #cat xxxxxxx 如此,列出這些垃圾信的內容,(可能要多看幾封)結果我發現大部份的垃圾信都是在前幾天的幾點幾分寄到A主機的。如此,我只要看那個時刻的log就可以了。 #bzcat /var/log/maillog.0.bz2 | grep 16:08 | grep auth 以上列指令,在正確的mail log檔裡找到該時刻的資訊,而其實我也只要知道是不是有人使用SMTP AUTH的方式驗證進入。所以這樣我很快的只要查看很少的資訊就發現,果然有。而且找到是那個帳號被利用了。再進行反覆確認,以這個帳號來查看當天寄了多少信,登入驗證多少次,果然都是很異常的大量,而且其ip, FQDN, enveloper的內容等,也都符合。 我甚至還猜了一次該帳號的密碼,還真的猜對了。實在太好猜了。 最後,我只好先將該帳號鎖定(其實系統只是改了他的密碼),並將所有在mailq中的所有垃圾信都刪除。再觀察情況都正常後就收工了。

Oracle SQL Developer可以對PL/SQL程式除錯

圖片
之前在使用Oracle SQL Developer寫PL/SQL的時候,就有發現有除錯的功能,但是也沒耐心去找說明文件看如何使用,就直接用用看。但是每次都是有錯誤訊息,一時之間也不知道問題在那裡,又急著寫出程式,就先使用老方法DBMS_OUTPUT.PUT_LINE()把變數的內容印出來,其實也都可以解決。所以就一直沒去想為什麼除錯功能都不能用,最近比較有時間可以找問題,稍微試了一下,發現除錯功能是可以用的。 首先,網路上很多文章都有在講怎麼使用,例如這篇 Testing and Debugging Procedures using SQL Developer 。但是都講的很順,沒提到會碰到的問題。所以都會告訴你正常進入除錯模式的樣子長怎樣: 基本的可以看變數的內容值,可以設中斷點,可以進入或往下跑的功能都有。 我碰到的問題是在按除錯時,就出現錯誤訊息,不會進入這個除錯的畫面。而錯誤訊息是連線到一個奇怪的ip address 169.95.x.x之類的。然後告訴我連不到,我一直沒想到這個位址是何方神聖,後來一想,我的機器有安裝過虛擬機器的軟體,所以會有一張軟體的網路卡,而其ip address就是這種奇怪的樣子。 福至心靈,把那張虛擬機器建的軟體網卡停用後,再按除錯,就出現“其他的錯誤訊息”了。但是原本的錯誤訊息不見了,這表示已成功了一步。 我再按一下“編譯以除錯”按鈕,之後再去試按除錯,就成功了!可以正常的出現選取要除錯目標的視窗。之後的操作也都正常。

用實例談CSS, jQuery搭配ASP.NET

感謝電子情報刊出我的文章: "用實例談CSS, jQuery搭配ASP.NET"。去年家裡多了一個成員, 小朋友現在滿周歲了, 這一年多來, 我回家都沒有時間做自己的事情。在電腦前面坐一下, 馬上就有一隻小手手要來幫你按東按西; 不然就是會有人問說: "那個重要嗎? 一定要現在做嗎?" 所以這篇文章幾乎都是白天利用工作之餘, 一點一滴慢慢累積而成。 而且在投稿後, 又有做一些修改; 這一點很對不起雜誌社的編輯先生小姐, 真的很謝謝他們。 但是還是有未來得及修改的部份, 就是程式碼十三, 應該如下:               程式碼十三 : 包裹 jQuery 指令碼及 ScriptManager 的類別 public static class js_Utility {     public static void Alert( Page p, string message)     {         message = message.Replace( "\n" , " " );         string js = @"var smb=$('#dialog p span').clone();                     $('#dialog p').remove();                     $('#dialog').append('<p> </...

微軟ODBC driver for oracle的問題

圖片
我知道微軟之前已宣告不再為Oracle資料庫寫driver了, 而且微軟的ODBC driver for oracle最近的版本, 也是2008年了, 距今也有4年多, 可算是很舊的。 不過, 十幾年前我開始使用微軟的ODBC driver for oracle時, 用得還很順手。和PowerBuilder配合起來也沒什麼問題, 可能我用的功能很少很單純! 後來, 碰到一些問題, 同事告訴我有一些SQL語句, 這個driver沒有辦法解析, 他的解決方法是把這個driver換掉, 換成Oracle自家寫的ODBC driver, 問題就解決了! 最近我也碰到同樣的情況: select xxx from p, e, d, s, ed, dp, ( select a, sum(hours) h from ( select a, 0 hours from p wherer y = :year union all select a, hours from pof where b between :d1 and :d2 ) group by a ) v where p.a = e.c and d.a = s.s ... and p.a = v.a 這個SQL語句, 使用微軟的ODBC driver時, 會傳回錯誤訊息ORA-01861:文字與格式字串不符, 但是把ODBC driver換成Oracle自家寫的那支, 卻會很正常的跑完, 並傳回正確的結果。那就換driver不就好了, 還有什麼好討論的呢? 問題就在於, 有些奇奇怪怪的情況下, 一定要用微軟的那支driver, 這個時候就很頭大了。 我試了一下, 發現這個SQL語句的問題在於: 1. 可能是太多層的子查詢, 2. 或者是union 3. 反正太複雜了會造成微軟那支driver出問題。 所以, 我把SQL語句改寫: select xxx from p, e, d. s. ed, dp, ( select a, sum(hours) h from pof where b between :d1 and :d2 group by a ) v where p.a = e.c and d.a = s.s ... and p.a = v.a...

FreeBSD mail指令出現/tmp: write failed, filesystem is full錯誤

在我的一台FreeBSD主機出現如下情況: 當我下mail指令時, 出現如下錯誤訊息: /tmp: write failed, filesystem is full 在一個連線中, 下mail指令後, 開另一個連線, 一直用df指令觀看, 果然看到/tmp一直被吃掉! 本想用加大/tmp的方式(把/tmp ln到更大的分割區)來處理, 但想想現有/tmp已經有500MB了, 還要加多大? 所以覺得應該看看為什麼500MB還不夠mail指令用, 也不用想太多, 其實就是因為我用root帳號, 而預設所有系統訊息都會寄給root, 但我卻從不去清其郵件, 如下: # ls -l /var/mail total 3084208 -rw------- 1 clamav clamav 0 Jul 30 2009 clamav -rw------- 1 cyrus cyrus 0 Jul 30 2009 cyrus -rw------- 1 root wheel 3156647058 Feb 18 11:01 root -rw------- 1 spamd spamd 0 Jul 30 2009 spamd root的信件已經3GB大了, 當然mail程式在讀取的時候就需要超過500GB的空間, 自然會爆掉了。只要把/var/mail/root清掉就好了。 #rm /var/mail/root #touch /var/mail/root

如何為Linux上的Oracle 11g做異地備份

異地備份, 好像很高貴的樣子, 當911發生後, 很多廠商推異地備份方案, 都不便宜。我們自己弄了一個不太花錢的簡單版: 其實就只是把備份的檔案, 利用網路FTP到另一個地點, 只要事後可以由備份檔還原資料即可。 規劃要備份的檔案有三種: 1.archivelog, 2. full backup, 3. export dump files 前兩者合在一起, 可以做幾乎任一個時點的資料還原, dump檔則可以簡單的找出之前資料的樣子, 算是多一個保險, 多一個還原資料的方式。 這三種檔案各寫一個Script來備份: 1. Archivelog #!/bin/sh HOST='ftp-server' USER='user1' PASSWD='pass1' #D1=`date -d '1 day ago' "+%Y_%m_%d"` ftp -n -i $HOST <<END_SCRIPT quote USER $USER quote PASS $PASSWD bin cd archivelog mkdir $1 cd $1 lcd /u03/app/oracle/FRA/PRINCO/archivelog/$1 mput * quit END_SCRIPT exit 0 2. Full Backup #!/bin/sh HOST='ftp-server' USER='user1' PASSWD='pass1' ftp -n -i $HOST <<END_SCRIPT quote USER $USER quote PASS $PASSWD bin cd backupset lcd /u03/app/oracle/FRA/PRINCO/backupset/$1 mput *FULL*.bkp quit END_SCRIPT exit 0 3. Export dump files #!/bin/sh HOST='ftp-server' USER='user1' PASSWD='pass1...