【Azure Function App】Python Function呼叫Powershell指令碼在Azure上執行失敗的案例

路邊兩盞燈發表於2023-10-07

問題描述

編寫Python Function,並且在Function中透過 subprocess  呼叫powershell.exe 執行 powershell指令碼。

import azure.functions as func
import logging
import subprocess


app = func.FunctionApp(http_auth_level=func.AuthLevel.FUNCTION)

def run(cmd):
    completed = subprocess.run(["powershell", "-Command", cmd], capture_output=True)
    return completed

@app.route(route="http_trigger")
def http_trigger(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')

    name = req.params.get('name')
    if not name:
        try:
            req_body = req.get_json()
        except ValueError:
            pass
        else:
            name = req_body.get('name')

    hello_command = "Write-Host 'Hello Wolrd!"+name+"'"
    hello_info = run(hello_command)
    if hello_info.returncode != 0:
        logging.info("An error occured: %s", hello_info.stderr)
    else:
        logging.info("Hello command executed successfully!")
    
    logging.info("-------------------------")

    logging.info(str(hello_info.stdout))

    if name:
        return func.HttpResponse(f"Hello, {name}. This HTTP triggered function executed successfully.")
    else:
        return func.HttpResponse(
             "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.",
             status_code=200
        )
    

本地測試環境為Windows,執行成功!

【Azure Function App】Python Function呼叫Powershell指令碼在Azure上執行失敗的案例

當透過VS Code部署到Azure Function App後,在門戶上呼叫就出現 500 Internal Server Error 錯誤。

【Azure Function App】Python Function呼叫Powershell指令碼在Azure上執行失敗的案例

這是什麼情況呢?

 

問題解答

檢視Azure Function的後臺日誌,進入Kudu站點(https://<your function app name>.scm.chinacloudsites.cn/newui), 檢視 Logfiles/Application/Functions/Function/<your function name>/xxxxxxx_xxxxx.log

【Azure Function App】Python Function呼叫Powershell指令碼在Azure上執行失敗的案例

2023-10-07T11:32:41.605 [Information] Executing 'Functions.http_trigger' (Reason='This function was programmatically called via the host APIs.', Id=353799e7-fb4f-4ec9-bb42-ed2cafbda9da)
2023-10-07T11:32:41.786 [Information] Python HTTP trigger function processed a request.
2023-10-07T11:32:41.874 [Error] Executed 'Functions.http_trigger' (Failed, Id=353799e7-fb4f-4ec9-bb42-ed2cafbda9da, Duration=275ms)
Result: Failure
Exception: FileNotFoundError: [Errno 2] No such file or directory: 'powershell'
Stack:   File "/azure-functions-host/workers/python/3.11/LINUX/X64/azure_functions_worker/dispatcher.py", line 479, in _handle__invocation_request
    call_result = await self._loop.run_in_executor(
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/concurrent/futures/thread.py", line 58, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/azure-functions-host/workers/python/3.11/LINUX/X64/azure_functions_worker/dispatcher.py", line 752, in _run_sync_func
    return ExtensionManager.get_sync_invocation_wrapper(context,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/azure-functions-host/workers/python/3.11/LINUX/X64/azure_functions_worker/extension.py", line 215, in _raw_invocation_wrapper
    result = function(**args)
             ^^^^^^^^^^^^^^^^
  File "/home/site/wwwroot/function_app.py", line 26, in http_trigger
    hello_info = run(hello_command)
                 ^^^^^^^^^^^^^^^^^^
  File "/home/site/wwwroot/function_app.py", line 9, in run
    completed = subprocess.run(["powershell", "-Command", cmd], capture_output=True)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/subprocess.py", line 548, in run
    with Popen(*popenargs, **kwargs) as process:
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/subprocess.py", line 1026, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/usr/local/lib/python3.11/subprocess.py", line 1950, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)

發現異常 “ Exception: FileNotFoundError: [Errno 2] No such file or directory: 'powershell' ”,

進入Kudu的Bash 或 SSH 頁面,透過powershell 和 pwsh 命令,驗證當前環境是否有安裝PowerShell

【Azure Function App】Python Function呼叫Powershell指令碼在Azure上執行失敗的案例

因為Azure中建立的Python Function均為Linux系統,而Linux中沒有安裝Powershell,所以才出現Python程式碼中呼叫Python失敗。

那是否可以自己在Function App的環境中安裝Powershell呢? 答案不可以。

【Azure Function App】Python Function呼叫Powershell指令碼在Azure上執行失敗的案例

那是否有其他的方案呢?

有的,Azure Function可以建立Powershell Function,把PowerShell作為一個HTTP Trigger的Function,在Python Function中呼叫Powershell Function的URL,就可以實現在Azure上呼叫PowerShell的目的。

【Azure Function App】Python Function呼叫Powershell指令碼在Azure上執行失敗的案例

 

 

參考資料

Installing PowerShell on Ubuntu : https://learn.microsoft.com/en-us/powershell/scripting/install/install-ubuntu?view=powershell-7.3

在 Azure 中使用 Visual Studio Code 建立 PowerShell 函式:https://docs.azure.cn/zh-cn/azure-functions/create-first-function-vs-code-powershell

在 Azure 中使用 Visual Studio Code 建立 Python 函式 : https://docs.azure.cn/zh-cn/azure-functions/create-first-function-vs-code-python?pivots=python-mode-configuration

 

相關文章