Powershell Invoke-Command remotely with -AsJob failed to launch remote program - powershell

I want to launch a long-running remote program but don't want to wait. So I put below one line command in PS script file and run "Powershell -file xxx.ps1"
Invoke-command server1 {xxx.exe} -AsJob
But the remote program is not running after the script run, but if I run above command in PS console interactively, remote program running ok. Seems the program is killed when script terminates.
Why is this?
UPDATE
If I sleep 1 second at end of script, the remote app running fine.

The best way around this is probably to use Wait-Job. It will wait for the job you launched until it's done. Otherwise the script just closes, probably before the connection has already been made completely.
If you want to wait for all jobs running in the background to be completed, you can use:
Invoke-command server1 {xxx.exe} -AsJob
Get-Job | Wait-Job

Related

PowerShell batch script Timeout ERROR: Input redirection is not supported, exiting the process immediately

I need to have a timeout in powershell code where I'm running batch file, in case the batch file runs for a longer time or gets stuck. I also have a timeout in the batch script timeout 300> nul from which I seem to be getting this error and it is just skipping through the timeout and executing next lines. I do not get this error if I remove the timeout from batch script. But I need timeouts at both places, how do I resolve this ?
Error- ERROR: Input redirection is not supported, exiting the process immediately.
PS Code-
$bs={
cd D:\files\
cmd.exe /c "mybatchfile.bat"
}
$timeoutseconds=800
$j=Start-Job -Scriptblock $bs
if(wait-Job $j -Timeout $timeoutseconds) {Receive-Job $j}
Remove-Job -force $j
batch script is something like this
cmd1
cmd2
timeout 300> nul
cmd3
Whenever timeout.exe detects that its stdin input is redirected (not attached to a console), it aborts with the error message you saw.
Because of how background jobs launched with Start-Job are implemented, whatever external processes you run from the job's script block invariably see stdin as redirected, so you won't be able to call timeout.exe.[1]
Your best bet is to use thread-based background jobs, where this problem doesn't arise:
Start-ThreadJob runs your script block in a separate thread in the same process, and stdin redirection isn't involved; also, because no new PowerShell (child) process must be started, thread jobs are faster to create and require fewer resources.
Start-ThreadJob is part of the ThreadJob module, which comes with PowerShell (Core) 7+, and can be installed on demand in Windows PowerShell (e.g., with Install-Module -Scope CurrentUser ThreadJob)
Since Start-ThreadJob also integrates with PowerShell's job-management infrastructure and shares the core parameter syntax with Start-Job, all that should be necessary is to replace Start-Job with Start-ThreadJob in your code.
[1] Unless there is a way to reattach stdin to the console in a timeout.exe call - I'm not aware of such a feature, however (<CON creates an Access denied error).
you might be intersted to add a delay in another way, one alternative is to wait with:
REM # waits a delay before refresh status of service
ping localhost
Indeed i had similar issue on remote powershell issue in a scenario where gitlab agent install script on remote server. by replacing timeout with ping the script do not finish anymore with an error.
My tech youtube channel in my profile

Remote Powershell script causes Selenium to timeout

When I use Invoke-Command from a Powershell script to run an .exe that uses Selenium Chromedriver, the execution of my .exe hangs until I get a timeout exception.
I have tried running the .exe with a local Powershell command, and it works just fine every time. It is only when I use Invoke-Command that the .exe stops working. Is there any way to actually run powershell scripts remotely, without Invoke-Command because Invoke-Command doesn't seem to be doing what I want it to.
I've also tried to -Wait the process of the .exe but it still hangs.

Returning success and then restarting computer

I'm integrating Jenkins with a bunch of stuff and im using powershell to do this. I have a script on a remote machine that is executed after a build is successful on jenkins. This script does a bunch of stuff and then will restart the machine.
What i need to do is:
Return to jenkins that the script was successful (meaning that it will end the job as SUCCESS)
Then restart the machine
So far i have not managed to send 'EXIT 0' to jenkins and then restart the machine. There's anyway to do this?
Thanks in advance.
Code example:
Write-Host "Code example"
Exit 0 #for jenkins success
Restart-Computer -Force
This will host a seperate command prompt that runs async from the powershell script and restarts the computer in 3 seconds, enough time for powershell to return the exit code to jenkins.
Start-Process -FilePath "cmd.exe" -ArgumentList '/c "timeout /t 3 /nobreak && shutdown -r -f -t 0"' -WindowStyle Hidden
Exit 0
As noted in a comment by #Avshalom, your problem is that the Exit statement will unconditionally exit your script without ever executing the Restart-Computer command placed after it.
Restart-Computer, when executed locally, is invariably asynchronous, so your script will continue to execute, at least for a while.
You can therefore try to call Restart-Computer first, and exit 0 afterwards:
Write-Host "Code example"
Restart-Computer -Force
exit 0 # for Jenkins success
However, there's no guarantee that control will return to Jenkins in time and that Jenkins itself will have time to process the successful exit before it is shut down itself.
You can improve the likelihood of that with a delay, via a separate, asynchronously launched PowerShell instance[1], similar to the approach in Evilcat's answer:
Write-Host "Code example"
# Asynchronously start a separate, hidden PowerShell instance
# that sleeps for 5 seconds before initiating the shutdown.
Start-Process -WindowStyle Hidden powershell.exe -Args '-command',
'Start-Sleep 5; Restart-Computer -Force'
exit 0 # for Jenkins success
This still isn't a fully robust solution, however; a fully robust solution requires changing your approach:
Let your script indicate success only, without initiating a restart.
Make Jenkins test for success and, if so, call another script that unconditionally initiates a shutdown.
[1] As Evilcat points out, using a background job with Start-Job does not work, because on exiting the calling PowerShell session with exit the background jobs are terminated too.

How to continue executing a Powershell script after starting a web server?

I have a script which calls two other scripts.
script0.ps1
Invoke-Expression C:\script1.ps1
Invoke-Expression C:\script2.ps1
The first script starts a web server:
script1.ps1
./activate anaconda_env
cd C:\webserver
python api_server.py
The second script starts a ngrok service:
script2.ps1
./activate anaconda_env
cd c:\ngrok
./ngrok -subdomain=mysd 8000
The problem is that the script0.ps1 only executes script1.ps1. At this point the web server starts running in the console and so the second command of script0.ps1 is not executed.
How to make write the scripts so both commands are executed? Or, how to write just one script to execute all commands but in two separate consoles?
The final result should be:
1) a web server running in a console with activated anaconda environment
2) a ngrok service running in a console with with activated anaconda environment
Change Script1.ps1 to launch python as a job:
./activate anaconda_env
cd C:\webserver
Invoke-Command -ScriptBlock {.\python.exe api_server.py} -AsJob -ComputerName .
I don't have the specific script you're using, so I tested this with turtle.py which ships with 3.43 and it seems to work.
You don't need to use Invoke-Expression to run a Powershell script from another script. Just run it as if you're on the command line
c:\script1.ps1
c:\script2.ps1
Now if script1.ps1 starts a process that doesn't exit, it will halt execution for the next statements in the script, and thus also prevent the second script from running.
In most cases this sequential execution is exactly what you want.
In your case you can start the scripts asynchronously by using Start-Process.
So your main script becomes something like:
start-process c:\script1.ps1
start-process c:\script2.ps1
Start-Process basically starts a new command shell to run the statement in. Check out the docs for more info. There's a bunch of parameters you can use to tweak how this happens.
To not have invoke-expression close your script you can pipe the output to Out-Null. Your code above would look like:
Invoke-Expression C:\script1.ps1 | Out-Null
Invoke-Expression C:\script2.ps1 | Out-Null

Executing invoke-item remotely in PowerShell

I am trying to execute this code willing to execute the program server.exe in the remote machine NODO-R01.Command completes, but nothing happens:
Invoke-Command -ComputerName NODO-R01 {Invoke-item C:\server.exe}
If I use any other *-Item cmdlet it works; like deleting, renaming, etc.