使用子进程发送密码

2025-04-10 09:47:00
admin
原创
24
摘要:问题描述:我正在尝试使用 python subprocess 模块登录到安全的 ftp 站点,然后获取文件。但是,当请求密码时,我总是卡在尝试发送密码上。到目前为止,我有以下代码:from subprocess import Popen, PIPE proc = Popen(['sftp','user@se...

问题描述:

我正在尝试使用 python subprocess 模块登录到安全的 ftp 站点,然后获取文件。但是,当请求密码时,我总是卡在尝试发送密码上。到目前为止,我有以下代码:

from subprocess import Popen, PIPE

proc = Popen(['sftp','user@server', 'stop'], stdin=PIPE)
proc.communicate('password')

这仍然会在密码提示处停止。如果我手动输入密码,它会转到 ftp 站点,然后在命令行中输入密码。我见过有人建议使用 pexpect,但长话短说,我需要一个标准库解决方案。有没有使用 subprocess 和/或任何其他 stdlib 的方法?我上面忘记了什么?


解决方案 1:

尝试

proc.stdin.write('yourPassword
')
proc.stdin.flush()

那应该可行。

您所描述的听起来就像stdin=None子进程继承了父进程(您的 Python 程序)的标准输入。

解决方案 2:

from subprocess import Popen, PIPE

proc = Popen(['sftp','user@server', 'stop'], stdin=PIPE)
proc.communicate(input='password')

在通信中尝试使用 input='password',这对我有用。

解决方案 3:

也许您应该使用类似expect的库?

例如Pexpect (示例)。还有其他类似的 Python 库。

解决方案 4:

用于ParamikoSFTP。对于其他任何内容,这有效:

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
')
proc.stdin.flush()

stdout, stderr = proc.communicate()
print stdout
print stderr

解决方案 5:

由于某种原因,我无法让这里的任何标准库答案为我工作 - 所有这些都遇到了非常奇怪的问题。这里的其他人:无法向带有子进程的进程提供密码 [python]遇到了同样的问题,并得出结论,最终你只需要使用 pexpect 就可以发送密码。

我想在这里添加我的最终代码,以节省遇到类似问题的任何人的时间,因为我在这上面浪费了太多时间(Python 3,2020):

ssh_password = getpass("user's password: ")
ssh_password = (ssh_password + "
").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.expect 调用中有一个

  • 必须将传入的字符串编码为字节,并且必须使用默认编码

  • 将 pexpect 输出写入 sys.stdout.buffer,以便您能够真正看到正在发生的事情

  • child.read()最后必须有一个

解决方案 6:

import subprocess

# Replace 'command' with your actual sudo command
command = ['sudo', '-S', 'your_command_here']

# Start the process
process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)

# Pass the password to sudo
sudo_password = 'your_sudo_password_here
'
out, err = process.communicate(sudo_password)

# Print output
print(out)

在此示例中,我们在 sudo 命令中添加了 -S 选项,以指示它从标准输入读取密码。我们还修改了 subprocess.Popen() 调用以包含 universal_newlines=True 参数,该参数指示 subprocess 将输入和输出流视为文本。

请注意,使用 -S 从标准输入读取密码可能存在安全风险,因为这意味着密码将在进程列表和命令历史记录中可见。如果可能,通常最好使用 askpass 帮助程序或将 sudo 配置为不需要您正在运行的特定命令的密码。

解决方案 7:

我建议放弃子进程方法,而使用 paramiko 包进行 sftp 访问。

解决方案 8:

同样的问题困扰了我一个星期。我不得不通过子进程安全地提交用户输入的密码,因为我试图避免引入命令注入漏洞。以下是我在同事的帮助下解决这个问题的方法。

import subprocess

command = ['command', 'option1', '--password']
subprocess.Popen(command, stdin=subprocess.PIPE).wait(timeout=60)

.wait(timeout=int) 是最重要的组件,因为它允许用户将输入提供给 stdin。否则,超时默认为 0,用户没有时间输入,从而导致 None 或空字符串。我花了很长时间才弄清楚这一点。

对于重复使用的情况,如果您知道必须多次执行此操作,则可以重写 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”的事实。

解决方案 9:

这是一个使用 expect(而不是 pexpect)的纯 Python 解决方案。

如果在 Ubuntu 上,你首先需要安装:

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}
"
expect "sftp>"
send "rename {from_name} {to_name}
"
expect "sftp>"
send "bye
"
expect "#"
"""
    sp = subprocess.Popen(['expect', '-c', commands], stdin=subprocess.PIPE, stdout=subprocess.PIPE)

解决方案 10:

因为你想要的只是抓取一个文件,所以我尝试使用“子进程”,但它对我来说不起作用。所以现在我使用 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()

解决方案 11:

Python 有一个名为的内置库ftplib,可以轻松用于 ftp 进程。(假设远程服务器正在运行 ftp 服务)

from ftplib import FTP
ftp = FTP('ftp.us.debian.org')  # connect to host, default port
ftp.login()                     # user anonymous, passwd anonymous@
##'230 Login successful.'
ftp.cwd('debian')               # change into "debian" directory
##'250 Directory successfully changed.'
ftp.retrlines('LIST') 

否则,您可以使用 scp 命令,这是一个命令行工具。可以为远程主机创建无密码用户,从而避免密码问题。

import os
os.system('scp remoteuser@remotehost:/remote/location/remotefile.txt /client/location/')

要在Linux系统中创建无密码用户,请遵循以下步骤。遵循此 SO 答案。

> ssh-keyscan remotehost 
> known_hosts ssh-keygen -t rsa # ENTER toevery field (One time) 
> ssh-copy-id remoteuser@remotehost

解决方案 12:

我刚刚写了这段代码,它在最新版本的 Raspberry Pi OS 上运行良好,使用的是 Python 3.11.2

SUDO_PASSWORD = 'My passw0rd!'

cmd = ['sudo', '-S', 'fxload', '-t', 'fx2', '-D', dev_path, '-I', FIRMWARE]
proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
proc.communicate((SUDO_PASSWORD + '
').encode())

解决方案 13:

最安全的方法是事先提示输入密码,然后将其输入到命令中。提示输入密码将避免将密码保存在代码中的任何地方。以下是示例:

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())

解决方案 14:

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)

解决方案 15:

您只是忘记了密码中的回车键(即用户按下 Enter 键)。

from subprocess import Popen, PIPE

proc = Popen(['sftp','user@server', 'stop'], stdin=PIPE)
proc.communicate('password
'.encode())

.encode()因为默认proc.communicate()接受类似字节的对象。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2482  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1533  
  PLM(产品生命周期管理)项目对于企业优化产品研发流程、提升产品质量以及增强市场竞争力具有至关重要的意义。然而,在项目推进过程中,范围蔓延是一个常见且棘手的问题,它可能导致项目进度延迟、成本超支以及质量下降等一系列不良后果。因此,有效避免PLM项目范围蔓延成为项目成功的关键因素之一。以下将详细阐述三大管控策略,助力企业...
plm系统   0  
  PLM(产品生命周期管理)项目管理在企业产品研发与管理过程中扮演着至关重要的角色。随着市场竞争的加剧和产品复杂度的提升,PLM项目面临着诸多风险。准确量化风险优先级并采取有效措施应对,是确保项目成功的关键。五维评估矩阵作为一种有效的风险评估工具,能帮助项目管理者全面、系统地评估风险,为决策提供有力支持。五维评估矩阵概述...
免费plm软件   0  
  引言PLM(产品生命周期管理)开发流程对于企业产品的全生命周期管控至关重要。它涵盖了从产品概念设计到退役的各个阶段,直接影响着产品质量、开发周期以及企业的市场竞争力。在当今快速发展的科技环境下,客户对产品质量的要求日益提高,市场竞争也愈发激烈,这就使得优化PLM开发流程成为企业的必然选择。缺陷管理工具和六西格玛方法作为...
plm产品全生命周期管理   0  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用