我编写了一个Perl脚本,它在机器A上复制可交付物(并且还在另一台机器B上备份相同的资源),然后调用已经存在于机器A上的shell脚本。这个shell脚本部署了机器A上的可交付(通常是一个war文件)虽然复制和调用shell脚本的整个任务可以很容易地用bash编写,但是我想使用Perl只是因为我没有编写Perl程序很长一段时间。我们有一个Jenkins的主从设置,Perl脚本从Jenkins奴隶运行。
use strict;
use warnings;
use Cwd;
use File::Copy;
use Getopt::Long;
use File::Basename;
use Net::SSH::Perl;
use Net::SCP::Expect;
my ($conf_file, $environment, $action, $job, $dest_file, $user, $host, $IP, $TARGET_SERVER, $JOB_ENV, $JENKINS_JOB, $wrapper, $src_file, $src_path, $src_dist_path, $src_dist_full_path, $dist_temp_archive_path, $dist_archive_host, $archive_user, $scpe, $id_file, @id_file, @array, $line);
my $ITE = "server.ite.com";
if ($environment eq "release") {
$IP = $ITE;
$JOB_ENV = "Release_";
$JENKINS_JOB = substr $ENV{'JOB_NAME'}, 8;
$dist_temp_archive_path = "/home/ec2-user/release_archive";
}
$conf_file = "/home/ec2-user/SCM/generic/deploy_build.cnf";
open (FH, "<", $conf_file) or die "Cannot open < $conf_file: $!";
while (<FH>) {
if ( $_ =~ /\b$JENKINS_JOB\b/ ) {
push @array, $_;
} else {
next;
}
}
foreach $line (@array) {
($job, $src_dist_path, $dest_file, $user, $wrapper) = split(':', $line);
if ($dest_file eq "") {
($src_file, $src_path) = fileparse($src_dist_path);
$dest_file = $src_file;
}
$job = $JOB_ENV . $job;
$id_file = "/home/ec2-user/.ssh/sandy";
@id_file = ("/home/ec2-user/.ssh/sandy");
if ($action eq "copy_distributable") {
printf "Initiating subroutine to copy distributable on remote machine...\n";
©_distributable;
} elsif ($action eq "exec_wrapper") {
if (defined $wrapper && length $wrapper) {
printf "Initiating subroutine for executing wrapper on remote machine...\n";
&exec_wrapper;
} else {
printf "*** No wrapper specified ****\n";
}
}
}
sub copy_distributable {
$archive_user="ec2-user";
$src_dist_full_path = "$ENV{WORKSPACE}/$src_dist_path";
$dist_archive_host = "55.666.77.88";
if ( -f $src_dist_full_path ) {
$scpe = Net::SCP::Expect->new(identity_file => $id_file, host => $dist_archive_host);
$scpe->scp("$src_dist_full_path", "$dist_temp_archive_path/$dest_file");
$scpe = Net::SCP::Expect->new(identity_file => $id_file, host => $IP, user => $user);
$scpe->scp("$src_dist_full_path", "/home/$user/$dest_file");
printf "Deliverable copied on deployment machine. Now moving on to next task of archiving the deliverable...\n\n";
my $ssh = Net::SSH::Perl->new($dist_archive_host, "identity_files" => \@id_file);
$ssh->login($archive_user);
printf "mv $dist_temp_archive_path/$dest_file $dist_temp_archive_path/latest\n\n";
my($stdout, $stderr, $exit) = $ssh->cmd("mv $dist_temp_archive_path/$dest_file $dist_temp_archive_path/latest");
printf "Output: $stdout\n" if $stdout;
printf "Error: $stderr\n" if $stderr;
printf "Deliverable archived on Jenkins master\n";
} else {
printf "Deliverable not found\n";
exit 1;
}
}
sub exec_wrapper {
my $ssh = Net::SSH::Perl->new($IP, "identity_files" => \@id_file);
$ssh->login($user);
my($stdout, $stderr, $exit) = $ssh->cmd("~/release/$wrapper");
printf "Output: $stdout\n" if $stdout;
printf "Error: $stderr\n" if $stderr;
}
构建工作区所在的Jenkins slave框的详细信息:
[ec2-user@jenkins_slave2 ~]$ uname -a
Linux jenkins_slave 3.10.35-43.137.amzn1.x86_64 #1 SMP Wed Apr 2 09:36:59 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
[ec2-user@jenkins_slave2 ~]$ free -m
total used free shared buffers cached
Mem: 7228 5688 1539 0 72 3824
-/+ buffers/cache: 1791 5436
Swap: 16382 163 16219
此外,盒子上有足够的内存来复制和最终部署可交付物。磁盘空间也不是任何一台机器上的问题。两者都是在AWS上运行的Linux实例。
现在的问题是,虽然程序通常可以运行很多次,但是在调用部署脚本(shell脚本)时它会挂起。为了调试,我使用Devel :: Trace在Jenkins中运行Perl脚本。当构建卡住时,我中止了构建。一旦我中止了构建,我就遇到了堆空间错误,所以我添加了Xms&amp; Xmx参数分别设置初始和最大Java堆大小。确认设置已应用后,我再次运行构建。一些构建过去了,一些再次陷入困境。我认为增加堆大小没有任何意义。编写shell脚本来执行相同的任务,并且不需要运行任何此类额外内存。现在我不知道在哪里寻找线索。
真的很感激任何帮助。
答案 0 :(得分:1)
我遇到了类似的问题。通过sftp上传文件的客户端将在3个文件后挂起。过了一会儿,我意识到客户端正在创建一个用于上传一个文件的新连接。
也许你可以在foreach循环之前打开连接(创建$ ssh / $ scpe变量)并将它们传递给copy_distributable函数以便重用。