I am new to powershell here. I can't figure out why after successfully installing AWS CLI, I intermittently get back aws command not recognized error. I put in sleep thinking some environment variables might be getting set in background. Need help figuring out what do I need to do here to able to to successfully execute $putItem command.
I followed the instructions here https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2-windows.html
PLEASE NOTE: The whole thing has to be automated, so I can't manually login to a host and fix something as this same script has to be run on 100+ hosts
Write-Output "Checking if AWS CLI support exists..."
cmd.exe /c "aws --version"
if ($LASTEXITCODE -eq 0){
Write-Output "AWS CLI installed already"
} else {
Write-Output "Installing AWS CLI V2"
cmd.exe /c "msiexec.exe /i https://awscli.amazonaws.com/AWSCLIV2.msi /qn"
if ($LASTEXITCODE -eq 0){
Write-Output "AWS CLI installed successfully"
Start-Sleep -s 5
} else {
Write-Output "Could not install AWS CLI"
exit 1
}
}
$putItem = 'aws dynamodb put-item --table-name ' + $instanceStatusDDBTable + ' --item "{\"HostName\" : {\"S\" : \"' + $instanceName + '\"}, \"Modules\" : {\"M\" : {}}, \"DAGName\" : {\"S\" : \"' + $dagName +'\"}}"'
Write-Output "Executing DB put item query $putItem"
cmd.exe /c $putItem
if ($LASTEXITCODE -eq 0){
Write-Output "Created entry for $instanceName in $instanceStatusDDBTable DDB table"
} else {
Write-Output "Could not complete put Item operation for $instanceName"
exit 1
}
Here is the output
Checking if AWS CLI support exists...
Installing AWS CLI V2
AWS CLI installed successfully
Executing DB put item query aws dynamodb put-item --table-name Ex2019-HostStatusTable --item "{\"HostName\" : {\"S\" : \"Host1\"}, \"Modules\" : {\"M\" : {}}, \"DAGName\" : {\"S\" : \"USW-D01\"}}"
Could not complete put Item operation for Host1
Error output -
'aws' is not recognized as an internal or external command,
operable program or batch file.
Try adding the below code to refresh your environment variables after you check your $LASTEXITCODE variable. The shell session has to regather the updated environment variables your installer just added. See this response for more info.
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
You may also want to consider using the Start-Process with the -wait and -passthru params to invoke your installer as the cmd may not wait long enough for the app to finish installing. You can read up on here. I do agree with David, you could just check to see if it's installed by running aws --version and then reading in the version number or catching the error in a try catch block.
Related
I have the following powershell script that runs via packer utility while creating aws ami image.
This script downloads and installs aws cli and then immediately try to use it. The installation process will update windows PATH environment variable but I think it will not be available immediately in the same script. So I set the location to where cli is installed before using it.
$SETUP_DIR = "C:\Setup"
New-Item -Path $SETUP_DIR -ItemType Directory -Force -ErrorAction SilentlyContinue
Clear-Host
Set-Location -Path $SETUP_DIR -PassThru
# install AWS CLI
msiexec.exe /i https://awscli.amazonaws.com/AWSCLIV2.msi /quiet
Write-Host "AWS CLI installation completed."
# Set location to AWS CLI
Set-Location -Path "C:\Program Files\Amazon\AWSCLIV2" -PassThru
# Download utility from AWS S3
aws s3 cp s3://tools/utility.exe
Write-Host "Utility download completed."
# switch the location back to c:\setup
Set-Location -Path $SETUP_DIR -PassThru
However when the script executed, it throws error as The term 'aws' is not recognized
aws s3 cp s3://tools/utility.exe ...
==> amazon-ebs.windows_server: + ~~~
==> amazon-ebs.windows_server: + CategoryInfo : ObjectNotFound: (aws:String) [], CommandNotFoundException
==> amazon-ebs.windows_server: + FullyQualifiedErrorId : CommandNotFoundException
==> amazon-ebs.windows_server:
amazon-ebs.windows_server:
==> amazon-ebs.windows_server: aws : The term 'aws' is not recognized as the name of a cmdlet, function, script file, or operable program.
Check the
==> amazon-ebs.windows_server: spelling of the name, or if a path was included, verify that the path is correct and try again.
When you run aws s3 ... system is trying to locate aws in the system path it knows about. The fact that you change directory to the location of the aws binary does not do anything for you.
As you probably know, even when you are in the same directory as a binary, if you simply try to use it, it won't work if it is not in the path, and that's why you would use .\binary_name.exe That's a safety feature in PowerShell.
You could try updating the path as suggested in the commends by adding that location:
$env:path="$env:path;C:\Program Files\Amazon\AWSCLIV2"
or point to the binary directly. You could also create an alias like:
set-alias -name aws -value "c:\program files\Amazon\awscliv2\aws.cmd"
Then use aws and it should run the aws.cmd (check that folder to make sure you are calling the correct binary. It used to be aws.cmd for aws cli v1 but may have changed)
Im trying to pass my applications connectionstring from Secrets Manager into Elastic Beanstalk during deployment. If i remote desktop onto the server i am deploying to, i can run the following command -
aws secretsmanager get-secret-value --secret-id XXX-MY-SECRET-ID --version-stage AWSCURRENT --query=SecretString --output text
And it outputs correctly. All good.
However when i try and automate this through the .ebextensions folder, it always returns an empty string.
So ive tried lots of things, firstly using a container command to point to a Powershell file that i placed in the .ebextensions folder, like so -
container_commands:
00-myscript:
command : powershell.exe -ExecutionPolicy Bypass -Command ".\\.ebextensions\\BuildConnectionStrings.ps1"
Then the Powershell command would be
$response = aws secretsmanager get-secret-value --secret-id XXX-MY-SECRET-ID --version-stage AWSCURRENT --query=SecretString --output text
$FileName = "ConnectionStrings.config"
New-Item $FileName -ItemType File
Set-Content $FileName $response
If i run this directly in powershell, it all works as expected. But when i deploy the site, it just creates an empty file.
Ive tried various combinations of putting the Powershell commands directly in the .ebextensions config files, always with the same result.
I just cant figure out why the same commands work when i run them directly on the server, but not when deployed through EB.
Ive been stuck for days on this, can anyone help?
So for anyone else that has this problem...
Simply installing the aws cli on the server is not enough. The error i was getting was caused by PowerShell not recognising the aws command (even tho it had been installed).
The solution was to run the following code at the beginning of my script -
$command = "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12"
Invoke-Expression $command
Invoke-WebRequest -Uri "https://awscli.amazonaws.com/AWSCLIV2.msi" -Outfile C:\AWSCLIV2.msi
$arguments = "/i `"C:\AWSCLIV2.msi`" /quiet"
Start-Process msiexec.exe -ArgumentList $arguments -Wait
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine")
aws --version
This ensured that the aws cli would be installed (again).
I dont know why this is necessary, but its the only solution ive found
Most of the AWS CLI calls are asynchronous.
Therefore, after you call them, you have no idea if end product was successful or not.
Is there a simple solution for, checking if environment was created successfully, as an example, other than creating timed polling verification calls, etc etc.
Sorry I did not mention previously, but I am specifically looking for solutions from Powershell
You can check the Exit Status for cli command.
What is an exit code in bash shell?
Every Linux or Unix command executed by the shell script or user has
an exit status. Exit status is an integer number. 0 exit status means
the command was successful without any errors
code snippet:
aws cli command
if [ $? -ne 0 ]
then
echo "Error"
exit 1;
else
echo "Passed"
fi
another method is to wait for a response from the command :
while :
do
sleep 10
echo "Waiting for elasticsearch domain endpoint..."
local ELASTICSEARCH_ENDPOINT=$(aws es describe-elasticsearch-domain --domain-name ${ES_DOMAIN_NAME} --region ${AWS_REGION} --output text --query 'DomainStatus.Endpoints.vpc')
if [ ${ELASTICSEARCH_ENDPOINT} != "null" ]
then
echo "Elasticsearch endpoint: ${ELASTICSEARCH_ENDPOINT}"
break
fi
done
A user data script will run the first time an EC2 is started.
How can I restore/reactivate this ability on a windows EC2?
Note
I have tried the script suggested here but it fails immediately as there is no file C:\Program Files\Amazon\Ec2ConfigService\Settings\Config.xml and nothing similarly named (not that I found; not even an Ec2ConfigService directory)
Also note, my question is identical to this question but for windows ec2, not linux
I understand that the point is about just running user-data, and not all the other stuff ...
To run (only) user-data script, you can run it by:
Import-Module (Join-Path (Join-Path $env:ProgramData -ChildPath "Amazon\EC2-Windows\Launch") -ChildPath "Module\Ec2Launch.psd1")
Invoke-Userdata -OnlyExecute
let's say you save this as 'C:\ProgramData\Amazon\EC2-Windows\Launch\Config\run-user-data.ps1', then you can use PowerShell to schedule a new task to run at startup:
$Action = New-ScheduledTaskAction -Execute 'Powershell.exe' -Argument '-ExecutionPolicy Bypass C:\ProgramData\Amazon\EC2-Windows\Launch\Config\run-user-data.ps1'
$Trigger = New-ScheduledTaskTrigger -AtStartup
$Settings = New-ScheduledTaskSettingsSet
$Task = New-ScheduledTask -Action $Action -Trigger $Trigger -Settings $Settings
Register-ScheduledTask -TaskName 'Execute user-data' -InputObject $Task -User 'NT AUTHORITY\SYSTEM' -Force
I use this sort of solution by creating the mentioned file and command on 'AWS::CloudFormation::Init' sections.
Hope it helps!
I have a Jenkins job which does below activity.
Stop WebService
Delete WebService
Copy items from Jenkins workspace to server path
Create WebService
Start WebService
Below is my PowerShell script:
Get-ChildItem "C:\Location\*"
$service = Get-Service -Name value -Computername $env:SERVER -ErrorAction SilentlyContinue
sc.exe \\$env:SERVER stop value
Write-Host "value STOPPED"
sc.exe \\$env:SERVER delete val
Write-Host "val DELETED"
Copy-Item "C:\Location\*" "\\$env:SERVER\d$\Location" -Force -Recurse
sc.exe \\$env:SERVER create val start=auto DisplayName ="val" binPath= D:\Location.exe
sc.exe \\$env:SERVER description value"value"
sc.exe \\$env:SERVER start value
Write-Host "value STARTED"
if ($error) { exit 1 }
Error logs:
Copy-Item : The process cannot access the file '\\Location' because it is being used by another process.
At C:\Users\Administrator\AppData\Local\Temp\hudson2059984936352103941.ps1:18 char:5
+ Copy-Item "C:\Location\*" " ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Copy-Item], IOException
+ FullyQualifiedErrorId : System.IO.IOException,Microsoft.PowerShell.Commands.CopyItemCommand
[SC] CreateService FAILED 1072:
The specified service has been marked for deletion.
[SC] ChangeServiceConfig2 FAILED 1072:
The specified service has been marked for deletion.
[SC] StartService FAILED 1058:
The service cannot be started, either because it is disabled or because it has no
enabled devices associated with it.
Can you please help me out with this error? Do I need to restart the deploy server so that my process gets killed? If so I feel this is not relevant and cannot do in prod servers.
The problem is that you have another process which is using the dll. Since it is being used you cannot remove it. You need to make sure that no process is using your dll before you can remove it. To achieve this you will need to find out which process is using it, why it is using it and make sure that it will be closed. If the problem occurs next time as well, then you will need to add closing that process to your script.