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

Hello all, I've written a perl script that logs takes in a couple of paramaters, logs into a firewall, executes a few commands (see $sshen), captures that output for analysis (see @output), writes out to a file, and then exits. It works great from the CMD line. When I try to run it from apache, it works but doesn't appear to pass the commands to the firewall correctly. Here's my code:
#!/usr/bin/perl use Net::OpenSSH; use strict; use warnings; $Net::OpenSSH::debug=-1; # Define varilables my $vpntype=$ARGV[2]; my $requestor=$ARGV[1]; my $user='username'; my $password='password'; my $peerIP=$ARGV[0]; my $log_file="/share/www/vpndb/tunnel_clear.log"; my $host; my $datestring; my $message; # Determine which host to connect to if($vpntype eq 'ASP VPN') { $host='192.168.254.1'; } else { $host='192.168.254.2'; } # Connect to host print "Connecting to $host\n"; #my $ssh = Net::OpenSSH->new($host, user => $user, password => $passwo +rd, master_opts => '-vv'); my $ssh = Net::OpenSSH->new($host, user => $user, password => $passwor +d); $ssh->error and die "Unable to connect: " . $ssh->error; print "Connected to $host\n"; # Clear the VPN tunnel my $cmd = "vpn-sessiondb logoff ipaddress $peerIP noconfirm"; my $sshen = "\nen\n$password\n$cmd\nexit\n"; my @output = $ssh->capture("$sshen"); # Check to make sure VPN was cleared successfully $datestring = localtime(); if ( grep( /logged off : 1/, @output ) ) { print "\nFound!\n\n"; $message = "Tunnel SUCCESSFULLY cleared for peer $peerIP, requ +ested by $requestor with service: $vpntype"; } else { print "\nNot Found!\n\n"; $message = "Tunnel NOT SUCCESSFULLY cleared for peer $peerIP, +requested by $requestor with service: $vpntype"; } # Write to log file open my $log_fh, ">>", $log_file; print "Output = @output\n\n"; write_to_log ($log_fh, $message); print $log_fh "Output = @output\n\n"; # Clean up close $log_fh; undef $ssh; # Sub Routines sub write_to_log { my $file_handle = shift; $message = shift; my $time = localtime(); return print $file_handle "$time: $message\n"; }
and here's the debug output I get when I run it from apache:

# open_ex: ['ssh','-V']
Connecting to 192.168.254.1
# io3 mloop, cin: 0, cout: 1, cerr: 0
# io3 fast, cin: 0, cout: 1, cerr: 0
# stdout, bytes read: 48 at offset 0
#> 4f 70 65 6e 53 53 48 5f 37 2e 34 70 31 2c 20 4f 70 65 6e 53 53 4c 20 31 2e 30 2e 32 6b 2d 66 69 | OpenSSH_7.4p1, OpenSSL 1.0.2k-fi
#> 70 73 20 20 32 36 20 4a 61 6e 20 32 30 31 37 0a | ps 26 Jan 2017.
# io3 fast, cin: 0, cout: 1, cerr: 0
# stdout, bytes read: 0 at offset 48
# leaving _io3()
# _waitpid(105560) => pid: 105560, rc:
# OpenSSH verion is 7.4p1,
# ctl_path: /root/.libnet-openssh-perl/username-192.168.254-105559-879808, ctl_dir: /root/.libnet-openssh-perl/
# _is_secure_path(dir: /root/.libnet-openssh-perl, file mode: 16832, file uid: 0, euid: 0
# _is_secure_path(dir: /root, file mode: 16744, file uid: 0, euid: 0
# set_error(0 - 0)
# call args: ['ssh','-o','ServerAliveInterval=30','-o','ControlPersist=no','-2MNx','-o','NumberOfPasswordPrompts=1','-o','PreferredAuthentications=keyboard-interactive,password','-S','/root/.libnet-openssh-perl/username-192.168.254-105559-879808','-l','username','192.168.254.1','--']
# file object not yet found at /root/.libnet-openssh-perl/username-192.168.254-105559-879808, state: waiting_for_passwd_prompt
# file object not yet found at /root/.libnet-openssh-perl/username-192.168.254-105559-879808, state: waiting_for_passwd_prompt
# file object not yet found at /root/.libnet-openssh-perl/username-192.168.254-105559-879808, state: waiting_for_passwd_prompt
# file object not yet found at /root/.libnet-openssh-perl/username-192.168.254-105559-879808, state: waiting_for_passwd_prompt
# file object not yet found at /root/.libnet-openssh-perl/username-192.168.254-105559-879808, state: waiting_for_passwd_prompt
# file object not yet found at /root/.libnet-openssh-perl/username-192.168.254-105559-879808, state: waiting_for_passwd_prompt
# tracer attached, ssh pid: 105561, tracer pid: 105562
# file object not yet found at /root/.libnet-openssh-perl/username-192.168.254-105559-879808, state: waiting_for_passwd_prompt
# passwd/passphrase requested (username@192.168.254.1's password:)
# file object not yet found at /root/.libnet-openssh-perl/username-192.168.254-105559-879808, state: waiting_for_mux_socket
# file object not yet found at /root/.libnet-openssh-perl/username-192.168.254-105559-879808, state: waiting_for_mux_socket
# file object found at /root/.libnet-openssh-perl/username-192.168.254-105559-879808
# call args: ['ssh','-O','check','-T','-S','/root/.libnet-openssh-perl/username-192.168.254-105559-879808','-l','username','192.168.254.1','--']
# open_ex: ['ssh','-O','check','-T','-S','/root/.libnet-openssh-perl/username-192.168.254-105559-879808','-l','username','192.168.254.1','--']
# io3 mloop, cin: 0, cout: 1, cerr: 0
# io3 fast, cin: 0, cout: 1, cerr: 0
# stdout, bytes read: 29 at offset 0
#> 4d 61 73 74 65 72 20 72 75 6e 6e 69 6e 67 20 28 70 69 64 3d 31 30 35 35 36 31 29 0d 0a | Master running (pid=105561)..
# io3 fast, cin: 0, cout: 1, cerr: 0
# stdout, bytes read: 0 at offset 29
# leaving _io3()
# _waitpid(105563) => pid: 105563, rc:
# call args: ['ssh','-S','/root/.libnet-openssh-perl/username-192.168.254-105559-879808','-l','username','192.168.254.1','--','
en
password
vpn-sessiondb logoff ipaddress 69.18.79.158 noconfirm
exit
']
# open_ex: ['ssh','-S','/root/.libnet-openssh-perl/username-192.168.254-105559-879808','-l','username','192.168.254.1','--','
en
password
vpn-sessiondb logoff ipaddress 69.18.79.158 noconfirm
exit
']
Connected to 192.168.254.1
# io3 mloop, cin: 0, cout: 1, cerr: 0
# io3 fast, cin: 0, cout: 1, cerr: 0
# stdout, bytes read: 52 at offset 0
#> 54 79 70 65 20 68 65 6c 70 20 6f 72 20 27 3f 27 20 66 6f 72 20 61 20 6c 69 73 74 20 6f 66 20 61 | Type help or '?' for a list of a
#> 76 61 69 6c 61 62 6c 65 20 63 6f 6d 6d 61 6e 64 73 2e 0d 0a | vailable commands...
# io3 fast, cin: 0, cout: 1, cerr: 0
Connection to 192.168.254.1 closed by remote host.
# stdout, bytes read: 0 at offset 52
# leaving _io3()
# _waitpid(105564) => pid: 105564, rc:
# set_error(5 - child exited with code 255)
# DESTROY(Net::OpenSSH=HASH(0x1a47cb8), pid: 105561)
# killing master
# sending exit control to master
# set_error(1 - control command failed: master ssh connection broken)
# _kill_master: 105561
# waitpid(master: 105561) => pid: 105561, rc: No such file or directory

The 'Type help or '?' for a list of available commands' output that is captured makes me think that the $sshen commands, even though they are seen in the debug output, aren't really being passed through.

Any thoughts?

Replies are listed 'Best First'.
Re: Perl script works differently from Apache then CMD line
by Eily (Monsignor) on Jan 05, 2018 at 09:52 UTC

    Where does @ARGV come from when executing from Apache? How do you feed the parameters? Maybe you can display the content of $cmd, either always, or whenever the output doesn't seem to be what you expect.

    Edit: and how do you even run your script "from Apache" anyway? There doesn't seem to be anything related to HTTP in your script.

Re: Perl script works differently from Apache then CMD line
by soonix (Chancellor) on Jan 05, 2018 at 11:11 UTC
    I suggest trying the script from Re: cgi/perl/fortran web program, calling it with both methods and comparing the outputs. (perhaps extended like below)
    use strict; use warnings; my $n; print "Content-Type: text/plain\n\nPerl Version $] ($^V)\n"; print "ARGV" . $n++ . ": >>$_<<\n" foreach @ARGV; print "\n$_:\n", qx($_ 2>&1) foreach qw(id pwd env);
Re: Perl script works differently from Apache then CMD line
by thanos1983 (Parson) on Jan 05, 2018 at 11:39 UTC

    Hello IT_not_Dev,

    Just to add a minor note here while we are waiting for your reply to the question of the fellow monk Eily.

    Why are you login in to the server with username and password? It is way way safer and faster to login with ssh keys.

    On module Net::OpenSSH it simple as that:

    In case you want to reach multiple servers take a look on Net::OpenSSH::Parallel. Simple example same theory as before:

    For a more complex example see also Re: multiple machines disk space alert.

    Hope this helps, BR.

    Seeking for Perl wisdom...on the process of learning...not there...yet!
Re: Perl script works differently from Apache then CMD line
by salva (Canon) on Jan 08, 2018 at 09:05 UTC
    There are several ways to run Perl scripts from Apache, but at least under mod_perl STDIN and STDOUT are not regular file handles (backed by a operating system file descriptor) and that can interfere with Net::OpenSSH.

    Specifically the remote SSH server may not like having its stdin stream closed. Try redirecting it from a pipe:

    pipe my($r_pipe), my($w_pipe); $ssh->capture({stdin_fh => $r_pipe}, ...);