[RESOLVED] ssh2_auth_pubkey_file(): Authentication failed, and Too many open files
Results 1 to 7 of 7

Thread: [RESOLVED] ssh2_auth_pubkey_file(): Authentication failed, and Too many open files

  1. #1
    Senior Member cbj4074's Avatar
    Join Date
    Feb 2004
    Location
    Portland, ME
    Posts
    225

    resolved [RESOLVED] ssh2_auth_pubkey_file(): Authentication failed, and Too many open files

    I'm using PHP's ssh2 PECL extension to issue shell commands to a number of different servers in an automated fashion.

    On each iteration of a loop, I create a new instance of my SSH2 class, open a new SSH connection using ssh2_connect(), and issue a command to one of any number of servers. Once the response is received, I disconnect (by issuing the "exit;" command via ssh2_exec()) and unset the variable that points to the SSH2 class instance. This has worked quite well in the past, and I was able to issue several thousand commands without issue.

    But, as of late, I've introduced an issue that is causing PHP to report:

    Code:
    Warning: ssh2_auth_pubkey_file(): Authentication failed for my-user-name using public key in file.php on line XXX
    This begins to happen after some 600 iterations of the loop have already completed.

    After this warning is issued, I receive another: "Too many open files". Once these two warnings occur the first time, they both occur on every attempt thereafter until the loop has run its course.

    As far as I'm aware, I'm not opening any file handles (e.g., via fopen() and family), so I'm not sure what the second warning is about.

    I'm almost thinking that the limit, whatever it may be, is being reached on the remote side, e.g., I have too many SSH connections open to the remote host, and the remote host refuses additional connections.

    Within each iteration of the loop, I'm checking if some files exist, e.g.:

    PHP Code:
    if (file_exists('ssh2.sftp://' $ssh->getSftp() . $fileName)) {
         
    }

    //where $ssh->getSftp() = ssh2_sftp($this->con) and $this->con = ssh2_connect($this->host, $this->port, array('hostkey', 'ssh-rsa')); 
    Does anything jump-out at anyone?

    Thanks in advance for any insights!
    Last edited by cbj4074; 01-04-2013 at 09:55 PM.
    To be wise is to listen exactly as often as you speak.

  2. #2
    Pna lbh ernq guvf¿
    Join Date
    Jul 2004
    Location
    Kansas City area
    Posts
    19,349
    Do you have shell access to the server where you're running this script? If so, which OS/distro are you running?

    You could try letting it run for a few hundred iterations and then listing the open files for the PHP process. That might shed some light on what isn't being release properly.

    Alternatively... you say "after some 600 iterations", but how many unique connections do you make? Is there a reason why you could keep a pool of connections open all the time and simply use whichever one is appropriate for any given iteration?

  3. #3
    Senior Member cbj4074's Avatar
    Join Date
    Feb 2004
    Location
    Portland, ME
    Posts
    225
    Hi, Brad; thanks for jumping in here!

    I meditated on this a bit more, trying to discern how the two error messages could possibly be related.

    I'm using public key authentication after connecting to the remote host, so PHP has to open the key files (both public and private) after establishing each connection. If there is a bug in the ssh2 library, and the file handles are not closed properly, this may explain why when the maximum number of files has been opened, public key authentication fails (PHP can't open the keys).

    But then I took your sound advice and let the loop run for a few hundred iterations before executing "lsof -c php". I was appalled to find that every SSH connection remains open! And, I don't see any mention of the key files. The entries look like this:

    Code:
    php     12030 root  953u  IPv4         2742068636      0t0        TCP example.com:59326->example2.com:ssh (ESTABLISHED)
    I had noticed before that ssh2_disconnect() is conspicuously absent from the library. How does one initiate an explicit disconnection with the ssh2 library? I thought that calling unset($ssh) on my object would suffice. That didn't fix this problem, so I tried issuing "exit;" via ssh2_exec(). No dice there either, although, I haven't made any effort to determine why that doesn't work just yet.

    To answer your question, yes, I do have shell access to the server on which the script is running. The OS is Ubuntu 10.04.

    Regarding your last point, what you describe is a much better implementation. The SSH connection will be made to one of only about four remote servers, so opening a pool of 4 connections and using each as needed seems like a much better idea. Thanks for the suggestion!

    That said, I do still want to figure out how to implement proper disconnections; this isn't the only place in which I use this SSH2 class.

    For what it's worth, if I kill the script (with Ctrl+C) once the warnings begin, all of those open SSH connections are closed immediately.

    Thanks again!
    Last edited by cbj4074; 01-05-2013 at 09:51 AM.
    To be wise is to listen exactly as often as you speak.

  4. #4
    Pna lbh ernq guvf¿
    Join Date
    Jul 2004
    Location
    Kansas City area
    Posts
    19,349
    Can you show us more of your code where you tried to execute the 'exit' command and unset the connection? Also, one more idea: ssh2_connect() returns a resource, so after you execute the 'exit' command (but before you try to unset the resource), try using fclose().

  5. #5
    Senior Member cbj4074's Avatar
    Join Date
    Feb 2004
    Location
    Portland, ME
    Posts
    225
    Sure!

    Once the SSH connection is established successfully, I request the sFTP subsystem:

    PHP Code:
    function sftpCon()
    {
        
    $sftp ssh2_sftp($this->con);
        
    $this->sftp $sftp;

    Then I perform a file_exists() check, as demonstrated in my initial post.

    Next, I attempt to disconnect by calling my custom function, e.g., $ssh->disconnect(). The two relevant functions are as follows:

    PHP Code:
    function cmdExec()
    {
        
    $argc func_num_args();
        
    $argv func_get_args();
        
        
    $cmd '';
        for (
    $i 0$i $argc$i ++) {
            if (
    $i != ($argc 1)) {
                
    $cmd .= $argv[$i] . ' && ';
            } else {
                
    $cmd .= $argv[$i];
            }
        }
        
        
    $stream ssh2_exec($this->con$cmd);
        if (
    $stream !== FALSE) {
            
    stream_set_blocking($streamtrue);
            
            
    $contents '';
            while(
    $line fgets($stream)) {
                
    flush();
                
    $contents .= $line;
            }
            
            
    fclose($stream);
            
            return 
    $contents;
        }
        else {
            
    $this->log[] = 'SSH command execution failed!';
            return 
    FALSE;
        }
    }

    function 
    disconnect()
    {
        
    $this->cmdExec('exit;');
        
    fclose($this->sftp);

    As you can see, I have tried adding the call to fclose() after issuing the "exit" command. Unfortunately, PHP complains:

    Code:
    Warning: fclose(): supplied resource is not a valid stream resource in file.php on line XXX
    If I var_dump($this->sftp), the output is "resource(XXX) of type (SSH2 SFTP)".

    I know the cmdExec() method is viable, because if I replace "exit;" with something else, like "ls -l", the remote directory listing is indeed returned.

    Please let me know if any other information would be helpful. Thanks again, Brad!
    Last edited by cbj4074; 01-05-2013 at 01:18 PM.
    To be wise is to listen exactly as often as you speak.

  6. #6
    Senior Member cbj4074's Avatar
    Join Date
    Feb 2004
    Location
    Portland, ME
    Posts
    225
    I finally figured it out after finding this thread:

    http://stackoverflow.com/questions/5...m-ssh2-connect

    The key was to call unset($this->sftp). Once I added that bit, sending the "exit" command via ssh2_exec() seemed unnecessary.

    My disconnect() method now looks like this:

    PHP Code:
    function disconnect()
    {
        unset(
    $this->shell);
        unset(
    $this->sftp);
        unset(
    $this->con);

    Now, there is only ever one connection at a time listed in the "lsof -c php" output.

    Thanks for pointing me in the right direction here, Brad!
    To be wise is to listen exactly as often as you speak.

  7. #7
    Pedantic Curmudgeon Weedpacket's Avatar
    Join Date
    Aug 2002
    Location
    General Systems Vehicle "Thrilled To Be Here"
    Posts
    21,771
    Just in passing, note that unset can take multiple arguments.
    THERE IS AS YET INSUFFICIENT DATA FOR A MEANINGFUL ANSWER
    FAQs! FAQs! FAQs! Most forums have them!
    Search - Debugging 101 - Collected Solutions - General Guidelines - Getting help at all

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •