writing shell ssh script for uploading compiled sketch on multiple arduino yun in network - shell

I work with a couple of arduino yuns and want to write a script to upload sketches on multiple of them. Let's assume I have a compiled arduino program:sketch.hex.
Now I'd like to upload this file via LAN. For a single device it works like this.
Copying the sketch onto the device. (password required)
scp sketch.hex root#yun1.local:/tmp/sketch.hex
Opening an ssh session with the device. (password required)
ssh root#yun1.local
And then load the program onto the Atmega with the following 2 commands.
merge-sketch-with-bootloader.lua /tmp/sketch.hex
run-avrdude /tmp/sketch.hex
Now my question would be, how to do this for multiple arduinos (yun1,yun2,...,yunN) without entering actually ssh-ing into each single device in order to run the bottom 2 commands.
Hope the question is not too confusing and thanks a lot in advance.
Update: could figure it out myself. Here is the code in case someone needs it.
#!/bin/sh
# globalUpload.sh
#
#
# Created by maggu on 21/02/16.
#
clear
FILENAME="valve_adjusting.hex"
SSHPASS="doghunter"
SSHCOMMAND="ssh -p 22 -T -o StrictHostKeyChecking=no -o BatchMode=no"
PREFIX="root#linino"
PREFIXO="linino"
SUFFIX=".local"
YUNS=8
for i in `seq 1 $YUNS`
do
SSHACCOUNT=$PREFIX$i$SUFFIX
ssh-keygen -R $PREFIXO$i$SUFFIX
sshpass -p "doghunter" scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null sketch.hex $SSHACCOUNT:/tmp/sketch.hex
sshpass -p $SSHPASS $SSHCOMMAND $SSHACCOUNT << EOF_run_commands
merge-sketch-with-bootloader.lua /tmp/sketch.hex
run-avrdude /tmp/sketch.hex
EOF_run_commands
done

#!/bin/sh
# globalUpload.sh
#
#
# Created by maggu on 21/02/16.
#
clear
FILENAME="valve_adjusting.hex"
SSHPASS="doghunter"
SSHCOMMAND="ssh -p 22 -T -o StrictHostKeyChecking=no -o BatchMode=no"
PREFIX="root#linino"
PREFIXO="linino"
SUFFIX=".local"
YUNS=8
for i in `seq 1 $YUNS`
do
SSHACCOUNT=$PREFIX$i$SUFFIX
ssh-keygen -R $PREFIXO$i$SUFFIX
sshpass -p "doghunter" scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null sketch.hex $SSHACCOUNT:/tmp/sketch.hex
sshpass -p $SSHPASS $SSHCOMMAND $SSHACCOUNT << EOF_run_commands
merge-sketch-with-bootloader.lua /tmp/sketch.hex
run-avrdude /tmp/sketch.hex
EOF_run_commands
done

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"

How to retain password for Rsync across the same script?

I have written this script:
#!/bin/bash
SSH_USER=${SSH_USER:=$USER}
for department in A B C E L M V
do
mkdir -p ./resources/${div}
rsync -Pruzh --copy-links \
${SSH_USER}#server:${department}/foo/files \
${SSH_USER}#server:${department}/foo/photos \
./resources/${department}/foo
rsync -Pruzh \
${SSH_USER}#server:${department}/bar/documents \
./resources/${department}/bar
done
It works perfect except that I have to write my password 14 times which is not really practical.
I have heard of ssh_agent but for some reasons it does not work on my WSL.
Is there any alternative that I can use to type my password only once?
If you are using openssh, then you can set up a master connection and reuse it with something like:
DEST="${SSH_USER}#server"
TMPL=/tmp/sshctl/"%L-%r#%h:%p"
mkdir -p /tmp/sshctl
if ! ssh -nNf -o ControlMaster=yes -o ControlPath="${TMPL}" "${DEST}"; then
echo "# Failed to setup SSH ControlMaster. Aborting."
exit
fi
# ...
rsync -e "ssh -o 'ControlPath=${TMPL}'" ... "${DEST}":... ...
rsync -e "ssh -o 'ControlPath=${TMPL}'" ... "${DEST}":... ...
# ...
ssh -O exit -o ControlPath="${TMPL}" "${DEST}"
Be sure to secure the socket.
Best practice would be to set up SSH key pairs for automated authentication; i.e. create an SSH key pair and copy the public key to the server where these files are located, then use the private key in the rsync command: rsync -Pruzh --copy-links -e "ssh -i /path/to/private.key" .... This is fairly simple, secure, and gets rid of the prompt.
You can also use a utility like sshpass to enter the password in the prompt, but that kind of approach is less secure.

Execute commands after sshpass login in the script

I'm an Ubuntu bash newbie. I successfully login to an sFTP server using sshpass. But once the connection is established I also need to download a directory from the server. My script cannot seem to pass the connection line though. This is what I have in my script (.sh) file:
#!/bin/bash
sshpass -p 'MY_PASSWORD' sftp -o StrictHostKeyChecking=no -o HostKeyAlgorithms=+ssh-dss MYUSER#MYSFTPSERVERADDRESS
echo "hello"
get -r Export
In the snipped above, my echo and my get are not executed. The terminal is waiting for my input with a sftp> prompt.
You would be better served using scp instead of sftp and sharing keys instead of putting the password in a script if you're able, but if you must use sftp for some reason, it can take its commands from a heredoc like:
sshpass -p 'MY_PASS' sftp -o StrictHostKeyChecking=no -o HostKeyAlgorithms=+ssh-dss MYUSER#MYSFTPSERVERADDRESS <<EOF
get -r Export
EOF
note that echo isn't a valid sftp command.
You can put whatever commands you want sftp to execute before the EOF and it will do them each in turn.
If all you want is to get that directory it's probably still simpler to use scp if you can:
sshpass -p 'MY_PASSWORD' scp -o StrictHostKeyChecking=no -o HostKeyAlgorithms=+ssh-dss -r MYUSER#MYSFTPSERVERADDRESS:Export .

tar over ssh in combination with sshpass

I (very) recently posted this question in regards to tar over ssh.
The question now has an answer, and I am now asking a different question.
I run the following command to push code from my local machine to my server where it will run.
tar -cJf - ./my_folder | ssh user#example 'tar -xJf - -C ./path-to-my_folder/'
I know that with ssh/scp I can use sshpass -p password to stop the command asking for my password each time. Note that I cannot use alternative methods of authentication.
Is it possible to combine sshpass with my above command so that I do not have to enter my password continually?
In other words how should I edit the above command to include sshpass so that I do not have to type in my password each time the above command runs?
Edit: Note the following does work
For example
sshpass -p <password> ssh ... blaa blaa
sshpass -p <password> scp ... blaa blaa
I think you can use something like this:
tar -cJf - ./my_folder | sshpass -p $remote_ssh_password ssh -o StrictHostKeyChecking=no $remote_ssh_username#$remote_web_address "tar -xJf - -C ./path-to-my_folder/"
Note: StrictHostKeyChecking=no for avoiding prompt for server's fingerprint confirmation. It could create a security issue:
"Therefore, if you want to know whether you are talking to the right server (and not some impersonator), then you "just" need to compute the server's key fingerprint (from the public key that the server just sent to you) and compare it with a "reference fingerprint"."
More info can be found on here

Connect to multiple ssh connections through scripts

I have been trying to automatically enter a ssh connection using a script. This previous SOF post has helped me so far. Using one connection works (the first ssh statement). However, I want to create another ssh connection once connected, which I thought could look like this:
#! /bin/bash
# My ssh script
sshpass -p "MY_PASSWORD1" ssh -o StrictHostKeyChecking=no *my_hostname_1*
sshpass -p "MY_PASSWORD2" ssh -o StrictHostKeyChecking=no *my_hostname_2*
When running the script, I get only connected to the my_hostname_1 and the second ssh command is not run until I exit the first ssh connection.
I've tried using an if statement like this:
if [ "$HOSTNAME" = my_host_name_1 ]; then
sshpass -p "MY_PASSWORD2" ssh -o StrictHostKeyChecking=no *my_hostname_2*
fi
but I can't get any commands to be read until I exit the first connection.
Here is a ProxyCommand example as suggested by #lihao:
#!/bin/bash
sshpass -p "MY_PASSWORD2" ssh -o StrictHostKeyChecking=no \
-o ProxyCommand='sshpass -p "MY_PASSWORD1" ssh m_hostname_1 netcat -w 1 %h %p' \
my_hostname_2
You are proxying through the first host to get to the second. This assumes you have netcat installed on my_hostname_2. If not, you'll need to install it.
You can also set this up in your ~/.ssh/config file so you don't need the proxy stuff on the command line:
Host my_hostname_1
HostName my_hostname_1
Host my_hostname_2
HostName my_hostname_2
ProxyCommand ssh my_hostname_1 netcat -w 1 %h %p
However, this is a little trickier with the password handling. While you could put the sshpass here, it's not a great idea to have passwords in plain text. Using key based authentication might be better.
A Bash script is a sequence of commands.
echo moo
echo bar
will run echo moo and wait for it to complete, then run the next command.
You can run a remote command like this:
ssh remote echo moo
which will connect to remote, run the command, and exit. If there are additional commands in the script file after this, the shell which is executing these commands will continue with the next one, obviously on the host where you started the script.
To connect to one host from another, you could in principle do
ssh host1 ssh host2
but the proxy command suggested by #zerodiff improves on several aspects of the experience.

Resources