我正在尝试使用python子进程模块登录到安全的ftp站点然后获取文件。但是,我一直在试图在请求密码时发送密码。到目前为止,我有以下代码:
from subprocess import Popen, PIPE
proc = Popen(['sftp','user@server', 'stop'], stdin=PIPE)
proc.communicate('password')
这仍然在密码提示下停止。如果我手动输入密码,则转到ftp站点,然后在命令行输入密码。我见过人们建议使用pexpect,但长话短说我需要一个标准的库解决方案。无论如何还有子进程和/或任何其他stdlib?我上面忘记了什么?
答案 0 :(得分:8)
答案 1 :(得分:6)
尝试
proc.stdin.write('yourPassword\n')
proc.stdin.flush()
这应该有效。
您所描述的内容听起来像stdin=None
,其中子进程继承父进程的stdin(您的Python程序)。
答案 2 :(得分:2)
from subprocess import Popen, PIPE
proc = Popen(['sftp','user@server', 'stop'], stdin=PIPE)
proc.communicate(input='password')
尝试使用input ='password'进行沟通,这对我有用。
答案 3 :(得分:1)
我建议废弃子流程方法并使用paramiko包进行sftp访问。
答案 4 :(得分:1)
使用Paramiko
进行SFTP。对于其他任何事情,这都有效:
import subprocess
args = ['command-that-requires-password', '-user', 'me']
proc = subprocess.Popen(args,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
proc.stdin.write('mypassword\n')
proc.stdin.flush()
stdout, stderr = proc.communicate()
print stdout
print stderr
答案 5 :(得分:0)
同样的问题困扰了我一个星期。我必须通过子进程安全地从用户输入提交密码,因为我试图避免引入命令注入漏洞。以下是我在同事的帮助下解决问题的方法。
import subprocess
command = ['command', 'option1', '--password']
subprocess.Popen(command, stdin=subprocess.PIPE).wait(timeout=60)
.wait(timeout = int)是最重要的组件,因为它允许用户将输入提供给stdin。否则,超时默认为0并使用户没有时间输入输入,从而导致无字符串或空字符串。让我永远想清楚这一点。
对于你知道你必须多次执行此操作的重复用例,你可以覆盖popen函数并将其用作私有方法,如果你预期,同一个程序员告诉我这是最好的做法其他人有兴趣稍后维护代码,你不希望他们搞砸它。
def _popen(cmd):
proc_h = subprocess.Popen(cmd, stdin=subprocess.PIPE)
proc_h.wait(timeout=60)
return proc_h.poll() == os.EX_OK
如果要提示用户输入,则删除stdout = subprocess.PIPE非常重要。否则,该过程似乎挂起60秒,并且用户没有得到提示,也没有意识到他们应该提供密码。 stdout将自然地转到shell窗口并允许用户将输入传递给popen()。
另外,只是为了解释为什么返回proc_h.poll()== os.EX_OK,如果命令成功则返回0。当你想要在函数失败的情况下返回系统错误代码时,这只是c风格的最佳实践,同时考虑到返回0将被视为" false"由翻译。
答案 6 :(得分:0)
这是使用Expect的纯Python解决方案,而不是pexpect。
如果在Ubuntu上,您首先需要使用以下命令安装Expect:
sudo apt install expect
Python 3.6或更高版本:
def sftp_rename(from_name, to_name):
sftp_password = 'abigsecret'
sftp_username = 'foo'
destination_hostname = 'some_hostname'
from_name = 'oldfilename.txt'
to_name = 'newfilename.txt'
commands = f"""
spawn sftp -o "StrictHostKeyChecking no"
{sftp_username}@{destination_hostname}
expect "password:"
send "{sftp_password}\r"
expect "sftp>"
send "rename {from_name} {to_name}\r"
expect "sftp>"
send "bye\r"
expect "#"
"""
sp = subprocess.Popen(['expect', '-c', commands], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
答案 7 :(得分:0)
最安全的方法是事先提示输入密码,然后将其输入命令。提示输入密码将避免将密码保存在代码中的任何位置。这是一个示例:
from getpass import getpass
from subprocess import Popen, PIPE
password = getpass("Please enter your password: ")
proc = Popen("sftp user@server stop".split(), stdin=PIPE)
# Popen only accepts byte-arrays so you must encode the string
proc.communicate(password.encode())
答案 8 :(得分:0)
import subprocess
args = ['command', 'arg1', 'arg2']
proc = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
proc.stdin.write(b'password') ##The b prefix is necessary because it needs a byte type
proc.stdin.flush()
stdout, stderr = proc.communicate()
print(stdout)
print(stderr)
答案 9 :(得分:0)
您只是忘记了密码中的换行符(又名用户按下Enter键)。
from subprocess import Popen, PIPE
proc = Popen(['sftp','user@server', 'stop'], stdin=PIPE)
proc.communicate('password\n'.encode())
也.encode()
,因为默认情况下proc.communicate()
接受类似字节的对象。
答案 10 :(得分:0)
由于某种原因,我在这里无法获得任何标准库答案来为我工作-所有这些都遇到了非常奇怪的问题。这里的其他人:unable to provide password to a process with subprocess [python]遇到了同样的问题,并得出结论,最终,您只需要使用pexpect就能发送密码。
我想在这里添加我的最终代码,以节省任何有类似问题的人的时间,因为我在此上浪费了很多时间(Python 3,2020):
ssh_password = getpass("user's password: ")
ssh_password = (ssh_password + "\n").encode()
scp_command = 'scp xx.xx.xx.xx:/path/to/file.log /local/save/path/'
child = pexpect.spawn(scp_command)
# make output visible for debugging / progress watching
child.logfile = sys.stdout.buffer
i = child.expect([pexpect.TIMEOUT, "password:"])
if i == 0:
print("Got unexpected output: {} {}".format(child.before, child.after))
return
else:
child.sendline(ssh_password)
child.read()
上面的代码运行一个SCP命令,将文件从远程服务器拉到本地计算机上-根据需要更改服务器IP和路径。
要记住的关键事项:
pexpect.TIMEOUT
child.read()
答案 11 :(得分:0)
由于您想要的只是获取文件,因此我尝试使用“子进程”,但它不适用于我。所以现在我正在使用paramiko,这是我的代码: 这是我在网上找到的一个教程 使用python的paramiko将文件从本地服务器传输到远程服务器,反之亦然 “ https://www.youtube.com/watch?v=dtvV2xKaVjw”
下面是我的代码,用于将一个文件夹中的所有文件从Linux传输到Windows
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname='11.11.11.1111', username='root', password='********', port=22)
sftp_client = ssh.open_sftp()
source_folder = '/var/ftp/file_pass'
local_folder = 'C:/temp/file_pass'
inbound_files = sftp_client.listdir(source_folder)
print(inbound_files)
for ele in inbound_files:
try:
path_from = source_folder + '/' + ele
path_to = local_folder + '/'+ ele
sftp_client.get(path_from, path_to)
except:
print(ele)
sftp_client.close()
ssh.close()