当尝试从用户的主目录获取远程文件时,如果尝试使用类似 '~/filename.txt' 的路径,可能会失败。似乎不喜欢波浪号,因此请使用完整的文件路径。
(PECL ssh2 >= 0.9.0)
ssh2_scp_recv — 通过 SCP 请求文件
使用 SCP 协议将文件从远程服务器复制到本地文件系统。
示例 #1 通过 SCP 下载文件
<?php
$connection = ssh2_connect('shell.example.com', 22);
ssh2_auth_password($connection, 'username', 'password');
ssh2_scp_recv($connection, '/remote/filename', '/local/filename');
?>
如果出现
警告:ssh2_scp_recv(): 无法接收 /some-php-file.php 中第 2 行的远程文件
请使用 `stream_get_contents` 函数。
示例
<?php
$stream = @fopen("ssh2.sftp://$sftp$remoteFile", 'r');
if (! $stream) {
throw new \Exception("无法打开文件: $remoteFile");
}
$contents = stream_get_contents($stream);
file_put_contents ($localFile, $contents);
@fclose($stream);
?>
尝试获取文件名中带有空格的远程文件?
切勿忘记在远程文件名中使用引号,但在本地文件名中不使用引号。
示例
<?php
$remote_file_name="my name with spaces.ext"
ssh2_scp_recv($cn,$remote_file_name,$local_path."/".$remote_file_name); // 错误
ssh2_scp_recv($cn,"\"".$remote_file_name."\"",$local_path."/".$remote_file_name); // 正确
ssh2_scp_recv($cn,"\"".$remote_file_name."\"","\"".$local_path."/".$remote_file_name."\""); // 错误
?>
因此,文件名中的引号仅对远程文件有效,而不是对本地文件有效。
问题
无法将数组传递给 sftp_scp_rec()
此外:对于 Windows:当连接到 Windows 目录时,sftp 不高兴。
例如:sftp_scp_rec($connection, "remote/directory","local/$directory[$i]");
解决方案
数组在变量的末尾放置了空格。
trim(" ","",$directory[$i]);
连接到 Windows 目录
sftp_scp_rec($connection, "linux/directory","\\windows\share[$i]");
此脚本根据文件的修改日期,将远程 Linux 目录备份到本地 Windows 目录。
想法是通过 ftp 客户端等获取目录的完整备份。
然后当脚本运行时,它将仅备份新修改的文件。
<?php
//error_reporting(0);
$file ='';
$arr2 ='';
$arr1 ='';
$ldir = '';
$remotedirs[0] = "域名或IP地址/";
$remotedirs[1] = "域名或IP地址/";
$remotedirs[2] = "域名或IP地址/";
$remotedirs[3] = "域名或IP地址/";
$fh = fopen("c:\dirlist.txt","w");
fwrite($fh, " ");
fclose($fh);
foreach ($remotedirs as $val){
echo $remotedir = "/data/www/$val/";
$localdir = "\\\\192.168.0.234\\C$\\xampp\\htdocs\\$val\\";
backupwebsites($remotedir,$localdir);
}
function backupwebsites($remotedir,$localdir){
$connection = ssh2_connect(Host IP 或域名 , 22);
$com ="ls -R -lt $remotedir";
ssh2_auth_password($connection, 'user', 'password');
$stream = ssh2_exec($connection, $com );
stream_set_blocking($stream, true);
$output = stream_get_contents($stream);
$fh = fopen("c:\dirlist.txt","a+");
fwrite($fh, $output);
fclose($fh);
$handle = @fopen('c:\dirlist.txt', "r");
if ($handle) {
while (!feof($handle)) {
$lines[] = fgets($handle, 4096);
}
fclose($handle);
}
foreach ($lines as $val)
{
$yr = date('Y-m-d');
$i++;
$arr1=split("200",$val);
$arr2=explode(" ",$arr1[1]);
if("200".$arr2[0]==$yr)
{
//if("200".$arr2[0]=='2008-04-21'){ //用于测试
$remotedir = $remotedir.$arr2[2];
$cpy=$arr2[2];
$file = $localdir;
glue($connection,$remotedir,$localdir,$cpy);
}
}
}
//echo $i;
function glue($connection,$remotedir,$localdir,$cpy){
$ldir[0] = "$localdir";
$ldir[1]="$cpy";
$file = $ldir[0].$ldir[1];
$file = trim($file);
$file;
gop($connection,$remotedir,$file);
}
function gop($connection,$remotedir,$file){
echo $file;
ssh2_scp_recv(
$connection,
$remotedir,
$file);
}
?>
如果您没有调用 ssh2_exec($connection,'exit'),则传输的文件可能会被截断。即使文件没有完全传输,ssh2_scp_send 也会返回 true。
例如。
ssh2_scp_send($connection, $infile, $remotefile, 0644);
ssh2_exec($connection, 'exit'); // 退出 ssh2 连接
此函数可用于使用 SSH 和 SCP 将所有文件复制到远程服务器上的目录中。
<?php
$connection = ssh2_connect('host', 22);
ssh2_auth_password($connection, 'user', 'password');
$remote_dir="/remote_dir/";
$local_dir="/local_dir/";
$com ="ls $remote_dir";
$stream = ssh2_exec($connection, $com);
stream_set_blocking($stream,true);
$cmd=fread($stream,4096);
$arr=explode("\n",$cmd);
$total_files=sizeof($arr);
for($i=0;$i<$total_files;$i++){
$file_name=trim($arr[$i]);
if($file_name!=''){
$remote_file=$remote_dir.$file_name;
$local_file=$local_dir.$file_name;
if(ssh2_scp_recv($connection, $remote_file,$local_file)){
echo "文件 ".$file_name." 已复制到 $local_dir<br />";
}
}
}
fclose($stream);
?>
由于仍在 Beta 测试阶段,我想它会有一些怪癖。我发现的一个问题是,如果远程文件名中包含括号,它就无法工作。
我应该将其提交为错误报告,但我发现整个流程非常令人畏惧——我一直都是一个不懂自己正在做什么的愚蠢用户!
但无论如何——在下载文件之前重命名文件的解决方法可以正常工作。
使用
$_new_path = str_replace("(", "", $_path );
$_new_path = str_replace(")", "", $_new_path );
ssh2_sftp_rename( $sftp, $_path, $_new_path );
说实话,我还没有确定是左括号还是右括号,或者两者都有问题。其他人可以调查一下。
与此同时,最好知道此函数存在问题的所有无效文件名字符,毫无疑问还有更多。
如果您使用 opendir 和 readdir 在从 ssh2_sftp() 获取的路径上扫描远程目录以获取文件列表,则最终将获得包含 ssh2.sftp://$sftp 前缀的完整文件路径列表,其中 $sftp 是 ssh2_sftp 返回的 sftp 资源字符串。
如果您稍后尝试使用 ssh2_scp_recv()(即使是在同一个连接上!)从远程路径本地复制文件,复制操作将失败,因为 ssh2_scp_recv() 不喜欢包装路径前缀。它期望远程文件引用位于远程文件系统的根目录(例如,“/”)。
道德:ssh2_scp_recv() 喜欢位于远程机器文件系统根目录的路径,而不是完整的网络路径。此例程将以一个关于无法复制文件的模糊消息失败 - 然而,当您去查看它时,它工作正常。更糟糕的是,当您连接并从 scp shell 会话中复制它们时,它也工作正常。
如果您遇到错误 - ssh2_scp_recv(): Unable to receive remote file
尝试使用 file_get_contents("ssh2.sftp://$sftp$fileLocation") 和 file_put_contents() 作为解决方法 - 这是在我尝试了各种远程文件路径格式但无济于事之后。
如果在尝试使用此函数时收到“Warning: ssh2_scp_send(): Failure creating remote file”,请尝试使用
$data = file_get_contents("ssh2.sftp://$sftp/path/to/file");