Skip to content

Comments

Check if realpath succeeded when changing SFTP directory#2098

Closed
toml-bipsync wants to merge 1 commit intophpseclib:masterfrom
toml-bipsync:check-realpath-succeeded
Closed

Check if realpath succeeded when changing SFTP directory#2098
toml-bipsync wants to merge 1 commit intophpseclib:masterfrom
toml-bipsync:check-realpath-succeeded

Conversation

@toml-bipsync
Copy link
Contributor

I've been troubleshooting an interesting intermittent issue with SFTP, where sometimes realpath() would fail but chdir would return true. pwd would be false though so future commands would fail the precheck with 'Please close the channel (256) before trying to open it again'.

I've added a simple check, wasn't quite sure if that was the preferred way.
Happy to change it to

$dir = $this->realpath($dir);
if ($dir === false) {
    return false;
}

or whatever.

@terrafrost
Copy link
Member

I prefer the alternative method you mentioned - if you could update your PR that'd be great - thanks!

I'm also curious... in those instances where realpath returns false and chdir returns true can you post the output of $sftp->getLastSFTPError() and of getServerIdentification()? Like when I try to change to a non existent directory with chmod $sftp->getLastSFTPError() returns this:

NET_SFTP_STATUS_NO_SUCH_FILE: No such file

None of that changes the merit of your PR (which is sound). None-the-less I'm curious!

@toml-bipsync toml-bipsync force-pushed the check-realpath-succeeded branch from c16b72a to 4ee55d1 Compare September 3, 2025 08:18
@toml-bipsync
Copy link
Contributor Author

@terrafrost done.

Apologies I think I messed up my initial report. It's quite a hard issue to diagnose because of where the code is and the fact I can't replicate it locally at all. I'll write out the issue in case you have any insight.

The code was basically:

$sftp->chdir($directory);
if ( !$sftp->put( $destinationFilename, $sourceFilename, 1 ) ) {
    $error = "Failed to upload to SFTP: " . $sftp->getLastSFTPError() . " copying " . $sourceFilename . " to " . $destinationFilename;
    return false;
}

Note at first we weren't checking the return value of chdir.
$directory is user configurable so values tend to vary "/directory", "directory" etc. In the case I'm looking at the $directory is "reports".
Sometimes the put() fails with 'Please close the channel (256) before trying to open it again', this was because pwd was false which triggered reconnection. When the failed upload is retried (hours later, different php process) it succeeds.

Yesterday I changed the code so we check the result of chdir() and pwd before the put(). It now reliably fails and getLastSFTPError() set to NET_SFTP_STATUS_NO_SUCH_FILE: /reports does not exist.

I can't run getServerIdentification() easily, but the servers are OpenSSH8.9 and Azure Blob Storage SFTP.

@terrafrost
Copy link
Member

I cherry picked this into the 1.0 branch and then merged that into the 2.0, 3.0 and master branches:

857245e

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants