【问题标题】:Returning file or directory not found, but no file or directory mentioned in bash command?返回文件或目录未找到,但 bash 命令中未提及文件或目录?
【发布时间】:2015-07-15 14:09:08
【问题描述】:

我正在尝试使用给定的特定命令从数据库中转储信息。

 db_dump = open('{}/dbdump.txt'.format(directory_name), 'w+')
    foo = subprocess.call('PGPASSWORD="-------" pg_dump -h vm-postgres -d "qa-test{}db" -U "qatest" -a -x'.format(str(driverlabelnum)), shell=True)
    print str(foo)
    db_dump.write(foo)
    db_dump.close()
    print "Done dumping"

当我将它复制粘贴到命令行时它工作得很好,但是当我尝试通过 subprocess.call() 自动化它时出现错误。

我尝试了几种不同的方法,但我一直遇到这个错误......

    Traceback (most recent call last):
  File "/home/csd-user/test/libs/utils/butler.py", line 427, in <module>
    main()
  File "/home/csd-user/test/libs/utils/butler.py", line 424, in main
    b.log_bug_exec(url)
  File "/home/csd-user/test/libs/utils/butler.py", line 52, in log_bug_exec
    cls.process_file(stdout)
  File "/home/csd-user/test/libs/utils/butler.py", line 109, in process_file
    cls.create_artifacts(nums[0], nums[1])
  File "/home/csd-user/test/libs/utils/butler.py", line 269, in create_artifacts
    foo = csd_shell_lib.check_output('PGPASSWORD="-------" pg_dump -h vm-postgres -d "qa-test{}db" -U "qatest" -a -x'.format(str(driverlabelnum)))
  File "/home/csd-user/test/libs/jupiter/csd_shell_lib.py", line 70, in check_output
    return subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT)
  File "/opt/cs/lib/python2.7/subprocess.py", line 566, in check_output
    process = Popen(stdout=PIPE, *popenargs, **kwargs)
  File "/opt/cs/lib/python2.7/subprocess.py", line 710, in __init__
    errread, errwrite)
  File "/opt/cs/lib/python2.7/subprocess.py", line 1335, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

我知道 subprocess.call 命令将命令拆分为substrings(.split(' ')) 的数组/列表,并且它本身正在调用 PGPASSWORD=""。但是,我不知道如何避免这种情况发生,也无法在网上找到。

附:我遇到的另一个问题是 Errno 13 权限被拒绝,Paramiko 试图 .get 一个文件。我不知道/理解如何在没有程序提示我输入密码的情况下以susudo 登录(仅使用单数 paramiko 命令)(我可以使用 ssh 来完成,但我不想这样做) .

【问题讨论】:

  • 什么是完整的回溯?

标签: python linux bash subprocess paramiko


【解决方案1】:

PGPASSWORD 是一个环境变量。当您必须提供特定的环境变量时,您不能使用 subprocess.call 。您可以改用 subprocess.Popen 并传递环境变量as a dedicated parameter

import os, subprocess
env = os.environ.copy()
env['PGPASSWORD'] = '------'
subprocess.Popen('pg_dump -h vm-postgres -d "qa-test{}db" -U "qatest" -a -x'.format(str(driverlabelnum)), env=env, shell=True)

【讨论】:

  • 谢谢伙计,效果很好。我可以将多个环境变量传递给 Popen 命令吗?谢谢! @devunt
  • @Ian 是的。只需在调用 Popen() 之前将更多项目添加到 env 字典中,例如 env['ANOTHER'] = 'VALUE'
【解决方案2】:

回溯说您的特定错误是由于csd_shell_lib.check_output() 中的cmd.split():您不应该在空格上拆分任意shell 命令。尽管在这种情况下即使shlex.split() 也不起作用,因为第一项设置了一个环境变量。

直接使用subprocess 模块,将shell命令作为字符串传递:

cmd = 'PGPASSWORD="-------" pg_dump -h vm-postgres -d "qa-test{}db" -U qatest -a -x'.format(driverlabelnum)
output = subprocess.check_output(cmd, shell=True)

或者(更好)手动拆分命令并删除shell=True

#!/usr/bin/env python
import os
import subprocess

with open(os.path.join(directory_name, 'dbdump.txt'), 'wb', 0) as db_dump:
    subprocess.check_call(['pg_dump', '-h', 'vm-postgres',
                           '-d', 'qa-test{}db'.format(driverlabelnum),
                           '-U', 'qatest', '-a', '-x'],
                           env=dict(os.environ, PGPASSWORD="-------"),
                           stdout=db_dump)
print("Done dumping")

注意:

  • check_call() 用于在 pg_dump 失败时引发异常
  • stdout=db_dump 用于将pg_dump 的输出直接重定向到文件而不加载到内存中
  • 没有shell=True
  • -d-U 值周围没有引号
  • 没有不必要的str()电话
  • dict(os.environ, PGPASSWORD="-------")用于为子进程创建环境dict

如果需要,添加 stderr=subprocess.STDOUT 以将 stderr 重定向到 stdout(因此将其与其余数据一起转储到文件中)。

【讨论】:

    猜你喜欢
    • 2021-12-19
    • 1970-01-01
    • 2017-09-18
    • 2021-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-04
    相关资源
    最近更新 更多