Bash While loop is not looping - bash

Im doing a backup script for Mikrotik devices using bash. I want to use a while loop that will read from a file.
The Contents of the file to read from will be like:
1.1.1.1 router1
2.2.2.2 router2
Here is my sample script:
while read -r ip name
do
sshpass -p "pass" ssh -o StrictHostKeyChecking=no export\#$ip "/export;/quit" 2> errors.log >> $name.export
done < iplistandnamefile
The problem is that the script will work for only the 1st IP address on the iplistandnamefile file but will not loop to the 2nd IP.
Any suggestions ?

ssh is eating the rest of the file as it defaults to reading stdin
add -n to the ssh command.
sshpass -p "pass" ssh -no StrictHostKeyChecking=no user#host command_to_run

Related

bash - executing ssh command in a loop

I have the loop:
IFS=','
for host in host1,host2
do
ssh root#$host script.sh
done
When I execute the loop, ssh command works fine for host1, but for host2 I see:
bash: host2: command not found
Could you tell me where can be the problem?
Just like this
for host in host1 host2
do
ssh root#$host script.sh
done
You above script will return an output command like this
ssh root#host1 host2 script.sh
Here host2 is considered as an argument or a command which the shell is not able to recognize and hence you are getting the above error.
Assuming your use case is to run the shell script on both hosts the following script might help you
IFS=', ' read -r -a array <<< host1,host2
for host in ${array[#]}; do ssh root#$host script.sh; done
output command will be similar to below
ssh root#host1 script.sh
ssh root#host2 script.sh
PSSH (https://github.com/lilydjwg/pssh)
Create your file with hosts/ip addresses, then try following:
pssh -h hostfile.txt -l root -i "echo 'hello world'; another_command; exit"
-h = hostfile with ip adddresses
-l = username to use
-i = command to execute on source
-A = for use password

sshpass from iplist and run tcptraceroute

Number of servers in a list = 40
I want to run tcptraceroute on each server for all 40 ips in the list. for this i need to loop sshpass and run tcptracetraceroute.
When i run the below code, it just runs for first ip in list and use same ip to run tcptraceroute and exits.
IFS=$IFS,
USER='*********'
PASSWORD='********'
PORT='22'
while read ip; do
sshpass -p $PASSWORD ssh -i turbot -t -o StrictHostKeyChecking=no
$USER#$ip "sudo -s /usr/bin/tcptraceroute "$ip" $PORT" >>Res.txt
done < .PrivateIP-List.txt
I'm trying to output the traceroute results to Res.txt file

How to copy echo 'x' to file during an ssh connection

I have a script which starts an ssh-connection.
so the variable $ssh start the ssh connection.
so $SSH hostname gives the hostname of the host where I ssh to.
Now I try to echo something and copy the output of the echo to a file.
SSH="ssh -tt -i key.pem user#ec2-instance"
When I perform a manual ssh to the host and perform:
sudo sh -c "echo 'DEVS=/dev/xvdbb' >> /etc/sysconfig/docker-storage-setup"
it works.
But when I perform
${SSH} sudo sh -c "echo 'DEVS=/dev/xvdb' > /etc/sysconfig/docker-storage-setup"
it does not seem to work.
EDIT:
Also using tee is working fine after performing an ssh manually but does not seem to work after the ssh in the script.sh
The echo command after an ssh of the script is happening on my real host (from where I'm running the script, not the host where I'm performing an ssh to). So the file on my real host is being changed and not the file on my host where I've performed an ssh to.
The command passed to ssh will be executed by the remote shell, so you need to add one level of quoting:
${SSH} "sudo sh -c \"echo 'DEVS=/dev/xvdb' > /etc/sysconfig/docker-storage-setup\""
The only thing you really need on the server is the writing though, so if you don't have password prompts and such you can get rid of some of this nesting:
echo 'DEVS=/dev/xvdb' | $SSH 'sudo tee /etc/sysconfig/docker-storage-setup'

Waiting for input from script that is running remotely via ssh

There is a script I'm running that I can not install on the remote machine.
clear && printf '\e[3J'
read -p "Please enter device: " pattern
read -p "Enter date: (YYYY-MM-DD): " date
pfix=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 5 | head -n 1)
mkdir /home/user/logCollectRes/"${pfix}"
ssh xxx.xxx.xxx.xxx 'bash -s' < /usr/local/bin/SearchAdvanced.sh ${pattern} ${date} ${pfix}
In that script, I would like to be able to use read.
ls -g *"${pattern}"*
read -p "Select one of these? [y/n] " "found";
I've tried adding the -n on the read as well as the -t -t option on ssh. As you can see the script presents information that is only seen once the script starts, so I can't use the read on local machine.
EDIT: So lets say server B stores syslogs for 5K computers. The file names are given by using the internal IP of the device and the date at the end.
/var/log/remotes/192.168.1.500201505050736.gz
/var/log/remotes/192.168.1.500201505050936.gz
/var/log/remotes/192.168.1.500201505051136.gz
/var/log/remotes/192.168.1.600201505050836.gz
/var/log/remotes/192.168.1.600201505051036.gz
/var/log/remotes/192.168.1.600201505051236.gz
I'd like to be able to select the IP address from the main script, list all the files matching that IP address, and then select which I want to scp to my local machine.
After speaking with some coworkers I found the answer to be running two scripts: The first pulls the ls -g result and directs the answer to a variable on the local machine. I then print that output with the read option of selecting on of the files. The 2nd script will take that answer and scp the file from the remote machine
In the main script
ssh xxx.xxx.xxx.xxx 'bash -s' < /usr/local/bin/SearchAdvanced.sh ${pattern} ${date} > ${result}
then as a follow up
printf "${result}"
read -p "Select file: "

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