SSH command options cause errors when stored in a variable - bash

I have a variable that stores an SSH command, since my script uses it quite often.
SSH_CMD="ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=yes"
However, I'm running into an issue where the SSH command works fine on its own, but doesn't work when I use the variable
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=yes $host exit 0
${SSH_CMD} $host exit 0
The first line works great. The second line fails with a No such file or directory message. When I remove -o UserKnownHostsFile=/dev/null from $SSH_CMD, the error message is command not found. If I remove either of the other two options, the message doesn't change, but when $SSH_CMD is just "ssh", it works.
What's causing this problem?

So why does it work without any issues in other scripts?
Many times answered. Try bash alias or bash function:
alias my_ssh='ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=yes'
my_ssh $host exit 0
Or rahter use ssh_config in your ~/.ssh/config.
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
BatchMode yes
and then you don't need any harakiri like this and just use
ssh $host exit 1

Related

Get output from a shell script that does ssh two level

I have two shell scripts like below:
Script1:
ssh -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null my_username#jump_box <<EOF
ls
ssh -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null actual_host <<EOF1
sudo docker ps --format='{{json .}}'
EOF1
EOF
Script2:
details=nothing
ssh -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null my_username#jump_box <<EOF
ls
details=$(ssh -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null actual_host "sudo docker ps --format='{{json .}}'")
EOF
echo "${details}"
I need the docker details in a varilable in my local machine so that I can do some operations on it. The first script runs fine and I can see the output of the docker command on my local machine but the second script doesn't work. It seems to be hung/stuck and doesn't do anything and I have to forcefully quit it.
Like the comment from #Gordon Davisson, use a jumpbox.
But you can define it in the ~/.ssh/config file, too.
HOST my_jump_box
hostname jump_box
user my_username
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
HOST actual
hostname actual_hostname
user actual_user
ProxyJump my_jump_box
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
RemoteCommand sudo docker ps --format='{{json .}}'"
Then you can just use ssh actual
To fetch the output details=$(ssh actual).
Btw. Your specific problem could also be solved by changing script2 to:
#!/bin/bash
details=$(./script1)
echo "$details"

What does sleep 0 do in a shell script and what does it do if it used in the ansible SSH config to append after each command?

What does sleep 0 do in a shell script? I read the man page for sleep and it says "delay for a specified amount of time" And the argument NUMBER specifies this time in SECONDS (by default).
But I see ansible using sh -c 'echo ~ec2-user && sleep 0' to start with each task.
Also, it uses this at the end of each remote command it is firing.
I didn't find any special case mention of sleep 0 on the man page and based on the functionality of the sleep command it doesn't make any sense to have sleep 0.
The sleep command on my server is from GNU coreutils 8.22
After looking into this for some more time, here are few things that I have learned,
this is a SSH configuration given to the ansible,
each time ansible using SSH to execute a task it is running SSH with -C with multiple options. These are not part of playbook or task.
I looked for ansible configuration on ansible page here. Checked all files and Env variables but found nothing related to ssh
Checked the /etc/ssh/ssh_config there are not all the parameters/arguments that I see in the SSH that ansible is doing
In the inventory as well the host is mentioned just like this
ansible_host=localhost ansible_user=ec2-user
e.g. log lines at the beginning when ansible executes any task:
<localhost> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="ec2-user"' -o C
onnectTimeout=120 -o ControlPath=/home/ec2-user/.ansible/cp/6bc5a26ee4 localhost '/bin/sh -c '"'"'echo ~ec2-user && sleep 0'"'"''
<localhost> (0, '/home/ec2-user\n', '')
<localhost> ESTABLISH SSH CONNECTION FOR USER: ec2-user
I'm executing an ansible playbook written by one team, there is no one in that team I can talk to. I'm struggling to find where Ansible is taking all these arguments it is using in each SSH and why is it using this sleep 0

i need execute command after ssh connection, but have command sustitution

but needed execute $() in server, it is running before ssh
ssh -t -o StrictHostKeyChecking=no -i "${SSH_KEY}" "${HOST}" "$(command)"
this is a script that I need to run that code on the server
If you run that, it will execute whats inside of the $() before connecting to the server. Then it will send the result to be executed.
I think what you want is do this :
ssh -t -o StrictHostKeyChecking=no -i "${SSH_KEY}" "${HOST}" 'command'
Where command might be something like :
ls -lh | grep someword
Let me know if I am correct.

golang ssh quiet mode

In golang ssh(golang.org/x/crypto/ssh) package how to force the ssh command to use quiet mode i.e. simulate 'ssh -q'
I looked at Config and ClientConfig structures as well as tried searching for 'quiet' or options in the documentation(https://godoc.org/golang.org/x/crypto/ssh) but can't find anything.
Credits: Thanks to #JimB and #Kenster for nailing this.
Quiet mode is not required for (golang.org/x/crypto/ssh). Extra messages that you would usually see when using a ssh CLI won't appear when using (golang.org/x/crypto/ssh). Here is an example of extra messages:
sshpass -ppassword ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no 10.10.10.10 'ls | wc -l'
Warning: Permanently added '10.10.10.10' (ECDSA) to the list of known hosts.
19
sshpass -ppassword ssh -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no 10.10.10.10 'ls | wc -l'
19

How can my script invoke SSH and avoid "Enter passphrase for key" messages?

I have a shell script that includes the following command:
/usr/local/bin/ssh -q -i /.ssh/id_rsa -l oracle \
-o UserKnownHostsFile=/dev/null \
-o StrictHostKeyChecking=no \
-o PasswordAuthentication=no \
${REMOTE_HOST} ${REMOTE_CMD}
The StrictHostKeyChecking=no avoids prompting if the remote host isn't recognized, while the PasswordAuthentication=no avoids prompting for passwords if the private key isn't known. However, if someone accidentally sets a passphrase for the private key, I still get a prompt to "Enter passphrase for key". This can cause the script to hang while waiting for a response, which is a bad thing. Is there some way to avoid the prompt and exit immediately?
ssh -o BatchMode=yes ... will disable passphrase/password querying.

Resources