문제

n개의 원격 서버를 통해 프로그래밍 방식으로 파일을 검색해야 하기 때문에 PHP로 간단한 SFTP 클라이언트를 작성하고 있습니다.PECL SSH2 확장을 사용하고 있습니다.

하지만 나는 도로 블록에 부딪혔습니다.php.net 문서에서는 다음과 같이 할 수 있다고 제안합니다.

$stream = fopen("ssh2.sftp://$sftp/path/to/file", 'r');

그러나 비슷한 것을 시도하는 ls 메소드가 있습니다.

public function ls($dir)
{
    $rd = "ssh2.sftp://{$this->sftp}/$dir";
    $handle = opendir($rd);
    if (!is_resource($handle)) {
        throw new SFTPException("Could not open directory.");
    }

    while (false !== ($file = readdir($handle))) {
        if (substr($file, 0, 1) != '.'){
            print $file . "\n";
        }
    }
    closedir($handle);
}

다음 오류가 발생합니다.

PHP Warning:  opendir(): Unable to open ssh2.sftp://Resource id #5/outgoing on remote host

이는 리소스를 문자열로 캐스팅할 때 발생하는 일이기 때문에 완벽하게 이해됩니다.문서가 잘못된 걸까요?리소스를 호스트, 사용자 이름 및 호스트로 바꾸려고 시도했지만 작동하지 않았습니다.명령줄에서 SFTP를 실행할 수 있고 제대로 작동하기 때문에 경로가 정확하다는 것을 알고 있습니다.

SFTP와 함께 SSH2 확장을 사용하려고 시도한 사람이 있습니까?여기서 분명한 것을 놓치고 있습니까?

업데이트:

사내의 다른 컴퓨터에 sftp를 설정했는데 제대로 작동합니다.따라서 연결하려는 서버에 뭔가가 작동하지 않는 것이 있는 것 같습니다.

도움이 되었습니까?

해결책

SFTP 서버에 연결하고 루트 폴더에 연결 해야하는 경우 (예 : 폴더의 내용을 읽기 위해) "/"만 사용할 때 경로로 오류가 발생합니다.

내가 찾은 솔루션은 "/./"경로를 사용하는 것이 었습니다. 그것은 루트 폴더를 참조하는 유효한 경로입니다. 이는 로그인하는 사용자가 자체 루트 폴더에만 액세스 할 수 있고 전체 경로를 사용할 수없는 경우 유용합니다.

따라서 루트 폴더의 내용을 읽으려고 할 때 서버에 대한 요청은 다음과 같습니다.

$rd = "ssh2.sftp://{$this->sftp}/./";

다른 팁

PHP 버전의 경우> 5.6.27 intval () 사용

$sftpConnection = ssh2_connect($host);
$sftp = ssh2_sftp($sftpConnection);
$fp = fopen("ssh2.sftp://" . intval($sftp) . $remoteFile, "r");

https://bugs.php.net/bug.php?id=73597

비슷한 문제가 있습니다. 나는 당신이 이것과 비슷한 일을하고 있다고 생각합니다.

    $dir = "ssh2.sftp://{$sftp}{$remote_dir}"; 
    $handle = opendir($dir);

언제 $remote_dir 그때 뿌리의 전체 경로입니다 open_dir 공장. 만약에 $remote_dir 그냥 '/'또는 '' ', 그런 다음'열 수 없다 '오류가 발생합니다.

필자의 경우 SSH는 FTP와 같이 '홈'디렉토리 대신 루트 폴더에서 연결되는 것 같습니다. 다른 서버에서 작동한다고 언급 했으므로 구성 문제 일지 궁금합니다.

연장 등을 설치하지 않고 PHP (창에서도) 내에서 SFTP가 작동하는 가장 쉬운 방법은 phpseclib입니다. http://phpseclib.sourceforge.net/ . SSH 재료는 PHP 클래스에서 완전히 구현됩니다.

당신은 다음과 같습니다.

<?php
include('Net/SFTP.php');

$sftp = new Net_SFTP('www.domain.tld');
if (!$sftp->login('username', 'password')) {
    exit('Login Failed');
}

echo $sftp->pwd();
?>

해당 페이지의 문서에는 오류가 포함되어 있습니다. 대신 여기의 예를 살펴보십시오. http://php.net/ssh2_sftp - 실제로해야 할 일은 fopen ()와 함께 사용하기 전에 ssh2_sftp ()를 사용하여 특수 SFTP 리소스를 여는 것입니다. 그렇습니다. 예를 들어 문자열로 변환 될 때 "리소스 #24"처럼 보입니다. 조금 이상하지만 분명히 작동합니다.

또 다른 경고는 SFTP가 원격 사용자의 홈 디렉토리 대신 루트 디렉토리에서 시작되므로 URI의 원격 경로는 항상 절대적인 경로 여야한다는 것입니다.

방금 같은 문제가 있었지만 문제를 알아낼 수있었습니다.

제 경우에는 서버에 연결할 때 계정의 루트로 이동했으며 서버 구성으로 인해 글을 쓸 수 없었습니다.

Fireftp를 사용하여 계정에 연결 했으므로 계정의 루트가 어디에 있는지 알 수있었습니다. 서버의 근본이었습니다.

글을 쓸 수있는 폴더까지 전체 경로를 포함시켜야했기 때문에 문제를 해결할 수있었습니다.

따라서 제 조언은 그래픽 인터페이스 (FireFTP를 사용했습니다)를 사용하여 경로를 얻고 코드에 전체 경로를 추가하는 것입니다.


$pathFromAccountRootFolderToMyDestinationFolder = '/Account/Root/Folder/To/My/Folder';
$stream = fopen("ssh2.sftp://".$sftp."/".$pathFromAccountRootFolderToMyDestinationFolder."/myFile.ext", 'r');

이것이 당신과 같은 문제를 가진 다른 사람들에게 도움이되기를 바랍니다!

건배!

나는 최근에 PHP 작업에서 SFTP를 얻으려고 노력했고 phpseclib를 사용하기가 훨씬 쉽다는 것을 알았습니다.

http://phpseclib.sourceforge.net/

공유 호스트에 있지 않은 사치가 있고 PECL 확장자가 더 좋을 수도 있지만 우리 모두가 운이 좋지는 않을 수있는 확장을 설치할 수 있다면. 또한 Phpseclib의 API는 조금 더 직관적 인 것처럼 보입니다.

내 문제는 기능을 연결하고 리소스 내부에 문자열 URL을 반환하고 있다는 것입니다. 불행한 Atelly 리소스는 기능 컨텍스트에서 생성되는 것보다 생성되며 쓰레기 수집기는 기능 끝에 리소스를 분리합니다. 솔루션 : 참조별로 리소스를 반환하고보다 복잡한 맥락에서 수동으로 설정하지 않습니다.

(PowerShell) 서버에서 SFTP 지원을 활성화하여 내 문제를 해결했습니다.

이것은 제가 몇 년 전에 발견하여 php.net에 패치를 게시한 ssh2 패키지의 버그입니다.이 문제는 해결되지만 ssh2 pecl 패키지를 다시 빌드해야 합니다.여기에서 자세한 내용을 읽을 수 있습니다. https://bugs.php.net/bug.php?id=69981.문제를 해결하기 위해 패키지의 ssh2_fopen_wrappers.c 파일에 패치를 포함시켰습니다.제가 포함시킨 코멘트는 다음과 같습니다:

다음은 이 버그를 일으키는 ssh2_fopen_wrappers.c의 코드 줄입니다.(댓글 포함)

/*
       Find resource->path in the path string, then copy the entire string from the original path.
       This includes ?query#fragment in the path string
*/
    resource->path = estrdup(strstr(path, resource->path));

이 코드 줄, 즉 이 버그는 버그 #59794에 대한 수정 사항으로 도입되었습니다.해당 코드 줄은 경로 변수에서 부품, 쿼리 및 조각이 포함된 문자열을 가져오려고 시도하고 있습니다.경로 변수에 대해 다음 값을 고려하십시오.

ssh2.sftp://Resource id #5/topdir?a=something#heading1

리소스->경로가 "/topdir"인 ​​경우 결과는 주석에서 말하는 것처럼 "/topdir?a=something#heading1"이 리소스->경로에 할당되는 것입니다.

이제 리소스->경로가 "/"인 경우를 고려해보세요.코드 줄이 실행되면 리소스->경로는 "//Resource id#5/topdir#heading1"이 됩니다.이것은 분명히 당신이 원하는 것이 아닙니다.이를 수행하는 코드 줄은 다음과 같습니다.

 resource->path = estrdup( strstr( strstr( path, "//" ) + 2, "/" ) );

php_url_parse()를 호출하기 전에 경로 문자열에서 "Resource id #"를 제거하는 버그 # 73597에 대한 패치를 적용해야 할 수도 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top