我有一个小脚本,可以通过 php 的 ssh2 库复制文件。我在 Windows 上尝试了不同版本的 php,它按预期工作,但是当我在 Linux 上上传代码时,它无法复制文件。
注意php代码相同,php版本相同。我没有收到任何错误消息。我在预设文件权限期间使用此命令。在此之前,我尝试使用 fopen,fwrite trough sftp,但在复制文件后我未能对文件进行 chmod。
这是代码(如果重要):
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;
}
这是 Linux 发行版:
cat /etc/*-release
CentOS release 5.9 (Final)
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
编辑:
我只是尝试使用 fopen/fwrite/fclose 代替 ssh_scp_send 并得到相同的结果。我完全糊涂了。这是文件上传的代码:
$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;
}
谢谢。
编辑 2: 这似乎是亚马逊 sftp 特有的问题。我在其他服务器上试过这个,它适用于两个平台。我首先想到的是某种IP保护。你怎么看?亚马逊 sftp 服务器位于:productads.amazon-digital-ftp.com