Environment variable overrides command - bash

I set the EC2_IP_ADDRESS variable
$ export EC2_IP_ADDRESS="`docker run -it -v $PWD/infrastructure:/terraform -v $PWD/data:/data terraform sh -c "terraform init; terraform state show module.aws_ec2.aws_eip.aws_instance_eip" | grep public_ip | awk '{print $3}'`"
And then I'm trying to copy some files into the EC2 instance:
$ scp -i key.pem -r src/* ec2-user#$EC2_IP_ADDRESS:/home/ec2-user/src/
But the output is an error: : nodename nor servname provided, or not known
Output of $ echo "scp -i key.pem -r src/* ec2-user#$EC2_IP_ADDRESS:/home/ec2-user/src/"
:/home/ec2-user/src/c/* ec2-user#X.X.X.X
It seems that anything after the variable EC2_IP_ADDRESS goes to the beginning of the string, overriding the command.
Any ideas on how to fix this?

It seems the variable contains $'\r' at the end. Remove it with
EC2_IP_ADDRESS=${EC2_IP_ADDRESS%$'\r'}

Related

xargs does not seem to separate parameters

I am trying to use xargs to set secrets in github using the gh CLI.
Given I have an .env file with the following entries
SECRET1=djfjgdfkjg
SECRET2=jbnfdgjn
SECRET3=A line of text
And the sed command sed -r 's/^([A-Za-z0-9_]*)=(.*)$/\1 -b "\2"/g' ./.env produces the following output:
SECRET1 -b "djfjgdfkjg"
SECRET2 -b "jbnfdgjn"
SECRET3 -b "A line of text"
I am unsure as to why the command:
sed -r 's/^([A-Za-z0-9_]*)=(.*)$/\1 -b "\2"/g' test.env | xargs -I {} gh secret set {}
fails for each secret with the message secret name can only contain letters, numbers, and _
Manually running gh secret set SECRET1 -b "djfjgdfkjg" works without an error.
I'm guessing that the issue is that the first arg (secret name) is being passed the value SECRET1 -b "djfjgdfkjg" rather than just SECRET1 but I'm unsure how I can fix this?
After doing a bit more digging I discovered that the problem is the use of -I and that:
sed -rn 's/^[[:space:]]*([[:alpha:]][[:alnum:]_]*)=(.*)$/\1 -b "\2"/p' .env | xargs -n 3 gh secret set
resolves the problem.

Bash Script fails with error: OCI runtime exec failed

I am running the below script and getting error.
#!/bin/bash
webproxy=$(sudo docker ps -a --format "{{.Names}}"|grep webproxy)
webproxycheck="curl -k -s https://localhost:\${nginx_https_port}/HealthCheckService"
if [ -n "$webproxy" ] ; then
sudo docker exec $webproxy sh -c "$webproxycheck"
fi
Here is my docker ps -a output
$sudo docker ps -a --format "{{.Names}}"|grep webproxy
webproxy-dev-01
webproxy-dev2-01
when i run the command individually it works. For Example:
$sudo docker exec webproxy-dev-01 sh -c 'curl -k -s https://localhost:${nginx_https_port}/HealthCheckService'
HEALTHCHECK_OK
$sudo docker exec webproxy-dev2-01 sh -c 'curl -k -s https://localhost:${nginx_https_port}/HealthCheckService'
HEALTHCHECK_OK
Here is the error i get.
$ sh healthcheck.sh
OCI runtime exec failed: exec failed: container_linux.go:348: starting container process caused "exec: \"webproxy-dev-01\": executable file not found in $PATH": unknown
Could someone please help me with the error. Any help will be greatly appreciated.
Because the variable contains two tokens (on two separate lines) that's what the variable expands to. You are running
sudo docker exec webproxy-dev-01 webproxy-dev2-01 ...
which of course is an error.
It's not clear what you actually expect to happen, but if you want to loop over those values, that's
for host in $webproxy; do
sudo docker exec "$host" sh -c "$webproxycheck"
done
which will conveniently loop zero times if the variable is empty.
If you just want one value, maybe add head -n 1 to the pipe, or pass a more specific regular expression to grep so it only matches one container. (If you have control over these containers, probably run them with --name so you can unambiguously identify them.)
Based on your given script, you are trying to "exec" the following
sudo docker exec webproxy-dev2-01
webproxy-dev-01 sh -c "curl -k -s https://localhost:${nginx_https_port}/HealthCheckService"
As you see, here is your error.
sudo docker exec webproxy-dev2-01
webproxy-dev-01 [...]
The problem is this line:
webproxy=$(sudo docker ps -a --format "{{.Names}}"|grep webproxy)
which results in the following (you also posted this):
webproxy-dev2-01
webproxy-dev-01
Now, the issue is, that your docker exec command now takes both images names (coming from the variable assignment $webproxy), interpreting the second entry (which is webproxy-dev-01 and sepetrated by \n) as the exec command. This is now intperreted as the given command which is not valid and cannot been found: That's what the error tells you.
A workaround would be the following:
webproxy=$(sudo docker ps -a --format "{{.Names}}"| grep webproxy | head -n 1)
It only graps the first entry of your output. You can of course adapt this to do this in a loop.
A small snippet:
#!/bin/bash
webproxy=$(sudo docker ps -a --format "{{.Names}}"| grep webproxy )
echo ${webproxy}
webproxycheck="curl -k -s https://localhost:\${nginx_https_port}/HealthCheckService"
while IFS= read -r line; do
if [ -n "$line" ] ; then
echo "sudo docker exec ${line} sh -c \"${webproxycheck}\""
fi
done <<< "$webproxy"

Read variables in nested quotes

I want to ssh into a host and start a container and run some commands. So the code will be like this:
ssh $host 'screen -L -d -m bash -c "docker run "\
"--network=host -v ~/data:/data myimage:${TAG_NAME}"\
" /bin/bash -c \" some command.... \""'
The question is simple, since I was using single quote, I can't read the ${TAG_NAME}. Is there any way to write this kind of nested quotes and also pass the variable?
You can stop and start your single quotes to include the environment variable, like so:
echo 'foo'"$HOME"'foo'
For your example, the way to include an env var (from your local system) in the command that runs on $host would be:
ssh $host 'screen -L -d -m bash -c "docker run'\
' --network=host -v ~/data:/data myimage:'"$TAG_NAME"\
' /bin/bash -c \" some command.... \""'

nested ssh -t -t not providing $PS1

I am trying to run a nested ssh -t -t but it won't provide me the environment variables when working with cat and echo.
#!/bin/bash
pass="password\n"
bla="cat <(echo -e '$pass') - | sudo -S su -"
ssh -t -t -t -t jumpserver "ssh -t -t -t -t server \"$bla\" "
I get an output without any variables taken into consideration. (e.g. PS1 does not get shown but commands work fine) The problem is related to cat <(echo -e '$pass') - but this was the way to keep echo alive after providing the password for sudo.
How can i achieve this and get environment variables to get a proper output?
Thanks.
The -tt is enough. Using more -t does not add any more effect and just makes an impression that you have no idea what are you doing.
What is the point of cat <(echo -e) construction? Writing just echo would result in the same, isn't it?
Why to use sudo su? sudo already does all you need, isn't it?
So how can it look in some fashionable manner?
pass="password\n"
bla="echo '$pass' | sudo -Si"
ssh -tt jumpserver "ssh -tt server \"$bla\""
And does it work? Try to debug the commands with -vvv switches to the ssh. It will show you what is actually executed and passed to each other shell.

Using shell expansion with Ansible

I'm trying to execute a remote command via Ansible which requires gathering the PID of the process:
ansible webserver -m shell -a 'jstack -l $(pgrep -f java)'
However it seems Ansible is not able to expand the shell command contained in parenthesis (tried as well with grave accent):
127.0.0.1 | FAILED | rc=1 >>
Usage:
jstack [-l] <pid>
Executing just the command in the expansion reveals that expansion does not take place:
ansible webserver -a 'echo $(pgrep -f java)'
192.168.0.1 | success | rc=0 >>
$(pgrep -f java)
You'll want to escape the $ dollar sign, like so:
ansible all -i inventories/prod/hosts -m shell -a "echo \$(pgrep -f java)"

Resources