免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: hwcomcn
打印 上一主题 下一主题

[已解决]perl子程序名可以用变量代替吗 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-08-13 17:01 |显示全部楼层 |倒序浏览
本帖最后由 hwcomcn 于 2014-08-14 16:54 编辑

以下的代码我不加strict就不会报错,正常执行,加了strict就报错,中途跳出,错误信息:thread failed to start: Can't use string ("proj_001") as a subroutine ref while "strict refs" in use at thread_02.pl line xxx.
perl子程序名可以用变量代替吗?如何修改?
(必须要加strict,因为程序比较大,需要严格语法检查,下面只是为了举例说明,实际情况有更多的proj_xxx,所以需要用数组来存储子程序名)
  1. #!/usr/bin/perl
  2. use warnings;
  3. use strict;


  4. my @sublist = ("proj_001","proj_002","proj_003","proj_004","proj_005","proj_006","proj_007","proj_008");

  5. while(@sublist>0)
  6. {
  7.   my $infosub = shift @sublist;
  8.   &$infosub;

  9. }


  10. sub proj_001 {
  11.     print "in sub proj_001","\n";
  12. }
  13. sub proj_002 {
  14.     print "in sub proj_002","\n";
  15. }
  16. sub proj_003 {
  17.     print "in sub proj_003","\n";
  18. }
  19. sub proj_004 {
  20.     print "in sub proj_004","\n";
  21. }
  22. sub proj_005 {
  23.     print "in sub proj_005","\n";
  24. }
  25. sub proj_006 {
  26.     print "in sub proj_006","\n";
  27. }
  28. sub proj_007 {
  29.     print "in sub proj_007","\n";
  30. }
  31. sub proj_008 {
  32.     print "in sub proj_008","\n";
  33. }
复制代码

论坛徽章:
0
2 [报告]
发表于 2014-08-14 09:17 |显示全部楼层
本帖最后由 hwcomcn 于 2014-08-14 09:34 编辑

谢谢大神们
2楼,4楼都都正解

但又遇到新问题:
普通数组可以定义成my $xxx : shared (比如我要同时多进程远程登陆多台主机,想并行登陆,还需要进程间共享变量)
普通数组比如
  1. my @sublist : shared = ("proj_001","proj_002","proj_003","proj_004","proj_005","proj_006","proj_007","proj_008");
复制代码
是不会出错的
但是下面的两个若加上shared会报错
  1. #my @sublist = (\&proj_001, \&proj_002, \&proj_003, \&proj_004, \&proj_005, \&proj_006, \&proj_007, \&proj_008);
  2. my @sublist : shared = (\&proj_001, \&proj_002, \&proj_003, \&proj_004, \&proj_005, \&proj_006, \&proj_007, \&proj_008);
复制代码
或者
  1. #my @sublist = ("proj_001","proj_002","proj_003","proj_004","proj_005","proj_006","proj_007","proj_008");
  2. #$_ = \&{$_} for @sublist;
  3. my @sublist : shared = ("proj_001","proj_002","proj_003","proj_004","proj_005","proj_006","proj_007","proj_008");
  4. $_ = \&{$_} for @sublist;
复制代码
贴上代码:
  1. #!/usr/bin/perl
  2. use warnings;
  3. #use strict;
  4. use threads;
  5. use threads::shared;

  6. #my @sublist : shared = (\&proj_001, \&proj_002, \&proj_003, \&proj_004, \&proj_005, \&proj_006, \&proj_007, \&proj_008);
  7. my @sublist  = (\&proj_001, \&proj_002, \&proj_003, \&proj_004, \&proj_005, \&proj_006, \&proj_007, \&proj_008);


  8. my $t1 = threads->create( \&thread_a );
  9. my $t2 = threads->create( \&thread_b );



  10. sub thread_a
  11. {
  12.   while(@sublist>0)
  13.   {
  14.     my $infosub = shift @sublist;
  15.     $infosub->();
  16.     sleep 2;
  17.   }
  18. }

  19. sub thread_b
  20. {
  21.   while(@sublist>0)
  22.   {
  23.     my $infosub = shift @sublist;
  24.     $infosub->();
  25.     sleep 2;
  26.   }
  27. }

  28. $t1->join();
  29. $t2->join();


  30. sub proj_001 {
  31.     print "in sub proj_001","\n";
  32. }
  33. sub proj_002 {
  34.     print "in sub proj_002","\n";
  35. }
  36. sub proj_003 {
  37.     print "in sub proj_003","\n";
  38. }
  39. sub proj_004 {
  40.     print "in sub proj_004","\n";
  41. }
  42. sub proj_005 {
  43.     print "in sub proj_005","\n";
  44. }
  45. sub proj_006 {
  46.     print "in sub proj_006","\n";
  47. }
  48. sub proj_007 {
  49.     print "in sub proj_007","\n";
  50. }
  51. sub proj_008 {
  52.     print "in sub proj_008","\n";
  53. }
复制代码
第7行和第8行的注释换一下就报错
想要的结果是每个进程执行一遍,不是执行2遍

论坛徽章:
0
3 [报告]
发表于 2014-08-14 09:17 |显示全部楼层
本帖最后由 hwcomcn 于 2014-08-14 09:32 编辑

不好意思,可能浏览器多刷新一次,多发了一个回帖,见6楼

论坛徽章:
0
4 [报告]
发表于 2014-08-14 16:53 |显示全部楼层
好。我开始学习下perl的多线程。大骆驼的16,17章是讲这个的。

论坛徽章:
0
5 [报告]
发表于 2014-08-15 14:41 |显示全部楼层
本帖最后由 hwcomcn 于 2014-08-15 14:47 编辑

回复 10# q1208c


telnet到多台思科的设备

要投一百多个测试大项,大多一个测试项投一条命令,有的测试项有多条命令


最花时间的是下面2种情况:
1. 有的测试项要投上千条,我这里最多的一个测试项就有5千个命令
2. 其中也有一个测试项虽然只有一条命令,一个cmd执行达数分钟,(就是telnet投入思科命令,返回要等几分钟)比如有一个条测试项的一条命令要要返回1百万行的文本信息
为此还纠结了下
因为telnet默认buffer只有1兆,改成120兆,才把这1百万行的数据给抓全
  1. $conn = new Net::Telnet(Timeout => 1800, Max_buffer_length => 120_000_000, Prompt => '/[#>]\s*$/');
复制代码
目前执行这1百多个测试大项的脚本执行时间是50分钟


因为任务做完了,
还有额外时间
就想起用多线程telnet改善了
我想可能会把时间缩短些吧
即使效果不理想,也可以把perl多线程给掌握

论坛徽章:
0
6 [报告]
发表于 2014-08-16 13:53 |显示全部楼层
回复 13# q1208c


    你是说用在shell环境下个多个console下且同时执行perl脚本吗?
    这个也想过
    现在是单个perl脚本执行时间过长
    想把单个脚本执行的时间缩短,所以想起尝试多线程
   

论坛徽章:
0
7 [报告]
发表于 2014-08-16 19:46 |显示全部楼层
本帖最后由 hwcomcn 于 2014-08-16 19:47 编辑

回复 15# laputa73

思科那型号的设备貌似默认同时telnet数最大5个

且可以用思科命令进入路由的特权模式修改的

所以这个应该不是最主要的担心

多进程执行和登陆有可能没提高多少效率甚至更慢,这个非常有可能的。但没试过,不清楚。想象中理论上可行。这个可能要看perl和思科路由设备的这方面的特性了决定了,所以想尝试看看实际效果

要是能做出来,最后不管效果如何,报告一声哈

论坛徽章:
0
8 [报告]
发表于 2014-08-18 15:01 |显示全部楼层
回复 17# q1208c


你说的登录到多台设备 和我说的同时执行perl,是一个意思

这个并行登录设备进行操作应该没有太大问题,

在shell下执行脚本:
#/usr/bin/csh -f
perl xx.pl -h host_ip -u username -p password& (地址,用户,密码作为命令参数)
perl xx.pl -h host_ip -u username -p password&
perl xx.pl -h host_ip -u username -p password&
perl xx.pl -h host_ip -u username -p password&
...


应该就可以并行执行

就想到能在同一个设备并行投命令,并行网络传命令让思科设备返回数据到桌面

你说的有道理,可能并行发给设备的命令,还是要排队等待执行,速度维持不变。若这样,缩短时间那是没有招了
至于提高perl语句,提高效率。这方面是很多可以优化的,但是这次测试通过抓出每条命令投入的时间点,发现perl执行的速度忽略不计,时间都花在在投入大量的命令和接收大量的数据上了。因为耗时间的测试项都是命令成千上万的或是数据成百万行的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP