【问题标题】:How to source script via python如何通过python获取脚本
【发布时间】:2016-04-18 23:32:45
【问题描述】:

我可以像终端中的 bash 命令一样轻松获取 bash 脚本(没有 shebang),但尝试通过 python 命令执行相同操作

sourcevars = "cd /etc/openvpn/easy-rsa && . ./vars"
runSourcevars = subprocess.Popen(sourcevars, shell = True)

sourcevars = [". /etc/openvpn/easy-rsa/vars"]
runSourcevars = subprocess.Popen(sourcevars, shell = True)

我收到:

请首先获取 vars 脚本(即“source ./vars”) 确保您已对其进行编辑以反映您的配置。

怎么了,如何正确地做到这一点?我在这里阅读了一些主题,例如here,但使用给定的建议无法解决我的问题。请举例说明。

更新:

# os.chdir = ('/etc/openvpn/easy-rsa')
initvars = "cd /etc/openvpn/easy-rsa && . ./vars && ./easy-rsa ..."


# initvars = "cd /etc/openvpn/easy-rsa && . ./vars"
# initvars = [". /etc/openvpn/easy-rsa/vars"]
cleanall = ["/etc/openvpn/easy-rsa/clean-all"]
# buildca  = ["printf '\n\n\n\n\n\n\n\n\n' | /etc/openvpn/easy-rsa/build-ca"]
# buildkey = ["printf '\n\n\n\n\n\n\n\n\n\nyes\n ' | /etc/openvpn/easy-rsa/build-key AAAAAA"]
# buildca  = "cd /etc/openvpn/easy-rsa && printf '\n\n\n\n\n\n\n\n\n' | ./build-ca"
runInitvars = subprocess.Popen(cmd, shell = True)
# runInitvars = subprocess.Popen(initvars,stdout=subprocess.PIPE, shell = True, executable="/bin/bash")
runCleanall = subprocess.Popen(cleanall , shell=True)

# runBuildca = subprocess.Popen(buildca , shell=True)
# runBuildca.communicate()
# runBuildKey = subprocess.Popen(buildkey, shell=True )

更新 2

buildca  = ["printf '\n\n\n\n\n\n\n\n\n' | /etc/openvpn/easy-rsa/build-ca"]
runcommands = subprocess.Popen(initvars+cleanall+buildca, shell = True)

【问题讨论】:

  • 您从那些 sn-ps 或之后的某些 other 调用中得到了那个错误?因为这些应该可以正常工作,但只会对该 一个 shell 实例有效,不会影响以后的 shell 实例或正在运行的 python 脚本/环境。
  • 通常我需要运行一组命令,其中显示的是第一个命令并从一开始就出现此错误
  • 您只需要在一个 subprocess.Popen 实例中运行所有命令,因为它们的范围仅限于一个 shell。
  • 顺便说一句,在赋值中应该在=s 周围使用空格,但不能在参数列表中使用空格。见python.org/dev/peps/pep-0008/#other-recommendations
  • 您显示的示例(并感谢您对其进行编辑)没有按照我的建议执行,尽管有相反的说法:它仍在单独运行您的 cleanall 命令运行 initvars 的 shell。

标签: python bash


【解决方案1】:

这本身绝对没有错:

# What you're already doing -- this is actually fine!
sourcevars = "cd /etc/openvpn/easy-rsa && . ./vars"
runSourcevars = subprocess.Popen(sourcevars, shell=True)

# ...*however*, it won't have any effect at all on this:
runOther = subprocess.Popen('./easy-rsa build-key yadda yadda', shell=True)

但是,如果您随后尝试运行第二个subprocess.Popen(..., shell=True) 命令,您会发现它没有任何通过采购该配置设置的变量。

这是完全正常的预期行为:使用source 的全部意义在于修改活动shell 的状态;每次使用shell=True 创建一个新的Popen 对象时,它都会启动一个新的shell——它们的状态不会被延续。

因此,合并为一个调用:

prefix = "cd /etc/openvpn/easy-rsa && . ./vars && "
cmd = "/etc/openvpn/easy-rsa/clean-all"
runCmd = subprocess.Popen(prefix + cmd, shell=True)

...这样您就可以在与实际获取脚本相同的 shell 调用中使用获取脚本的结果。


或者(这就是我要做的),要求您的 Python 脚本由一个在其环境中已经具有必要变量的 shell 调用。因此:

# ask your users to do this
set -a; . ./vars; ./yourPythonScript

...如果人们不那么容易做到这一点,您可能会出错:

import os, sys
if not 'EASY_RSA' in os.environ:
    print >>sys.stderr, "ERROR: Source vars before running this script"
    sys.exit(1)

【讨论】:

  • 我已经按照你的建议做了,现在也做了,但仍然出现同样的错误(
  • easy-rsa ... 本来是一个占位符,供您替换为您的全部脚本等。我认为这从上下文中是显而易见的。
  • 非常感谢您的详细解释!似乎组合命令(前缀+ cmd)有效,最后我没有收到错误,但是如何在用户提示下附加下一个命令以按Enter?如果我只是通过“+”将它添加到语句中,它不起作用!
  • 您需要显示确切的命令。如果您使用我在上一个问题中建议的机制来避免任何提示,那么这将没有实际意义。 :)
  • 您不能像这样使用+ 直接加入它们,因为cleanall 和buildca 之间没有&&。这就是为什么我提出了一种方法,可以在我对问题的评论中自动添加这些分隔符。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-06
  • 2016-02-06
  • 2021-03-11
  • 2011-02-12
  • 1970-01-01
  • 2015-06-13
  • 1970-01-01
相关资源
最近更新 更多