in reply to Net::SFTP::Foreign Connection STDERR

Hi Again,

Been doing some more playing.. reading the docs for open3 and realised the fh order is different to open2.. so now I get the connection.

I have created a new fh called $sftp->{ssh_err} however how do I read the error from this when the code bombs?

Think I am going to give up for tonight.. any help would be still gratefully received! Not that great at process / io stuff....

Al

  • Comment on Re: Net::SFTP::Foreign Connection STDERR

Replies are listed 'Best First'.
Re^2: Net::SFTP::Foreign Connection STDERR
by salva (Canon) on Sep 24, 2008 at 09:57 UTC
    The new method for Net::SFTP::Foreign accepts a transport option that lets you control how the SSH transport is constructed.

    Unfortunately it is not so simple as linking ssh stderr stream back to Perl through a pipe as it would block the child if you don't read from it at the right times, and that means going into the select loop at the core of Net::SFTP::Foreign.

    But there is a simple work around, just send ssh stderr to a file and read it afterwards:

    use Net::SFTP::Foreign; use File::Temp; my $hostname = 'localhost'; my $ssherr = File::Temp->new or die "File::Temp->new failed"; open my $stderr_save, '>&STDERR' or die "unable to dup STDERR"; open STDERR, '>&'.fileno($ssherr); my $sftp = Net::SFTP::Foreign->new($hostname, more => ['-v']); # the child ssh process has already been created with the redirected S +TDERR # so we can reset it on the parent: open STDERR, '>&'.fileno($stderr_save); if ($sftp->error) { print "sftp error: ".$sftp->error."\n"; seek($ssherr, 0, 0); while (<$ssherr>) { print "captured stderr: $_"; } } close $ssherr;
      Fantastic! I never thought of just redirecting the whole SDTOUT but it works a charm.

      Just makes it easier now to see which hosts fail because the account is locked, connection is refused or the SSH key has been refused.

      Thank you so much!

      Al

      File::Temp sets the close-on-exec flag, so for ssh to be able to actually write to the file, you need to clear it:
      use Fcntl qw(F_SETFD F_GETFD FD_CLOEXEC); my $ssherr = File::Temp->new; my $flags = fcntl($ssherr, F_GETFD, 0) or die "Can't get FD flags for '$ssherr': $!"; fcntl($ssh_err, F_SETFD, $flags & ~FD_CLOEXEC) or die "Cant clear close-on-exec flag for '$ssherr': $!"; <the rest of your code>
        This may be operative system dependent.

        In Linux, it seems that the dup2 system call behind the "open ... >&..." does not copy the close-on-exit flag, and so your proposed change is not required.

        Which perl version and operative system are you using?