pythonpowershellflaskubuntu-17.04

Calling a .ps1 script in Linux Powershell from a Flask route in Python


I'm trying to invoke a .ps1 script in Powershell for Linux by passing a variable and triggering it in reaction to a web call to a Flask/Python API.

All the files are in the same directory in this example - Ideally the .ps1 script and other relevant files to the action it needs to take would be in another directory, but for testing, they're all in the main directory of my venv.

If I run the following code manually, via my_venv >> python script.py

# this is script.py
import subprocess

arg1 = 'xyz'
arg2 = 'abc'

subprocess.run(['pwsh', '.\example.ps1', arg1, arg2])

It will work properly. Powershell will run, and the actions in the script example.ps1 will execute. However, if I add the same Python code to a Flask app route so it can be triggered by an API request like so:

from flask import Flask, request
import subprocess
app = Flask(__name__)
app.debug = True

# example route
@app.route('/example/', methods=['GET'])
def example():

    var1 = request.args.get('var1')
    arg1 = var1
    arg2 = 'abc'

    subprocess.run(['pwsh', '.\example.ps1', arg1, arg2])

    return ('success', 200)

It doesn't do anything. Flask debugging gives me the error:

Exception: builtins.FileNotFoundError: [Errno 2] No such file or directory: 'pwsh'

Which makes me think it's not locating the binary for pwsh but I'm not clear on how to fix that in this situation. In Windows, you'd put the path the the powershell.exe executable in your command, but that's obviously not how it works here.

One note is the variable above - I've tried it without, just letting a value pass to var1 via GET and then ignoring it and hardcoding arg1 to test, makes no difference. The real code does need the variable.

Any obvious dumb thing I'm doing wrong here? This question doesn't seem to have been asked for Linux, although there are some similar Windows questions.


Solution

  • In Windows, it's usually a best-practice to fully path your executables and arguments if you're unsure of the environment variables. You can accomplish this in your example by using

    subprocess.run(['/usr/bin/pwsh', '.\example.ps1', arg1, arg2])
    

    to fully qualify the pwsh executable path in Linux.