【问题标题】:Password is being used as a command密码被用作命令
【发布时间】:2017-10-04 15:39:32
【问题描述】:

我正在尝试从 python 文件运行命令:

p = subprocess.Popen("mysqldump -h" + hostname + " -u" + mysql_user + " --password=" + mysql_pw + " " + db + " >   dump_" + hostname + "_" + timestamp + ".sql", shell=True)

但是--password= 甚至-p 一直挂断我的密码字符串

密码类似这样的结构:

Z@F&sfeafxegwa

命令行错误:

'sfeafxegwa' is not recognized as an internal or external command,
operable program or batch file.

【问题讨论】:

  • 尝试使用:--password='" + mysql_pw + "' " + db bash 正在解释单个 '&',并将命令的前半部分分叉为自己的进程,然后在后半部分失败。上面提到的将在密码字符串周围添加单引号。
  • 另外,恕我直言,使用格式字符串会更易读。
  • @MattClark 这很有意义,但我仍然遇到错误:'sfeafxegwa' ',这次是额外的' 非常非常真实@tobias_k - 谢谢!
  • shell=True 在存在用户输入参数的情况下是完全不安全和不可靠的。您应该将该命令拆分为一个单独的标志和参数列表,并使用该列表调用subprocess.Popen()shell=False。以这种方式将输出重定向到文件确实变得更加工作,您必须从 Popen 的标准输出中读取并自己用 Python 代码写入文件。
  • 顺便说一句,还要注意在命令行上传递密码根本是一种安全隐患,因为大多数 UNIXy 系统上的用户可以读取彼此的命令行。 mysqldump 也可以通过环境变量获得密码,在现代系统上,这些密码只能由同一用户(或 root,但 root 无论如何都可以看到所有内容)读取;请改用该机制。

标签: python cmd python-3.4


【解决方案1】:

正如 cmets 中已经提到的,不要使用 shell=True。见https://docs.python.org/3/library/subprocess.html#security-considerations

将参数列表直接传递给Popen 构造函数,而不是让shell 进行拆分。

with open('dump_{}_{}.sql'.format(hostname, timestamp), 'w') as dump_file:
    p = subprocess.Popen(
        [
            'mysqldump', '-h', hostname, '-u', mysql_user,
            '--password={}'.format(mysql_pw), db
        ],
        stdout=dump_file
    )

shell=True 的问题在旧版本的文档中得到了更好的解释:https://docs.python.org/2/library/subprocess.html#frequently-used-arguments

【讨论】:

  • 谢谢,这是行之有效的解决方案,似乎与文档最相符。
【解决方案2】:

您需要引用密码以保护shell元字符(例如&)不被shell特殊处理,例如:

cmd = "mysqldump -h {} -u {} -p'{}' {} > dump_{}_{}.sql".format(
    hostname, mysql_user, mysql_pw, db, hostname, timestamp)
subprocess.run(cmd, shell=True, check=True)

但是,如果密码本身可以包含引号,这将不起作用。更好的选择是将参数 list 传递给 subprocess 并自己进行重定向:

args = ["mysqldump", "-h", hostname, "-u", mysql_user, "-p{}".format(mysql_pw), db]
outfile = "dump_{}_{}.sql".format(hostname, timestamp)

with open(outfile, "w") as f:
    subprocess.run(args, check=True, stdout=f)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-13
    • 1970-01-01
    相关资源
    最近更新 更多