Simultaneous Perl SSH Sessions - perl

I am wondering if anyone has a Perl script (or can write one) to execute on multiple hosts at once via ssh, without any modules. I used to have something like this but cannot find it now and can't remember how it was done.

Are you looking for ClusterSSH? It's Perl, and it's used to run the same commands on several hosts at once, so this might be what you're looking for...

You might want to try using Expect.pm which is similar to #cnicutar's suggestion of calling an Expect script from Perl, except that you write it all in Perl. (This of course down not fit the requirement of "without any modules", but that requirement leads to bad Perl )

Learn how to install and use modules even when you don't have admin privileges on the host
Use Net::OpenSSH::Parallel

If you cannot use any additional modules from CPAN or any other source , all I can recommend you are:
1) Use Expect script and call it internally in your Perl script [Only if you are not willing to use Expect.pm module]
2) Use SSH keygen in all the servers to which you will connect to , so that password wont be necessary in the script. As mentioned by "cnicutar"
3) Use "remsh" if SSH usage is not that necessary.

Related

Is there a way / Perl Module to Control CRON on remote hosts

The idea is to have a central controller, that can manage cron, for many hosts. I have looked at Schedule::Cron and Config::Crontab
But none of them provide the remote capability. There is one that looks promising, IPC::PerlSSH, but not sure if i understand how to run Config::Crontab using IPC::PerlSSH
If anyone has some experience in this area please let me know. Perl does claim to be good for Linux admin tasks and this seems like one of the top tasks to be scripted. But doing it JUST on the local machine, after ssh'ng into it does not sound like fun.
# untested!
use Net::OpenSSH;
use Config::Crontab;
my $ssh = Net::OpenSSH->new($host, ...);
$ssh->system({stdout_file => 'crontab.out'}, 'crontab -l');
my $cc = Config::Crontab->new;
$cc->read('crontab.out');
# manipulate $cc crontab here:
# ...
$cc->write('crontab.out.1');
$ssh->system({stdin_file => 'crontab.out.1'}, 'crontab -');
IPC::PerlSSH simply uses SSH to execute Perl code remotely. The catch is that all remote nodes must also have the Schedule::Cron or Config::Crontab modules installed for this to work.
It would be preferable to use a SCP library (e.g. Net::SCP or Net::SCP::Expect) to simply bring over the crontab of interest from the remote node, massage it locally using the Cron library of your choice, then upload the massaged crontab back to the remote node. With this approach there is no need for the remote nodes to even have Perl installed.

Is there a perl function similar to lsof command in linux?

I have a shell script which archives log files based on the whether the process is running or not. If the log file is not used by the process then I archive it. Until now, I'm using lsof to get the log file being used but in future, I have decided to use perl to do this function.
Is there a perl module similar to what lsof in linux can perform ?
There is a perl module, which wraps around lsof. See Unix::Lsof.
As I see it, the big problem with not using lsof is that one would need to work in a way that is independent of the operating system. Using lsof allows the perl programmer to work with a consistent application allowing for operating system independence.
To have a perl module developer to write lsof would, in effect, be writing lsof as a library and then link that into perl - which is much more work than just using the existing binary.
One could also use the fuser command, which shows the process IDs with the file handle. There is also a module which seeks to implement the same functionality. Note from the perldoc:
The way that this works is highly unlikely to work on any other OS
other than Linux and even then it may not work on other than 2.2.*
kernels.
One might try walking /proc/*/fd and looking at the file descriptors in there to see if any are pointing to the file in question. If it is known what the process ID of a running process that would be opening the log file, it would be just as easy to look at that process. Note, that this is how the fuser module works.
That said, it should be asked "why do you want to move away from lsof"?

replacing telnet with ssh

I have some programs that use the Net::Telnet module to connect to several servers. Now the administrators have decided to replace the Telnet service for SSH, keeping everything else like before (for example the user accounts)
I've taken a look at Net::SSH2 and I see that I would have to change most part of the programs. Do you know of other SSH modules, better suited for this same replacement?
The client is a Windows box (ActiveState Perl or Cygwin Perl)
Net::OpenSSH!
And check the chapter about how to integrate it with Net::Telnet.
Thanks for your suggestions, but I finally used Net::SSH::Perl on ActivePerl for Windows
Pros:
quite similar to Net::Telnet. There is no close method, but instead of $host->close you can do $host->cmd("exit")
native Perl implementation
Cons:
each cmd() call has a different state, for example it doesn't keep the current directory between calls, like Net::Telnet did
needs a modification in the module code to work on Windows, see: https://rt.cpan.org/Public/Bug/Display.html?id=18154
cmd("su - user") doesn't work, but cmd("su - user -c 'commands'") does

Query a remote server's operating system?

is there a way to query a server for its OS type in Perl? For example, if I knew that a remote server was running Windows, I might send it a winver from my local machine and get the output to determine which version of Windows it's running. Yet, is there a way to be even more abstract and simply ask "what are you?"
Since CPAN is huge, I was wondering if there were a module that encapsulated this sort of functionality.
If you can get command-line access on the remove server, then you should be able to use %ENV:
jmaney> perl -e 'print "$ENV{OSTYPE}\n";'
linux
Edit: It looks as though the key in Windows (or, at least on Windows 7 on my laptop) is OS. So, unfortunately, the exact solution via %ENV is OS-dependent... You could, however, check to see which of $ENV{OS} or $ENV{OSTYPE} is defined (and if they're both defined, then canonically pick which one you want to use), and proceed accordingly.
There is no foolproof way to do this, but the HTTP Server header -- which the server isn't required to send -- often contains the OS. For example, it may look like this (from Wikipedia):
Server: Apache/1.3.27 (Unix) (Red-Hat/Linux)
The Perl CGI module has an http function that gets the HTTP headers. You could use it like this:
my $server = $q->http('Server');
# Test $server for Windows, *nix, etc
# My Perl experience is minimal and I haven't used it in
# a while, so I'm not going to give an example here, but
# someone can feel free to edit one in.
CPAN probably has a module to do the testing on the Server header for you.

What are the advantages of rsh versus Perl's Expect.pm?

I have a Perl Expect.pm script that does some moderately complex stuff like packaging applications, deploying the application, checking for logs, etc. on multiple remote unix hosts.
My predecessor had written similar scripts using rsh.
Is there a better approach between the two? Or should I use something all together different?
I am guessing somebody will bring up SSH; it's basically replacement for rsh, right? Unfortunately, however SSH is not an option for me right now.
Another thing I should add is that after logging in I need to be able to SUDO to a particular user to do most of the actions on the remote hosts.
Another thing I should add is that after logging in I need to be able to SUDO to a particular user to do most of the actions on the remote hosts.
To address this one particular point: using rsh (or ssh) you can specify which user to become in the remote session:
$ rsh -l username hostname
There's no need to use sudo in this case. Now would definitely be the time to look into ssh due to security issues. The syntax is the same, but ssh also allows a slightly different (and I'd say better) syntax:
$ ssh username#hostname
I found expect to be too finicky, but my experience with it is not substantial.
They do different things. Expect is a way to script what would otherwise be manual responses. rsh -- remote shell, not restricted shell, an unfortunate name clash -- allows you to run commands remotely on another system.
That said, the security holes and other disadvantages of using rsh to do remote commands, run sudo, etc, are immense.
I can see multiple ways of doing this:
Expect over telnet, rsh, or ssh
pros: single connection, fewer escaping issues
cons: fragility in a changing environment
rsh/ssh each command individually
pros: fewer escaping issues, more reliable in a changing environment
cons: each connection takes time for authentication, and, for ssh, handshaking the encryption
rsh/ssh all commands at once
pros: single connection (less overhead), more reliable than expect
cons: fragility in maintenance especially as you get more than a handful of statements in there, escaping issues are more prevalent (escape in perl so that it's still escaped by rsh/ssh so that it's still escaped by the remote shell so that it's properly handled by the sudo'd remote shell?)
rsh/ssh and run a script
pros: single connection, more reliable, more maintainable
cons: finding a way to get it over there (rcp/scp work, NFS works, you need to determine the best way for you).
All things considered, this is the most minor con as you could simply do something like
open my $fh, "|ssh user#host 'cat > /tmp/myscript'";
print $fh $script;
system qw(ssh user#host), "chmod u+x /tmp/myscript; /tmp/myscript; rm /tmp/myscript";
Of course, you'd add in some error handling (failed open, what if /tmp/myscript exists, etc.), but that's the idea.
Given a choice between rsh and telnet via expect, I would chose rsh. Expect scripts are fragile. All it takes to break one is someone changing the value of PS1 on the remote machine. Using rsh also prepares you for the day you will finally enter the '90s and start using ssh (since you can mostly just change rcp to scp and rsh to ssh and everything still works).