1

I can source bash script (without shebang) easy as bash command in terminal but trying to do the same via python command

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

or

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

I receive :

Please source the vars script first (i.e. "source ./vars") Make sure you have edited it to reflect your configuration.

What's the matter, how to do it correctly?I've read some topics here,e.g here but could not solve my problem using given advices. Please explain with examples.

UPDATED:

# 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 )

UPDATE 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)
Community
  • 1
  • 1
Andriy
  • 311
  • 1
  • 7
  • 19
  • You get that error from those snippets or from some *other* call after that? Because those should work fine but will only be in effect for that **one** shell instance and will not affect later shell instances or the running python script/environment. – Etan Reisner Jan 13 '16 at 20:21
  • Generally I need to run set of commands where shown is the first one and get this error from very beginning – Andriy Jan 13 '16 at 20:28
  • You need to run all the commands in just one `subprocess.Popen` instance, since they're scoped to a single shell. – Charles Duffy Jan 13 '16 at 21:20
  • BTW, spaces should be used around `=`s in assignments, but not argument lists. See https://www.python.org/dev/peps/pep-0008/#other-recommendations – Charles Duffy Jan 13 '16 at 21:24
  • Your example shown (and thank you for editing it in) *doesn't* do as I recommended, contrary claim notwithstanding: It's still running your `cleanall` command in a separate shell from where you ran `initvars`. – Charles Duffy Jan 13 '16 at 21:34
  • `runCleanall = subprocess.Popen(' && '.join([initvars] + cleanall))` would be a little closer. – Charles Duffy Jan 13 '16 at 21:36
  • That said, why are you doing this in the first place? I mean, the impedence mismatch between Python and shell is making your life much harder and buying you no advantage over either using easy-rsa directly from shell or using a native Python CA library. – Charles Duffy Jan 13 '16 at 21:37

1 Answers1

4

There's absolutely nothing wrong with this in and of itself:

# 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)

However, if you subsequently try to run a second subprocess.Popen(..., shell=True) command, you'll see that it doesn't have any of the variables set by sourcing that configuration.

This is entirely normal and expected behavior: The entire point of using source is to modify the state of the active shell; each time you create a new Popen object with shell=True, it's starting a new shell -- their state isn't carried over.

Thus, combine into a single call:

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

...such that you're using the results of sourcing the script in the same shell invocation as that in which you actually source the script.


Alternately (and this is what I'd do), require your Python script to be invoked by a shell which already has the necessary variables in its environment. Thus:

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

...and you can error out if people don't do so very easy:

import os, sys
if not 'EASY_RSA' in os.environ:
    print >>sys.stderr, "ERROR: Source vars before running this script"
    sys.exit(1)
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • I have done like you recommend early and did it now but still get same error( – Andriy Jan 13 '16 at 21:29
  • `easy-rsa ...` was meant to be a placeholder for you to replace with your clean-all script or such. I thought this was obvious from the context. – Charles Duffy Jan 13 '16 at 21:39
  • Thank you very much for your detailed explanation! seems combined command (prefix + cmd) works and at last I didn't get error but how to attach next command with user prompt to press enter? If I simply add it to statement via "+" it doesn't work! – Andriy Jan 13 '16 at 22:16
  • You'll need to show the exact command. If you were using the mechanisms I suggested in your prior question to avoid any prompting, this would be moot. :) – Charles Duffy Jan 13 '16 at 22:18
  • You can't use `+` to join them directly like that because there's no `&&` between cleanall and buildca. That's why I suggested an approach that would automatically add those separators in my comment on the question. – Charles Duffy Jan 13 '16 at 22:32
  • Also, why are you using the pipeline and ignoring the answer I gave you elsewhere (showing how to provide the newlines on stdin from your Python code), *and* ignoring the suggestion to use `-batch` to prevent openssl from prompting at all? – Charles Duffy Jan 13 '16 at 22:32
  • ...you could also use `prefix + cleanall` as one command, and `prefix + buildca` as another. (Need to make `cleanall` and `buildca` strings, not arrays, but that's a separate discussion). – Charles Duffy Jan 13 '16 at 22:34
  • I get all variables from user and insert them in vars, thats why I guess no need to edit openssl(btw, whitch of them,I have 3 ).I try to follow your recommendations but not sure I clear understand what to do (. – Andriy Jan 13 '16 at 22:44
  • I run prefix + cleanall and prefix + buildca as two separate commands and it works!Thanks again! – Andriy Jan 13 '16 at 22:49