|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2005-06-23 05:58 UTC] david dot richard at euroconnect dot fr
Description:
------------
I have encountered a problem with ssh2-0.8 and ssh2_scp_send command (it was working very well with ssh2-0.6).
The problem is, when I copy a file to the remote server, the result is always an empty file.
Somebody can help me ?
Thanks
David
Reproduce code:
---------------
<?php
if( ($ssh = ssh2_connect("192.168.128.25" , 22)) ){
if( ssh2_auth_password($ssh, user, password) ){
ssh2_scp_send($ssh,"/complitepath/script.sh", "script.sh");
}
}
?>
Expected result:
----------------
The file may be copy to the remote host
Actual result:
--------------
The file is copy but it is empty
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Tue Nov 04 21:00:01 2025 UTC |
I am experiencing similar transfer problems using the latest versions of libssh (libssh2-0.11) and ssh2 (ssh2-0.9) on Linux ASE 3. When using the function below not all of a file will transfer to the destination server (Windows or Linux). any help would be appreciated. <code> define("SCP_SERVER", "<server>"); define("SCP_USER", "<user>"); define("SCP_PASSWORD", "<password>"); define("SCP_PATH", "<path>"); function dat_xmit_file_scp($i_src_file_nm, $i_dst_file_nm) { $methods = array('client_to_server'=>array ('comp'=>'none'),'server_to_client'=>array('comp'=>'none')); $connection = ssh2_connect(SCP_SERVER, 22, $methods) or die("Couldn't connect to ".SCP_SERVER); $rc=false; if (@ssh2_auth_password($connection, SCP_USER, SCP_PASSWORD)) { print("i_src_file_nm:". $i_src_file_nm." i_dst_file_nm:".SCP_PATH.u rlencode($i_dst_file_nm)."<br />"); $rc = ssh2_scp_send($connection, $i_src_file_nm, SCP_PATH.urlencode($i_dst_file_nm), 0644); } unset($connection); $desc = (($rc !== false)? ("Upload Successful:\n" . $i_dst_file_nm ) : "Upload Failed: " . $i_dst_file_nm); $status = array("result"=>$rc, "desc"=>$desc); return ($status); } </code>This is what I had to do to copy a txt file from a Windows/php command line through to a cygwin (linux emulator for windows): copy winscp3.exe in the php's folder <? //we'll get rid of the extension and then rename it back to .txt once it's copied $file = $path.$filename; rename ( $file , str_replace ( ".txt" , "" , $file )); $file = str_replace ( ".txt" , "" , $file ); //in the php source create a temp winscp script file $tempfile = 'tempscript.txt'; $somecontent = "# Automatically answer all prompts negatively not to stall # the script on errors option batch on # Disable overwrite confirmations that conflict with the previous option confirm off # Connect using a password open ".$user.":".$pwd."@".$server." # Change remote directory # cd /blah/ # Force binary mode transfer # option transfer binary # Upload the file to current working directory put ".$file." # rename the file to a .txt remotely mv ".str_replace ( ".txt" , "" , $filename )." ".$filename." # Disconnect close # Exit WinSCP exit\n"; if (!$handle = fopen($tempfile, 'w')) { echo "Cannot open file ($tempfile)"; exit; } // Write $somecontent to our opened file. if (fwrite($handle, $somecontent) === FALSE) { echo "Cannot write to file ($tempfile)"; exit; } //echo "Success, wrote ($somecontent) to file ($tempfile)"; fclose($handle); $command1 = "winscp3.exe /console /script=tempscript.txt"; //run command $result = system($command1); echo $result; //delete temp file unlink($tempfile); //rename file back to txt rename ( $file , $file.".txt"); ?> hope this will help someone Cris.If you dont want to execute "exit" command or use unset() function; you can patch ssh2 extension: Open ssh2.c 1) Add following lines before " PHP_FUNCTION(ssh2_fingerprint) " and after " /* }}} */ " /* {{{ proto resource ssh2_disconnect(resource session) * Close the SSH server connection and return a true on success, false on error */ PHP_FUNCTION(ssh2_disconnect) { zval *zsession; /* check & parse parameters */ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zsession) == FAILURE) { RETURN_FALSE; } /* decrease the refcount and call destructor if needed */ if (zend_list_delete(Z_LVAL_P(zsession)) == FAILURE) { RETURN_FALSE; } /* destruct pointer */ zval_ptr_dtor(&zsession); RETURN_TRUE; } /* }}} */ 2) Declare the ssh2_disconnect() function again by adding a line after the existing PHP_FE() line. find following line : PHP_FE(ssh2_connect, NULL) after add: PHP_FE(ssh2_disconnect, NULL) Important Note: Do it only if you know what you do. You should close all streams before calling ssh2_disconnect()A user on our php installation reported that ssh2_scp_send would sometimes fail to write data to the remote target, which is similar to many of the issues reported by others on this ticket. The following diff (lightly tested on our installation, not guaranteed to be correct) fixes the issue in our case: --- ssh2-0.11.2/ssh2_fopen_wrappers.c 2010-11-03 15:24:33.000000000 -0700 +++ ssh2-0.11.2-new/ssh2_fopen_wrappers.c 2011-09-28 09:35:35.000000000 -0700 @@ -1047,13 +1047,19 @@ libssh2_channel_free(remote_file); RETURN_FALSE; } + size_t sent = 0; + size_t justsent = 0; - if (bytesread != libssh2_channel_write(remote_file, buffer, bytesread)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed copying file"); - php_stream_close(local_file); - libssh2_channel_free(remote_file); - RETURN_FALSE; + while (bytesread - sent > 0) { + if ((justsent = libssh2_channel_write(remote_file, (buffer + sent), bytesread - sent)) <= 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed copying file"); + php_stream_close(local_file); + libssh2_channel_free(remote_file); + RETURN_FALSE; + } + sent = sent + justsent; } + ssb.sb.st_size -= bytesread; } I'd be interested in seeing/knowing if that's similar to what Cedric did.We had to add flush to solve the problem --- ssh2-0.11.3/ssh2_fopen_wrappers.c.orig 2011-09-27 13:05:05.000000000 -0700 +++ ssh2-0.11.3/ssh2_fopen_wrappers.c 2012-02-08 23:40:13.000000000 -0800 @@ -1052,13 +1052,19 @@ libssh2_channel_free(remote_file); RETURN_FALSE; } + size_t sent = 0; + size_t justsent = 0; - if (bytesread != libssh2_channel_write(remote_file, buffer, bytesread)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed copying file"); - php_stream_close(local_file); - libssh2_channel_free(remote_file); - RETURN_FALSE; + while (bytesread - sent > 0) { + if ((justsent = libssh2_channel_write(remote_file, (buffer + sent), bytesread - sent)) <= 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed copying file"); + php_stream_close(local_file); + libssh2_channel_free(remote_file); + RETURN_FALSE; + } + sent = sent + justsent; } + ssb.sb.st_size -= bytesread; } --- ssh2-0.11.3/ssh2_fopen_wrappers.c 2012-02-08 23:42:12.000000000 -0800 +++ ssh2-0.11.3/ssh2_fopen_wrappers.c.new 2012-02-08 23:58:59.000000000 -0800 @@ -1068,6 +1068,7 @@ ssb.sb.st_size -= bytesread; } + libssh2_channel_flush_ex(remote_file, LIBSSH2_CHANNEL_FLUSH_ALL); php_stream_close(local_file); libssh2_channel_free(remote_file); RETURN_TRUE;We had to change the line in the fix from: if ((justsent = libssh2_channel_write(remote_file, (buffer + sent), bytesread - sent)) <= 0) { to: if ((justsent = libssh2_channel_write(remote_file, (buffer + sent), bytesread - sent)) < 0) { as in our case for some reason (probably network timing) the write was returning 0 as it hadn't had time to write anything from the buffer. As there was no error condition here, just continuing and retrying solved the problem. During debugging it also helped to change the error message in this new piece of code to "Failed copying file. Destination write failed" as this distinguishes it from a possible read failure message earlier that otherwise had the same message.