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 脚本添加更多调试,捕获异常并打印它们,并在关闭它们之前检查 sftp
和 transport
是否有 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()
我有一个 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 脚本添加更多调试,捕获异常并打印它们,并在关闭它们之前检查 sftp
和 transport
是否有 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()