分享
 
 
 

使用Expect和命名管状远程控制SQL*Plus

王朝mssql·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

在初始化一个SQL*Plus会话的时候,对shell的访问会受到HOST命令和运行存储的SQL*Plus脚本的限制。SQL*Plus不具有别名(alias)或者历史等特性,也不具备把一个命令的输出通过管道传入别的命令的能力。如果能将SQL*Plus的特性添加到现有的shell环境中岂不是一件美事?这里正好有一种方法可以实现这一想法。

在UNIX中,创建一个守护进程来将命令从独立的shell命令传入一个SQL*Plus会话是可能实现的。第一步是创建一样能与SQL*Plus交互环境进行交互的东西。虽然SQL*Plus是可交互的,但是它仅限于STDOUT和STDIN,所以它可以放入一个管道中:

sqlplus /nolog < commands.sql output.log

然而,如果我们想一次发出一条SQL*Plus命令,那么就需要检查SQL*Plus命令提示符“SQL”来判断SQL*Plus是否在等待输入,然后使用非阻塞管道,这样我们可以在遇到提示符时停止读取数据而等待SQL*Plus更多的输入。

一种天生可以完成这项工作的脚本描述语言是Expect,它是Tcl/Tk程序设计语言的衍生物。这个进程可以是守护进程或者是服务进程,它接收单个的远程控制命令并将它们传递给从属SQL*Plus会话。要与这个服务进程通信,用法最简单的协议是UNIX Domain Protocol(UDP) sockets。shell可以通过UDP客户端发出命令,然后命令由服务进程接收,然后其结果就通过socket发回到客户端。

Expect需要一个扩展才能够使用UDP sockets。与其安装该扩展到Expect,不如在Perl中使用Expect,因为Perl已经能够很好地处理sockets。在Perl归档中可以找到Expect.pm。这个程序提供在Perl中使用Expect相同的功能。

下面是我的简单示例服务程序,使用Perl、UDP和Expect.pm作为我的行程控制服务程序:

#!/usr/bin/perl -w

# spd.pl - the SQL*Plus daemon server

use strict;

use Expect;

use Socket;

# set up expect

# -- timeout after about 10 minutes

my $timeout = 600;

# -- scan for the SQL*Plus prompt

my $prompt = 'SQL';

my $exp = new Expect();

$exp-raw_pty(1);

$exp-log_stdout(0);

$exp-spawn('sqlplus','/nolog') || die "unable to spawn sqlplus: $!";

$exp-expect($timeout,'-ex',$prompt) || die $exp-error();

print $exp "set sqlprompt $prompt;\n";

$exp-expect($timeout,'-ex',$prompt) || die $exp-error();

$exp-clear_accum();

my $name = "/tmp/sp_$ENV{USER}";

unlink($name);

socket(S,PF_UNIX,SOCK_STREAM,0) || die "socket: $!";

bind(S,sockaddr_un($name)) || die "bind: $!";

listen(S,SOMAXCONN) || die "listen: $!";

while(accept(C,S))

{

# single threaded to avoid confusion

my $cmd = <C;

$cmd =~ s/[\r\n]*$//g;

print $exp $cmd,"\n";

if ($cmd =~ /^exit$/mi)

{

print C "exit.\n";

close C;

last;

}

$exp-expect($timeout,$prompt) || die $exp-error();

print C $exp-before();

close C;

}

$exp-soft_close();

close S;

unlink($name);

exit;

我把管道名叫做“sp_{username}”。这样就允许同一个用户的两个不同会话共享同一个SQL*Plus会话。我使用默认的“SQL”提示符,但是为了避免“SQL”显示我的数据并导致数据被截断的可能性,最好还是使用一个长的随机字符串。

下一步是Perl客户端:

#!/usr/bin/perl -w

# spc.pl

use Socket;

use strict;

my $cmd = join(' ',@ARGV);

my $name = "/tmp/sp_$ENV{USER}";

my $proto = getprotobyname('udp');

socket(S,PF_UNIX,SOCK_STREAM,0) or die "socket: $!";

select S; $| = 1; select STDOUT;

connect(S,sockaddr_un($name)) or die "connect: $!";

print S $cmd,"\n";

print while (<S);

close(S);

exit;

这段脚本连接到UDP服务器,发送一条单行命令(所有命令行参数的串联),然后将数据发回标准输出。最后,如果服务进程还没有运行,两个Perl脚本的前面的CSH将启动服务程序然后将它们的参数传给客户端程序:

#!/bin/csh

# sp.csh

set f=/tmp/sp_$user

if (-e $f == 0) then

perl spd.pl &

sleep 1

endif

perl spc.pl "$*"

现在,有了这个远程控制程序,我就可以像下面这样来做了:

$ alias sp sp.csh

$ sp "connect scott/tiger"

Connected.

$ sp "select * from dual;"

D

-

X

$ sp "select sysdate from dual;" | grep MAY

05-MAY-03

$ sp "select * from emp;" | wc

70

184

1890

$ sp "exit"

最后一条命令将关闭服务程序。

这个提示中的脚本非常粗糙;不允许使用多行SQL语句。如果一个SQL语句不完整,服务进程将会挂起等待SQL提示符;如果SQL提示符改变服务进程也会挂起。但是在使用SQL*Plus的时候不丢掉shell环境依然非常有用。对于一般的命令使用它可以创建别名和使用shell功能,使用历史和替代变量,或者在内嵌环境中使用SQL*Plus。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有