【问题标题】:python3 - subprocess with sudo to >> append to /etc/hostspython3 - 带有 sudo 的子进程 >> 附加到 /etc/hosts
【发布时间】:2015-06-08 21:32:36
【问题描述】:

我一直在努力解决“How do I use sudo to redirect output to a location I don't have permission to write to?”和“append line to /etc/hosts file with shell script”的解决方案,但没有成功。

我想在 /etc/hosts 的末尾“追加 10.10.10.10 puppetmaster”。 (Oracle/Red-Hat linux)。

一直在尝试以下变化:

subprocess.call("sudo -s", shell=True)

subprocess.call('sudo sh -c" "10.10.10.10 puppetmaster" >> /etc/hosts"', shell=True)

subprocess.call(" sed -i '10.10.10.10 puppetmaster' /etc/hosts", shell=True)

但是 /etc/hosts 文件静止不动。 有人可以指出我做错了什么吗?

【问题讨论】:

  • 为什么不直接使用 python 追加到文件中?
  • 坦率地说,我是 python 新手(来自 java 背景)。有一种方法可以在不调用 bash shell 的情况下使用 python 追加?我会查一下这个。谢谢。
  • 是的,就是用sudo运行脚本,我加了两行代码

标签: python subprocess


【解决方案1】:

只需使用dd:

subprocess.Popen(['sudo', 'dd', 'if=/dev/stdin',
    'of=/etc/hosts', 'conv=notrunc', 'oflag=append'],
    stdin=subprocess.PIPE).communicate("10.10.10.10 puppetmaster\n")

【讨论】:

  • 不错!根本没有贝壳。
  • ...虽然没有必要,因为 OP 以 root 身份运行脚本,所以他们可以直接打开输出文件进行追加,根本不需要 sudo
【解决方案2】:

使用 sudo 运行脚本后,您可以在 python 中轻松完成:

with open("/etc/hosts","a") as f:
    f.write('10.10.10.10 puppetmaster\n')

a 开头将追加。

【讨论】:

  • OP 是否要提升整个脚本的权限?我们不知道它的某些部分是否处理不受信任的数据等。
  • @CharlesDuffy,如果 OP 是编写脚本的人,将会发生什么?
  • 我打算做“sudo ./script”或以root身份
  • @PadraicCunningham,这取决于脚本的其他功能:)
  • 顺便说一句,你这里不是少了一个换行符吗?
【解决方案3】:

您面临的问题在sudo 的范围内。

您正在尝试使用参数sh-c" "10.10.10.10 puppetmaster" 调用sudo 的代码。但是,>> 运算符的重定向是由周围的 shell 完成的,当然还有它的权限。

为了达到你想要的效果,尝试使用 sudo 启动一个 shell,然后给出命令:

sudo bash -c 'sh -c" "10.10.10.10 puppetmaster" >> /etc/hosts"'

这可以解决问题,因为您以sudo 开头的bash 具有超级用户权限,因此当它尝试使用>> 执行输出重定向时不会失败。

要在 Python 中执行此操作,请使用以下命令:

subprocess.call("""sudo bash -c 'sh -c" "10.10.10.10 puppetmaster" >> /etc/hosts"'""", shell=True)

当然,如果您已经使用超级用户权限运行 Python 脚本(以 sudo 开始),则所有这些都不是必需的,原始代码将可以工作(在 call 中没有额外的 sudo ):

subprocess.call('sh -c" "10.10.10.10 puppetmaster" >> /etc/hosts"', shell=True)

【讨论】:

  • 这似乎...与shell=False 版本相比,它非常复杂且容易出错,只有一个shell 作为sudo 的子进程运行。
  • 你是对的。我主要解释了sudo>> 效果以及如何处理它。具体情况需要更简单的解决方案。
【解决方案4】:

如果您没有升级整个脚本的权限,我建议您执行以下操作:

p = subprocess.Popen(['sudo', 'tee', '-a', '/etc/hosts'],
                     stdin=subprocess.PIPE, stdout=subprocess.DEVNULL)
p.stdin.write(b'10.10.10.10 puppetmaster\n')
p.stdin.close()
p.wait()

然后您可以将任意内容写入进程的标准输入 (p.stdin)。

【讨论】:

  • "sudo ./charles.py" 导致 {Traceback (最近一次调用最后): File "./charles.py", line 8, in p.stdin.write(' 10.10.10.10 puppetmaster\n') TypeError: a bytes-like object is required, not 'str'} 我做错了吗?
  • @SndLt: subprocess 默认使用字节。使用字节文字:b'10...'。顺便说一句,您可以使用 p.communicate(b'10.10.10.10 puppetmaster\n') 而不是代码示例中的最后 3 行。另外,使用stdout=DEVNULL(看来您使用的是Python 3)并且不需要shell=False(这是默认设置)。
  • @SndLt,...J.F.塞巴斯蒂安所说的。您做错的唯一一件事是在您的问题中没有明确指出这是 Python 3 而不是 Python 2。
  • @Charles Duffy,我明白了。所以如果我想在 python3 中运行这个标准输入,只需将标准输出设置为空?或使用 p.communicate 而不是最后 3 行?谢谢。
  • @SndLt,好吧,如果您将字符串设置为字节字符串而不是 Unicode 字符串,那么最后三行将按原样工作,您可以使用communicate() . (那里可能也需要一个字节串;我需要检查文档——就像现实世界中大多数编写商业软件一样,我仍在使用 Python 2)。
猜你喜欢
  • 1970-01-01
  • 2014-12-13
  • 2013-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-20
  • 2011-07-05
  • 1970-01-01
相关资源
最近更新 更多