【问题标题】:Getting permission denied error when executing a command via subprocess.Popen but not in shell通过 subprocess.Popen 但不在 shell 中执行命令时获取权限被拒绝错误
【发布时间】:2019-03-07 07:59:53
【问题描述】:

我正在尝试将一个文件夹移动到另一个文件夹,但是当我尝试在 Python 脚本中执行此操作时出现 Permission Denied 错误,而当我在 bash 甚至 Python 交互模式下运行它时移动成功。

cmd = ['sudo', 'mv', '/path1/dir', '/path2']
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
if p.returncode != 0:
     print(stderr)    

我也尝试添加 shell=True。

p = subprocess.Popen(' '.join(cmd), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
if p.returncode != 0:
     print(stderr)

在这两种情况下,我都会收到以下错误:

 "mv: cannot move '/path1/dir' to '/path2/dir': Permission denied\n"

我以以下方式调用我的脚本:

sudo python script.py

我尝试在 shell 以及 Python 交互模式下执行每个命令,但没有收到任何错误。知道这里发生了什么吗?

【问题讨论】:

  • mv 是一个 shell 命令,尝试通过默认 shell 执行它:cmd = ['sudo', '-s', 'mv', '/path1/dir', '/path2']。问题是 - 既然您已经以超级用户身份执行 Python 脚本,为什么还要借助子进程来移动文件 - 只需直接通过 Python 执行(例如,检查 shutil 模块)。
  • 如果没有 sudo,它会抛出 Permission Denied 错误。当你说默认 shell 时,你的意思是不做 shell=True 吗?
  • 目前,无论是否使用 sudo,都会引发 Permission Denied 错误。我认为添加 sudo 会有所帮助。
  • 不,只需将 -s 添加到命令列表中,就像我在第一条评论中输入的那样 - 这将告诉 sudo 以超级用户身份运行 shell 进程,然后执行移动命令它。但是,如果您将 Python 脚本作为 sudoer 运行,则根本不需要子进程 - shutil.move() 应该就可以了。
  • 我尝试删除 sudo 并在 sudo 之后添加 -s。都没有奏效。 shutil 是我唯一的选择吗?

标签: python subprocess sudo mv


【解决方案1】:

在浪费了几个小时调试出了什么问题之后,我终于弄清楚了发生了什么。我正在使用 tempfile 创建/path1 和/path2。这是代码的sn-p:

class UtilitiesTest(unittest.TestCase):
    @staticmethod
    def createTestFiles():
        dir = tempfile.mkdtemp()
        _, file = tempfile.mkstemp(dir=dir)
        return dir, file

    def test_MoveFileToAnotherLocation(self):
        src_dir, src_file = UtilitiesTest.createTestFiles()
        dest_dir, dest_file = UtilitiesTest.createTestFiles()
        cmd = ['sudo', 'mv', src_dir, dest_dir]
        p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        stdout, stderr = p.communicate()
        if p.returncode != 0:
             print(stderr)

就像 zwer 在 cmets 中所说,如果我使用 sudo 运行这个脚本,我不需要在我的 mv 命令中添加 sudo。因为我不断收到权限被拒绝的错误,所以我一直认为 sudo 会解决我的问题。这里的实际问题是当 tempfile.mkstemp() 被调用时,它会返回一个 open 文件描述符以及文件路径。第一个参数我并没有太在意,所以当我将我的 createTestFiles() 修改为下面时,一切都开始工作了。

    @staticmethod
    def createTestFiles():
        dir = tempfile.mkdtemp()
        fd, file = tempfile.mkstemp(dir=dir)
        os.close(fd)
        return dir, file

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-02
    • 1970-01-01
    • 2020-02-03
    • 1970-01-01
    相关资源
    最近更新 更多