Cmdr_Tofu has asked for the wisdom of the Perl Monks concerning the following question:

Greetings wise ones. I have been trying to work with Net::SSH::Perl instead of Expect.pm and ssh, and up until now everything has seemed easy. I am trying to automate "apt-get installing" packages on multiple machines.
I thought:
($stdout,$stderr,$exit) = $ssh -> cmd ("apt-get install anjuta");
was pretty straightforward, but the ssh connection disconnects right before the package can be installed. I'm not sure what the workaround is. Can anyone offer suggestions? print "the output is: $stdout" looks like this:
the output is:Reading Package Lists... Building Dependency Tree... The following NEW packages will be installed: anjuta 0 packages upgraded, 1 newly installed, 0 to remove and 0 not upgrade +d. Need to get 0B/2633kB of archives. After unpacking 6955kB will be used +.
I think I am close but not quite there. For the curious, here is the whole script:
#!/usr/local/perl/bin/perl -w use Term::ReadKey; use Net::SSH::Perl; use Net::SFTP; my @machinelist = qw ( machine1.myip.com machine2.myip.com ); foreach my $machine (@machinelist) { print "We are going to clobber $machine\n"; } print "is this ok y/n? "; my $input = <stdin>; chomp $input; if (!($input eq "y")) { die; } print "what is your root password: "; ReadMode ('noecho'); my $rootpw=<stdin>; chomp $rootpw; ReadMode ('normal'); print "\n"; print "are you sure you want to continue y/n? "; $input = <stdin>; chomp $input; if (!($input eq "y")) { die; } foreach my $machine (@machinelist) { my $status=0; eval { my $ssh = Net::SSH::Perl->new($machine,protocol=>2); $ssh -> login ("root", $rootpw); my ($stdout,$stderr,$exit) = $ssh -> cmd ("apt-get install anjuta" +); #for debugging print "the output is:$stdout\n"; $status=1; }; if ($@) { $status=0; } if ($status) { print "$machine updated successfully.\n"; } else { print "there was a failure updating $machine\n"; } }
Thanks in advance for any guidance!
Rohit Mehta

UPDATE (for anyone interested). My problem was not a missing -y or anything, but a bad PATH. When I viewed the contents of $stderr, it became pretty apparent that my PATH was set incorrectly. So I changed my command to "export PATH=\"/sbin:/usr/sbin:/usr/bin:...\";apt-get ..." and voila! it works!
cheers!

Replies are listed 'Best First'.
Re: Net::SSH::Perl with apt-get
by flyingmoose (Priest) on Feb 14, 2004 at 00:13 UTC

    apt is asking for user input and is dying. You need to disable prompting.

    apt-get install mozilla-firebird --yes

    I recommend you read the man pages for 'apt-get' to understand the differences between "--yes" and "--assume-yes" before proceeding to implement this solution. They mean different things.

Re: Net::SSH::Perl with apt-get
by Elijah (Hermit) on Feb 14, 2004 at 02:34 UTC
    Why not write a cron job for the update process and stick it on each machine? I wrote a simple one a while back that has worked pretty good for me.
    #!/usr/bin/perl -w ################################################################ # Program: auto-update # Programmer: Elijah # Requires: apt for Red Hat/Fedora # # This app does nightly checks for upgradable system packages. # Simply drop this program in your cron.daily directory # and set to executable (chmod +x). # # Note* # This could cause issues or loss of service, use at your own # risk. If a package is updated and has problems you might not # even be aware of the outage until hours (or days) later. # ############################################################### use strict; my $timestamp = `date`; my @time = split(/ /, $timestamp); my $file = $time[2]."-".$time[1]."-".$time[5]; my $create_log = "/var/log/system-update/$file"; my $grab_list = `apt-get -y update`; my $update_status = `apt-get -y dist-upgrade`; my $clean = `apt-get -y clean`; my $timestamp2 = `date`; open (FILE, ">>$create_log") || die "Cannot open $create_log\n"; print FILE "Log started at: ".$timestamp,"\n\n"; print FILE "###################\n"; print FILE "### List Status ###\n"; print FILE "###################\n"; print FILE $grab_list,"\n\n"; print FILE "##############################\n"; print FILE "### Package Upgrade Status ###\n"; print FILE "##############################\n"; print FILE $update_status,"\n\n"; print FILE "#######################\n"; print FILE "### Clean Up Status ###\n"; print FILE "#######################\n"; if ($clean eq "") { print FILE "Cleanup was successfull!\n\n"; }else{ print FILE $clean,"\n\n"; } print FILE "Log ended at: ".$timestamp2,"\n"; close(FILE);
    This would probably be your easiest bet. Just be carefull and read the header about using this to update crucial servers because this will update all new packages and Kernels and that could cause a problem on some systems.

      (off topic)

      I run Fedora myself, but I ran Debian for a good while, and (from experience) with Debian packages, you really want to be there (interactively) to handle the questions Debian will ask you. Things like "keep this version or install the package maintainers version" can be important.

      With Fedora, there is no package configuration on install/upgrade, so it doesn't matter as much. I haven't even seen a testing package ask questions yet.

      For the record, the point of his script is not to run apt-get update / apt-get dist-upgrade on each of his servers, it's to run "apt-get install $app"

      While you script may be usefull to him, it doesn't address his problem.

        Well it most definately addresses his problem if you would care to even read the source for the script. It really does not matter what he is trying to upgrade (an entire distro list or a single package) the syntax for apt-get is the same.

        What he needed from my script was the "-y" argument telling apt-get to answer yes to all asked questions. You can take my entire script and change a few lines and have it upgrade single packages. So as I am sure you can see now is that yes it does address his problem.