Python - 通过 PHP 使用 Paramiko 的 SFTP

Python - SFTP using Paramiko via PHP

我有一个 PHP 脚本可以执行以下操作

$command = '/usr/bin/python /srv/www/vhosts/someurl.com/html/SftpUpload.py ' .
    $config::SFTP_SERVER . ' ' . $config::SFTP_USER . ' ' . $config::SFTP_PASSWORD . ' ' .
    $downloadZip . ' ' . $config::UPLOAD_LOCATION.$extDetails;
exec($command, $retval);
print_r($retval);

所以它本质上是执行一个 Python 文件并传递给它某些参数。 Python 文件如下所示

import sys, paramiko

if len(sys.argv) < 5:
    print "args missing"
    sys.exit(1)

print 'Argument List:', str(sys.argv)

hostname = sys.argv[1]
username = sys.argv[2]
password = sys.argv[3]
localpath = sys.argv[4]
filepath = sys.argv[5]

port = 22

try:
    transport = paramiko.Transport((host, port))

    # Auth

    transport.connect(username = username, password = password)

    # Go!

    sftp = paramiko.SFTPClient.from_transport(transport)

    # Upload

    sftp.put(localpath, filepath)

finally:
    sftp.close()
    transport.close()

所以它应该使用 SFTP 文件到服务器的参数。在顶部,我打印出争论列表只是为了看看我得到了什么,它看起来像这样

Array
(
    [0] => Argument List: ['/srv/www/vhosts/someurl.com/html/SftpUpload.py', 'SFTPHostUrl.com', 'someUsername', 'somePassword', 'http://localurl.com/thefile.zip', '/srv/www/vhosts/destinationurl.com/html/thefile.zip']
)

我尝试更改 argv 编号并为每个编号加一个,以防第一个参数是 Python 文件。

无论如何,文件似乎在执行,但没有任何反应。有什么方法可以让我看到一些错误或其他东西,以便找出问题所在,因为目前我只看到争论列表。

谢谢

调用transport = paramiko.Transport((host, port))时未定义变量host。您很可能改用 hostname 。请参阅下面的代码,该代码修复了该问题并添加了更多调试输出。

除此之外,您的脚本还不错,尽管您正在做的事情会带来高安全风险,因为 none 个变量是 sanitized/validated(路径遍历、shell 命令注入)和 shellcmd 都不会以安全的方式执行。因此,如果您打算将此脚本留在生产服务器上并允许其他人调用它,请记住这一点。

调试这类问题

首先尝试使用从 php 脚本传递的完全相同的参数调用外部脚本并检查 exceptions/errors。由于您用 try catch 包装了脚本的有趣部分,默默地忽略了所有异常,因此您不会看到任何错误。这是主要问题。因此,要么删除 try catch finally 块,要么添加更多调试输出,如下所示。

为了从 php 进行调试,您必须在执行命令时捕获输出(修改后的 .py 将错误打印到标准输出):

<?php
$command = '/usr/bin/python /srv/www/vhosts/someurl.com/html/SftpUpload.py ' . $config::SFTP_SERVER . ' ' . $config::SFTP_USER . ' ' . $config::SFTP_PASSWORD . ' ' .  $downloadZip . ' ' . $config::UPLOAD_LOCATION.$extDetails;
$output = shell_exec($command);
echo "<pre>$output</pre>";
?>

向您的 sftp 脚本添加更多调试,捕获异常并打印它们,并在关闭它们之前检查 sftptransport 是否有 None

import sys, paramiko

if __name__=="__main__":
    if len(sys.argv) < 5:
        print "args missing"
        sys.exit(1)

    print 'Argument List:', str(sys.argv)

    hostname, username, password, localpath, filepath = sys.argv[1:6]
    port = 22
    sftp, transport = None, None
    try:
        print "connecting to: %s"%hostname
        transport = paramiko.Transport((hostname, port))
        print  "Auth"
        transport.connect(username = username, password = password)
        print  "Go!"
        sftp = paramiko.SFTPClient.from_transport(transport)
        print "Upload"
        sftp.put(localpath, filepath)
        print "Upload succeeded"
    except Exception, e:
        print "Exception: %s"%repr(e)
    finally:
        if sftp:
            sftp.close()
        if transport:
            transport.close()