Start a Windows web server in the background with Ansible - powershell

I am looking to start a Go web server (a single .exe) on Windows Server via Ansible.
The equivalent in Linux that works great looks like:
- name: Start web server
become: true
become_user: root
shell:
cmd: nohup /home/centos/webserver </dev/null >/dev/null 2>&1 &
I can do it in PowerShell using Start-Process -FilePath -NoNewWindow .\webserver.exe but it terminates when I close the PowerShell window.
I have also looked into doing it with Start-Job { & C:\Path\to\webserver.exe } and Get-Job shows it completed, but not sure what that means since it's a web server and should just keep running until it's killed.
I need something that will star the webserver but not be tied to the shell so Ansible can do it via the win_shell module. I would have hoped this would work, but no luck:
- name: Start the webserver processes
win_shell: Start-Process -FilePath .\webserver.exe
args:
chdir: C:\Users\Administrator
Any and all suggestions much appreciated!

Looks like I was trying to find a more complicated way to do it with PowerShell when Ansible had built in functionality all along. This achieves exactly what I want:
- name: Start webserver
win_shell: .\webserver.exe
args:
chdir: C:\Users\Administrator
async: 180
poll: 0

Related

Ansible - delete files on a remote NTFS file share

I need to create a playbook that will delete files older then X days on a remote share location which has Windows NTFS share permissions. Account that can access the share is AD service account (different then the one used for Ansible). Ansible is Tower version with RedHat as OS. There is no PowerShell host which I can use as intermediary.
There is a win-share-module https://docs.ansible.com/ansible/latest/collections/ansible/windows/win_share_module.html#ansible-collections-ansible-windows-win-share-module but host that execute module must be Windows not Linux.
There is also ansible.windows.win_powershell module, but for this I have to install PowerShell in Ansible Tower, right?
What would be the best and easiest you would do it?
UPDATE
Let me add that I installed powershell on Linux but when doing this basic test
---
- name: Delete old PowerFlex storage backups
hosts: localhost
gather_facts: no
connection: local
tasks:
- name: Run basic PowerShell script
ansible.windows.win_powershell:
script: |
echo "Hello World"
I get the error
"module_stderr": "/bin/sh: powershell: command not found\n",
On the other hand when I login to linux CLI, I can enter into PowerShell with pwsh (not powershell), so I guess this module calls different version of PowerShell.
What is a workaround on this?
Thanks.
The win_powershell module is not going to work on your Tower machine. It will only work on windows OS.
Since you need to run this script a linux hosts, you can use shell module, and specify the executable path to wherever pwsh is on your machine. I would use a script for easier development/testing, but you can also use direct commands.
- name: execute pwsh
ansible.builtin.shell: /path/to/Invoke-Script.ps1
args:
executable: /bin/pwsh

Prevent Gitlab adding -NoProfile to PowerShell when starting a docker container

1. How can I prevent Gitlab from adding -NoProfile when creating the docker container?
2. What's the difference between using powershell with -NoProfile and without it?
3. Is there any way if I run powershell -NoProfile to somehow load/run the default profile and to revert the effect of setting -NoProfile flag?
And now the story behind these questions:
MSBuild (Visual Studio build tool command) fails to build Xamarin app when used in docker container started by Gitlab with Powershell -NoProfile.
I created a docker image for CI purspose and everything is working properly if I run the container manually, but when it is run during Gitlab runner job, it fails (more exactly msbuild /t:SignAndroidPackage fails, because of some file does not gets generated). I inspected this (put a sleep of 1 hour in gitlab-ci.yml and attached to the container on the runner machine) and found out that Gitlab starts the container with PowerShell -NoProfile...I tried that manually(start the container with -NoProfile) and I reproduced the issue.
the error is:
Could not find a part of the path 'C:\builds\gitlab\HMI.Framework\KDI\sub\HostApplicationToolkit\sub\KBle\KBle\sub\XamarinBluetooth\Source\Plugin.BLE.Android\Resources\Resource.Designer.cs'
Here the Resource.Designer.cs is missing (and it should be auto-generated during the build process)
This is the dockerFile:
# escape=`
# Use the latest Windows Server Core image with .NET Framework 4.8.
FROM mcr.microsoft.com/dotnet/framework/sdk:3.5-windowsservercore-ltsc2019
ENV VS_STUDIO_INSTALL_LINK=https://download.visualstudio.microsoft.com/download/pr/befdb1f9-8676-4693-b031-65ee44835915/c541feeaa77b97681f7693fc5bed2ff82b331b168c678af1a95bdb1138a99802/vs_Community.exe
ENV VS_INSTALLER_PATH=C:\TEMP\vs2019.exe
ENV ANDROID_COMPILE_SDK=29
# Restore the default Windows shell for correct batch processing.
SHELL ["cmd", "/S", "/C"]
ADD $VS_STUDIO_INSTALL_LINK $VS_INSTALLER_PATH
RUN %VS_INSTALLER_PATH% --quiet --wait --norestart --nocache --includeRecommended --includeOptional`
--add Microsoft.VisualStudio.Workload.NetCrossPlat `
--add Microsoft.VisualStudio.Workload.XamarinBuildTools `
|| IF "%ERRORLEVEL%"=="3010" EXIT 0
RUN del %VS_INSTALLER_PATH%
# set some util paths
RUN setx JAVA_HOME "c:\Program Files\Android\jdk\microsoft_dist_openjdk_1.8.0.25\"
RUN setx path "%path%;c:\Program Files (x86)\Android\android-sdk\tools\bin;c:\Program Files (x86)\Android\android-sdk\platform-tools"
# update android SDK with API 29
RUN echo y| sdkmanager "platforms;android-%ANDROID_COMPILE_SDK%"
#ENTRYPOINT ["powershell.exe", "-NoLogo", "-ExecutionPolicy", "Bypass"]
This is the gitlab-ci.yml
image: visualstudio2019-xamarin-ci:1.0-windowsservercore-ltsc2019
stages:
- build
- test
variables:
GIT_SUBMODULE_STRATEGY: 'recursive'
build_kdi:
stage: build
only:
- CI_CD
tags:
- docker-windows
script:
- '& "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe" ./src/KDI/KDI.sln /t:Restore /p:AndroidBuildApplicationPackage=true /p:Configuration=Release'
- '& "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe" /p:Configuration=Release /t:SignAndroidPackage /property:SolutionDir="C:\builds\gitlab\HMI.Framework\KDI\src\KDI\" /p:AndroidSigningKeyStore="C:\builds\gitlab\HMI.Framework\KDI\distribution\Android\KrohneAndroidKeystore.keystore" .\src\KDI\KDI\KDI.Android\KDI.Android.csproj'
run_bb_tests:
stage: test
only:
- CI_CD
tags:
- docker-windows
script:
- docker-ci/install_and_run_bb_tests.bat "phone_ip" "5555" arg1 arg2 || true
- adb pull /storage/emulated/0/Android/data/myApp/files/Exports/BBT_Exports/BBTests_CI C:\test_results
artifacts:
paths:
- c:\test_results\BBTests_CI #expire in 1 month by default
If I start this image using : docker run -it myImage powershell everything works well, but if I run it docker run -it myImage powershell -NoProfile, msbuild fails at some step in building the xamarin app
How can I prevent Gitlab from adding -NoProfile when creating the docker container?
Apparently you can't...yet but there is a feature request in place
What's the difference between using powershell with -NoProfile and without it?
A PowerShell profile is just a file that contains things, like custom functions, for a specific user. For instance, if I were to have Function Banana(){Write-Host "Awesome"} in my PowerShell profile e.g $Home[My ]Documents\PowerShell\Profile.ps1. Whenever I open up PowerShell, it loads that function automatically. So I can open PowerShell, type banana and have the string Awesome written to stdout. If I were to start powershell with -NoProfile, and enter banana, I'd get CommandNotFoundException.
source
Is there any way if I run powershell -NoProfile to somehow load/run the default profile and to revert the effect of setting -NoProfile flag?
Maybe. And I only say maybe because I haven't personally tested it, but in theory it should work. If the profile is in the container, all you have to do is dot source it.
. "C:\path\to\powershell\profile.ps1"
dot sourcing the .ps1 file will run anything within it, inside the current scope, which includes loading functions, if any are present.
dot source docs
My expertise on Gitlab is limited, but due to my overall experience with Windows containers, PowerShell, as well as the nature of PowerShell profiles, I have doubts that the profiling is the root cause of this issue, but I don't have enough information/evidence to definitively say. Hope this helps in some way!

win_shell completing command but not ending process

I'm learning Ansible and am running into something I haven't seen a good reference for anywhere -
I have a .ps1 on my target machine that I want to run via Ansible, while passing it a variable as well. My playbook for it is pretty simple:
---
- name: run stuff
hosts: all
gather_facts: no
vars:
force_all_hosts: false
tasks:
- name: run mounter script
win_shell: C:\folder\file.ps1 -password (ConvertTo-SecureString "{{vault_pw}}" -AsPlainText -Force)
The contents of the .ps1 work when I run them manually local to the Windows machine, so I know the actual commands work. When I run the playbook it works as well - the Powershell script runs succesfully and the changes are made - but the actual task never completes so the playbook can't finish.
I added a "< NUL" to the end of the win_shell line to force a message that said the return code wasn't 0 - the RC was 1 - but then I updated Ansible to 2.8 and now the "<" character is reserved so I can't recreate the return code failure anymore.
Is there a way to force the return code, and filter if it's <= 2 or something? Or better yet, is there another way to ensure the job ends other than using async/poll since that causes the play to report that it failed?
Can you try the async option in ansible?
https://docs.ansible.com/ansible/latest/user_guide/playbooks_async.html

Ansible command wont output as playbook

Im using ansible 2.7.5 and a windows 10 host over winRM.
If I execute:
ansible win -I hosts -m win_command -a "PowerShell.exe ipconfig"
I get an output and it works fine.
But I want to write it inside a playbook and not as an ansible command but I won't get any output so I tried to use stdout but it wont work:
- hosts: win
gather_facts: no
tasks:
- name: PowerShell Command
win_command: powershell.exe
register: shell_result
args:
stdin: ipconfig
-debug:
var: shell_result.stdout_lines
Any suggestions how to get the first command working as a playbook?
Your - debug task isn't indented properly and doesn't have the right spacing. I'm not sure if that's just from posting here or if it's in your original file.
Your call to powershell.exe left out the - parameter which is what tells it to accept input on stdin. So it should be win_command: powershell.exe -.
That said, ipconfig is actually ipconfig.exe so instead of trying to run a shell with win_command just run ipconfig.exe directly:
- hosts: win
gather_facts: no
tasks:
- name: ipconfig
win_command: ipconfig.exe
register: shell_result
- debug:
var: shell_result.stdout_lines

Sleep command in batch file?

When I'm writing a batch file to run automatically, how do I write it so that when the batch file is run, it can pause for a couple seconds in between commands?
Context:
psexec \\server -u user -p pass cmd
[there needs to be a pause here for psexec to establish a connection]
dir /s >output.txt \\server\shared
*Note: the reason I run the dir command server-side using psexec and not locally is because it's much faster to run dir on a local machine than remotely, and time is of the essence.
When I'm doing this by hand it's obviously easy, I just wait. But running a batch file makes it run all commands at near instant speeds next to each other, regardless of the completion status of the last command. How do I put in a pause?
On Windows Vista / Windows 7 you can use the timeout command:
timeout /T [delay in seconds] /NOBREAK > NUL
On previous versions of Windows, you can use the ping command (the ping command has 1000 ms of delay between each iteration):
ping -n [delay in seconds + 1] 127.0.0.1 > NUL
Some versions of Windows (like Windows Server 2003) has the sleep.exe executable:
sleep [delay in seconds]
Note: Windows Resource kit for 2003 contains sleep.exe command.
If you don't know the Windows version, simply use the ping hack since it'll be available.
There is timeout command in more recent version of Windows:
timeout /T 10
Windows Resource kit for 2003 will install on Windows XP. It contains SLEEP.EXE which can be used from a command batch file.
download is here http://www.microsoft.com/download/en/details.aspx?id=17657
I think the information here: http://malektips.com/xp_dos_0002.html would explain it better than I.
There's still the case of error handling though (what if the remote machine isn't up?). cmd.exe is quite useless for doing any remote activities for the most part, using powershell would enable so much more.
EDIT::
In fact, you can execute a program stored locally with psexec (it gets copied across and executed locally server-side) - would using that be a more viable alternative?
Without knowing what commands you're intending to run it's hard to take it much further.
EDIT(2)::
If it's just the one command you're running, simply store it in a dedicated file, like 'remote_dir_listing.cmd', and then use psexec with:
psexec \\server -u <user> -p <pass> -c -f remote_dir_listing.cmd
This will force a copy of the local file to the remote side each time you execute it (in case you want to expand it). In this way, you bypass the need for a pause at all - only when psexec has got the pipes open will it run, and once it completes, it closes itself silently.