分类: LINUX
2009-02-08 17:14:34
$ tar zxvf torque-2.3.3.tar.gz
$ cd torque-2.3.3
$ ./configure --with-scp
$ make
$ sudo make install
如果有多台机器需要安装,可以使用 torque 提供的安装包功能。
$ make packages
这样在目录下会产生 torque-package- 系列包。在 master 机器上需要安装的是 server 包,在节点上需要安装的是 mom 包。在需要提交 PBS 任务的机器上需要安装 clients 包。
在安装相应的包之后需要进行配置。可以手工进行配置,但是推荐使用 torque 提供的 torque.setup 脚本生成初始化配置。方法是在 master 机器上使用命令:
$ sudo ./torque.setup yewenb
initializing TORQUE (admin: yewenb@ubuntu.ubuntu-domain)
Max open servers: 4
Max open servers: 4
在正确配置之后可以使用 qmgr -c 'print server' 检查配置是否成功。
$ qmgr -c 'p s'
#
# Create queues and set their attributes.
#
#
# Create and define queue batch
#
create queue batch
set queue batch queue_type = Execution
set queue batch resources_default.nodes = 1
set queue batch resources_default.walltime = 01:00:00
set queue batch enabled = True
set queue batch started = True
#
# Set server attributes.
#
set server scheduling = True
set server acl_hosts = ubuntu
set server managers = yewenb@ubuntu.ubuntu-domain
set server operators = yewenb@ubuntu.ubuntu-domain
set server default_queue = batch
set server log_events = 511
set server mail_from = adm
set server scheduler_iteration = 600
set server node_check_rate = 150
set server tcp_timeout = 6
set server mom_job_sync = True
set server keep_completed = 300
然后需要启动调度进程。可以选择使用单独的调度程序比如 maui。这里直接使用 torque 提供的调度程序 pbs_sched。
$ sudo pbs_sched
在各节点上启动 mom 进程:
$ sudo pbs_mom
在启动 mom 之后,需要在 master 机器加上节点:
$ qmgr -c 'create node ubuntu np=2'
在加入节点之后可以用 pbsnodes 命令检查节点是否可用 (在创建节点之后可能需要过一段时间节点的状态才能变成 free):
$ pbsnodes
ubuntu
state = free
np = 2
ntype = cluster
status = opsys=linux,uname=Linux ubuntu 2.6.27-7-generic #1 SMP Tue Nov 4 19:33:20 UTC 2008 i686,sessions=4378 4853 5161 5298 5301 5307 5315 5317 5318 5320 5327 5354 5366 5436 5446 25697 25770 25777 25778 25779 25780 27368,nsessions=22,nusers=3,idletime=935,totmem=640676kb,availmem=319392kb,physmem=319416kb,ncpus=1,loadave=0.13,netload=111712774,state=free,jobs=,varattr=,rectime=1229343008
先安装ssh server
$ sudo apt-get install openssh-server
对安装了节点的机器还需要配置 ssh 以保证日志文件成顺利传送回到 master 机器上。这需要在节点上产生 SSH key。
$ ssh-keygen -t rsa
如果不要用passphrase则使用:
$ ssh-keygen -P "" -t rsa
TIP: ubuntu 8.10的openssh-server用的protocol 2,所以要用rsa,而不能用rsa1
如果设置了passphrase还需要配置 ssh-agent 来记住密码。运行下面的命令:
$ eval `ssh-agent`
$ ssh-add ~/.ssh/id_rsa
在这样设置之后,将 ~/.ssh/id_rsa.pub 添加到 master 机器的 ~/.ssh/authorized_keys 文件中。
修改配置 ~/.ssh/config
StrictHostKeyChecking no
如果在节点上使用下面命令不需要提示密码则应该能正常传递任务的输出文件:
$ scp file user@server_host:/tmp
对咱们这里搭建的单机系统,只需要测试可以不要密码ssh到单机即可:
$ ssh localhost
在以上配置和测试都通过,就可以提交一个任务测试一下:
$ echo 'sleep 10 && echo hello world' | qsub
0.ubuntu
$ qstat -q
server: ubuntu
Queue Memory CPU Time Walltime Node Run Que Lm State
---------------- ------ -------- -------- ---- --- --- -- -----
batch -- -- -- -- 1 0 -- E R
----- -----
1 0
$ ls -l
总用量 8
-rw------- 1 yewenb yewenb 0 2008-12-15 20:36 STDIN.e0
-rw------- 1 yewenb yewenb 12 2008-12-15 20:36 STDIN.o0
以上测试通过的话,恭喜你,终于有了一个自己的 PBS 系统了。
cc1: warnings being treated as errors
pbsd_main.c: In function ‘lock_out’:
pbsd_main.c:1621: error: format not a string literal and no format arguments
make[2]: *** [pbsd_main.o] Error 1
make[2]: Leaving directory `/home/yewenb/softwares/torque-2.3.3/src/server'
这个错误我在 Ubuntu 8.10 编译过程中遇到,原因是由于一个十分著名的漏洞Format string attack,编译器不予通过编译。
解决办法是将出错代码进行修改,把直接输出非字符串常量的地方都改成使用格式化字符串,如 fprintf(stderr, "%s", var)。
可以用这个命令修复代码中有问题的fprintf使用:
$ cd /home/yewenb/softwares/torque-2.3.3/
$ find . -name *.c | xargs -n1 perl -i.bak -e 'while(<>){if(/\bfprintf\(stderr,/&&!/stderr,$/&&!/stderr, ?"/&&!/msg_momsetlim/){s/stderr,/stderr,"%s",/;print}else{print}}'
$ find . -name *.bak -exec rm {} \;
如此之后,还有少量prinf也存在问题:
qmgr.c:1780: error: format not a string literal and no format arguments
qmgr.c:1782: error: format not a string literal and no format arguments
手工编辑修复即可(把 prinf( 改为 printf("%s" )
$ tar zxvf postgresql-8.3.5.tar.gz
$ cd postgresql-8.3.5
$ ./configure --with-perl
$ make
$ sudo make install
在安装之后就可以创建自己的数据库。
$ export PGDATA=/path/to/db
$ initdb
$ tar zxvf plproxy-2.0.7.tar.gz
$ cd plproxy-2.0.7
$ make
$ sudo make install
编译 pg_bulkload 需要有 PostgreSQL 的源代码。
$ cp pg_bulkload-2.4beta1.tar.gz postgresql-8.3.5/contrib
$ cd postgresql-8.3.5/contrib
$ tar zxvf pg_bulkload-2.4beta1.tar.gz
$ cd pg_bulkload
$ make
$ sudo make install
$ mkdir $PGDATA/pg_bulkload
$ make
$ sudo make install
$ perl Makefile.PL
$ make
$ make install
日志解析使用的 LogParser 模块可以从 Farsail 源代码的 demo 目录中得到。
日志数据库的表结构如下:
CREATE TABLE log_daily (
thedate date,
ip text,
log_time timestamptz,
url text,
method text,
status int,
referer text,
user_agent text
);
我们将把日志按 ip 进行 hash 分桶。目前我们使用的数据库有两个,为日后数据库扩容着想,实际的分桶数我们定成 8 个。
使用日期进行分表,每天的日志将存储到单独的表中。创建新表的语句如下:
CREATE TABLE log_daily_20081225 (
check (thedate = '20081225')
) INHERITS (log_daily);
首先需要进行配置文件设计。
log.datadir = ../data
log.tempdir = ../tmp
log.buckets = 8
在所有配置里,为了防止冲突,我们加入 log 前缀。日志文件可能是每天更新的,这里设定为在 $FARSAILDIR/../data 目录下每天都有一个 $date.log 文件。tempdir 用于指定分桶文件写入目录。buckets 用于指定分桶数。
将上面的配置写到 log.conf 文件中,然后保存到 $FARSAILDIR/app 目录中。在 farsail.conf 文件里加上一行:
include = app/*.conf
这样 app 目录下所有后缀是 conf 的文件都将作为配置读入。
由于日志 ETL 是每天进行,所以至少需要一个日期参数。所以需要写一个这样的 action:
log:
module: Etl::ApacheLog
daily:
args:
date: { type: date, default: yesterday }
将上面的内容保存到 $FARSAILDIR/app/log.act 文件。程序将自动加载这个文件。
最后进行我们的 etl 代码编写。
package Etl::ApacheLog;
use strict;
use warnings;
use Carp;
use LogParser;
use Path::Class;
use Farsail::Util qw/parse_date/;
use Pg::Hashtext qw/hashtext/;
my $farsail;
sub init {
my $pkg = shift;
$farsail = shift;
$farsail->load_modules("Farsail::Bulkload");
}
sub ACTION_daily {
my $config = $farsail->config;
my $args = $farsail->args;
my $date = parse_date( $args->date ) || confess "Argument date need!\n";
$date = $date->ymd('');
my $buckets = $config->get('log.buckets');
my $logfile = $config->get_expand_file( 'log.datadir', "$date.log" );
my $dir = dir( $config->get_expand_file( 'log.tempdir', $date ) );
my $prefix = "log_";
if ( !-d $dir ) {
$dir->mkpath or die "can't make directory $dir: $!";
}
my @fh = map { file( $dir, $prefix . "$_.dat" )->openw } 0 .. ($buckets-1);
my $p = LogParser->new($logfile->openr);
while ( my $ent = $p->next ) {
my $date = substr( $ent->{time}, 0, 11 );
print { $fh[ hashtext( $ent->{ip} ) % $buckets ] } join(
"\x01", $date,
map {
!defined( $ent->{$_} )
|| $ent->{$_} eq '-'
? ''
: $ent->{$_}
} qw/ip time url method status referer ua/
),
"\n";
}
my $sql = <<SQL;
DROP TABLE IF EXISTS \$table;
CREATE TABLE \$table (
CHECK (thedate = '$date')
) INHERITS (log_daily);
SQL
Farsail::Bulkload->bulkload(
dir => $dir,
prefix => $prefix,
suffix => 'dat',
cluster => 'farsail',
format => 'ctrla',
table => "log_daily_date",
create_sql => $sql,
);
Farsail::PBS::Job->new({command => 'sleep 1'})->submit();
check_done($config->get('bulkload.done_file'));
}
sub check_done {
my $file = shift;
print "Wait done $file\n";
for ( 1..100 ) {
if ( !-e $file ) {
print "Sleep $_\n";
sleep 30;
} else {
return 1;
}
}
confess "The done file '$file' is not generate\n";
}
1;
可以用 farsail_do 来运行定义好的 action:
$ farsail_do log.daily --date 20081224
检查数据确实导入到数据库中:
$ psql proxy -c "SELECT * from dquery('select current_database(), count(*) from log_daily') as(db name, cnt int8)"
db | cnt
------+--------
db_1 | 111256
db_2 | 138744
(2 笔资料列)