Open as many terminals as the number of ssh-s logged out and close the terminals in which ssh-s where logged out - linux

There are several terminals in a single localhost in which I have ssh-ed into the same user and same IP address. I want to find all the terminals in which a remote host has been logged, terminate all processes running in those and log out of that remote host. I succeeded using the following shell script.
#Find list of terminals in which the remote host is logged in.
openedTerminals=`ssh $user#$publicIP "ps -aux | grep -i $user#pts | grep -v grep | cut -d' ' -f 3"`
#close all the ssh sessions to that remote host
i=1
terminalPID=`echo $openedTerminals | cut -d' ' -f $i`
while [[ -n "$terminalPID" ]]
do
ssh $user#$publicIP "kill $terminalPID"
i=`expr $i + 1`
terminalPID=`echo $openedTerminals | cut -d' ' -f $i`
done
I used the following command to open a new terminal and ssh into a remote host which worked fine when executed from the command prompt:
gnome-terminal -window-with-profile=NOCLOSEPROFILE -e "ssh -X $user#$publicIP"
Apart from doing the work of the 1st code, I want to open a new terminal (by ssh-ing into another remote machine) for every remote machine which was terminated by the 1st code. So I tried to insert the above command in the 1st code as:
#Find list of terminals in which the remote host is logged in.
openedTerminals=`ssh $user#$publicIP "ps -aux | grep -i $user#pts | grep -v grep | cut -d' ' -f 3"`
#close all the ssh sessions to that remote host
i=1
terminalPID=`echo $openedTerminals | cut -d' ' -f $i`
while [[ -n "$terminalPID" ]]
do
ssh $user#$publicIP "kill $terminalPID"
gnome-terminal -window-with-profile=NOCLOSEPROFILE -e "ssh -X $newUser#$newPublicIP"
i=`expr $i + 1`
terminalPID=`echo $openedTerminals | cut -d' ' -f $i`
done
But this starts running in an infinite loop and opens infinite number of new terminals.
Please tell me where I am wrong and suggest a way to correct it in order to get the desired solution.
Also, I wish to add a command in the same shell script (1st code) to close the terminals in which the remote machine was logged out. Can anyone please guide me on this?
Thanks in advance,
Saeya

When only one terminal which is ssh-ed to the remote machine is opened, this runs in an infinite loop because of the "cut" command. If there is a separate case to handle one terminal this will work fine.

Related

Testing active ssh keys on the local network

I am trying currently to achieve a bash script that will validate if SSH keys on a server are still linked to known hosts that are active on the local area network. You can find below the beginning of my bash script to achieve this:
#!/bin/bash
# LAN SSH KEYS DISCOVERY SCRIPT
# TRYING TO FIND THOSE SSH KEYS NOW
cat /etc/passwd | grep /bin/bash > bash_users
cat bash_users | cut -d ":" -f 6 > cutted.bash_users_home_dir
for bash_users in $(cat cutted.bash_users_home_dir)
do
ls -al $bash_users/.ssh/*id_* >> ssh-keys.txt
done
# DISCOVERING THE KNOWN_HOSTS NOW
for known_hosts in $(cat cutted.bash_users_home_dir)
do
cat $bash_users/.ssh/known_hosts | awk '{print $1}' | sort -u >>
hosts_known.txt
sleep 2
done
hosts_known=$(wc -l hosts_known.txt)
echo "We have $hosts_known known hosts that could be still active via SSH
keys"
# TIME TO TEST WHICH SSH servers are still active with the SSH keys
# AND THIS IS WHERE I AM FROZEN...
# Would love to have bash script that could
# ssh -l $users_that_have_/bin/bash -i $ssh_keys $ssh_servers
# Would also be very nice if it could save active
# SSH servers with the valid keys in output.txt in the format
# username:local-IP:/path/to/SSH_key
Please feel very comfortable to edit/modify the bash script above if it can serve better the goals described.
Any help would be very appreciated,
Thanks
The following works cool:
</etc/passwd \
grep /bin/bash |
cut -d: -f6 |
sudo xargs -i -- sh -c '
[ -e "$1" ] && cat "$1"
' -- {}/.ssh/known_hosts |
cut -d' ' -f1 |
tr ',' '\n' |
sed '
/^\[/{
s/\[\(.*\)\]:\(.*\)/\1 \2/;
t;
};
s/$/ 22/;
' |
sort -u |
xargs -l1 -- sh -c '
if echo "~" | nc -q1 -w3 "$1" "$2" | grep -q "^SSH"; then
echo "#### SUCCESS $1 $2";
else
echo "#### ERROR $1 $2";
fi
' --
So:
Start with /etc/passwd
Filter all "bash_users" as you call them
Filter user home directories only cut -d: -f6
For each user home directory sudo xargs -i -- run
Check if the file .ssh/known_hosts inside the user home directory exists
If it does, print it
Filter only hosts names
Multiple hosts signatures may share same key and are separated by a comma. Replace comma for newline
Now a sed script:
If a line starts with a [ that means it has a format of [host]:port and I want to replace it with host port
If the line does not start with a [ I add 22 to the end of the line so it's host 22
Then I sort -u
Now for each line:
I get the ssh version from ssh echo "~" | nc hostname port returns smth like "SSH-2.0-OpenSSH_6.0" + newline + "Protocol mismatch".
So if the line returned by nc hostname port starts with SSH that means there is ssh running on the other side
I added timeout for unresponsive hosts, but I think nc -w timeout option may also be used. Probably also nc -q 1 should be specified.
Now the real fun is, when you add the max-procs option to the last xargs line, you can check all hosts simultaneously. On my host I have 47 unique addresses and xargs -P30 checks them ALL in like 2 seconds.
But really there are some problems. The script needs root to read from all users known_hosts. But worse, the known_hosts may be hashed. It would be better to firstly know the list of hosts on your network, and then generate known_hosts from it. It would look like ssh-keyscan -f list_of_hosts > ~/.ssh/known_hosts or similar. Generaly ssh-keygen -F hostname should be used if a host exists in known_hosts, sadly there is no listing command. known_hosts file format may be found in ssh documentation.

Multiple ssh in a Single command

I need to pipe multiple ssh commands in order to run commands on a remote machine.
The commands are working fine with a single ssh but not after piping ssh.
E.g
ssh abc#remotemachine1.com "a=hello ; echo \$a"
return hello
but
ssh abc#remotemachine1.com ssh abc#remotemachine2.com"a=hello ; echo \$a"
produces no output.
Similarly:
ssh abc#remotemachine1.com "mountedDir=\$(df \tmp | grep -vi filesystem | rev | cut -d ' ' -f 1); mount | grep -w \$mountedDir"
Is working fine producing the following output :
/dev/sda2 on / type xfs (rw,relatime,attr2,inode64,noquota)
but
ssh abc#remotemachine1.com ssh abc#remotemachine2.com "mountedDir=\$(df \tmp | grep -vi filesystem | rev | cut -d ' ' -f 1); mount | grep -w \$mountedDir"
is throwing the following error:
Usage: grep [OPTION]... PATTERN [FILE]...
Try 'grep --help' for more information.
Note: Passwordless ssh is established from my machine to remotemachine1.com and from remotemachine1.com to remotemachine2.com
If for some reason you do not want to modify your ssh_config file, you need to use ssh -t which will cause a real TTY to be allocated on machine 2, like so:
ssh -t abc#remotemachine1.com ssh abc#remotemachine2.com"a=hello ; echo \$a"
Be wary, as using this method implies that all the SSH login authentication procedures will happen at remotemachine1.com, so if you have security concerns, you are better off with #allo 's answer.
ssh abc#remotemachine1.com ssh abc#remotemachine2.com"a=hello ; echo \$a"
Looks wrong. If you want to jump from remotemachine1 to remotemachine2 have a look at the ProxyJump option in the ssh config. You can give it on the command line using the -o option of the ssh binary.
It finally worked after I added multiple escape characters
ssh abc#remotemachine1.com " ssh abc#remotemachine2.com \" a=hello ;echo \\\$a \" "
And
ssh abc#remotemachine1.com " ssh abc#remotemachine2.com \" mountedDir=\\\$(df /var | grep -vi filesystem | rev | cut -d ' ' -f 1); mount | grep -w \\\$mountedDir | grep -vi 'noexec' \" "

Retrieving the result of a bash command run from ssh into a variable

The following command runs well when i run it localy on the dsired machine:
app_name=*some_proccess_name*
pid=`pgrep $app_name | tail -n 1`
But when i run it in the following way, from a remote pc using ssh it dosn't work:
pid=$(ssh $USER_NAME#$HOST_NAME "echo `pgrep $app_name | tail -n 1`")
The value of pid afterwards is just blank. I am not sure what's wrong (just to clarify i have tried several processes names that are all running on the target pc- that's not the problem ).
P.S when i run the command without echo, like that, i just get stuck inside the remote pc and have to use exit in order to get unstuck and return to my local pc:
pid=$(ssh tester#mir1 "`pgrep indicator-apple | tail -n 1`")
Less is more
pid=$(ssh tester#mir1 pgrep indicator-apple \| tail -n 1)

Bash for loops on a remote server

I am attempting to run multiple commands via a bash script on a remote server. specifically, the for loop to be run on the remote server is giving me issues. I suspect it is because I don't know how to properly escape characters or use $().
Below is the code.
ssh (user)#(server) <<EOF
sudo su - (username)
whoami
'for e in $(`ls -lrt /usr/jboss/jbosseap | awk '{print $9}' | grep multichannel`);
do
echo "$e";
done'
Removing user and server names for obvious reasons. Just concentrate on the for loop. when I run that for loop command line (without the $()) its works fine. Just not sure how to nest it in a remote call.
Thanks very much for any and all help!
If you've got a complex script that you're trying to run over ssh you're going to be better off putting that script in a file and piping that file into ssh like:
cat remote_script.sh | ssh user#host
or:
cat remote_script.sh | ssh user#host sudo -u username
And now you don't have to worry about N levels of escaping.
You can run it as below .
here file "list " includes your list of nodes and script should be present in all nodes
for i in $(cat list ) ;do ssh -o StrictHostKeyChecking=no $i "/path/your_script" ;done

ssh command output to save in a text file in shell script

I want to write shell script, in which i am using ssh command.
Whatever output i will get through ssh command i want save this in text file or varibale, so i can use this in my shell script.
Currently i am saving output in a variable , but when i used that variable outside ssh command , value is showing blank.
Code is
ssh hostname -c "'
`pwd`;
var=$(ps -ef | grep Consumer | cut -f6 -d' ')
'";
echo $?;
echo "vbar $var";
var value is blank when i print.
To save ssh's output in local file "file.log":
ssh hostname > file.log << EOF
pwd
ps -ef | grep Consumer | cut -f6 -d' '
EOF

Resources