Do the following:
by adding the init.ora parameters:
event="60 trace name errorstack level 3;name systemstate level 10"
Note that this can generate a very large trace file which may get
truncated unless MAX_DUMP_FILE_SIZE is large enough to accommodate the output.
When this is set any session encountering an ORA-60 error will write
information about all processes on the database at the time of the error.
This may help show the cause of the deadlock as it can show information
about both users involved in the deadlock.
This man is too old to remember everything in his brain. Right now, he needs a place to write down what he has studied.
標籤
4GL
(1)
人才發展
(10)
人物
(3)
太陽能
(4)
心理
(3)
心靈
(10)
文學
(31)
生活常識
(14)
光學
(1)
名句
(10)
即時通訊軟體
(2)
奇狐
(2)
爬蟲
(1)
音樂
(2)
產業
(5)
郭語錄
(3)
無聊
(3)
統計
(4)
新聞
(1)
經濟學
(1)
經營管理
(42)
解析度
(1)
遊戲
(5)
電學
(1)
網管
(10)
廣告
(1)
數學
(1)
機率
(1)
雜趣
(1)
證券
(4)
證券期貨
(1)
ABAP
(15)
AD
(1)
agentflow
(4)
AJAX
(1)
Android
(1)
AnyChart
(1)
Apache
(14)
BASIS
(4)
BDL
(1)
C#
(1)
Church
(1)
CIE
(1)
CO
(38)
Converter
(1)
cron
(1)
CSS
(23)
DMS
(1)
DVD
(1)
Eclipse
(1)
English
(1)
excel
(5)
Exchange
(4)
Failover
(1)
Fedora
(1)
FI
(57)
File Transfer
(1)
Firefox
(3)
FM
(2)
fourjs
(1)
Genero
(1)
gladiatus
(1)
google
(1)
Google Maps API
(2)
grep
(1)
Grub
(1)
HR
(2)
html
(23)
HTS
(8)
IE
(1)
IE 8
(1)
IIS
(1)
IMAP
(3)
Internet Explorer
(1)
java
(4)
JavaScript
(22)
jQuery
(6)
JSON
(1)
K3b
(1)
ldd
(1)
LED
(3)
Linux
(117)
Linux Mint
(4)
Load Balance
(1)
Microsoft
(2)
MIS
(2)
MM
(51)
MSSQL
(1)
MySQL
(27)
Network
(1)
NFS
(1)
Office
(1)
OpenSSL
(1)
Oracle
(126)
Outlook
(3)
PDF
(6)
Perl
(60)
PHP
(33)
PL/SQL
(1)
PL/SQL Developer
(1)
PM
(3)
Postfix
(2)
postfwd
(1)
PostgreSQL
(1)
PP
(50)
python
(5)
QM
(1)
Red Hat
(4)
Reporting Service
(28)
ruby
(11)
SAP
(234)
scp
(1)
SD
(16)
sed
(1)
Selenium
(3)
Selenium-WebDriver
(5)
shell
(5)
SQL
(4)
SQL server
(8)
sqlplus
(1)
SQuirreL SQL Client
(1)
SSH
(2)
SWOT
(3)
Symantec
(2)
T-SQL
(7)
Tera Term
(2)
tip
(1)
tiptop
(24)
Tomcat
(6)
Trouble Shooting
(1)
Tuning
(5)
Ubuntu
(37)
ufw
(1)
utf-8
(1)
VIM
(11)
Virtual Machine
(2)
VirtualBox
(1)
vnc
(3)
Web Service
(2)
wget
(1)
Windows
(19)
Windows
(1)
WM
(6)
Xvfb
(2)
youtube
(1)
yum
(2)
2012年1月29日 星期日
2012年1月28日 星期六
Perl : 用LWP實現GET/POST數據發送
1. GET ,获取网页内容,3句话,很简单吧!
#!perl -w
use strict;
use LWP;
my $browser = LWP::UserAgent->new();
my $response= $browser->get("http://www.toolmao.com");
print $response->content; # 输出获得的网页内容
2. POST,发送数据
#!perl -w
use strict;
use LWP;
my $browser = LWP::UserAgent->new();
$browser->cookie_jar( {} ); #有些網站需要cookie,比如群益
my $response= $browser->post("http://www.toolmao.com", { "test" => 123 , "data" => "gainover"}); #多加了一个被发送的数据的数组
print $response->content; # 输出获得的网页内容
3. multipart/form-data 类型的,一般上传文件的时候会用到
#!perl -w
use strict;
use LWP;
my $browser = LWP::UserAgent->new();
my $response = $browser->post(
'http://www.toolmao.com',
{ 'subject' => 'test for toolmao.com',
'uploadfile' => ["./file/工具猫.txt"], #这里是被上传的文件路径
'user' => 'Adm. Kang',
},
'Content_Type' => 'form-data' #这句不可少,表示类型为 multipart/form-data
);
print $response->content; # 输出返回的网页内容 更多的用法,例如设置User-Agent, cookies等,可以查看perl手册里关于lwp的用法部分!
#!perl -w
use strict;
use LWP;
my $browser = LWP::UserAgent->new();
my $response= $browser->get("http://www.toolmao.com");
print $response->content; # 输出获得的网页内容
2. POST,发送数据
#!perl -w
use strict;
use LWP;
my $browser = LWP::UserAgent->new();
$browser->cookie_jar( {} ); #有些網站需要cookie,比如群益
my $response= $browser->post("http://www.toolmao.com", { "test" => 123 , "data" => "gainover"}); #多加了一个被发送的数据的数组
print $response->content; # 输出获得的网页内容
3. multipart/form-data 类型的,一般上传文件的时候会用到
#!perl -w
use strict;
use LWP;
my $browser = LWP::UserAgent->new();
my $response = $browser->post(
'http://www.toolmao.com',
{ 'subject' => 'test for toolmao.com',
'uploadfile' => ["./file/工具猫.txt"], #这里是被上传的文件路径
'user' => 'Adm. Kang',
},
'Content_Type' => 'form-data' #这句不可少,表示类型为 multipart/form-data
);
print $response->content; # 输出返回的网页内容 更多的用法,例如设置User-Agent, cookies等,可以查看perl手册里关于lwp的用法部分!
2012年1月26日 星期四
謝比雪夫定理及經驗法則
p謝比雪夫定理:一組n或N個之量測值的資料組,至少有(1-(1/k2))比率的量測值,會落在距離平均數個標準差以內,此處之k大於等於1。
p
經驗法則:已知量測組近似鐘形分配,其區間在
(μ+σ)將包含約68%的量測值
(μ+2σ)將包含約95%的量測值
(μ+3σ)將包含幾乎100%的量測值
p謝比雪夫定理(Tchebysheff's theorem)
不限於量測組分配的型態,也不限於樣本或母體。
證明一組n或N個之量測值的資料組,至少有(1-(1/k2))比率的量測值,會落在距離平均數個標準差以內,此處之k大於等於1。
p標準差與謝比雪夫定理對應的比率,如表3-1所示
p兩個及三個標準差的部份,提供了有效的方式來說明量測值落於某特定區間之比率
p經驗法則
可以準確地估算近似鐘形分配量測組的分配型態,如圖3-3,資料組的相對次數直方圖愈接近鐘形(bell-sharped)分配,法則愈正確。
鐘形分配通常稱為常態分配。
p經驗法則被定義為已知量測組近似鐘形分配,其區間在
a.(μ+σ)或(x+s)將包含約68%的量測值。
b.(μ+2σ)或(x+2s)將包含約95%的量測值。
c.(μ+3σ)或(x+3s)將包含幾乎100%的量測值。
圖3-3 鐘形分配
p標準差的檢查
由謝比雪夫定理與經驗法則,大部份的量測值會落在距離平均數兩倍標準差的區間內。
因此,資料組的全距(R),大約等於四倍標準差。
2012年1月21日 星期六
Perl : unpack
問題:
從網路抓html下來有時會有怪怪的字元,難在由於是特殊字元且不可見,不知道如何用regular s///消除
解法:
後來找到unpack function,知道用以下方法可以print出16進位碼,如此就可用s///消除特殊字元了。
print unpack("H*",$xxx);
從網路抓html下來有時會有怪怪的字元,難在由於是特殊字元且不可見,不知道如何用regular s///消除
解法:
後來找到unpack function,知道用以下方法可以print出16進位碼,如此就可用s///消除特殊字元了。
print unpack("H*",$xxx);
Perl : Pack 與unpack使用說明
http://easun.org/archives/3_1.html
最近在看perlpacktut的document,整理了下面的文章,
希望對大家有幫助,瞭解pack/unpack怎麼用...
還沒寫完..後面跟C有關係..
======================================
最近在看perlpacktut的document,整理了下面的文章,
希望對大家有幫助,瞭解pack/unpack怎麼用...
還沒寫完..後面跟C有關係..
======================================
Pack 與unpack使用說明:
資料來源摘自perlpacktut,初學perl的時候,想必大家對於 pack與unpack都不是很瞭解,因此本人擷取perldoc裡面的文章,為各位簡單說明pack與unpack的使用方法:首先定義一下pack與 unpack:pack可視為將一系列的片段的數值打包在一起,可用於對dev檔案、socket、memory的讀寫,因為這些需要一塊完整的 memory,而且需要事先打包成特定格式;而unpack可以視為將將這些完整的 memory切割計算,取得我們所需要各部分的Variable。例子如下:
print pack(“H2”x10,map{ “3$_” } (0..9);
得到
0123456789
因為ASCII中30~39代表數字0-9。所以pack後可以得到ascii編碼的0->9,而我們可以利用unpack將string作逆向操作。
print unpack(“H*”,”0123456789”);
得到
30313233343536373839
同樣的作法可以用在中文字中,至是你要注意OS的編碼格式,UTF-8、GB2312、Big5得到的數值並不會相同。
Pack與unpack也可以用在對於對於固定格式的文件作處理的情形下:
代码:
Date |Description | Income|Expenditure
01/24/2001 Ahmed's Camel Emporium 1147.99
01/28/2001 Flea spray 24.99
01/29/2001 Camel rides to tourists 235.00
看到上面格式,想必大家很多人都用用substr將固定欄位中的字串取出來,或利用有點點複雜的Regular Expression將上面的文件欄位匹配出來,而實際上我們要將上面欄位一個一個匹配出來可以用一行搞定
例子:
while(<FF>){
my($date,$desc,$income,$expend) = unpack(“A10xA27xA7xA*”);
}
簡 單說明:A表示ASCII,A10表示10個ASCII character,x表示null byte也等於skip a byte,也就是說我們要跳過一個char(|),然後接著27個ASCII char,然後跳過一個vhar,再接上7個ASCII,在跳過一個char,最後A*表示不管後面char有多少個,我全含括進來。
這 樣子就可以得到各個欄位相對應的資料,很簡單吧!:) 不需要什麼太多的技巧,一行搞定。之後將income與expend作加總,得到total_income、total_expend,數值,然後再輸出 的時候,如果也要格式對稱,要怎麼辦?大多數人都會用format或sprintf,然後一行一行很辛苦的,將結果輸出。其實可以簡化成:
$income = sprintf("%.2f", $income); # Get them into
$expend = sprintf("%.2f", $expend); # "financial" format
將$income與$expend先格式化,然後同上例將結果輸出:
print pack("A11 A28 A8 A*", $date, "Totals", $income, $expend);
注意:這邊多加一個char主要是因為’x’表示的是null byte,所以如果用A7xA27xA7xA*,則輸出的字串會連在一起,而多給他一個char,就可以讓字串不會都連在一起。
完成程式如下:
代码:
#!/usr/bin/perl
use POSIX;
open(FF,"tt.txt");
while(<FF>){
my ($date,$desc,$income,$expend) = unpack("A10xA27xA7xA*",$_);
$tot_income += $income;
$tot_expend += $expend;
$income = sprintf("%.2f", $income);
$expend = sprintf("%12.2f", $expend);
print pack("A11 A28 A8 A*", $date, "$desc", $income, $expend),"\n";
}
$tot_income = sprintf("%.2f", $tot_income); # Get them into
$tot_expend = sprintf("%12.2f", $tot_expend); # "financial" format
$date = POSIX::strftime("%m/%d/%Y", localtime);
print pack("A11 A28 A8 A*", $date, "Totals", $tot_income, $tot_expend),"\n";
整數的pack:
對於整數需要注意各個OS所定義的int的長度,與各個OS所用的byte order順序是little-endian還是big-endian,就是高位元在前還是低位元在前的意思。
例子:
my $ps = pack(‘s’,20302);
s:a signed short intger,一般都是16bits=2bytes,如果我們將他print出來(列印這些pack後的字元,實際上是不具任何意義的),會發現他等於NO或ON,然後將$ps在unpack可以得到20302
unpack(‘s’,’NO’); ----------------->20302
注意:如果今天你用”s”,pack一個大於65535的數字,高位元會自動被刪除,而得到與你想要的數字不同的結果,這點需要注意。
“l”: signed 32bits integer
“L”:unsigned 32bits integer
“q”:signed 64bits intger
“Q”:unsigned 64bits integer
“i”:signed integers of “local custom” variety
“I”:unsigned integers of “local custom” variety
這兩個”i”與”I”主要與機器的OS定義有關係,其長度等於c中的sizeof(int),如果要用於perl與其他語言的溝通,最好使用這個編碼原則。
對照表:(其中%Config要先use Config;才能使用)
代码:
signed unsigned byte length in C byte length in Perl
s! S! sizeof(short) $Config{shortsize}
i! I! sizeof(int) $Config{intsize}
l! L! sizeof(long) $Config{longsize}
q! Q! sizeof(longlong) $Config{longlongsize}
對memory stack作pack:
例子如下:memory stack長得像下面這樣,接著利用unpack將stack中的各個欄位取出。
代码:
+---------+ +----+----+ +---------+
TOS: | IP |TOS+4:| FL | FH | FLAGS TOS+14:| SI |
+---------+ +----+----+ +---------+
| CS | | AL | AH | AX | DI |
+---------+ +----+----+ +---------+
| BL | BH | BX | BP |
+----+----+ +---------+
| CL | CH | CX | DS |
+----+----+ +---------+
| DL | DH | DX | ES |
+----+----+ +---------+
代码:
my( $ip, $cs, $flags, $ax, $bx, $cd, $dx, $si, $di, $bp, $ds, $es ) = unpack( 'v12', $frame );
‘v’ :unsigned short in ‘VAX ‘ order
這是取出橫列的IP、CS、FLAGS、AX、BX、CX、DX、SI、DI、BP、DS、ES
代码:
my( $fl, $fh, $al, $ah, $bl, $bh, $cl, $ch, $dl, $dh ) =
unpack( 'C10', substr( $frame, 4, 10 ) );
‘C’:unsign character value,用於bytes讀取
這樣子分兩行很麻煩,所以將他們放在一起得到:
my( $ip, $cs,
$flags,$fl,$fh,
$ax,$al,$ah, $bx,$bl,$bh, $cx,$cl,$ch, $dx,$dl,$dh,
$si, $di, $bp, $ds, $es ) =
unpack( 'v2' . ('vXXCC' x 5) . 'v5', $frame );
‘X’:Backup a byte
網路應用:
‘n’: An unsigned short in "network" (big-endian) order
‘N’: An unsigned long in "network" (big-endian) order
在作網路連結時,往往需要將長度先送給Server,使其知道後面有多少character要讀取,因此如果有一段msg,可以利用下列方式打包:
my $buf = pack( 'N', length( $msg ) ) . $msg;
說明:等於「長度」( unsigned long)加上訊息內容,也可簡化為:
my $buf = pack(‘NA*’,length($msg),$msg);
然後將$buf送至對方server。同樣對方可用unpack(‘NA*’,$buf)取得送出的數據。
Floating Point Numbers:
‘f’: float (A single-precision float in the native format)
‘d’:double(A double-precision float in the native format)
對於浮點數(float point)可以使用f或d來作pack與unpack動作。
奇特的例子:
Bit Strings:
String中都是0或1,對其作pack/unpack的轉換,需要注意那一系列的0/1,與每八個bit一個字元的順序性。假設今天有個string等於 ”10001100”可以用下列方式:
$byte = pack( 'B8', '10001100' ); # start with MSB
$byte = pack( 'b8', '00110001' ); # start with LSB
b A bit string (ascending bit order inside each byte, like vec()).(漸增)
B A bit string (descending bit order inside each byte).(漸減)
如果要對string中的一部份bits作pack/unpack是不可能的,因為pack會從最旁邊開始,然後以8個bits為一組,如果不足八個則補0。
代码:
+-----------------+-----------------+
| S Z - A - P - C | - - - - O D I T |
+-----------------+-----------------+
MSB LSB MSB LSB
例子:如上圖中「-」表示保留的bit,不使用。
將上列這2 bytes 轉換成一個string,可以利用’b16’來作:
#!usr/bin/perl
$status = "1101010100001111";
$ps= pack('b16',$status);
print "$ps\n";
$status=unpack('b16',$ps);
print "$status\n";
@aa = split(//,$status);
print "@aa\n";
#---簡化
#---可取得各個bit的數值
($carry, undef, $parity, undef, $auxcarry, undef, $sign,
$trace, $interrupt, $direction, $overflow) =
split( //, unpack( 'b16', $status ) );
如果使用’b12’則,後面的4個bit會被忽略並不會被使用。
Uuencode:(Unix-To-Unix Encode)
如 果對於UNIX很熟悉的,應該知道uuencode與uudecode是幹什麼用的,他可視為早期UNIX之間互相傳送資料,所用的一種編碼方法,將文件 編碼,以便利於在早期的網路上傳送資料,現在很少使用,但是有時還是有人會用到,編碼原理:取出三個bytes,將之切割成6份,每份4個 bits,然後在後面填入\x20,如此直到整個文件編碼完成。Pack可使用’u’作這件事情。
my $uubuf = pack( 'u', $bindat );
計算總和:(Do Sums)
pack中有個特殊的template,%<number>專門用來計算總和的,但是他不能在pack中使用,而且他只能用於其他數字的前置位置(prefix)。
用於數字時:
my $buf = pack( 'iii', 100, 20, 3 );
print unpack( '%32i3', $buf ), "\n"; # prints 123
用於字串時:
print unpack( '%32A*', "\x01\x10" ), "\n"; # prints 17
上面兩個例子,%會將後面i3、A*加總起來,得到最後結果123與17,這可以用來得到最後的check sum。另外不要太相信他所得到的數值,因為他們無法保證正確(?)。
用來取得netmask的bits數目:
my $bitcount = unpack( '%32b*', $mask );
my $evenparity = unpack( '%1b*', $mask );
取得evenparity的數值…mask=pack(‘b*’,”11111111111111111…0”);
Unicode:
$UTF8{Euro} = pack( 'U', 0x20AC );
歐洲用字編碼\0x20AC,其UTF8的編碼字元為$URF{Euro}。
# pack and unpack the Hebrew alphabet
my $alefbet = pack( 'U*', 0x05d0..0x05ea );
my @hebrew = unpack( 'U*', $utf );
用於pack/unpack unicode編碼
另一種Portable編碼:
w A BER compressed integer. Its bytes represent an unsigned integer in base 128, most significant digit first, with as few digits as possible. Bit eight (the high bit) is set on each byte except the last.
my $berbuf = pack( 'w*', 1, 128, 128+1, 128*128+127 );
長度與寬度(Length and Width)
字串長度(String Length)
在傳送網路資料時,往往需要將資料的長度放在封包的標頭處,讓對方Server知道後續還有多少資料需要處理:下列例子為兩個null terminated字串加上資料長度,再加上資料,得到最後要送出的資料。
Z:A null terminated (ASCIZ) string, will be null padded.
my $msg = pack( 'Z*Z*CA*', $src, $dst, length( $sm ), $sm );
而要取出資料可以用下列方式:
( $src, $dst, $len, $sm ) = unpack( 'Z*Z*CA*', $msg );
但是,如果我們在pack後面加上另一個C,則在unpack時,會無法正確得到資料。因為A*會把所有的剩餘character都抓給$sm,而使得$prio變成無定義。
# pack a message
my $msg = pack( 'Z*Z*CA*C', $src, $dst, length( $sm ), $sm, $prio );
# unpack fails - $prio remains undefined!
( $src, $dst, $len, $sm, $prio ) = unpack(
因此可以使用下列方式取得資料:
# pack a message: ASCIIZ, ASCIIZ, length/string, byte
my $msg = pack( 'Z* Z* C/A* C', $src, $dst, $sm, $prio );
# unpack
( $src, $dst, $sm, $prio ) = unpack( 'Z* Z* C/A* C', $msg );
加上”/”符號,可以使得perl在pack A*會記住$sm的長度,然後後續的$prio就可以區別出來儲存,而在unpack時,就可以依照$sm的長度,而將$sm的資料取出,剩下來的就是$prio的資料。”/”只有在後面接上A*、a*、Z*時有意義。
“/”表示後面A*的長度,佔1個byte
# pack a message: ASCIIZ, ASCIIZ, length/string, byte
my $msg = pack( 'Z* Z* C/A* C', $src, $dst, $sm, $prio );
# unpack
( $src, $dst, $sm, $prio ) = unpack( 'Z* Z* C/A* C', $msg );
“/”可以代表任何數字,用以表示其後A*的長度
# pack/unpack a string preceded by its length in ASCII
my $buf = pack( 'A4/A*', "Humpty-Dumpty" );
# unpack $buf: '13 Humpty-Dumpty'
my $txt = unpack( 'A4/A*', $buf );
“/”在perl 5.6以後才出現,之前版本並不支援。針對舊版本需要做如下修改已取得長度。
# pack a message: ASCIIZ, ASCIIZ, length, string, byte (5.005 compatible)
my $msg = pack( 'Z* Z* C A* C', $src, $dst, length $sm, $sm, $prio );
# unpack
( undef, undef, $len) = unpack( 'Z* Z* C', $msg );#--先取得長度
#--依照長度設定A的長度
($src, $dst, $sm, $prio) = unpack ( "Z* Z* x A$len C", $msg );
Dynamic Template
從前面到現在我們看到的都是有固定長度的範例,但是如果碰到沒有固定長度的怎麼辦?以下有個例子來說明:
my $env = pack( 'A*A*Z*' x keys( %Env ) . 'C',
map( { ( $_, '=', $Env{$_} ) } keys( %Env ) ), 0 );
為 了方便讓C來Parsing這個string,所以利用兩個string與一個null terminated字串,利用map將$ENV中的參數讀出來,然後利用(AAA,=,BBB)的方式,儲存成一個array,然後傳給pack,然後 pack利用”A*A*Z*將AAA,=,BBB給打包起來,keys(%ENV)表示ENV hash總共有多少個$element在裡面。最後為了方便C parsing,在最後面加上一個”0”。
my $n = $env =~ tr/\0// - 1;
my %env = map( split( /=/, $_ ), unpack( 'Z*' x $n, $env ) );
而在unpack時,要先算出$env裡面到底有多少個$element在裡面,這可以透過tr來計算。
資料來源摘自perlpacktut,初學perl的時候,想必大家對於 pack與unpack都不是很瞭解,因此本人擷取perldoc裡面的文章,為各位簡單說明pack與unpack的使用方法:首先定義一下pack與 unpack:pack可視為將一系列的片段的數值打包在一起,可用於對dev檔案、socket、memory的讀寫,因為這些需要一塊完整的 memory,而且需要事先打包成特定格式;而unpack可以視為將將這些完整的 memory切割計算,取得我們所需要各部分的Variable。例子如下:
print pack(“H2”x10,map{ “3$_” } (0..9);
得到
0123456789
因為ASCII中30~39代表數字0-9。所以pack後可以得到ascii編碼的0->9,而我們可以利用unpack將string作逆向操作。
print unpack(“H*”,”0123456789”);
得到
30313233343536373839
同樣的作法可以用在中文字中,至是你要注意OS的編碼格式,UTF-8、GB2312、Big5得到的數值並不會相同。
Pack與unpack也可以用在對於對於固定格式的文件作處理的情形下:
代码:
Date |Description | Income|Expenditure
01/24/2001 Ahmed's Camel Emporium 1147.99
01/28/2001 Flea spray 24.99
01/29/2001 Camel rides to tourists 235.00
看到上面格式,想必大家很多人都用用substr將固定欄位中的字串取出來,或利用有點點複雜的Regular Expression將上面的文件欄位匹配出來,而實際上我們要將上面欄位一個一個匹配出來可以用一行搞定
例子:
while(<FF>){
my($date,$desc,$income,$expend) = unpack(“A10xA27xA7xA*”);
}
簡 單說明:A表示ASCII,A10表示10個ASCII character,x表示null byte也等於skip a byte,也就是說我們要跳過一個char(|),然後接著27個ASCII char,然後跳過一個vhar,再接上7個ASCII,在跳過一個char,最後A*表示不管後面char有多少個,我全含括進來。
這 樣子就可以得到各個欄位相對應的資料,很簡單吧!:) 不需要什麼太多的技巧,一行搞定。之後將income與expend作加總,得到total_income、total_expend,數值,然後再輸出 的時候,如果也要格式對稱,要怎麼辦?大多數人都會用format或sprintf,然後一行一行很辛苦的,將結果輸出。其實可以簡化成:
$income = sprintf("%.2f", $income); # Get them into
$expend = sprintf("%.2f", $expend); # "financial" format
將$income與$expend先格式化,然後同上例將結果輸出:
print pack("A11 A28 A8 A*", $date, "Totals", $income, $expend);
注意:這邊多加一個char主要是因為’x’表示的是null byte,所以如果用A7xA27xA7xA*,則輸出的字串會連在一起,而多給他一個char,就可以讓字串不會都連在一起。
完成程式如下:
代码:
#!/usr/bin/perl
use POSIX;
open(FF,"tt.txt");
while(<FF>){
my ($date,$desc,$income,$expend) = unpack("A10xA27xA7xA*",$_);
$tot_income += $income;
$tot_expend += $expend;
$income = sprintf("%.2f", $income);
$expend = sprintf("%12.2f", $expend);
print pack("A11 A28 A8 A*", $date, "$desc", $income, $expend),"\n";
}
$tot_income = sprintf("%.2f", $tot_income); # Get them into
$tot_expend = sprintf("%12.2f", $tot_expend); # "financial" format
$date = POSIX::strftime("%m/%d/%Y", localtime);
print pack("A11 A28 A8 A*", $date, "Totals", $tot_income, $tot_expend),"\n";
整數的pack:
對於整數需要注意各個OS所定義的int的長度,與各個OS所用的byte order順序是little-endian還是big-endian,就是高位元在前還是低位元在前的意思。
例子:
my $ps = pack(‘s’,20302);
s:a signed short intger,一般都是16bits=2bytes,如果我們將他print出來(列印這些pack後的字元,實際上是不具任何意義的),會發現他等於NO或ON,然後將$ps在unpack可以得到20302
unpack(‘s’,’NO’); ----------------->20302
注意:如果今天你用”s”,pack一個大於65535的數字,高位元會自動被刪除,而得到與你想要的數字不同的結果,這點需要注意。
“l”: signed 32bits integer
“L”:unsigned 32bits integer
“q”:signed 64bits intger
“Q”:unsigned 64bits integer
“i”:signed integers of “local custom” variety
“I”:unsigned integers of “local custom” variety
這兩個”i”與”I”主要與機器的OS定義有關係,其長度等於c中的sizeof(int),如果要用於perl與其他語言的溝通,最好使用這個編碼原則。
對照表:(其中%Config要先use Config;才能使用)
代码:
signed unsigned byte length in C byte length in Perl
s! S! sizeof(short) $Config{shortsize}
i! I! sizeof(int) $Config{intsize}
l! L! sizeof(long) $Config{longsize}
q! Q! sizeof(longlong) $Config{longlongsize}
對memory stack作pack:
例子如下:memory stack長得像下面這樣,接著利用unpack將stack中的各個欄位取出。
代码:
+---------+ +----+----+ +---------+
TOS: | IP |TOS+4:| FL | FH | FLAGS TOS+14:| SI |
+---------+ +----+----+ +---------+
| CS | | AL | AH | AX | DI |
+---------+ +----+----+ +---------+
| BL | BH | BX | BP |
+----+----+ +---------+
| CL | CH | CX | DS |
+----+----+ +---------+
| DL | DH | DX | ES |
+----+----+ +---------+
代码:
my( $ip, $cs, $flags, $ax, $bx, $cd, $dx, $si, $di, $bp, $ds, $es ) = unpack( 'v12', $frame );
‘v’ :unsigned short in ‘VAX ‘ order
這是取出橫列的IP、CS、FLAGS、AX、BX、CX、DX、SI、DI、BP、DS、ES
代码:
my( $fl, $fh, $al, $ah, $bl, $bh, $cl, $ch, $dl, $dh ) =
unpack( 'C10', substr( $frame, 4, 10 ) );
‘C’:unsign character value,用於bytes讀取
這樣子分兩行很麻煩,所以將他們放在一起得到:
my( $ip, $cs,
$flags,$fl,$fh,
$ax,$al,$ah, $bx,$bl,$bh, $cx,$cl,$ch, $dx,$dl,$dh,
$si, $di, $bp, $ds, $es ) =
unpack( 'v2' . ('vXXCC' x 5) . 'v5', $frame );
‘X’:Backup a byte
網路應用:
‘n’: An unsigned short in "network" (big-endian) order
‘N’: An unsigned long in "network" (big-endian) order
在作網路連結時,往往需要將長度先送給Server,使其知道後面有多少character要讀取,因此如果有一段msg,可以利用下列方式打包:
my $buf = pack( 'N', length( $msg ) ) . $msg;
說明:等於「長度」( unsigned long)加上訊息內容,也可簡化為:
my $buf = pack(‘NA*’,length($msg),$msg);
然後將$buf送至對方server。同樣對方可用unpack(‘NA*’,$buf)取得送出的數據。
Floating Point Numbers:
‘f’: float (A single-precision float in the native format)
‘d’:double(A double-precision float in the native format)
對於浮點數(float point)可以使用f或d來作pack與unpack動作。
奇特的例子:
Bit Strings:
String中都是0或1,對其作pack/unpack的轉換,需要注意那一系列的0/1,與每八個bit一個字元的順序性。假設今天有個string等於 ”10001100”可以用下列方式:
$byte = pack( 'B8', '10001100' ); # start with MSB
$byte = pack( 'b8', '00110001' ); # start with LSB
b A bit string (ascending bit order inside each byte, like vec()).(漸增)
B A bit string (descending bit order inside each byte).(漸減)
如果要對string中的一部份bits作pack/unpack是不可能的,因為pack會從最旁邊開始,然後以8個bits為一組,如果不足八個則補0。
代码:
+-----------------+-----------------+
| S Z - A - P - C | - - - - O D I T |
+-----------------+-----------------+
MSB LSB MSB LSB
例子:如上圖中「-」表示保留的bit,不使用。
將上列這2 bytes 轉換成一個string,可以利用’b16’來作:
#!usr/bin/perl
$status = "1101010100001111";
$ps= pack('b16',$status);
print "$ps\n";
$status=unpack('b16',$ps);
print "$status\n";
@aa = split(//,$status);
print "@aa\n";
#---簡化
#---可取得各個bit的數值
($carry, undef, $parity, undef, $auxcarry, undef, $sign,
$trace, $interrupt, $direction, $overflow) =
split( //, unpack( 'b16', $status ) );
如果使用’b12’則,後面的4個bit會被忽略並不會被使用。
Uuencode:(Unix-To-Unix Encode)
如 果對於UNIX很熟悉的,應該知道uuencode與uudecode是幹什麼用的,他可視為早期UNIX之間互相傳送資料,所用的一種編碼方法,將文件 編碼,以便利於在早期的網路上傳送資料,現在很少使用,但是有時還是有人會用到,編碼原理:取出三個bytes,將之切割成6份,每份4個 bits,然後在後面填入\x20,如此直到整個文件編碼完成。Pack可使用’u’作這件事情。
my $uubuf = pack( 'u', $bindat );
計算總和:(Do Sums)
pack中有個特殊的template,%<number>專門用來計算總和的,但是他不能在pack中使用,而且他只能用於其他數字的前置位置(prefix)。
用於數字時:
my $buf = pack( 'iii', 100, 20, 3 );
print unpack( '%32i3', $buf ), "\n"; # prints 123
用於字串時:
print unpack( '%32A*', "\x01\x10" ), "\n"; # prints 17
上面兩個例子,%會將後面i3、A*加總起來,得到最後結果123與17,這可以用來得到最後的check sum。另外不要太相信他所得到的數值,因為他們無法保證正確(?)。
用來取得netmask的bits數目:
my $bitcount = unpack( '%32b*', $mask );
my $evenparity = unpack( '%1b*', $mask );
取得evenparity的數值…mask=pack(‘b*’,”11111111111111111…0”);
Unicode:
$UTF8{Euro} = pack( 'U', 0x20AC );
歐洲用字編碼\0x20AC,其UTF8的編碼字元為$URF{Euro}。
# pack and unpack the Hebrew alphabet
my $alefbet = pack( 'U*', 0x05d0..0x05ea );
my @hebrew = unpack( 'U*', $utf );
用於pack/unpack unicode編碼
另一種Portable編碼:
w A BER compressed integer. Its bytes represent an unsigned integer in base 128, most significant digit first, with as few digits as possible. Bit eight (the high bit) is set on each byte except the last.
my $berbuf = pack( 'w*', 1, 128, 128+1, 128*128+127 );
長度與寬度(Length and Width)
字串長度(String Length)
在傳送網路資料時,往往需要將資料的長度放在封包的標頭處,讓對方Server知道後續還有多少資料需要處理:下列例子為兩個null terminated字串加上資料長度,再加上資料,得到最後要送出的資料。
Z:A null terminated (ASCIZ) string, will be null padded.
my $msg = pack( 'Z*Z*CA*', $src, $dst, length( $sm ), $sm );
而要取出資料可以用下列方式:
( $src, $dst, $len, $sm ) = unpack( 'Z*Z*CA*', $msg );
但是,如果我們在pack後面加上另一個C,則在unpack時,會無法正確得到資料。因為A*會把所有的剩餘character都抓給$sm,而使得$prio變成無定義。
# pack a message
my $msg = pack( 'Z*Z*CA*C', $src, $dst, length( $sm ), $sm, $prio );
# unpack fails - $prio remains undefined!
( $src, $dst, $len, $sm, $prio ) = unpack(
因此可以使用下列方式取得資料:
# pack a message: ASCIIZ, ASCIIZ, length/string, byte
my $msg = pack( 'Z* Z* C/A* C', $src, $dst, $sm, $prio );
# unpack
( $src, $dst, $sm, $prio ) = unpack( 'Z* Z* C/A* C', $msg );
加上”/”符號,可以使得perl在pack A*會記住$sm的長度,然後後續的$prio就可以區別出來儲存,而在unpack時,就可以依照$sm的長度,而將$sm的資料取出,剩下來的就是$prio的資料。”/”只有在後面接上A*、a*、Z*時有意義。
“/”表示後面A*的長度,佔1個byte
# pack a message: ASCIIZ, ASCIIZ, length/string, byte
my $msg = pack( 'Z* Z* C/A* C', $src, $dst, $sm, $prio );
# unpack
( $src, $dst, $sm, $prio ) = unpack( 'Z* Z* C/A* C', $msg );
“/”可以代表任何數字,用以表示其後A*的長度
# pack/unpack a string preceded by its length in ASCII
my $buf = pack( 'A4/A*', "Humpty-Dumpty" );
# unpack $buf: '13 Humpty-Dumpty'
my $txt = unpack( 'A4/A*', $buf );
“/”在perl 5.6以後才出現,之前版本並不支援。針對舊版本需要做如下修改已取得長度。
# pack a message: ASCIIZ, ASCIIZ, length, string, byte (5.005 compatible)
my $msg = pack( 'Z* Z* C A* C', $src, $dst, length $sm, $sm, $prio );
# unpack
( undef, undef, $len) = unpack( 'Z* Z* C', $msg );#--先取得長度
#--依照長度設定A的長度
($src, $dst, $sm, $prio) = unpack ( "Z* Z* x A$len C", $msg );
Dynamic Template
從前面到現在我們看到的都是有固定長度的範例,但是如果碰到沒有固定長度的怎麼辦?以下有個例子來說明:
my $env = pack( 'A*A*Z*' x keys( %Env ) . 'C',
map( { ( $_, '=', $Env{$_} ) } keys( %Env ) ), 0 );
為 了方便讓C來Parsing這個string,所以利用兩個string與一個null terminated字串,利用map將$ENV中的參數讀出來,然後利用(AAA,=,BBB)的方式,儲存成一個array,然後傳給pack,然後 pack利用”A*A*Z*將AAA,=,BBB給打包起來,keys(%ENV)表示ENV hash總共有多少個$element在裡面。最後為了方便C parsing,在最後面加上一個”0”。
my $n = $env =~ tr/\0// - 1;
my %env = map( split( /=/, $_ ), unpack( 'Z*' x $n, $env ) );
而在unpack時,要先算出$env裡面到底有多少個$element在裡面,這可以透過tr來計算。
Perl的基本語法
http://ind.ntou.edu.tw/~dada/cgi/Perlsynx.htm
前言:
這篇文章是花了我很多時間、費了我很多心血才完成的,雖然連我自己都覺得無法達到盡善盡美的境界,但希望能幫助大家入門,稍微了解到Perl到底是個什麼樣的東西,Perl到底有那些強大的功能,那麼這篇文章的目的就達到了。 我分做資料型態、控制敘述、副程式、I/O和檔案處理、Regular Expressions、Spectial Variables、Help 這幾部分來講解,但只是敘述了一些Perl的基本語法而已,Perl活潑的特性和程式的技巧就無法一一詳述了,甚為缺憾。
(1) 資料型態(Data type):
Perl的資料型態大致分為四種:Scalar、Scalar Array、Hash Array、References, 看起來雖少但用起來卻綽綽有餘。尤其在寫Perl程式時可以不必事先宣告變數,這一點對剛學程式語言的人甚為方便, 不過為了以後程式除錯和維護方便,我建議你還是養成事先宣告變數的習慣比較好。
(a) Scalar: 純量變數是Perl裡最基本的一種資料型態,它可以代表一個字元、字串、整數、甚至浮點數,而Perl把它們都看成是一樣的東東! 你甚至可以混著用,不可思議吧。例如:
那麼程式怎麼判斷這是數值還是字串呢? 其實不是程式判斷,而是你自己要判斷。Perl分別提供了一堆運算子來處理數字和字串,你必須知道這個變數是數值或字串,才能使用個別的運算子來對變數做運算。我分別列出字串運算子和數值運算子,好讓大家能區分它們的不同。
◎字串運算子
◎數值運算子
(b) Scalar Array: 純量陣列,陣列內的每一個元素都是Scalar variable。宣告及使用方式如下:
看到$#array這個奇怪的東東沒? 這是Perl的一個特殊用法,代表這個陣列最後一個元素的註標。 由於Perl不必事先宣告變數,也不必預先宣告陣列的大小,甚至可以隨時增加新元素,那我們怎麼知道這個陣列到底有多大呢? 透過這個特殊變數我們可以得知這個這個陣列最後一個元素的註標,自然而然也就知道這個陣列究竟有多大了。 另外Perl只定義了一維陣列的語法,二維以上只能用指標間接來達成。
(c) Hash Array(Associative Array): 雜湊陣列也叫做相關陣列,它和一般陣列沒什麼不同,差別只是在它的索引值用的是字串,而非一般陣列所用的整數值, 因此相關陣列不像一般陣列一樣有次序的概念,它沒有所謂的第一項資料這種說法。它就相當於把一堆變數組合成一個group,然後我們可以透過索引字串存取這個group每一個元素的值。 相關陣列的宣告及使用方式如下:
Perl有上述三個函數可對相關陣列做運算:keys函數可取出相關變數的索引值,組成一純量陣列,注意這些由keys函數取出的索引值沒有次序性;values函數可取出相關變數的元素值;each函數則會取出(索引、元素)對。使用者可視情況而用。
(d) References(Pointer): Perl 5新增了參考指標的資料型態,使Perl和C一樣可借由指標建立一些複雜的資料結構。 普通程式是用不到指標這玩意的,下面也只是簡單介紹一下,看不懂的人可不必深究。
⊙如何取得變數的位址?
⊙如何使用指標?
⊙Anonymous Array References:(二維陣列)
⊙Anonymous Hash References:
(2) 控制敘述(Control Statements)
(a) Conditional Control Statements: Perl的條件控制敘述和C語言很像,讓使用者很快就能掌握它。不過Perl比C語言又另外多了些實用的語法,我用底線標出來,大家一看便知:
看吧! C 語言有的Perl大部分都有,學過 C 的人可以毫不費力的學會Perl。
(b) Loop Control Statements: Perl的迴圈控制敘述也和C語言很像,當然,照例Perl也另外多了些實用的語法:
(3) 副程式(Subroutines)
(a) Syntax: sub NAME {Code}
(b) 呼叫副程式: &NAME(para1, para2,...)
(c) 參數傳遞: @_ Perl和C一樣是採用Call by value的方式,不過因為Perl不用事先宣告變數,所以建立副程式的時候也不用宣告要傳遞什麼參數。 當主程式在傳遞參數給副程式時,Perl會把括號括起來的參數按順序放在一個特殊的全域變數 @_ 陣列中,然後副程式就可以隨意使用陣列 @_ 裡的參數,例如 $_[0] 是第一個參數, $_[1] 是第二個,或是用
(d) Variable Localization:my or local 通常我們在程式中定義的變數都是全域變數,所以在副程式中若要把變數區域化則要加上 my 或 local 關鍵字,例如:
(4) I/O和檔案處理
(a) Syntax: open(FILEHANDLE,"Expression");
close(FILEHANDLE); 這裡的Expression是一個敘述加上檔案名稱,若Expression只有檔案名稱沒有加上敘述,則預設是唯讀。Expressions敘述如下:
(b) Input: Perl沒有特別用來輸入的函數,因為Perl在執行程式時,會自動開啟標準輸入裝置,其filehandle定為STDIN,所以在Perl中要輸入資料的方法就是使用<STDIN>:
(c) Output: print "variables or 字串"; Perl也有printf()函數,語法和C語言一模一樣,我就不多做介紹了。Perl另外有個print函數,比printf()更方便、更好用,包你愛不釋手。 Output不外乎是輸出到螢幕或檔案,用例子來說明比較容易了解。
(5) Regular Expressions Regular Expression通常是用來尋找特定的字串樣式(pattern),也就是所謂格式辨認(pattern-matching)的功能。 它的運算子是『=~』和『!~』,可以把它念做match和not match。
Syntax: $string =~ /regular expression/expression modifier
例:$sentence =~ /Hello/
(a) Modifiers:修飾選項可有可無,它是用來對整個敘述作修正的。
(b) Metacharacter:下面這些字元都具有特殊意義,可以讓你建立更複雜的搜尋樣式(searching pattern)。
(c) Pattern Quantifier:用來表示字元的數量關係。
(d) Character Patterns:下列的sequence用來match一些特定格式的字元:
(e) Examples: Regular Expression這個東東非常強大、非常重要,但是對初學者來說簡直是個惡夢,記得我當初剛接觸時也是霧煞煞的,就算現在的我也不敢說全懂了:p 但你若了解了它的基本技巧後,包你愛不釋手,每每為它強大的功能讚歎。上面那些表格相信你也是有看沒有懂,這種東西要借由範例入門比較快,下面我列出一些基本範例,希望能幫助你了解它的基本技巧。
找到含有abc的字串 找到開頭是abc的字串 找到結尾是abc的字串 找到有a或b的字串,也可以用來找整個字(word) 找到a後面跟著2-4個b,再跟著c的字串,若只有/ab{2,}c/則會找二個以上的b 找到a後面跟著0個或多個b,再跟著c的字串,如同/ab{0,}c/ 找到a後面跟著一個以上的b,再跟著c的字串,如同/ab{1,}c/ .可以代表任何字元,除了new line字元(\n)外。 找到含有這三個字元中任何一個的字串 找到含有數字的字串,如同/[0-9]/ 找到含有字母的字串,如同/[a-zA-Z0-9_]/ 找到含有white space的字串,如同/[ \t\r\n\f]/ 找到沒有abc任一字元的字串 找到含有字元*的字串,在反斜線"\"後面的字元Perl會把它當作普通字元看待。若你不確定這個符號是否為特殊字元,乾脆全加上\以策安全。 忽略abc的大小寫 找到類似IP的字串,並將IP的四個數字分別存在$1,$2,$3,$4四個特殊變數中,以便在其後加以利用。例: m命令可以讓你自訂pattern的分隔符號,而gimosx則是它的修飾選項,請參看(a)Modifiers。例如:
m後面跟著的就是分隔符號,| |裡面的就是pattern。
match一個字串,裡面沒有/和:字元。找到的字串存在$1中。
match 0或1個:,後面跟著一串數字或nothing。找到的字串存在$2中,若找不到,$2就是空的。
match一串非空白字元,並以找到的字串為結尾。找到的字串存在$3中。
($host, $port, $file)=($1, $2, $3)
即$host="my.machine.tw"
$port=8080
$file="/cgi-bin/test.pl"
沒錯,這就是取代的命令。它會尋找符合PATTERN的字串,並取代成REPLACEMENT字串。它的修飾選項多了e選項,其他的和上面都一樣,我將它列表如下:
例:
這是也是取代的命令,和上一個不同的是SEARCHLIST和REPLACEMENTLIST只能是普通字串,而不是Regular Expression,所以速度比較快。它的修飾選項也比較少:
例:
(6) Spectial Variables
Perl的特色之一就是有超過50個以上的特殊變數,這些變數都是全域變數,用來設定程式的執行環境和其它細節。 若你想深入了解Perl程式設計,那麼這些東西是不可或缺的。在這裡我只列幾個常用的特殊變數以供參考,有興趣的人請自行查閱。
(7) Help
目前市面上有關Perl語言的書並不多,就算是原文書也只有那幾本聖經本。不過只要是有關CGI的書,其內容大都會提到Perl,但卻很少教到基本語法,常常使人一頭霧水。 所以我建議:如果你真的想學好Perl語言,真得想拿Perl來寫程式,那我建議你最好去買一本書來看,在觀念上會比較清楚,在實際應用上也會比較有幫助; 如果你只是想寫一些簡單的CGI程式,或只想看得懂別人所寫的CGI程式,那在網路上的資料就綽綽有餘了。
首先你可以到各大BBS站的WWW板或program板的精華區找找,不過資料不會很多,而且有點雜亂。 再不然你可以到蕃薯藤輸入perl或cgi關鍵字找找,有不少人的homepage上有教人如何用Perl寫CGI程式,還有一堆別人已經寫好的CGI程式可以抓來用用。 說到這裡順便打一下廣告,在http://ind.ntou.edu.tw/documents下有Perl的說明文件,做得相當不錯,不過全是英文的就是了,而我這份講義打好後也會放在IND的homepage上,大家可以抓回去參考參考。
第三種資源就是Perl本身的man pages,你在IND帳號下鍵入 man perl 就可以查閱了,這份文件做得不錯,還根據Perl的各個部分寫了man pages,如Perl syntax, builtin function, regular expression, data structure等, 大家可以用man指令一一查詢,有時候在寫程式時一時忘了某個函數怎麼用,這倒是個方便又快速的查詢方法。我會把這些man pages轉成html格式,放在WWW上讓大家參考。
Perl的基本語法 |
這篇文章是花了我很多時間、費了我很多心血才完成的,雖然連我自己都覺得無法達到盡善盡美的境界,但希望能幫助大家入門,稍微了解到Perl到底是個什麼樣的東西,Perl到底有那些強大的功能,那麼這篇文章的目的就達到了。 我分做資料型態、控制敘述、副程式、I/O和檔案處理、Regular Expressions、Spectial Variables、Help 這幾部分來講解,但只是敘述了一些Perl的基本語法而已,Perl活潑的特性和程式的技巧就無法一一詳述了,甚為缺憾。
(1) 資料型態(Data type):
Perl的資料型態大致分為四種:Scalar、Scalar Array、Hash Array、References, 看起來雖少但用起來卻綽綽有餘。尤其在寫Perl程式時可以不必事先宣告變數,這一點對剛學程式語言的人甚為方便, 不過為了以後程式除錯和維護方便,我建議你還是養成事先宣告變數的習慣比較好。
# 井字號開頭的後面都是註解。
# 純量變數以$開頭。
# my 是一種宣告變數的方式,它可以使變數區域化。
# 宣告變數時若不加 my 或 local 則Perl會把它當作全域變數使用。
# 習慣上,我們會將字串用雙引號括起來,而數值就不用加引號。
my $x="abc";
my $x=123;
my $x=4.56;
那麼程式怎麼判斷這是數值還是字串呢? 其實不是程式判斷,而是你自己要判斷。Perl分別提供了一堆運算子來處理數字和字串,你必須知道這個變數是數值或字串,才能使用個別的運算子來對變數做運算。我分別列出字串運算子和數值運算子,好讓大家能區分它們的不同。
String Operator | Purpose |
x | Returns a string consisting of the string on the left of the operand, repeated the number of times of the right operand. |
. | Concatenates the two strings on both sides of the operator. |
eq | Returns True if the two operands are equivalent, False otherwise. |
ne | Returns True if the two operands are not equal, False otherwise. |
le | Returns True if the operand on the left is stringwise less than the operand on the right of the operator. Returns False otherwise. |
lt | Returns True if the operand on the left is stringwise less than or equal to the operand on the right of the operator. Returns False otherwise. |
ge | Returns True if the operand on the left is stringwise greater than or equal to the operand on the right of the operator. Returns False otherwise. |
gt | Returns True if the operand on the left is stringwise greater than the operand on the right of the operator. Returns False otherwise. |
cmp | Returns -1, 0, or 1 if the left operand is stringwise less than, equal to, or greater than the right operand. |
, | Evaluates the left operand, the evaluates the right operand. It returns the result of the right operand. |
++ | Increments the string by one alphabetic value. |
Value Operator | Purpose |
+ | Computes the additive value of the two operands. |
- | Computes the difference between the two operands. |
* | Computes the multiplication of the two operands. |
/ | Computes the division between the two operands. |
% | Computes the modulus(remainder) of the two operands. |
= = | Returns Ture if the two operands are equivalent, False otherwise. |
!= | Returns Ture if the two operands are not equal, False otherwise. |
<= | Returns Ture if the operand on the left is numerically less than or equal to the operand on the right of the operator. Returns False otherwise. |
=> | Returns Ture if the operand on the left is numerically greater than or equal to the operand on the right of the operator. Returns False otherwise. |
< | Returns Ture if the operand on the left is numerically less than the operand on the right of the operator. Returns False otherwise. |
> | Returns Ture if the operand on the left is numerically greater than the operand on the right of the operator. Returns False otherwise. |
< = > | Returns -1 if the left operand is less than the right, +1 if is it greater than, and 0(False) otherwise. |
&& | Performs a logical AND operation. If the left operand is True m then the right operator is not evaluated. |
|| | Performs a logical OR operation. If the left operand is True m then the right operator is not evaluated. |
& | Returns the valueof the two operators bitwise ANDed. |
| | Returns the valueof the two operators bitwise ORed. |
^ | Returns the valueof the two operators bitwise XORed. |
++ | Increment operator. Increments the variable's value by 1. |
-- | Decrement operator. Decrements the variable's value by 1. |
** | Computes the power of the left-hand value to the power of the rihght-hand value. |
+= | Adds the value of the right-hand operand to the value of the left-hand operand. |
-+ | Subtracts the value of the right-hand operand to the value of the left-hand operand. |
*= | Mlutiplies the value of the left-hand operand to the value of the right-hand operand. |
>> | Shifts the left operand right by the number of bits that is specified by the right operand. |
<< | Shifts the left operand left by the number of bits that is specified by the right operand. |
~ | Performs a 1s complement of the operator. This is a unary operator. |
# 純量陣列以 @ 開頭。
my @array;
my @array=qw(a b c d);
# qw 函數會將其後的每個元素用逗點隔開,效果就像下面這行。
my @array=("a","b","c","d");
# 當然你也可以一個個元素宣告,下面就是存取每一個元素的方法。
# 因為陣列中的每一個元素都是純量變數,所以要以 $ 開頭,
# 剛開始容易搞混,請注意。
$array[0]="a"; $array[1]="b"; $array[2]="c"; $array[3]="d";
# 使用for loop印出陣列內每個元素的值。
for($i=0; $i<=$#array; $i++) {
print "$array[$i]\n";
}
看到$#array這個奇怪的東東沒? 這是Perl的一個特殊用法,代表這個陣列最後一個元素的註標。 由於Perl不必事先宣告變數,也不必預先宣告陣列的大小,甚至可以隨時增加新元素,那我們怎麼知道這個陣列到底有多大呢? 透過這個特殊變數我們可以得知這個這個陣列最後一個元素的註標,自然而然也就知道這個陣列究竟有多大了。 另外Perl只定義了一維陣列的語法,二維以上只能用指標間接來達成。
# 相關陣列是以 % 符號開頭的。
my %hash;
# => 這個符號是Perl5新增的,是為了相關陣列量身定做的,
# 因為索引和元素值都是純量,若使用 => 這個符號,
# (索引=>元素值) 兩兩對應,就不容易發生失誤。
my %hash=("i1"=>"aaa","i2"=>"bbb","i3"=>"ccc");
# 上面這行的效果和下面這行是一樣的。
my %hash=("i1","aaa","i2","bbb","i3","ccc");
# 下面是存取每個元素的方法,注意是用大括號把索引括起來哦。
# 習慣上索引值用單引號、元素值用雙引號括起來。
$hash{'i1'}="aaa"; $hash{'i2'}="bbb"; $hash{'i3'}="ccc";
# 下面是使用相關陣列的三個例子:
foreach $key (keys %hash) {
print "$hash{$key}\n";
}
foreach $value (values %hash)
while(($key,$value)=each %hash)
Perl有上述三個函數可對相關陣列做運算:keys函數可取出相關變數的索引值,組成一純量陣列,注意這些由keys函數取出的索引值沒有次序性;values函數可取出相關變數的元素值;each函數則會取出(索引、元素)對。使用者可視情況而用。
⊙如何取得變數的位址?
$scalarRef=\$scalarVar;
$arrayRef=\@arrayVar;
$hashRef=\%hashVar;
$funcRef=\&funcName;
print $$scalarRef;
print "@$arrayRef";
print $hashRef->{$key};
&$funcRef;
$arrayRef=[[1,2,3,4],a,b,[x,y,z],c];
print "$arrayRef->[0][0]\t$arrayRef->[2]\t$arrayRef->[3][2]\n";
$hashRef={a=>aa,b=>bb,c=>cc};
print "$hashRef->{a}\t$hashRef->{b}\t$hashRef->{c}\n";
(2) 控制敘述(Control Statements)
# Expression 就是條件敘述式,Perl和C一樣沒有定義布林資料型態(Boolean data type),
# 因此 0 是false、非0 是ture。另外要注意字串運算子和數值運算子要分清楚哦。
# Code Segment 就是用大括號括起來的一堆指令,也就是一個Block。
if (Expression) {Code Segment}
if (Expression) {Code Segment} else {Code Segment}
if (Expression) {Code Segment} elsif (Expression) {Code Segment} else {Code Segment}
# elsif 就是 else if
# 如果指令(statement)只有一項,我們可以使用倒裝句法,看起來比較簡潔。
statement if (Expression);
# unless 就是if not
statement unless (Expression);
例:
print "HELLO!\n" if ($name eq "friend");
$x-=10 if ($x == 100);
看吧! C 語言有的Perl大部分都有,學過 C 的人可以毫不費力的學會Perl。
# 注意:純量變數前面要加個 $ 字號,這一點和C語言不一樣哦。
for($i=0; $i<=10; $i++) {Code Segment}
# foreach 是承襲UNIX的shell script來的,
# 第一個引數是純量變數,第二個引數要用括號括起來,裡面是一個純量陣列,
# 顧名思義它就是把陣列中的每個元素依序傳給第一個引數,直到全部傳完。
# 它和 for($i=0; $i<=$#array; $i++) 用法雖然不同,但目的都是要取出陣列的每個元素。
foreach $i (@array) {Code Segment}
# 其實在Perl中,for和foreach是可以混著用的,就看個的人習慣了。
# 下面這行就等於上面第一個敘述,不過簡潔多了,大家可以試著用用看。
for $i (0..10) {Code Segment}
# while控制迴圈和後置迴圈。
while($i<=10) {Code Segment}
do {Code Segment} while(Expression);
# Perl也有和C語言的break和continue一樣的指令,Perl叫它做 last 和 next (較口語化)。
# last是跳出現在所在的迴圈,next則是跳過下面的指令直接執行下一次的迴圈。
while(chomp($i=<STDIN>)) {
next if ($i == 5);
last unless ($i > 10);
}
Perl還有提供label(標記)的語法,也就是 goto 指令,不過有經驗的programer並不喜歡用它,我也不建議大家使用,所以就此按下不講。有興趣的人請自行查閱。 還有一點值得注意的是Perl沒有提供像C語言一樣的 switch 敘述,不過Perl的pattern match的功能非常強,所以我建議你直接用 if else 敘述來做就好了。 (3) 副程式(Subroutines)
my ($a1,$a2,$a3,...) = @_;
來取出各個參數,當然 my @arg=@_;
或 my %arg=@_;
也是可以的。 由於Perl的語法非常活潑,使得程式在維護時特別棘手,因此寫註解成為一項很重要的工作。 我建議你最好在每個副程式前面加上對這段副程式的描述,特別是需要傳遞的參數要註明清楚。 my $x=3;
,若副程式所用的變數名不小心和主程相同,Perl會以目前正在執行的副程式裡的變數為優先。 (4) I/O和檔案處理
close(FILEHANDLE);
Expression | Effect |
open(FH, "<filename") | Opens filename for reading. |
open(FH, "+<filename") | Opens filename for both reading and writing. |
open(FH, ">filename") | Opens filename for writing. |
open(FH, "+>filename") | Opens filename for both reading and writing. |
open(FH, ">>filename") | Appends to filename. |
open(FH, "command|") | Runs the command and pipes its output to the filehandle. |
open(FH, "command|") | Pipes the output along the filehandle to the command. |
open(FH, "-") | Opens STDIN. |
open(FH, ">-") | Opens STDOUT. |
open(FH, "<&=N") | Where N is a number, this performs the equivalent of C's fdopen for reading. |
open(FH, ">&=N") | Where N is a number, this performs the equivalent of C's fdopen for writing. |
例:
# 開啟$filename這個檔案,若開啟失敗則印出die後面的訊息,並結束程式。
open(FILE, $filename) || die "Can't open file $filename : $!\n";
# 下面是一個十分精簡的寫法,和 while($_=<FILE>){print "$_";} 是等效的。
print while(<FILE>);
# 檔案開啟後要記得隨手關閉,這才是寫程式的好習慣。
close(FILE);
# $!和$_都是Perl的特殊變數,下面會介紹的。
# Perl不會自動去掉結尾的CR/LF,跟C語言不同,所以要用chomp函數幫你去掉它。
# 大家常常會忘記這個動作,導致結果跟你想的不一樣,要特別注意一下。
$input=<STDIN>; chomp $input;
# 下面是較簡潔的寫法。
chomp($input=<STDIN>);
# 不用再指定變數的data type,這樣不是比printf()方便多了嗎?
print "Scalar value is $x\n";
# . 是字串加法的運算子,上下這兩行是等效的。
print "Scalar value is " . $x . "\n";
# 輸出到檔案的方法。
print FILE "print $x to a file.";
# 下面是print的特殊用法,學自shell script的用法:
print<<XXX;
這招叫做 here document,XXX可以是你取的任何識別字,
在識別字之間的字都會按照你所寫的樣子輸出,就像<pre>標籤一樣。
而當一行的開頭是XXX你取的這個識別字時,才會停止輸出。
XXX
Perl 也有和 C 一樣以 "\" 開頭的特殊字元: \t tab \n newline \r return \f form feed \b backspace \a alarm(bell) \e escape \033 octalchar \x1b hex char \c[ control char \l lowercase next char \u uppercase next char \L lowercase till \E \U uppercase till \E \E end case modification \Q quoteregexp metacharacters till \E另外需要說明的是 Perl 融合了 unix shell script 的使用慣例,以雙引號("")括起來的字串會先經過展開,但反斜線(\)後面的字元則不展開,當作一般字元看待。 而以單引號('')括起來的字串完全不會展開,以反單引號(``)括起來的字串會把它當作命令列指令一樣執行,等於system()一樣。 初學者常常會搞混,但習慣之後就會覺得不這樣分清楚反而不行哩。舉個例吧:
$x="ls -l";
print "$x"; # Output ls -l
print "\$x"; # Output $x
print '$x'; # Output $x
print `$x`; # Output files in this directory
(5) Regular Expressions Regular Expression通常是用來尋找特定的字串樣式(pattern),也就是所謂格式辨認(pattern-matching)的功能。 它的運算子是『=~』和『!~』,可以把它念做match和not match。
Syntax: $string =~ /regular expression/expression modifier
例:$sentence =~ /Hello/
g | Match globally, i.e. find all occurrences. |
i | Makes the search case-insensitive. |
m | If the string has new-line characters embedded within it, the metacharacters ^ and $ will not work correctly. This modifier tells Perl to treat this line as a multiple line. |
o | Only compile pattern once. |
s | The character . matches any character except a new line. This modifier treats this line as a single line, which allows . to match a new-line character. |
x | Allows white space in the expression. |
\ | Tells Perl to accept the following characters as a regular character; this removes special meanings from any metacharacter. |
^ | Matches the beginning of the string, unless /m is used. |
. | Matches any character except a new line character, unless /s is used. |
$ | Matches the end of the string, unless /m is used. |
| | Expresses alternation. This means the expressions will search for multiple patterns in the same string. |
( ) | Groups expressions to assist in alternation and back referencing. |
[ ] | Looks for a set of characters. |
* | Matchs 0 or more times. |
+ | Matchs 1 or more times. |
? | Matchs 0 or 1 times. |
{n} | Matches exactly n times. |
{n,} | Matches at least n times. |
{n,m} | Matches at least n times but no more than m times. |
\r | Carriage return(CR), ASCII 13(十進位) |
\n | New line, UNIX中代表ASCII 10(十進位), DOS(Windows)系統中則是ASCII 13 + ASCII 10(十進位). |
\t | Tab, ASCII 9(十進位) |
\w | Matches an alphanumeric character. Alphanumeric also includes _. 即 [A-Za-z0-9_]. |
\W | Matches a nonalphanumeric character. 即 [^A-Za-z0-9_]. |
\s | Matches a white space character. This includes space, tab, FormFeed and CR/LF. 即 [\ \t\f\r\n]. |
\S | Matches a non-whote space character. 即 [^\ \t\f\r\n]. |
\d | Matches a digit. 即 [0-9]. |
\D | Matches a nondigit character. 即 [^0-9]. |
\b | Matches a word boundary. |
\B | Matches a nonword boundary. |
\033 | octal char |
\x1B | hex char |
/abc/
/^abc/
/abc$/
/a|b/
/ab{2,4}c/
/ab*c/
/ab+c/
/a.c/
/[abc]/
/\d/
/\w/
/\s/
/[^abc]/
/\*/
/abc/i
/(\d+)\.(\d+)\.(\d+)\.(\d+)/
if ($x =~ /(\d+\.\d+)\.\d+\.\d+/) {
print "海洋大學" if ($1 eq "140.121");
}
m//gimosx
$url="my.machine.tw:8080/cgi-bin/test.pl";
($host, $port, $file)=($url=~m|http://([^/:]+):{0,1}(\d*)(\S*)$|);
這個Regular Expression相當複雜,主要目的是分析指定的URL,然後取得host名稱、port號碼及對應的檔案。我一項項慢慢解釋:$url=~m||
m後面跟著的就是分隔符號,| |裡面的就是pattern。
([^/:]+)
match一個字串,裡面沒有/和:字元。找到的字串存在$1中。
:{0,1}(\d*)
match 0或1個:,後面跟著一串數字或nothing。找到的字串存在$2中,若找不到,$2就是空的。
(\S*)$
match一串非空白字元,並以找到的字串為結尾。找到的字串存在$3中。
()=()
($host, $port, $file)=($1, $2, $3)
即$host="my.machine.tw"
$port=8080
$file="/cgi-bin/test.pl"
s/PATTERN/REPLACEMENT/egimox
e | Evaluate the right side as an expression. |
g | Replace globally, i.e. all occurrences. |
i | Do case-insensitive pattern matching. |
m | Treat string as multiple lines. |
o | Only compile pattern once. |
s | Treat string as single line. |
x | Use extended regular expressions. |
$x =~ s/\s+//g
把所有的white space全部去除掉$x =~ s/([^ ]*):*([^ ]*)/$2:$1/
把用":"分開的兩個欄位互相對調$path =~ s|/usr/bin|/usr/local/bin|
它也可以讓你自訂分隔符號哦tr/SEARCHLIST/REPLACEMENTLIST/cds
c | Complement the SEARCHLIST. |
d | Delete found but unreplaced characters. |
s | Squash duplicate replaced characters. |
$x =~ tr/this/that/
把"this"替換成"that"$x =~ tr/a-z/A-Z/
把小寫字母全部替換成大寫字母$count = $x =~ tr/*/*/
計算$x中有幾個"*"(6) Spectial Variables
Perl的特色之一就是有超過50個以上的特殊變數,這些變數都是全域變數,用來設定程式的執行環境和其它細節。 若你想深入了解Perl程式設計,那麼這些東西是不可或缺的。在這裡我只列幾個常用的特殊變數以供參考,有興趣的人請自行查閱。
$_ | The default input and pattern-searching space. |
$digit | Contains the subpattern from a successful parentheses pattern match. |
$. | The current input line number of last filehandle read. |
$! | Contains the current value of errno. |
$0 | The name of the file of the Perl script. |
@ARGV | The command line arguments issued when the script was started. |
@_ | The parameter array for subroutines. |
%ENV | This associative array contains your current environment. |
(7) Help
目前市面上有關Perl語言的書並不多,就算是原文書也只有那幾本聖經本。不過只要是有關CGI的書,其內容大都會提到Perl,但卻很少教到基本語法,常常使人一頭霧水。 所以我建議:如果你真的想學好Perl語言,真得想拿Perl來寫程式,那我建議你最好去買一本書來看,在觀念上會比較清楚,在實際應用上也會比較有幫助; 如果你只是想寫一些簡單的CGI程式,或只想看得懂別人所寫的CGI程式,那在網路上的資料就綽綽有餘了。
首先你可以到各大BBS站的WWW板或program板的精華區找找,不過資料不會很多,而且有點雜亂。 再不然你可以到蕃薯藤輸入perl或cgi關鍵字找找,有不少人的homepage上有教人如何用Perl寫CGI程式,還有一堆別人已經寫好的CGI程式可以抓來用用。 說到這裡順便打一下廣告,在http://ind.ntou.edu.tw/documents下有Perl的說明文件,做得相當不錯,不過全是英文的就是了,而我這份講義打好後也會放在IND的homepage上,大家可以抓回去參考參考。
第三種資源就是Perl本身的man pages,你在IND帳號下鍵入 man perl 就可以查閱了,這份文件做得不錯,還根據Perl的各個部分寫了man pages,如Perl syntax, builtin function, regular expression, data structure等, 大家可以用man指令一一查詢,有時候在寫程式時一時忘了某個函數怎麼用,這倒是個方便又快速的查詢方法。我會把這些man pages轉成html格式,放在WWW上讓大家參考。
cron
http://en.wikipedia.org/wiki/Cron
Each line of a crontab file represents a job and is composed of a CRON expression, followed by a shell command to execute. Some implementations of cron, such as that in the popular 4th BSD edition written by Paul Vixie and included in many Linux distributions, add a sixth field to the format: an account username that the specified job will be run by (subject to user existence and permissions). This is only allowed in the system crontabs, not in others which are each assigned to a single user to configure. The sixth field is also sometimes used for year instead of an account username; the nncron daemon for Windows does this. However vixie cron does not use the sixth column as a year and if used will treat the year as the command to run and fail.
For "day of the week" (field 5), both 0 and 7 are considered Sunday, though some versions of Unix such as AIX do not list "7" as acceptable in the man page. While normally the job is executed when the time/date specification fields all match the current time and date, there is one exception: if both "day of month" and "day of week" are restricted (not "*"), then either the "day of month" field (3) or the "day of week" field (5) must match the current day.
The following line causes the user program
In the August, 1977 issue of the Communications of the ACM, W. R. Franta and Kurt Maly published an article entitled "An efficient data structure for the simulation event set" describing an event queue data structure for discrete event-driven simulation systems that demonstrated "performance superior to that of commonly used simple linked list algorithms," good behavior given non-uniform time distributions, and worst case complexity , "n" being the number of events in the queue.
A graduate student, Robert Brown, reviewing this article, recognized the parallel between cron and discrete event simulators, and created an implementation of the Franta-Maly event list manager (ELM) for experimentation. Discrete event simulators run in "virtual time", peeling events off the event queue as quickly as possible and advancing their notion of "now" to the scheduled time of the next event. By running the event simulator in "real time" instead of virtual time, a version of cron was created that spent most of its time sleeping, waiting for the moment in time when the task at the head of the event list was to be executed.
The following school year brought new students into the graduate program, including Keith Williamson, who joined the systems staff in the Computer Science department. As a "warm up task" Brown asked him to flesh out the prototype cron into a production service, and this multi-user cron went into use at Purdue in late 1979. This version of cron wholly replaced the
The algorithm used by this cron is as follows:
The resources consumed by this cron scale only with the amount of work it is given and do not inherently increase over time with the exception of periodically checking for changes.
Williamson completed his studies and departed the University with a Masters of Science in Computer Science and joined AT&T Bell Labs in Murray Hill, New Jersey, and took this cron with him. At Bell Labs, he and others incorporated the Unix
This version of cron later appeared largely unchanged in Unix System V and in BSD and their derivatives, the Solaris Operating System from Sun Microsystems, IRIX from Silicon Graphics, HP-UX from Hewlett-Packard, and IBM AIX. Technically, the original license for these implementations should be with the Purdue Research Foundation who funded the work, but this took place at a time when little concern was given to such matters.
In 2007, RedHat forked vixie-cron 4.1 to the cronie project and included anacron 2.3 in 2009.
Other popular implementations include anacron, dcron and fcron. However, anacron is not an independent cron program; it relies on another cron program to call it in order to perform. dcron was the work of Dragonfly BSD founder Matt Dillon, the code is currently maintained by Jim Pryor.
A webcron solution schedules recurring tasks to run on a regular basis wherever cron implementations may not be available in a web hosting environment.
In some uses of the CRON format there is also a seconds field at the beginning of the pattern.[5]
cron
From Wikipedia, the free encyclopedia
This article needs additional citations for verification. Please help improve this article by adding citations to reliable sources. Unsourced material may be challenged and removed. (November 2011) |
For other uses, see CRON (disambiguation).
Cron is a time-based job scheduler in Unix-like computer operating systems. Cron enables users to schedule jobs (commands or shell scripts) to run periodically at certain times or dates. It is commonly used to automate system maintenance or administration, though its general-purpose nature means that it can be used for other purposes, such as connecting to the Internet and downloading email.[1]Contents |
Overview
Cron is driven by a crontab (cron table) file, a configuration file that specifies shell commands to run periodically on a given schedule. The crontab files are stored where the lists of jobs and other instructions to the cron daemon are kept. Users can have their own individual crontab files and often there is a system wide crontab file (usually in/etc
or a subdirectory of /etc
) which only system administrators can edit.Each line of a crontab file represents a job and is composed of a CRON expression, followed by a shell command to execute. Some implementations of cron, such as that in the popular 4th BSD edition written by Paul Vixie and included in many Linux distributions, add a sixth field to the format: an account username that the specified job will be run by (subject to user existence and permissions). This is only allowed in the system crontabs, not in others which are each assigned to a single user to configure. The sixth field is also sometimes used for year instead of an account username; the nncron daemon for Windows does this. However vixie cron does not use the sixth column as a year and if used will treat the year as the command to run and fail.
For "day of the week" (field 5), both 0 and 7 are considered Sunday, though some versions of Unix such as AIX do not list "7" as acceptable in the man page. While normally the job is executed when the time/date specification fields all match the current time and date, there is one exception: if both "day of month" and "day of week" are restricted (not "*"), then either the "day of month" field (3) or the "day of week" field (5) must match the current day.
Examples
The following line specifies that the Apache error log is to be cleared at one minute past midnight (00:01) of every day of the month, of every day of the week, assuming that the default shell for the cron user is Bourne shell compliant:1 0 * * * printf > /www/apache/logs/error_log
test.pl
– possibly a Perl script – to be run every two hours, namely at midnight, 2am, 4am, 6am, 8am, and so on:0 */2 * * * /home/username/test.pl
Predefined scheduling definitions
There are several special predefined values which can be used to substitute the CRON expression.Entry | Description | Equivalent To |
---|---|---|
@yearly (or @annually) | Run once a year, midnight, Jan. 1st | 0 0 1 1 * |
@monthly | Run once a month, midnight, first of month | 0 0 1 * * |
@weekly | Run once a week, midnight on Sunday | 0 0 * * 0 |
@daily | Run once a day, midnight | 0 0 * * * |
@hourly | Run once an hour, beginning of hour | 0 * * * * |
@reboot | Run at startup |
* * * * * command to be executed ┬ ┬ ┬ ┬ ┬ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └───── day of week (0 - 6) (Sunday=0 ) │ │ │ └────────── month (1 - 12) │ │ └─────────────── day of month (1 - 31) │ └──────────────────── hour (0 - 23) └───────────────────────── min (0 - 59)
@reboot
configures a job to run once when the daemon is started. Since cron is typically never restarted, this typically corresponds to the machine being booted. This behavior is enforced in some variations of cron, such as that provided in Debian,[2] so that simply restarting the daemon does not re-run @reboot
jobs.@reboot
can be useful if there is a need to start up a server or daemon under a particular user, and the user does not have access to configure init to start the program.Cron permissions
The following two files play an important role:- /etc/cron.allow - If this file exists, then you must be listed therein (your username must be listed) in order to be allowed to use cron jobs.
- /etc/cron.deny - If the cron.allow file does not exist but the /etc/cron.deny file does exist, then you must not be listed in the /etc/cron.deny file in order to use cron jobs.
Timezone handling
Most cron implementations simply interpret crontab entries in the system time zone setting under which the cron daemon itself is run. This can be a source of dispute if a large multiuser machine has users in several time zones, especially if the system default timezone includes the potentially confusing DST. Thus, a cron implementation may special-case any "TZ=<timezone>" environment variable setting lines in user crontabs, interpreting subsequent crontab entries relative to that timezone.[3]History
Early versions
The cron in Version 7 Unix, written by Brian Kernighan, was a system service (later called daemons) invoked from/etc/inittab
when the operating system entered multi-user mode. Its algorithm was straightforward:- Read
/usr/etc/crontab
- Determine if any commands are to be run at the current date and time and if so, run them as the Superuser, root.
- Sleep for one minute
- Repeat from step 1.
Multi-user capability
The next version of cron, with the release of Unix System V, was created to extend the capabilities of cron to all users of a Unix system, not just the superuser. Though this may seem trivial today with most Unix and Unix-like systems having powerful processors and small numbers of users, at the time it required a new approach on a 1 MIPS system having roughly 100 user accounts.In the August, 1977 issue of the Communications of the ACM, W. R. Franta and Kurt Maly published an article entitled "An efficient data structure for the simulation event set" describing an event queue data structure for discrete event-driven simulation systems that demonstrated "performance superior to that of commonly used simple linked list algorithms," good behavior given non-uniform time distributions, and worst case complexity , "n" being the number of events in the queue.
A graduate student, Robert Brown, reviewing this article, recognized the parallel between cron and discrete event simulators, and created an implementation of the Franta-Maly event list manager (ELM) for experimentation. Discrete event simulators run in "virtual time", peeling events off the event queue as quickly as possible and advancing their notion of "now" to the scheduled time of the next event. By running the event simulator in "real time" instead of virtual time, a version of cron was created that spent most of its time sleeping, waiting for the moment in time when the task at the head of the event list was to be executed.
The following school year brought new students into the graduate program, including Keith Williamson, who joined the systems staff in the Computer Science department. As a "warm up task" Brown asked him to flesh out the prototype cron into a production service, and this multi-user cron went into use at Purdue in late 1979. This version of cron wholly replaced the
/etc/cron
that was in use on the Computer Science department's VAX 11/780 running 32/V.The algorithm used by this cron is as follows:
- On start-up, look for a file named
.crontab
in the home directories of all account holders. - For each crontab file found, determine the next time in the future that each command is to be run.
- Place those commands on the Franta-Maly event list with their corresponding time and their "five field" time specifier.
- Enter main loop:
- Examine the task entry at the head of the queue, compute how far in the future it is to be run.
- Sleep for that period of time.
- On awakening and after verifying the correct time, execute the task at the head of the queue (in background) with the privileges of the user who created it.
- Determine the next time in the future to run this command and place it back on the event list at that time value.
The resources consumed by this cron scale only with the amount of work it is given and do not inherently increase over time with the exception of periodically checking for changes.
Williamson completed his studies and departed the University with a Masters of Science in Computer Science and joined AT&T Bell Labs in Murray Hill, New Jersey, and took this cron with him. At Bell Labs, he and others incorporated the Unix
at
command into cron, moved the crontab files out of users' home directories (which were not host-specific) and into a common host-specific spool directory, and of necessity added the crontab
command to allow users to copy their crontabs to that spool directory.This version of cron later appeared largely unchanged in Unix System V and in BSD and their derivatives, the Solaris Operating System from Sun Microsystems, IRIX from Silicon Graphics, HP-UX from Hewlett-Packard, and IBM AIX. Technically, the original license for these implementations should be with the Purdue Research Foundation who funded the work, but this took place at a time when little concern was given to such matters.
Modern versions
With the advent of the GNU Project and Linux, new crons appeared. The most prevalent of these is the Vixie cron, originally coded by Paul Vixie in 1987. Version 3 of Vixie cron was released in late 1993. Version 4.1 was renamed to ISC Cron and was released in January 2004. Version 3, with some minor bugfixes, is used in most distributions of Linux and BSDs.In 2007, RedHat forked vixie-cron 4.1 to the cronie project and included anacron 2.3 in 2009.
Other popular implementations include anacron, dcron and fcron. However, anacron is not an independent cron program; it relies on another cron program to call it in order to perform. dcron was the work of Dragonfly BSD founder Matt Dillon, the code is currently maintained by Jim Pryor.
A webcron solution schedules recurring tasks to run on a regular basis wherever cron implementations may not be available in a web hosting environment.
CRON expression
A CRON expression is a string comprising 5 or 6 fields separated by white space[4] that represents a set of times, normally as a schedule to execute some routine.Format
Field name | Mandatory? | Allowed values | Allowed special characters |
---|---|---|---|
Minutes | Yes | 0-59 | * / , - |
Hours | Yes | 0-23 | * / , - |
Day of month | Yes | 1-31 | * / , - ? L W |
Month | Yes | 1-12 or JAN-DEC | * / , - |
Day of week | Yes | 0-6 or SUN-SAT | * / , - ? L # |
Year | No | 1970–2099 | * / , - |
Special characters
- Asterisk ( * )
- The asterisk indicates that the cron expression will match for all values of the field; e.g., using an asterisk in the 4th field (month) would indicate every month.
- Slash ( / )
- Slashes are used to describe increments of ranges. For example 3-59/15 in the 1st field (minutes) would indicate the 3rd minute of the hour and every 15 minutes thereafter. The form "*/..." is equivalent to the form "0-59/...".
- Percent ( % )
- Percent-signs (%) in the command, unless escaped with backslash (\), will be changed into newline characters, and all data after the first % will be sent to the command as standard input. [6]
- Comma ( , )
- Commas are used to separate items of a list. For example, using "MON,WED,FRI" in the 5th field (day of week) would mean Mondays, Wednesdays and Fridays.
- Hyphen ( - )
- Hyphens are used to define ranges. For example, 2000-2010 would indicate every year between 2000 and 2010 CE inclusive.
- Question mark ( ? )
- The '?' character is used to omit the specification of a value for the day-of-month and day-of-week fields. Since it's not valid to specify values for both fields, '?' becomes necessary to omit one of either ('*' is considered a specific value). NOTE: Question mark is a non-standard character; it may not be allowed in some versions (e.g., the Cron daemon installed with Ubuntu).
- L
- 'L' stands for "last". When used in the day-of-week field, it allows you to specify constructs such as "the last Friday" ("5L") of a given month. In the day-of-month field, it specifies the last day of the month.
- W
- The 'W' character is allowed for the day-of-month field. This character is used to specify the weekday (Monday-Friday) nearest the given day. As an example, if you were to specify "15W" as the value for the day-of-month field, the meaning is: "the nearest weekday to the 15th of the month". So if the 15th is a Saturday, the trigger will fire on Friday the 14th. If the 15th is a Sunday, the trigger will fire on Monday the 16th. If the 15th is a Tuesday, then it will fire on Tuesday the 15th. However if you specify "1W" as the value for day-of-month, and the 1st is a Saturday, the trigger will fire on Monday the 3rd, as it will not 'jump' over the boundary of a month's days. The 'W' character can only be specified when the day-of-month is a single day, not a range or list of days.
- Hash ( # )
- '#' is allowed for the day-of-week field, and must be followed by a number between one and five. It allows you to specify constructs such as "the second Friday" of a given month.[citation needed]
Examples
Every minute* * * * *Every 5 minutes
*/5 * * * *23:00:00 every weekday night
0 23 ? * MON-FRIIn 2003 on the 11th to 26th of each month in January to June every third minute starting from 2 past 1am, 9am and 10pm
2-59/3 1,9,22 11-26 1-6 ? 2003
Minutes | Hours | Day of month | Month | Weekday | Year[ex 1] | |
---|---|---|---|---|---|---|
Every 2 hours at :30 | 30 | 0/2 or */2[ex 2] | * | * | ? | * |
Every day at 11:45PM | 45 | 23 | * | * | ? | * |
Every Sunday at 1:00AM | 0 | 1 | ? | * | 0 | * |
Every last day of month at 10:00AM and 10:00PM | 0 | 10,22 | L | * | ? | * |
See also
References
- ^ Newbie Introduction to cron
- ^ Bugs.debian.org
- ^ Sun.com
- ^ Ubuntu Cron Howto
- ^ "CronTrigger Tutorial". Quartz Scheduler Website. Retrieved 24 October 2011.
- ^ mcron crontab reference
External links
crontab
: schedule periodic background work – Commands & Utilities Reference, The Single UNIX® Specification, Issue 7 from The Open Group- GNU cron (mcron)
- ISC Cron 4.1
- Fedorahosted.org - a fork of vixie-cron 4.1 and anacron 2.3 from the RedHat project
- ACM Digital library – Franta, Maly, "An efficient data structure for the simulation event set" (requires ACM pubs subscription)
- UNIX / Linux cron tutorial - a quick tutorial for UNIX like operating systems with sample shell scripts.
- All about Cron on one page - a page covering Cron, starting with theory and ending with many practical examples about its usage.
- Dillon's cron (dcron)
- Cron Reference - Information on the cron and its usage
- Cron Expression translator - Small Site which tries to convert a cron tab expression to English
|
訂閱:
文章 (Atom)