2

I have a Perl script. I want to remote to a different host, and run multiple commands (not 5,10 but 100-150 commands) there. Like,

Algorithm of Script1.pl (the script on local machine):

ssh machine10
// Then execute command1 on machine10
// Then execute command2 on machine10
// Then execute command3 on machine10
.
.
.
// Then execute command100 on machine10, and so on

Then exit, from the remote host.
Then, run the commands on the local machine.

How can it be implemented?

I am new to Perl, and after internet browsing, I saw that system command could help [system (ssh remote_host "command1; command2;..")], but this system command seems not to be feasible as 100-150 commands to run can't be written as such.

Can anyone please help? Is there any way like we open an SSH server, and run multiple commands, and then close it? I am actually looking for such type of technique.

Thank you!

AskQuestionsP
  • 153
  • 1
  • 9
  • 1
    Does this answer your question? [How can I ssh inside a Perl script?](https://stackoverflow.com/questions/2848725/how-can-i-ssh-inside-a-perl-script) (in short: use `Net::SSH::Perl` and its `->cmd` method) – Dada Dec 09 '21 at 07:30
  • I can't install a new module. Is there anything like below which you are aware of: open(SSH,"/usr/bin/ssh user\@serverHost ") or die "$!\n"; while () { # perform command } close SSH; – AskQuestionsP Dec 09 '21 at 07:55
  • 2
    Are you sure that you can't install new modules? You can [install modules locally, without root privileges](https://stackoverflow.com/a/543918/4990392) if needed. – Dada Dec 09 '21 at 08:34
  • Yes, but this script will not just be used by me. It has to be used by many users, and I couldn't ask all of them to get the modules installed on their systems locally due to some restrictions. – AskQuestionsP Dec 09 '21 at 09:21
  • Check also [Net::OpenSSH](https://metacpan.org/pod/Net::OpenSSH) and [Net::OpenSSH::Parallel](https://metacpan.org/pod/Net::OpenSSH::Parallel)! – salva Dec 10 '21 at 17:27
  • What version of Perl do you have? Based on another one of your questions I'm guessing 5.8.8? – lordadmira Dec 12 '21 at 03:27

2 Answers2

2

You could be hitting the limit of the command line length.

my @remote_cmds = ...;

open( my $pipe, "|-", "ssh", "machine10", "sh" );
for my $remote_cmd ( @remote_cmds ) {
   say $pipe $remote_cmd;
}

close( $pipe );

Demo:

$ hostname
tribble00000006

$ perl -M5.010 -e'
   my @remote_cmds = ( "hostname" );

   open( my $pipe, "|-", "ssh", "ikegami\@CENSORED.com", "sh" );
   for my $remote_cmd ( @remote_cmds ) {
      say $pipe $remote_cmd;
   }

   close( $pipe );
'
springfield

Workaround:

use String::ShellQuote qw( shell_quote );

my @remote_cmds = ...;

my $local_cmd = shell_quote( "ssh", "machine10", "sh" );

open( my $pipe, "|-", $local_cmd );
for my $remote_cmd ( @remote_cmds ) {
   say $pipe $remote_cmd;
}

close( $pipe );
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • Hi @ikegami, Ran the way you suggested. Got the error: "Internal error: open(my $pipe, |-, ssh, machine10, sh): Do not expect to get 5 arguments at (eval 19) line 126." ; Also, I don't even have 126 lines in my file. – AskQuestionsP Dec 09 '21 at 11:11
  • Are you using autodie? That might get in the way – ikegami Dec 09 '21 at 13:56
  • I just tried it with autodie without issue. Well, no idea if it does the right thing, but it doesn't give the error you showed. Whatever it is, it sounds like you replaced `open` with something else. I added a workaround. – ikegami Dec 09 '21 at 14:52
  • Also, is there any way by which I can save the logs which come after running commands in remote host under open( my $pipe, "|-", "ssh", "machine10", "sh" ) in a separate file by adding the filename in the write/append mode in the same line? If yes, can you please tell the syntax? If not along with this ssh command it can be done, how can it be executed? Any idea? – AskQuestionsP Dec 10 '21 at 06:17
  • [`open`](https://perldoc.perl.org/functions/open) – ikegami Dec 10 '21 at 06:18
  • Not clear what you're asking. To save the output of `ssh` to a file, use `shell_quote( "ssh", "machine10", "sh" ) . " >/var/log/foo 2>&1"`. – ikegami Dec 10 '21 at 06:19
  • I apologize for the misunderstanding. Nothing is working properly. open( my $pipe, "|-", "ssh", "machine10", "sh" ) is not working. It is not taking (ssh) to the remote machine (machine10). Instead, it is doing all the things/commands on the same machine from which it is called. Actually, I was sshing to the machine of the same site earlier. That's why gave a GO. My bad! – AskQuestionsP Dec 10 '21 at 08:21
  • eh, no. If you send something to `ssh`'s STDIN, it doesn't cause program to run on the local machine. Did you change `say` to `system` or something?? – ikegami Dec 10 '21 at 15:54
2

One option might be to write your list of commands into a script file (in whatever format is appropriate for your remote system - bash, PowerShell, whatever). You can then use scp to copy the script to the remote server and ssh to run the script remotely.

Dave Cross
  • 68,119
  • 3
  • 51
  • 97