powershellpowershell-jobs

How to insert user inputs in powershell jobs?


I have a PowerShell script which starts a background job (it does port-forwarding using kubectl):

$forwardjob = Start-Job -ScriptBlock{kubectl port-forward service/db 7125:7125} -Name "Database Port-Forwarder"

This works fine, however every so often kubectl asks for credentials. I am wondering how I could capture and insert some user input in that case?

My idea with the following additional two lines was to wait some time until we have a response for sure, then check the result and if there is a prompt for a password, simply enter it. However, at that point, the job always results in an error (due to the missing input) and the job is completed.

$forwardjob = Start-Job -ScriptBlock{kubectl port-forward service/db 7125:7125} -Name "Database Port-Forwarder"
Start-Sleep -Milliseconds 1000
$result = Receive-Job -Job $forwardjob

So, the question is how can one capture a input prompt and enter it correctly?


Solution

  • The only way to respond to interactive prompts presented by an external program in the context of Start-Job (a PowerShell background job) is to send all responses ahead of time, via the pipeline.

    This is the same technique you'd use to automate responses to the interactive prompts of external programs in direct invocation. However, note that - unlike in direct invocation - you fundamentally cannot respond to interactive prompts interactively when using background jobs.

    That is:

    Note that external programs may (sensibly) print their prompt messages directly to the terminal (e.g., Enter your password: ), which means that they will not show up in what the background job captures and outputs via Receive-Job.

    Here are self-contained, platform-specific examples that show the technique: they use the platform-native shell to simulate some processing, then prompt for a "password" and echo the response, which is provided up front via PowerShell's pipeline: Perhaps needless to say, providing plain-text passwords this way is a security risk.

    'somepassword' | 
      Start-Job { cmd /v /c 'echo doing things... & powershell -NoProfile sleep 2  & set /p pass=Enter^ password: & echo You entered: !pass!' } |
      Receive-Job -AutoRemoveJob -Wait
    
    'somepassword' |
      Start-Job { bash -c 'echo doing things...; sleep 2; read -p ''Enter password: '' pass; echo You entered: $pass' } |
      Receive-Job -AutoRemoveJob -Wait