简体   繁体   English

ssh2_scp_send仅在Windows上有效,但不能在linux上复制到amazon.com

[英]ssh2_scp_send works only on windows, but doesn't copy on linux to amazon.com

I have a little script that copy files trough ssh2 library for php. 我有一个小脚本,可以通过ssh2库复制文件用于php。 I tried on different version of php on windows and it works as expected, but when i upload the code on Linux, it fails to copy the file. 我在Windows上尝试了不同版本的php,它可以按预期工作,但是当我在Linux上上传代码时,它无法复制文件。

Note that the php code is same, php version are same. 注意,PHP代码是相同的,PHP版本是相同的。 I don't get any error messages. 我没有收到任何错误消息。 I use this command during presetting of file permissions. 我在预设文件权限时使用此命令。 Before that i tried with fopen, fwrite trough sftp, but i failed to chmod the file after copy it. 在此之前,我尝试使用fopen,fwrite槽sftp,但在复制文件后无法对文件进行chmod设置。

Here is the code (if matters): 这是代码(如果有的话):

public function connect() {

    if (empty($this->ftpProps['ftpServer'])) {
        $result['errorMsg'] = 'No FTP Server Provided';
        $this->callFunc($this->callbackFunction, '<span class="error">'.$result['errorMsg'].'</span><br>'."\n");
        return $result;
    }

    $this->ftpProps['ftpServer'] = str_replace("sftp://", "", $this->ftpProps['ftpServer']);
    $this->callFunc($this->callbackFunction, 'Connecting to: <b>'.$this->ftpProps['ftpServer'].'</b>...'."\n");

    if (!function_exists('ssh2_connect')) {
        $result['errorMsg'] = 'Missing Secure Shell2 Library';
        $this->callFunc($this->callbackFunction, '<span class="error">'.$result['errorMsg'].'</span><br>'."\n");
        return $result;
    }

    $this->connection = ssh2_connect($this->ftpProps['ftpServer'], 22);
    if (empty($this->connection)) {
        $result['errorMsg'] = "Couldn't connect to ".$this->ftpProps['ftpServer'];
        $this->callFunc($this->callbackFunction, '<span class="error">'.$result['errorMsg'].'</span><br>'."\n");
        return $result;
    }
    $this->callFunc($this->callbackFunction, '<span class="successfull">Done</span><br />');

    // login
    if (empty($this->ftpProps['ftpUser'])) {
        $result['errorMsg'] = 'No FTP UserName Provided';
        $this->callFunc($this->callbackFunction, '<span class="error">'.$result['errorMsg'].'</span><br>'."\n");
        return $result;
    }

    $this->callFunc($this->callbackFunction, 'Logging in as <b>'.$this->ftpProps['ftpUser'].'</b>...'."\n");

    $this->authResult = ssh2_auth_password($this->connection, $this->ftpProps['ftpUser'], $this->ftpProps['ftpPass']);

    if (!$this->authResult) {
        $result['errorMsg'] = 'Failed to connect to '.$this->ftpProps['ftpServer'].'. Wrong credentials.';
        $this->callFunc($this->callbackFunction, '<span class="error">'.$result['errorMsg'].'</span><br>'."\n");
        return $result;
    }

    $this->callFunc($this->callbackFunction, '<span class="successfull">Done</span><br />');
    $this->callFunc($this->callbackFunction, 'Initializing SFTP subsystem of <b>'.$this->ftpProps['ftpServer'].'</b>...'."\n");

    $sftp = ssh2_sftp($this->connection);
    if (!$sftp) {
        $result['errorMsg'] = 'Failed to initialize SFTP subsystem of '.$this->ftpProps['ftpServer'];
        $this->callFunc($this->callbackFunction, '<span class="error">'.$result['errorMsg'].'</span><br>'."\n");
        return $result;
    }

    $this->callFunc($this->callbackFunction, '<span class="successfull">Done</span><br />');
    $result['message'] = 'Success';
    $result['isTestSuccessful'] = true;
    return $result;
}

//@Override
public function upload() {
    $timer = lloader()->getTimer();

    $uploadStartedOn = time();
    $connectResult = $this->connect();
    if (!empty($connectResult['errMsg'])) { return $connectResult; }

    $targetFileNames = $this->ftpProps['targetFileNames'];
    $sourceFileNames = $this->ftpProps['sourceFileNames'];

    foreach ($sourceFileNames as $nameIndex => $sourceFileName) {
        $targetFileName = $targetFileNames[$nameIndex];
        echoFlush('Uploading <b>'.$targetFileName.'</b>...');

        // use ssh2_scp_send instead fopen because of opportunity to set file mode. amazon disables chmod command
        $writeResult = ssh2_scp_send($this->connection, $sourceFileName, $this->ftpProps['destPath'].$targetFileName, 0755);
        if (!$writeResult) {
            $result['errorMsg'] = 'Failed to upload '.$targetFileName;
            $this->callFunc($this->callbackFunction, '<span class="error">'.$result['errorMsg'].'</span><br>'."\n");
            return $result;
        }
        $this->callFunc($this->callbackFunction, '<span class="successfull">Done</span><br />');
    }

    $this->callFunc($this->callbackFunction, '<span class="successfull">Done</span><br>'."\n");
    $this->callFunc($this->callbackFunction, 'The Upload Took '.$timer->getFormattedElapsedTime(time() - $uploadStartedOn).'<br>'."\n");

    $result['message'] = 'Success';
    $result['isSubmitSuccessful'] = true;
    return $result;
}

Here is the Linux distribution: 这是Linux发行版:

cat /etc/*-release
CentOS release 5.9 (Final)

Some of the returned lines of php -i command: php -i命令返回的一些行:

Registered PHP Streams => https, ftps, compress.zlib, compress.bzip2, php, file, data,
               http, ftp, ssh2.shell, ssh2.exec, ssh2.tunnel, ssh2.scp, ssh2.sftp, zip
Registered Stream Socket Transports => tcp, udp, unix, udg, ssl, sslv3, sslv2, tls
...
ssh2
libssh2 version => 1.2.9
banner => SSH-2.0-libssh2_1.2.9
...
Stream Wrapper support => compress.zlib://
zlib.output_compression => Off => Off
zlib.output_compression_level => -1 => -1

EDIT: 编辑:

I just tried to use fopen/fwrite/fclose instead ssh_scp_send and got same results. 我只是尝试使用fopen / fwrite / fclose而不是ssh_scp_send并得到了相同的结果。 I'm totaly confused. 我完全感到困惑。 Here is the code for file upload: 这是文件上传的代码:

$targetHandler = fopen("ssh2.sftp://".$this->sftp."/".$this->ftpProps['ftpDestPath'].$targetFileName, 'w');
        if (empty($targetHandler)) {
            $result['errorMsg'] = 'Failed to open '.$targetFileName;
            return $result;
        }
        $sourceHandler = @fopen($sourceFileName, "r");
        while (!feof($sourceHandler)) {
            $readBlock = fread($sourceHandler, 16384);
            $resultWrite = fwrite($targetHandler, $readBlock);
            if ($resultWrite === false) {
                $result['errorMsg'] = 'Failed to upload '.$targetFileName;
                fclose($targetHandler);
                fclose($sourceHandler);
                return $result;
            }
        }

        $chmodResult = ssh2_sftp_chmod($this->sftp, $this->ftpProps['destPath'].$targetFileName, 0755);
        if (empty($chmodResult)) {
            $result['errorMsg'] = 'Failed to chmod '.$targetFileName;
            return $result;
        }

Thanks. 谢谢。

EDIT 2: It seems this is amazon sftp specific issue. 编辑2:看来这是亚马逊sftp特定的问题。 I tried this on other server and it works on both platform. 我在其他服务器上尝试过,它在两个平台上都可以工作。 First thing in my mind is some kind of protection by ip. 我首先想到的是IP的某种保护。 What do you think? 你怎么看? The amazon sftp server is located at: productads.amazon-digital-ftp.com 亚马逊sftp服务器位于:productads.amazon-digital-ftp.com

Looks like there are two pre-requisites for the SSH2 library, have you verified the Linux box meets them? 看起来SSH2库有两个先决条件,您是否已验证Linux是否满足要求?

http://www.php.net/manual/en/ssh2.requirements.php http://www.php.net/manual/zh/ssh2.requirements.php

I found the reason for this behavior of the script. 我找到了此脚本行为的原因。 It is the ssh2 library version. 它是ssh2库版本。 On my localhost and one linux server it is SSH-2.0-libssh2_1.4.3. 在我的本地主机和一台Linux服务器上,它是SSH-2.0-libssh2_1.4.3。 On the problematic machine the version of the library is SSH-2.0-libssh2_1.2.9. 在有问题的计算机上,该库的版本为SSH-2.0-libssh2_1.2.9。 So it seems this is a library bug. 因此,这似乎是一个库错误。

I leave this post for those who use this library and don't want to change their code. 我将这些帖子留给那些使用此库且不想更改其代码的人使用。

Thanks for your time. 谢谢你的时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM